RHEL 8 Beta Workshop: İşləyən Veb Tətbiqlərin qurulması

RHEL 8 Beta tərtibatçılara bir çox yeni funksiyalar təklif edir, onların siyahısı səhifələri əhatə edə bilər, lakin yeni şeyləri öyrənmək praktikada həmişə daha yaxşıdır, ona görə də aşağıda Red Hat Enterprise Linux 8 Beta əsasında tətbiq infrastrukturunun həqiqətən yaradılmasına dair seminar təklif edirik.

RHEL 8 Beta Workshop: İşləyən Veb Tətbiqlərin qurulması

Tərtibatçılar arasında populyar proqramlaşdırma dili olan Python-u əsas götürək, tətbiqlər yaratmaq üçün kifayət qədər ümumi kombinasiya olan Django və PostgreSQL birləşməsini götürək və RHEL 8 Beta-nı onlarla işləmək üçün konfiqurasiya edək. Sonra daha bir neçə (təsnif olunmamış) inqrediyent əlavə edəcəyik.

Test mühiti dəyişəcək, çünki avtomatlaşdırma imkanlarını araşdırmaq, konteynerlərlə işləmək və çoxsaylı serverlərlə mühitləri sınamaq maraqlıdır. Yeni layihəyə başlamaq üçün əl ilə kiçik, sadə prototip yaratmaqla başlaya bilərsiniz ki, nəyin baş verməsi və onun necə qarşılıqlı əlaqədə olduğunu dəqiq görə biləsiniz, sonra avtomatlaşdırmağa və daha mürəkkəb konfiqurasiyalar yaratmağa keçə bilərsiniz. Bu gün biz belə bir prototipin yaradılmasından danışırıq.

RHEL 8 Beta VM şəklini yerləşdirməklə başlayaq. Siz sıfırdan virtual maşın quraşdıra və ya Beta abunəliyinizlə mövcud olan KVM qonaq şəklini istifadə edə bilərsiniz. Qonaq şəklini istifadə edərkən, bulud başlatma (cloud-init) üçün metadata və istifadəçi məlumatlarını ehtiva edən virtual CD-ni konfiqurasiya etməlisiniz. Disk strukturu və ya mövcud paketlərlə xüsusi bir şey etməyə ehtiyac yoxdur; istənilən konfiqurasiya bunu edəcək.

Bütün prosesə daha yaxından nəzər salaq.

Django quraşdırılması

Django-nun ən yeni versiyası ilə sizə Python 3.5 və ya daha sonrakı versiyaları olan virtual mühit (virtualenv) lazımdır. Beta qeydlərində Python 3.6-nın mövcud olduğunu görə bilərsiniz, gəlin bunun həqiqətən belə olub olmadığını yoxlayaq:

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

Red Hat RHEL-də sistem alət dəsti kimi Python-dan fəal şəkildə istifadə edir, bəs niyə bu nəticə verir?

Fakt budur ki, bir çox Python tərtibatçıları hələ də Python 2-dən Python 2-yə keçid haqqında düşünürlər, Python 3 isə aktiv inkişaf mərhələsindədir və getdikcə daha çox yeni versiyalar daim ortaya çıxır. Buna görə, istifadəçilərə Python-un müxtəlif yeni versiyalarına çıxış təklif edərkən sabit sistem alətlərinə olan ehtiyacı ödəmək üçün Python sistemi yeni paketə köçürüldü və həm Python 2.7, həm də 3.6-nı quraşdırmaq imkanı verdi. Dəyişikliklər və onların nə üçün edildiyi haqqında daha çox məlumatı nəşrdə tapa bilərsiniz Lenqdon Uaytin bloqu (Lenqdon Uayt).

Beləliklə, işləmək üçün Python-u əldə etmək üçün yalnız iki paket quraşdırmalısınız, python3-pip asılılıq kimi daxil edilmişdir.

sudo yum install python36 python3-virtualenv

Niyə Lenqdonun təklif etdiyi kimi birbaşa modul zənglərindən istifadə edib pip3-ü quraşdırmırsınız? Qarşıdan gələn avtomatlaşdırmanı nəzərə alaraq, məlumdur ki, Ansible işləmək üçün quraşdırılmış pip tələb edəcək, çünki pip modulu xüsusi pip icra olunan virtualenvləri dəstəkləmir.

Sizin ixtiyarınızda olan işləyən python3 tərcüməçisi ilə siz Django quraşdırma prosesinə davam edə və digər komponentlərimizlə birlikdə işləyən sistemə sahib ola bilərsiniz. İnternetdə bir çox tətbiq variantları mövcuddur. Burada təqdim olunan bir versiya var, lakin istifadəçilər öz proseslərindən istifadə edə bilərlər.

Yum istifadə edərək standart olaraq RHEL 8-də mövcud olan PostgreSQL və Nginx versiyalarını quraşdıracağıq.

sudo yum install nginx postgresql-server

PostgreSQL psycopg2 tələb edəcək, lakin o, yalnız virtualenv mühitində mövcud olmalıdır, ona görə də onu Django və Gunicorn ilə birlikdə pip3 istifadə edərək quraşdıracağıq. Ancaq əvvəlcə virtualenv qurmalıyıq.

Django layihələrini quraşdırmaq üçün düzgün yer seçmək mövzusunda həmişə çoxlu müzakirələr aparılır, lakin şübhə olduqda, həmişə Linux Fayl Sistemi İerarxiya Standartına müraciət edə bilərsiniz. Xüsusilə, FHS deyir ki, /srv aşağıdakılar üçün istifadə olunur: "host-xüsusi məlumatların saxlanması - sistemin istehsal etdiyi verilənlər, məsələn, veb server məlumatları və skriptlər, FTP serverlərində saxlanılan məlumatlar və idarəetmə sistem depoları." versiyalar (FHS-də görünür. 2.3-cü ildə -2004).

Bu, bizim vəziyyətimizdir, ona görə də biz lazım olan hər şeyi proqram istifadəçimizə (bulud istifadəçisi) məxsus olan /srv-ə qoyuruq.

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 və Django quraşdırmaq asandır: verilənlər bazası yaradın, istifadəçi yaradın, icazələri konfiqurasiya edin. PostgreSQL-i ilkin olaraq quraşdırarkən yadda saxlamaq lazım olan bir şey postgresql-server paketi ilə quraşdırılmış postgresql-quraşdırma skriptidir. Bu skript klasterin işə salınması və ya təkmilləşdirmə prosesi kimi verilənlər bazası klasterinin idarə edilməsi ilə bağlı əsas tapşırıqları yerinə yetirməyə kömək edir. RHEL sistemində yeni PostgreSQL nümunəsini konfiqurasiya etmək üçün əmri yerinə yetirməliyik:

sudo /usr/bin/postgresql-setup -initdb

Daha sonra systemd istifadə edərək PostgreSQL-ə başlaya, verilənlər bazası yarada və Django-da layihə qura bilərsiniz. Tətbiq istifadəçisi üçün parol yaddaşını konfiqurasiya etmək üçün müştəri identifikasiyası konfiqurasiya faylına (adətən pg_hba.conf) dəyişikliklər etdikdən sonra PostgreSQL-i yenidən başlatmağı unutmayın. Başqa çətinliklərlə qarşılaşsanız, pg_hba.conf faylında IPv4 və IPv6 parametrlərini dəyişdirdiyinizə əmin olun.

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 faylında:

# 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 faylında:

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

Layihədə settings.py faylını konfiqurasiya etdikdən və verilənlər bazası konfiqurasiyasını qurduqdan sonra hər şeyin işlədiyinə əmin olmaq üçün inkişaf serverini işə sala bilərsiniz. İnkişaf serverini işə saldıqdan sonra verilənlər bazası ilə əlaqəni yoxlamaq üçün idarəçi istifadəçi yaratmaq yaxşı fikirdir.

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

WSGI? Vay?

İnkişaf serveri sınaq üçün faydalıdır, lakin proqramı işə salmaq üçün Veb Server Şlüz İnterfeysi (WSGI) üçün müvafiq server və proksi konfiqurasiya etməlisiniz. Bir neçə ümumi kombinasiya var, məsələn, uWSGI ilə Apache HTTPD və ya Gunicorn ilə Nginx.

Web Server Gateway Interface-in işi veb serverdən Python veb çərçivəsinə sorğu göndərməkdir. WSGI, CGI mühərriklərinin mövcud olduğu dəhşətli keçmişin yadigarıdır və bu gün WSGI istifadə olunan veb serverdən və ya Python çərçivəsindən asılı olmayaraq faktiki standartdır. Ancaq geniş istifadəsinə baxmayaraq, bu çərçivələrlə işləyərkən hələ də bir çox nüanslar və bir çox seçim var. Bu halda, bir yuva vasitəsilə Gunicorn və Nginx arasında qarşılıqlı əlaqə yaratmağa çalışacağıq.

Bu komponentlərin hər ikisi eyni serverdə quraşdırıldığından, şəbəkə yuvası əvəzinə UNIX yuvasından istifadə etməyə çalışaq. Rabitə istənilən halda rozetka tələb etdiyi üçün gəlin daha bir addım atmağa və sistem vasitəsilə Gunicorn üçün rozetkanın aktivləşdirilməsini konfiqurasiya etməyə çalışaq.

Socket aktivləşdirilmiş xidmətlərin yaradılması prosesi olduqca sadədir. Əvvəlcə UNIX yuvasının yaradılacağı nöqtəyə işarə edən ListenStream direktivindən ibarət vahid fayl yaradılır, sonra Requires direktivinin yuva vahid faylına işarə edəcəyi xidmət üçün vahid fayl. Bundan sonra, xidmət vahidi faylında yalnız virtual mühitdən Gunicorn-a zəng etmək və UNIX yuvası və Django tətbiqi üçün WSGI bağlamasını yaratmaq qalır.

Burada əsas kimi istifadə edə biləcəyiniz vahid faylların bəzi nümunələri verilmişdir. Əvvəlcə rozetkanı quraşdırırıq.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

İndi Gunicorn demonunu konfiqurasiya etməlisiniz.

[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 üçün proksi konfiqurasiya faylları yaratmaq və istifadə edirsinizsə, statik məzmunu saxlamaq üçün kataloq qurmaq sadə məsələdir. RHEL-də Nginx konfiqurasiya faylları /etc/nginx/conf.d-də yerləşir. Aşağıdakı nümunəni /etc/nginx/conf.d/default.conf faylına köçürə və xidmətə başlaya bilərsiniz. server_name-ni host adınıza uyğunlaşdırdığınızdan əmin olun.

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;
   }
}

Systemd istifadə edərək Gunicorn rozetkasını və Nginx-i işə salın və sınamağa başlamağa hazırsınız.

Bad Gateway xətası?

Ünvanı brauzerinizə daxil etsəniz, çox güman ki, 502 Bad Gateway xətası alacaqsınız. Səhv konfiqurasiya edilmiş UNIX soket icazələri səbəb ola bilər və ya SELinux-da giriş nəzarəti ilə bağlı daha mürəkkəb problemlərə görə ola bilər.

Nginx səhv jurnalında belə bir xətt görə bilərsiniz:

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-u birbaşa sınaqdan keçirsək, boş cavab alacağıq.

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

Bunun niyə baş verdiyini anlayaq. Əgər jurnalı açsanız, çox güman ki, problemin SELinux ilə əlaqəli olduğunu görəcəksiniz. Heç bir siyasət yaradılmamış bir demon işlətdiyimiz üçün o, init_t olaraq qeyd olunur. Gəlin bu nəzəriyyəni praktikada yoxlayaq.

sudo setenforce 0

Bütün bunlar tənqidə və qan gözyaşlarına səbəb ola bilər, lakin bu, sadəcə prototipi aradan qaldırmaqdır. Problemin bu olduğuna əmin olmaq üçün çeki söndürək, bundan sonra hər şeyi öz yerinə qaytaracağıq.

Brauzerdə səhifəni təzələməklə və ya curl əmrimizi yenidən işə salmaqla siz Django test səhifəsini görə bilərsiniz.

Beləliklə, hər şeyin işlədiyinə və artıq icazə probleminin olmadığına əmin olduqdan sonra SELinux-u yenidən işə salırıq.

sudo setenforce 1

Mən burada audit2allow və ya sepolgen ilə xəbərdarlıq əsaslı siyasətlər yaratmaq haqqında danışmayacağam, çünki hazırda faktiki Django tətbiqi yoxdur, ona görə də Gunicorn-un nəyə daxil olmaq istəyə biləcəyi və nəyə girişi rədd etməsi barədə tam xəritə yoxdur. Buna görə də, sistemi qorumaq üçün SELinux-u işlək vəziyyətdə saxlamaq lazımdır, eyni zamanda tətbiqin işləməsinə və audit jurnalında mesajlar buraxmasına icazə vermək lazımdır ki, onlardan faktiki siyasət yaradılsın.

İcazə verilən domenlərin təyin edilməsi

Hər kəs SELinux-da icazə verilən domenlər haqqında eşitməmişdir, lakin onlar yeni bir şey deyil. Çoxları hətta fərqinə varmadan onlarla işləyirdi. Audit mesajları əsasında siyasət yaradıldıqda, yaradılmış siyasət həll edilmiş domeni təmsil edir. Gəlin sadə icazə siyasəti yaratmağa çalışaq.

Gunicorn üçün xüsusi icazə verilən domen yaratmaq üçün sizə bir növ siyasət lazımdır, həmçinin müvafiq faylları qeyd etməlisiniz. Bundan əlavə, yeni siyasətləri yığmaq üçün alətlər lazımdır.

sudo yum install selinux-policy-devel

İcazə verilən domenlər mexanizmi problemləri müəyyən etmək üçün əla vasitədir, xüsusən də artıq yaradılmış siyasətlər olmadan göndərilən xüsusi proqram və ya proqramlara gəldikdə. Bu halda, Gunicorn üçün icazə verilən domen siyasəti mümkün qədər sadə olacaq - əsas növü elan edin (gunicorn_t), bir neçə icraedici faylı qeyd etmək üçün istifadə edəcəyimiz növü elan edin (gunicorn_exec_t) və sonra sistemin düzgün işarələnməsi üçün keçid qurun. çalışan proseslər. Son sətir siyasəti yüklənərkən defolt olaraq aktiv olaraq təyin edir.

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;

Siz bu siyasət faylını tərtib edib sisteminizə əlavə edə bilərsiniz.

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

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

SELinux-un naməlum demonumuzun daxil olduğu şeydən başqa bir şeyi bloklayıb-bilmədiyini yoxlayaq.

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-in Gunicorn tərəfindən istifadə edilən UNIX yuvasına məlumat yazmasının qarşısını alır. Tipik olaraq, belə hallarda siyasətlər dəyişməyə başlayır, lakin qarşıda başqa problemlər də var. Siz həmçinin domen parametrlərini məhdudiyyət domenindən icazə domeninə dəyişə bilərsiniz. İndi httpd_t-ni icazələr domeninə keçirək. Bu, Nginx-ə lazımi girişi verəcək və biz əlavə sazlama işinə davam edə bilərik.

sudo semanage permissive -a httpd_t

Beləliklə, SELinux-u qoruyub saxlamağa nail olduqdan sonra (siz həqiqətən SELinux layihəsini məhdudlaşdırılmış rejimdə tərk etməməlisiniz) və icazə domenləri yükləndikdən sonra hər şeyin düzgün işləməsi üçün gunicorn_exec_t kimi tam olaraq nəyin qeyd edilməli olduğunu başa düşməlisiniz. yenidən. Giriş məhdudiyyətləri ilə bağlı yeni mesajları görmək üçün vebsayta daxil olmağa cəhd edək.

sudo ausearch -m AVC -c gunicorn

Siz /srv/djangoapp-dakı fayllarda müxtəlif işlər görən 'comm="gunicorn"' ehtiva edən çoxlu mesajlar görəcəksiniz, ona görə də bu, açıq-aydın işarələməyə dəyər əmrlərdən biridir.

Ancaq əlavə olaraq, belə bir mesaj görünür:

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

Əgər siz gunicorn xidmətinin vəziyyətinə baxsanız və ya ps əmrini işlətsəniz, heç bir işləyən prosesi görməyəcəksiniz. Deyəsən, gunicorn virtualenv mühitimizdə Python tərcüməçisinə daxil olmağa, ola bilsin ki, işçi skriptlərini işə salmağa çalışır. İndi gəlin bu iki icra olunan faylı qeyd edək və Django test səhifəmizi aça bildiyimizi yoxlayaq.

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

Yeni teq seçilməzdən əvvəl gunicorn xidməti yenidən işə salınmalıdır. Siz onu dərhal yenidən başladın və ya xidməti dayandıra və saytı brauzerdə açdığınız zaman rozetkanın işə başlamasına icazə verə bilərsiniz. ps istifadə edərək proseslərin düzgün etiketləri aldığını yoxlayın.

ps -efZ | grep gunicorn

Daha sonra normal SELinux siyasəti yaratmağı unutmayın!

İndi AVC mesajlarına baxsanız, sonuncu mesajda proqramla əlaqəli hər şey üçün icazə verilən=1, sistemin qalan hissəsi üçün isə icazə verilən=0 var. Həqiqi tətbiqin hansı girişə ehtiyacı olduğunu başa düşsəniz, bu cür problemləri həll etməyin ən yaxşı yolunu tez tapa bilərsiniz. Lakin o vaxta qədər sistemi təhlükəsiz saxlamaq və Django layihəsinin aydın, istifadəyə yararlı auditini əldə etmək daha yaxşıdır.

sudo ausearch -m AVC

baş verdi!

Nginx və Gunicorn WSGI-yə əsaslanan bir cəbhə ilə işləyən Django layihəsi ortaya çıxdı. Python 3 və PostgreSQL 10-u RHEL 8 Beta depolarından konfiqurasiya etdik. İndi siz irəliləyə və konfiqurasiya prosesini avtomatlaşdırmaq, performansı yaxşılaşdırmaq və hətta bu konfiqurasiyanı konteynerləşdirmək üçün RHEL 8 Beta-da Django proqramları yarada (və ya sadəcə yerləşdirə) və ya digər mövcud alətləri araşdıra bilərsiniz.

Mənbə: www.habr.com

Добавить комментарий