Workshop RHEL 8 Beta: Bini ta' applikazzjonijiet tal-web li jaħdmu

RHEL 8 Beta joffri lill-iżviluppaturi ħafna karatteristiċi ġodda, li l-elenkar tagħhom jista 'jieħu paġni, madankollu, it-tagħlim ta' affarijiet ġodda huwa dejjem aħjar fil-prattika, għalhekk hawn taħt noffru workshop dwar il-ħolqien ta 'infrastruttura ta' applikazzjoni bbażata fuq Red Hat Enterprise Linux 8 Beta.

Workshop RHEL 8 Beta: Bini ta' applikazzjonijiet tal-web li jaħdmu

Ejja nieħdu Python, lingwa ta 'programmar popolari fost l-iżviluppaturi, bħala bażi, taħlita ta' Django u PostgreSQL, kombinazzjoni pjuttost komuni għall-ħolqien ta 'applikazzjonijiet, u kkonfigurat RHEL 8 Beta biex jaħdem magħhom. Imbagħad inżidu ftit ingredjenti oħra (mhux klassifikati).

L-ambjent tat-test se jinbidel, minħabba li huwa interessanti li jiġu esplorati l-possibbiltajiet ta 'awtomazzjoni, taħdem ma' kontenituri u tipprova ambjenti b'diversi servers. Biex tibda bi proġett ġdid, tista 'tibda billi toħloq prototip żgħir u sempliċi bl-idejn sabiex tkun tista' tara eżattament x'jeħtieġ li jiġri u kif jinteraġixxi, u mbagħad timxi biex awtomat u toħloq konfigurazzjonijiet aktar kumplessi. Illum qed nitkellmu dwar il-ħolqien ta 'prototip bħal dan.

Nibdew billi niskjeraw l-immaġni RHEL 8 Beta VM. Tista' tinstalla magna virtwali mill-bidu, jew tuża l-immaġni tal-mistieden KVM disponibbli bl-abbonament Beta tiegħek. Meta tuża immaġni mistieden, ser ikollok bżonn tikkonfigura CD virtwali li jkun fih metadata u data tal-utent għall-inizjalizzazzjoni tas-sħab (cloud-init). M'għandekx bżonn tagħmel xi ħaġa speċjali bl-istruttura tad-disk jew pakketti disponibbli; kwalunkwe konfigurazzjoni se tagħmel.

Ejja nagħtu ħarsa aktar mill-qrib lejn il-proċess kollu.

Installazzjoni ta' Django

Bl-aktar verżjoni ġdida ta 'Django, ser ikollok bżonn ambjent virtwali (virtualenv) b'Python 3.5 jew aktar tard. Fin-noti Beta tista 'tara li Python 3.6 huwa disponibbli, ejja niċċekkjaw jekk dan huwiex tabilħaqq il-każ:

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

Red Hat juża Python b'mod attiv bħala sett ta 'għodda tas-sistema f'RHEL, allura għaliex dan jirriżulta?

Il-fatt hu li ħafna żviluppaturi ta 'Python għadhom qed jikkontemplaw it-tranżizzjoni minn Python 2 għal Python 2, filwaqt li Python 3 innifsu jinsab taħt żvilupp attiv, u aktar u aktar verżjonijiet ġodda qed jidhru kontinwament. Għalhekk, biex tissodisfa l-ħtieġa għal għodod tas-sistema stabbli filwaqt li toffri lill-utenti aċċess għal diversi verżjonijiet ġodda ta 'Python, is-sistema Python ġiet imċaqalqa f'pakkett ġdid u pprovdiet l-abbiltà li tinstalla kemm Python 2.7 kif ukoll 3.6. Aktar informazzjoni dwar il-bidliet u għaliex saru jistgħu jinstabu fil-pubblikazzjoni fi Il-blog ta' Langdon White (Langdon Abjad).

Allura, biex tibda taħdem Python, għandek bżonn biss tinstalla żewġ pakketti, b'python3-pip inkluż bħala dipendenza.

sudo yum install python36 python3-virtualenv

Għaliex ma tużax sejħiet diretti tal-moduli kif jissuġġerixxi Langdon u tinstalla pip3? Filwaqt li wieħed iżomm f'moħħu l-awtomazzjoni li jmiss, huwa magħruf li Ansible se jeħtieġ pip installat biex jaħdem, peress li l-modulu pip ma jappoġġjax virtualenvs b'eżekutibbli pip personalizzat.

B'interpretu python3 li jaħdem għad-dispożizzjoni tiegħek, tista 'tkompli bil-proċess ta' installazzjoni ta 'Django u jkollok sistema ta' ħidma flimkien mal-komponenti l-oħra tagħna. Hemm ħafna għażliet ta' implimentazzjoni disponibbli fuq l-Internet. Hemm verżjoni waħda ppreżentata hawn, iżda l-utenti jistgħu jużaw il-proċessi tagħhom stess.

Aħna se ninstallaw il-verżjonijiet PostgreSQL u Nginx disponibbli f'RHEL 8 b'mod awtomatiku billi tuża Yum.

sudo yum install nginx postgresql-server

PostgreSQL se jeħtieġ psycopg2, iżda jeħtieġ li jkun disponibbli biss f'ambjent virtualenv, għalhekk aħna se ninstallawh bl-użu ta 'pip3 flimkien ma' Django u Gunicorn. Imma l-ewwel irridu nwaqqfu virtualenv.

Dejjem hemm ħafna dibattitu dwar is-suġġett tal-għażla tal-post it-tajjeb biex jiġu installati proġetti Django, iżda meta jkollok dubju, tista 'dejjem iddur għall-Linux Filesystem Hierarchy Standard. Speċifikament, l-FHS tgħid li / srv jintuża biex: "taħżen data speċifika għall-host—data li tipproduċi s-sistema, bħal data u skripts tal-web server, data maħżuna fuq servers FTP, u repożitorji tas-sistema ta' kontroll." verżjonijiet (li jidhru fl-FHS -2.3 fl-2004)."

Dan huwa eżattament il-każ tagħna, għalhekk inpoġġu dak kollu li neħtieġu f'/srv, li huwa proprjetà tal-utent tal-applikazzjoni tagħna (cloud-user).

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

It-twaqqif ta' PostgreSQL u Django huwa faċli: toħloq database, toħloq utent, ikkonfigura l-permessi. Ħaġa waħda li għandek iżżomm f'moħħok meta inizjalment tinstalla PostgreSQL hija l-iskrittura postgresql-setup li hija installata mal-pakkett postgresql-server. Din l-iskrittura tgħinek twettaq kompiti bażiċi assoċjati mal-amministrazzjoni tal-clusters tad-database, bħall-inizjalizzazzjoni tal-clusters jew il-proċess tal-aġġornament. Biex tikkonfigura istanza PostgreSQL ġdida fuq sistema RHEL, irridu nħaddmu l-kmand:

sudo /usr/bin/postgresql-setup -initdb

Imbagħad tista 'tibda PostgreSQL billi tuża systemd, toħloq database, u twaqqaf proġett f'Django. Ftakar li terġa 'tibda PostgreSQL wara li tagħmel bidliet fil-fajl tal-konfigurazzjoni tal-awtentikazzjoni tal-klijent (ġeneralment pg_hba.conf) biex tikkonfigura l-ħażna tal-password għall-utent tal-applikazzjoni. Jekk tiltaqa' ma' diffikultajiet oħra, kun żgur li tibdel is-settings IPv4 u IPv6 fil-fajl pg_hba.conf.

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

Fil-fajl /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

Fil-fajl /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 }}',
   }
}

Wara li kkonfigurat il-fajl settings.py fil-proġett u twaqqaf il-konfigurazzjoni tad-database, tista 'tibda s-server tal-iżvilupp biex tiżgura li kollox jaħdem. Wara li tibda s-server tal-iżvilupp, hija idea tajba li toħloq utent admin sabiex tittestja l-konnessjoni mad-database.

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

WSGI? Wai?

Is-server tal-iżvilupp huwa utli għall-ittestjar, iżda biex tħaddem l-applikazzjoni trid tikkonfigura s-server u l-prokura xierqa għall-Interface tal-Gateway tas-Server tal-Web (WSGI). Hemm diversi kombinazzjonijiet komuni, pereżempju, Apache HTTPD ma 'uWSGI jew Nginx ma' Gunicorn.

Ix-xogħol tal-Web Server Gateway Interface huwa li jgħaddi talbiet mis-server tal-web lill-qafas tal-web Python. WSGI huwa relikwa tal-passat terribbli meta l-magni CGI kienu madwar, u llum WSGI huwa l-istandard de facto, irrispettivament mis-server tal-web jew il-qafas Python użat. Iżda minkejja l-użu mifrux tiegħu, għad hemm ħafna sfumaturi meta taħdem ma 'dawn l-oqfsa, u ħafna għażliet. F'dan il-każ, se nippruvaw nistabbilixxu interazzjoni bejn Gunicorn u Nginx permezz ta 'socket.

Peress li dawn iż-żewġ komponenti huma installati fuq l-istess server, ejja nippruvaw nużaw socket UNIX minflok socket tan-netwerk. Peress li l-komunikazzjoni teħtieġ sokit fi kwalunkwe każ, ejja nippruvaw nagħmlu pass ieħor u kkonfiguraw l-attivazzjoni tas-socket għal Gunicorn permezz ta 'systemd.

Il-proċess tal-ħolqien ta 'servizzi attivati ​​minn socket huwa pjuttost sempliċi. L-ewwel, jinħoloq fajl tal-unità li fih direttiva ListenStream li tipponta lejn il-punt li fih se jinħoloq is-socket UNIX, imbagħad fajl tal-unità għas-servizz li fih id-direttiva Requires se tipponta lejn il-fajl tal-unità tas-socket. Imbagħad, fil-fajl tal-unità tas-servizz, kulma jibqa 'huwa li ċċempel lil Gunicorn mill-ambjent virtwali u toħloq rbit WSGI għas-socket UNIX u l-applikazzjoni Django.

Hawn huma xi eżempji ta 'fajls ta' unità li tista 'tuża bħala bażi. L-ewwel waqqafna s-sokit.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Issa għandek bżonn tikkonfigura d-daemon 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

Għal Nginx, hija kwistjoni sempliċi li toħloq fajls ta 'konfigurazzjoni ta' prokura u twaqqaf direttorju biex jaħżen kontenut statiku jekk qed tuża wieħed. F'RHEL, il-fajls tal-konfigurazzjoni Nginx jinsabu f'/etc/nginx/conf.d. Tista 'tikkopja l-eżempju li ġej fil-fajl /etc/nginx/conf.d/default.conf u tibda s-servizz. Kun żgur li tissettja l-isem tas-server biex jaqbel mal-isem tal-host tiegħek.

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

Ibda s-socket Gunicorn u Nginx billi tuża systemd u tkun lest biex tibda tittestja.

Żball Bad Gateway?

Jekk iddaħħal l-indirizz fil-browser tiegħek, x'aktarx tirċievi żball 502 Bad Gateway. Jista 'jkun ikkawżat minn permessi tas-socket UNIX konfigurati ħażin, jew jista' jkun minħabba kwistjonijiet aktar kumplessi relatati mal-kontroll tal-aċċess f'SELinux.

Fil-log ta 'żbalji nginx tista' tara linja bħal din:

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"

Jekk nittestjaw Gunicorn direttament, se nġibu tweġiba vojta.

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

Ejja nsemmu għaliex jiġri dan. Jekk tiftaħ il-log, x'aktarx se tara li l-problema hija relatata ma 'SELinux. Peress li qed inħaddmu daemon li għalih ma nħolqot ebda politika, huwa mmarkat bħala init_t. Ejja nittestjaw din it-teorija fil-prattika.

sudo setenforce 0

Dan kollu jista 'jikkawża kritika u tiċrit tad-demm, iżda dan huwa biss debugging tal-prototip. Ejja tiddiżattiva l-kontroll biss biex niżguraw li din hija l-problema, u wara nerġgħu lura kollox lura f'postu.

Billi taġġorna l-paġna fil-browser jew terġa' tmexxi l-kmand tal-curl tagħna, tista' tara l-paġna tat-test Django.

Għalhekk, wara li għamilna ċert li kollox jaħdem u ma jkunx hemm aktar problemi ta 'permess, nerġgħu nippermettu SELinux.

sudo setenforce 1

Mhux se nitkellem dwar audit2allow jew dwar il-ħolqien ta' politiki bbażati fuq it-twissija b'sepolgen hawn, peress li m'hemm l-ebda applikazzjoni Django attwali bħalissa, għalhekk m'hemm l-ebda mappa kompluta ta 'dak li Gunicorn jista' jkun irid jaċċessa u għalxiex għandu jiċħad l-aċċess għalih. Għalhekk, huwa meħtieġ li SELinux jibqa' jaħdem biex jipproteġi s-sistema, filwaqt li fl-istess ħin tħalli l-applikazzjoni taħdem u tħalli messaġġi fir-reġistru tal-verifika sabiex il-politika attwali tista 'mbagħad tinħoloq minnhom.

L-ispeċifikazzjoni ta' oqsma permissivi

Mhux kulħadd sema 'dominji permessi f'SELinux, iżda m'huma xejn ġdid. Ħafna saħansitra ħadmu magħhom mingħajr ma ndunaw. Meta tinħoloq politika bbażata fuq messaġġi ta' verifika, il-politika maħluqa tirrappreżenta d-dominju solvut. Ejja nippruvaw noħolqu politika ta' permessi sempliċi.

Biex toħloq dominju permess speċifiku għal Gunicorn, għandek bżonn xi tip ta 'politika, u trid ukoll timmarka l-fajls xierqa. Barra minn hekk, huma meħtieġa għodod biex jinġabru politiki ġodda.

sudo yum install selinux-policy-devel

Il-mekkaniżmu tad-dominji permessi huwa għodda kbira biex jiġu identifikati l-problemi, speċjalment meta niġu għal applikazzjoni jew applikazzjonijiet personalizzati li jintbagħtu mingħajr politiki diġà maħluqa. F'dan il-każ, il-politika tad-dominju permess għal Gunicorn se tkun sempliċi kemm jista 'jkun - tiddikjara tip ewlieni (gunicorn_t), tiddikjara tip li se nużaw biex timmarka eżekutibbli multipli (gunicorn_exec_t), u mbagħad waqqaf transizzjoni biex is-sistema timmarka b'mod korrett tmexxija ta 'proċessi. L-aħħar linja tistabbilixxi l-politika bħala ppermettiet awtomatikament fil-ħin li titgħabba.

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;

Tista' tiġbor dan il-fajl tal-politika u żżidu mas-sistema tiegħek.

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

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

Ejja niċċekkjaw biex naraw jekk SELinux hux qed jimblokka xi ħaġa oħra għajr dak li qed jaċċessa d-daemon mhux magħruf tagħna.

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 jipprevjeni lil Nginx milli jikteb data fis-socket UNIX użat minn Gunicorn. Tipikament, f'każijiet bħal dawn, il-politiki jibdew jinbidlu, iżda hemm sfidi oħra quddiemhom. Tista 'wkoll tibdel is-settings tad-dominju minn dominju ta' restrizzjoni għal dominju ta 'permess. Issa ejja nimxu httpd_t għad-dominju tal-permessi. Dan jagħti lil Nginx l-aċċess meħtieġ u nistgħu nkomplu b'aktar xogħol ta' debugging.

sudo semanage permissive -a httpd_t

Għalhekk, ladarba tkun irnexxielek iżżomm SELinux protett (verament m'għandekx tħalli proġett SELinux f'mod ristrett) u d-dominji tal-permessi huma mgħobbija, trid tara x'hemm bżonn eżattament li jiġi mmarkat bħala gunicorn_exec_t biex kollox jaħdem kif suppost. mill-ġdid. Ejja nippruvaw inżuru l-websajt biex naraw messaġġi ġodda dwar ir-restrizzjonijiet tal-aċċess.

sudo ausearch -m AVC -c gunicorn

Int ser tara ħafna messaġġi li fihom 'comm="gunicorn"' li jagħmlu diversi affarijiet fuq fajls f'/srv/djangoapp, għalhekk dan ovvjament huwa wieħed mill-kmandi li jiswew jimmarkaw.

Iżda barra minn hekk, jidher messaġġ bħal dan:

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

Jekk tħares lejn l-istatus tas-servizz tal-gunicorn jew tħaddem il-kmand ps, ma tara l-ebda proċess li qed jaħdem. Jidher li gunicorn qed jipprova jaċċessa l-interpretu Python fl-ambjent virtualenv tagħna, possibilment biex imexxi skripts tal-ħaddiema. Allura issa ejja nimmarkaw dawn iż-żewġ fajls eżekutibbli u niċċekkjaw jekk nistgħux niftħu l-paġna tat-test Django tagħna.

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

Is-servizz tal-gunicorn jeħtieġ li jerġa 'jinbeda qabel ma tkun tista' tintgħażel it-tikketta l-ġdida. Tista 'terġa' tibda immedjatament jew twaqqaf is-servizz u ħalli s-socket jibdah meta tiftaħ is-sit fil-browser. Ivverifika li l-proċessi jkunu rċevew it-tikketti korretti billi tuża ps.

ps -efZ | grep gunicorn

Tinsiex li toħloq politika SELinux normali aktar tard!

Jekk tħares lejn il-messaġġi AVC issa, l-aħħar messaġġ fih permissiv=1 għal dak kollu relatat mal-applikazzjoni, u permissiv=0 għall-bqija tas-sistema. Jekk tifhem x'tip ta' aċċess teħtieġ applikazzjoni reali, tista' ssib malajr l-aħjar mod biex issolvi problemi bħal dawn. Iżda sa dakinhar, huwa aħjar li żżomm is-sistema sigura u tikseb awditjar ċar u użabbli tal-proġett Django.

sudo ausearch -m AVC

Ġara!

Deher proġett ta' Django li jaħdem b'frontend ibbażat fuq Nginx u Gunicorn WSGI. Aħna kkonfigurajna Python 3 u PostgreSQL 10 mir-repożitorji RHEL 8 Beta. Issa tista 'timxi 'l quddiem u toħloq (jew sempliċement tuża) applikazzjonijiet Django jew tesplora għodod oħra disponibbli f'RHEL 8 Beta biex tawtomatizza l-proċess ta' konfigurazzjoni, ittejjeb il-prestazzjoni, jew saħansitra tikkontelizza din il-konfigurazzjoni.

Sors: www.habr.com

Żid kumment