RHEL 8 Бета семинар: Ажиллаж буй вэб програмуудыг бий болгох

RHEL 8 Beta нь хөгжүүлэгчдэд олон шинэ боломжуудыг санал болгодог бөгөөд тэдгээрийн жагсаалтад хуудас авч болох боловч шинэ зүйл сурах нь практик дээр үргэлж илүү сайн байдаг тул доор бид Red Hat Enterprise Linux 8 Бета дээр суурилсан хэрэглээний дэд бүтцийг бодитоор бий болгох сургалтыг санал болгож байна.

RHEL 8 Бета семинар: Ажиллаж буй вэб програмуудыг бий болгох

Хөгжүүлэгчдийн дунд түгээмэл хэрэглэгддэг програмчлалын хэл болох Python-г үндэс болгон программ үүсгэхэд түгээмэл хэрэглэгддэг Django болон PostgreSQL-ийн хослолыг авч, RHEL 8 Beta-г тэдэнтэй ажиллахаар тохируулцгаая. Дараа нь бид хэд хэдэн (ангилагдаагүй) найрлагыг нэмнэ.

Туршилтын орчин өөрчлөгдөх болно, учир нь автоматжуулалтын боломжуудыг судлах, контейнертэй ажиллах, олон сервер бүхий орчинг туршиж үзэх нь сонирхолтой юм. Шинэ төслийг эхлүүлэхийн тулд та гараараа жижиг, энгийн загвар бүтээж эхлэх боломжтой бөгөөд ингэснээр та яг юу болох ёстойг, энэ нь хэрхэн харьцаж байгааг харж, автоматжуулж, илүү төвөгтэй тохиргоог бий болгох боломжтой. Өнөөдөр бид ийм прототипийг бүтээх тухай ярьж байна.

RHEL 8 Бета VM дүрсийг байрлуулж эхэлцгээе. Та виртуал машиныг эхнээс нь суулгаж эсвэл Бета захиалгаар ашиглах боломжтой KVM зочны зургийг ашиглаж болно. Зочин дүрсийг ашиглахдаа та үүлэн эхлүүлэх (cloud-init)-д зориулсан мета өгөгдөл болон хэрэглэгчийн өгөгдлийг агуулсан виртуал CD-г тохируулах шаардлагатай болно. Та дискний бүтэц эсвэл боломжтой багцуудын талаар тусгай зүйл хийх шаардлагагүй, ямар ч тохиргоо хийх болно.

Бүх үйл явцыг нарийвчлан авч үзье.

Django суулгаж байна

Django-ийн хамгийн сүүлийн хувилбарыг ашигласнаар танд Python 3.5 ба түүнээс дээш хувилбар бүхий виртуал орчин (virtualenv) хэрэгтэй болно. Бета тэмдэглэлээс та Python 3.6 байгаа эсэхийг харж болно, энэ нь үнэхээр байгаа эсэхийг шалгацгаая:

[cloud-user@8beta1 ~]$ python
-bash: python: command not found
[cloud-user@8beta1 ~]$ python3
-bash: python3: command not found

Red Hat нь Python-ийг RHEL-д системийн хэрэглүүр болгон идэвхтэй ашигладаг тул яагаад ийм үр дүнд хүрсэн бэ?

Баримт нь олон Python хөгжүүлэгчид Python 2-оос Python 2 руу шилжих талаар бодож байгаа бол Python 3 өөрөө идэвхтэй хөгжиж байгаа бөгөөд улам олон шинэ хувилбарууд байнга гарч ирж байна. Тиймээс тогтвортой системийн хэрэгслийн хэрэгцээг хангахын зэрэгцээ Python-ийн янз бүрийн шинэ хувилбаруудад хандах боломжийг хэрэглэгчдэд олгохын тулд Python системийг шинэ багцад шилжүүлж, Python 2.7 болон 3.6-г хоёуланг нь суулгах боломжийг олгосон. Өөрчлөлт, яагаад хийгдсэн тухай дэлгэрэнгүй мэдээллийг нийтлэлээс олж болно Лангдон Уайтын блог (Лангдон Уайт).

Тиймээс Python-г ажиллуулахын тулд python3-pip-г хамаарал болгон оруулсан хоёр багцыг суулгахад л хангалттай.

sudo yum install python36 python3-virtualenv

Яагаад Лангдоны санал болгосноор шууд модулийн дуудлагыг ашиглаж, pip3-г суулгаж болохгүй гэж? Удахгүй болох автоматжуулалтыг санаж, pip модуль нь захиалгат pip-тэй виртуал файлуудыг дэмждэггүй тул Ansible-д pip суулгасан байх шаардлагатай гэдгийг мэдэж байгаа.

Ажиллаж байгаа python3 орчуулагчийн тусламжтайгаар та Django-г суулгах процессыг үргэлжлүүлж, бусад бүрэлдэхүүн хэсгүүдийн хамт ажиллах системтэй байх боломжтой. Интернет дээр хэрэгжүүлэх олон сонголтууд байдаг. Энд танилцуулсан нэг хувилбар байгаа боловч хэрэглэгчид өөрсдийн процессыг ашиглах боломжтой.

Бид RHEL 8-д байгаа PostgreSQL болон Nginx хувилбаруудыг Yum ашиглан анхдагчаар суулгана.

sudo yum install nginx postgresql-server

PostgreSQL-д psycopg2 хэрэгтэй, гэхдээ энэ нь зөвхөн virtualenv орчинд байх ёстой тул бид үүнийг Django болон Gunicorn-ийн хамт pip3 ашиглан суулгах болно. Гэхдээ эхлээд бид virtualenv-г тохируулах хэрэгтэй.

Django төслүүдийг суулгах зөв газрыг сонгох сэдвээр маш их маргаан үргэлжилдэг боловч эргэлзэж байвал та Linux файлын системийн шатлалын стандарт руу хандаж болно. Тодруулбал, /srv-ийг дараах зорилгоор ашигладаг: "хостын тусгай өгөгдлийг хадгалах - вэб серверийн өгөгдөл, скриптүүд, FTP серверүүд дээр хадгалагдсан өгөгдөл, хяналтын системийн агуулахууд гэх мэт өгөгдлийг хадгалах." хувилбарууд (FHS-д гарч ирдэг. 2.3 онд -2004).

Энэ бол яг бидний хэрэг тул бид хэрэгцээтэй бүх зүйлээ манай програмын хэрэглэгчийн (cloud-user) эзэмшдэг /srv-д оруулдаг.

sudo mkdir /srv/djangoapp
sudo chown cloud-user:cloud-user /srv/djangoapp
cd /srv/djangoapp
virtualenv django
source django/bin/activate
pip3 install django gunicorn psycopg2
./django-admin startproject djangoapp /srv/djangoapp

PostgreSQL болон Django-г тохируулах нь амархан: мэдээллийн сан үүсгэх, хэрэглэгч үүсгэх, зөвшөөрлийг тохируулах. PostgreSQL-ийг анх суулгахдаа анхаарах нэг зүйл бол postgresql-server багцтай суулгасан postgresql-тохируулгын скрипт юм. Энэ скрипт нь кластер эхлүүлэх эсвэл шинэчлэх процесс зэрэг мэдээллийн сангийн кластерын удирдлагатай холбоотой үндсэн ажлуудыг гүйцэтгэхэд тусална. RHEL систем дээр шинэ PostgreSQL жишээг тохируулахын тулд бид дараах тушаалыг ажиллуулах хэрэгтэй.

sudo /usr/bin/postgresql-setup -initdb

Дараа нь та PostgreSQL-г systemd ашиглан эхлүүлж, мэдээллийн сан үүсгэж, Django дээр төсөл тохируулж болно. Үйлчлүүлэгчийн баталгаажуулалтын тохиргооны файлд (ихэвчлэн pg_hba.conf) өөрчлөлт хийсний дараа програмын хэрэглэгчийн нууц үг хадгалах тохиргоог хийсний дараа PostgreSQL-г дахин эхлүүлэхээ бүү мартаарай. Хэрэв танд өөр асуудал тулгарвал pg_hba.conf файлын IPv4 болон IPv6 тохиргоог өөрчлөхөө мартуузай.

systemctl enable -now postgresql

sudo -u postgres psql
postgres=# create database djangoapp;
postgres=# create user djangouser with password 'qwer4321';
postgres=# alter role djangouser set client_encoding to 'utf8';
postgres=# alter role djangouser set default_transaction_isolation to 'read committed';
postgres=# alter role djangouser set timezone to 'utc';
postgres=# grant all on DATABASE djangoapp to djangouser;
postgres=# q

/var/lib/pgsql/data/pg_hba.conf файлд:

# IPv4 local connections:
host    all        all 0.0.0.0/0                md5
# IPv6 local connections:
host    all        all ::1/128                 md5

/srv/djangoapp/settings.py файлд:

# Database
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.postgresql_psycopg2',
       'NAME': '{{ db_name }}',
       'USER': '{{ db_user }}',
       'PASSWORD': '{{ db_password }}',
       'HOST': '{{ db_host }}',
   }
}

Төсөл дэх settings.py файлыг тохируулж, мэдээллийн баазын тохиргоог тохируулсны дараа бүх зүйл ажиллаж байгаа эсэхийг шалгахын тулд хөгжүүлэлтийн серверийг эхлүүлж болно. Хөгжүүлэгч серверийг ажиллуулсны дараа мэдээллийн сантай холболтыг шалгахын тулд админ хэрэглэгч үүсгэх нь зүйтэй.

./manage.py runserver 0.0.0.0:8000
./manage.py createsuperuser

WSGI? Вай?

Хөгжүүлэгч сервер нь туршилт хийхэд тустай боловч програмыг ажиллуулахын тулд вэб серверийн гарц интерфэйс (WSGI)-д тохирох сервер болон проксиг тохируулах шаардлагатай. Хэд хэдэн нийтлэг хослолууд байдаг, жишээлбэл, uWSGI-тай Apache HTTPD эсвэл Gunicorn-тэй Nginx.

Web Server Gateway Interface-ийн ажил нь вэб серверээс Python вэб фреймворк руу хүсэлтийг дамжуулах явдал юм. WSGI бол CGI хөдөлгүүрүүд ажиллаж байсан аймшигт өнгөрсөн үеийн үлдэгдэл бөгөөд өнөөдөр WSGI нь вэб сервер эсвэл Python фреймворк ашиглаж байгаагаас үл хамааран де факто стандарт юм. Гэхдээ өргөн хэрэглэгддэг хэдий ч эдгээр хүрээтэй ажиллахад олон нюансууд, олон сонголтууд байсаар байна. Энэ тохиолдолд бид Gunicorn болон Nginx-ийн хооронд холболтыг залгуураар бий болгохыг хичээх болно.

Эдгээр хоёр бүрэлдэхүүн хэсэг нь нэг сервер дээр суурилагдсан тул сүлжээний залгуурын оронд UNIX сокет ашиглаж үзье. Харилцаа холбоо ямар ч тохиолдолд залгуур шаарддаг тул дахиад нэг алхам хийж, Gunicorn-д зориулсан залгуурын идэвхжүүлэлтийг systemd-ээр тохируулахыг хичээцгээе.

Сокет идэвхжүүлсэн үйлчилгээг бий болгох үйл явц нь маш энгийн. Эхлээд UNIX сокет үүсгэх цэгийг зааж өгсөн ListenStream удирдамж агуулсан нэгж файл үүсгэгдэж, дараа нь Requires заавар нь залгуурын нэгж файл руу чиглэх үйлчилгээний нэгж файлыг үүсгэнэ. Дараа нь үйлчилгээний нэгжийн файлд виртуал орчноос Gunicorn-г дуудаж, UNIX залгуур болон Django програмд ​​зориулсан WSGI холболт үүсгэх л үлдлээ.

Үндэс болгон ашиглаж болох нэгж файлуудын зарим жишээ энд байна. Эхлээд бид залгуурыг тохируулна.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Одоо та Gunicorn дэмоныг тохируулах хэрэгтэй.

[Unit]
Description=Gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=cloud-user
Group=cloud-user
WorkingDirectory=/srv/djangoapp

ExecStart=/srv/djangoapp/django/bin/gunicorn 
         —access-logfile - 
         —workers 3 
         —bind unix:gunicorn.sock djangoapp.wsgi

[Install]
WantedBy=multi-user.target

Nginx-ийн хувьд прокси тохиргооны файлуудыг үүсгэх, хэрэв та ашиглаж байгаа бол статик контент хадгалах лавлах үүсгэх нь энгийн асуудал юм. RHEL-д Nginx тохиргооны файлууд /etc/nginx/conf.d дотор байрладаг. Та дараах жишээг /etc/nginx/conf.d/default.conf файл руу хуулж, үйлчилгээг эхлүүлж болно. Server_name-г өөрийн хостын нэрэнд тааруулж тохируулахаа мартуузай.

server {
   listen 80;
   server_name 8beta1.example.com;

   location = /favicon.ico { access_log off; log_not_found off; }
   location /static/ {
       root /srv/djangoapp;
   }

   location / {
       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_pass http://unix:/run/gunicorn.sock;
   }
}

Gunicorn залгуур болон Nginx-ийг systemd ашиглан эхлүүлснээр та туршилтаа эхлүүлэхэд бэлэн боллоо.

Муу гарцын алдаа?

Хэрэв та хөтөчдөө хаягаа оруулбал 502 Bad Gateway алдаа хүлээн авах магадлалтай. Энэ нь буруу тохируулагдсан UNIX залгуурын зөвшөөрлөөс үүдэлтэй эсвэл SELinux дахь хандалтын хяналттай холбоотой илүү төвөгтэй асуудлуудаас үүдэлтэй байж болно.

Nginx алдааны бүртгэлд та иймэрхүү мөрийг харж болно:

2018/12/18 15:38:03 [crit] 12734#0: *3 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.122.1, server: 8beta1.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/", host: "8beta1.example.com"

Хэрэв бид Gunicorn-ийг шууд туршиж үзэх юм бол бид хоосон хариулт авах болно.

curl —unix-socket /run/gunicorn.sock 8beta1.example.com

Яагаад ийм зүйл болж байгааг олж мэдье. Хэрэв та логыг нээвэл асуудал нь SELinux-тай холбоотой болохыг харах болно. Бид ямар ч бодлого үүсгээгүй дэмон ажиллуулж байгаа тул init_t гэж тэмдэглэсэн. Энэ онолыг практик дээр туршиж үзье.

sudo setenforce 0

Энэ бүхэн шүүмжлэл, нулимс урсгаж болох ч энэ нь зүгээр л прототипийг дибаг хийх явдал юм. Асуудал ийм байгаа эсэхийг шалгахын тулд чекийг идэвхгүй болгоё, үүний дараа бид бүгдийг байрандаа буцаана.

Хөтөч дээрх хуудсыг шинэчлэх эсвэл curl командыг дахин ажиллуулснаар та Django тестийн хуудсыг харах боломжтой.

Тиймээс, бүх зүйл ажиллаж байгаа бөгөөд зөвшөөрлийн асуудал байхгүй эсэхийг шалгасны дараа бид SELinux-г дахин идэвхжүүлнэ.

sudo setenforce 1

Одоогоор Django програм байхгүй тул Gunicorn юунд хандахыг хүсэж болох, юунд хандахыг хориглох талаар бүрэн зураглал байхгүй тул би Audi2allow эсвэл sepolgen-тэй дохиололд суурилсан бодлогыг энд ярихгүй. Тиймээс системийг хамгаалахын тулд SELinux-ийг ажиллуулах шаардлагатай бөгөөд үүний зэрэгцээ програмыг ажиллуулж, аудитын бүртгэлд мессеж үлдээх боломжтой бөгөөд ингэснээр бодит бодлогыг тэдгээрээс үүсгэж болно.

Зөвшөөрөгдсөн домайнуудыг зааж өгч байна

SELinux дахь зөвшөөрөгдсөн домэйнуудын талаар хүн бүр сонсоогүй ч шинэ зүйл биш юм. Олонхи нь өөрсдөө ч мэдэлгүй тэдэнтэй хамтарч ажилласан. Аудитын мессеж дээр тулгуурлан бодлогыг үүсгэх үед үүсгэсэн бодлого нь шийдвэрлэгдсэн домэйныг илэрхийлнэ. Энгийн зөвшөөрлийн бодлогыг бий болгохыг хичээцгээе.

Gunicorn-д зориулсан тусгай зөвшөөрөгдсөн домэйн үүсгэхийн тулд танд ямар нэгэн бодлого хэрэгтэй бөгөөд зохих файлуудыг тэмдэглэх хэрэгтэй. Нэмж дурдахад шинэ бодлогыг нэгтгэхэд багаж хэрэгсэл хэрэгтэй.

sudo yum install selinux-policy-devel

Зөвшөөрөгдсөн домэйны механизм нь ялангуяа захиалгат програм эсвэл аль хэдийн үүсгэсэн бодлогогүйгээр илгээгддэг програмуудтай холбоотой асуудлыг тодорхойлох гайхалтай хэрэгсэл юм. Энэ тохиолдолд Gunicorn-д зориулсан зөвшөөрөгдсөн домэйны бодлого аль болох энгийн байх болно - үндсэн төрлийг (gunicorn_t) зарлаж, олон гүйцэтгэгдэх файлыг (gunicorn_exec_t) тэмдэглэхэд ашиглах төрлийг зарлаж, системд зөв тэмдэглэгээ хийх шилжилтийг тохируулна уу. ажиллаж байгаа процессууд. Сүүлийн мөрөнд уг бодлогыг ачаалах үед анхдагчаар идэвхжүүлсэн байдлаар тохируулна.

gunicorn.te:

policy_module(gunicorn, 1.0)

type gunicorn_t;
type gunicorn_exec_t;
init_daemon_domain(gunicorn_t, gunicorn_exec_t)
permissive gunicorn_t;

Та энэ бодлогын файлыг эмхэтгэж системдээ нэмж болно.

make -f /usr/share/selinux/devel/Makefile
sudo semodule -i gunicorn.pp

sudo semanage permissive -a gunicorn_t
sudo semodule -l | grep permissive

SELinux нь бидний үл мэдэгдэх демон руу хандаж байгаа зүйлээс өөр зүйлийг хааж байгаа эсэхийг шалгацгаая.

sudo ausearch -m AVC

type=AVC msg=audit(1545315977.237:1273): avc:  denied { write } for pid=19400 comm="nginx" name="gunicorn.sock" dev="tmpfs" ino=52977 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0

SELinux нь Nginx-ийг Gunicorn-ийн ашигладаг UNIX залгуурт өгөгдөл бичихээс сэргийлдэг. Ихэвчлэн ийм тохиолдолд бодлого өөрчлөгдөж эхэлдэг ч өөр сорилтууд хүлээж байдаг. Та мөн домайн тохиргоог хязгаарлалтын домэйноос зөвшөөрлийн домэйн болгон өөрчилж болно. Одоо httpd_t-г зөвшөөрлийн домайн руу шилжүүлье. Энэ нь Nginx-д шаардлагатай хандалтыг өгөх бөгөөд бид дибаг хийх ажлыг үргэлжлүүлж болно.

sudo semanage permissive -a httpd_t

Тиймээс, та SELinux-ийг хамгаалж чадсан (чи үнэхээр SELinux төслийг хязгаарлагдмал горимд орхиж болохгүй), зөвшөөрлийн домэйнууд ачаалагдсан бол бүх зүйлийг зөв ажиллуулахын тулд яг юуг gunicorn_exec_t гэж тэмдэглэх хэрэгтэйг олж мэдэх хэрэгтэй. дахин. Хандалтын хязгаарлалтын талаарх шинэ мессежүүдийг үзэхийн тулд вэбсайтад зочилж үзье.

sudo ausearch -m AVC -c gunicorn

Та /srv/djangoapp доторх файлууд дээр янз бүрийн зүйл хийдэг 'comm="gunicorn"' агуулсан маш олон мессежийг харах болно, тиймээс энэ нь дарцаглах хэрэгтэй командуудын нэг нь мэдээж юм.

Гэхдээ үүнээс гадна иймэрхүү мессеж гарч ирнэ:

type=AVC msg=audit(1545320700.070:1542): avc:  denied { execute } for pid=20704 comm="(gunicorn)" name="python3.6" dev="vda3" ino=8515706 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0

Хэрэв та gunicorn үйлчилгээний статусыг харвал эсвэл ps командыг ажиллуулбал ямар ч ажиллаж байгаа процесс харагдахгүй. gunicorn нь манай virtualenv орчинд Python орчуулагч руу хандах, магадгүй ажилчны скриптүүдийг ажиллуулах гэж оролдож байх шиг байна. Одоо эдгээр хоёр гүйцэтгэгдэх файлыг тэмдэглээд Django тестийн хуудсыг нээж чадах эсэхийг шалгацгаая.

chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6

Шинэ шошгыг сонгохын өмнө gunicorn үйлчилгээг дахин эхлүүлэх шаардлагатай. Та үүнийг даруй дахин эхлүүлэх эсвэл үйлчилгээгээ зогсоож, сайтыг хөтөч дээр нээх үед залгуурыг ажиллуулж болно. ps ашиглан процессууд зөв шошгыг хүлээн авсан эсэхийг шалгана уу.

ps -efZ | grep gunicorn

Дараа нь ердийн SELinux бодлогыг үүсгэхээ бүү мартаарай!

Хэрэв та одоо AVC мессежийг харвал сүүлийн мессеж нь програмтай холбоотой бүх зүйлд зөвшөөрөгдсөн=1, системийн бусад хэсэгт зөвшөөрөгдөх=0 гэсэн утгатай байна. Хэрэв та жинхэнэ програмд ​​ямар төрлийн хандалт хэрэгтэйг ойлгож байгаа бол ийм асуудлыг шийдэх хамгийн сайн аргыг хурдан олох боломжтой. Гэхдээ тэр болтол системийг аюулгүй байлгаж, Django төслийн талаар ойлгомжтой, ашиглах боломжтой аудит авах нь дээр.

sudo ausearch -m AVC

Боллоо!

Nginx болон Gunicorn WSGI дээр суурилсан урд талбар бүхий Django төсөл гарч ирэв. Бид RHEL 3 Бета репозитороос Python 10 болон PostgreSQL 8-ыг тохируулсан. Одоо та тохиргооны процессыг автоматжуулах, гүйцэтгэлийг сайжруулах эсвэл бүр энэ тохиргоог хадгалахын тулд RHEL 8 Бета хувилбарт Django програмуудыг үүсгэж (эсвэл зүгээр л байрлуулж) эсвэл бусад боломжтой хэрэгслүүдийг судлах боломжтой.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх