Warsha ya RHEL 8 Beta: Kuunda programu za wavuti zinazofanya kazi

RHEL 8 Beta inawapa wasanidi programu vipengele vingi vipya, uorodheshaji wake ambao unaweza kuchukua kurasa, hata hivyo, kujifunza mambo mapya huwa bora zaidi kivitendo, kwa hivyo hapa chini tunatoa warsha ya kuunda muundo msingi wa programu kulingana na Red Hat Enterprise Linux 8 Beta.

Warsha ya RHEL 8 Beta: Kuunda programu za wavuti zinazofanya kazi

Wacha tuchukue Python, lugha maarufu ya programu kati ya watengenezaji, kama msingi, mchanganyiko wa Django na PostgreSQL, mchanganyiko wa kawaida wa kuunda programu, na usanidi RHEL 8 Beta kufanya kazi nao. Kisha tutaongeza viungo kadhaa zaidi (havijaainishwa).

Mazingira ya mtihani yatabadilika, kwa sababu inavutia kuchunguza uwezekano wa automatisering, kufanya kazi na vyombo na mazingira ya kujaribu na seva nyingi. Ili kuanza na mradi mpya, unaweza kuanza kwa kuunda mfano mdogo, rahisi kwa mkono ili uweze kuona ni nini hasa kinachohitajika kutokea na jinsi inavyoingiliana, na kisha uendelee kubinafsisha na kuunda usanidi ngumu zaidi. Leo tunazungumza juu ya uundaji wa mfano kama huo.

Hebu tuanze kwa kupeleka picha ya RHEL 8 Beta VM. Unaweza kusakinisha mashine pepe kuanzia mwanzo, au utumie picha ya mgeni ya KVM inayopatikana na usajili wako wa Beta. Unapotumia picha ya mgeni, utahitaji kusanidi CD pepe ambayo itakuwa na metadata na data ya mtumiaji kwa ajili ya kuanzisha wingu (cloud-init). Huna haja ya kufanya chochote maalum na muundo wa diski au vifurushi vinavyopatikana; usanidi wowote utafanya.

Hebu tuangalie kwa makini mchakato mzima.

Inasakinisha Django

Ukiwa na toleo jipya zaidi la Django, utahitaji mazingira ya kawaida (virtualenv) na Python 3.5 au baadaye. Katika maelezo ya Beta unaweza kuona kuwa Python 3.6 inapatikana, wacha tuangalie ikiwa hii ndio kesi:

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

Red Hat hutumia Python kikamilifu kama zana ya mfumo katika RHEL, kwa nini hii inatokea?

Ukweli ni kwamba watengenezaji wengi wa Python bado wanatafakari mabadiliko kutoka Python 2 hadi Python 2, wakati Python 3 yenyewe iko chini ya maendeleo ya kazi, na matoleo mapya zaidi na zaidi yanaonekana mara kwa mara. Kwa hivyo, ili kukidhi hitaji la zana za mfumo thabiti wakati wa kutoa watumiaji ufikiaji wa matoleo mapya ya Python, Python ya mfumo ilihamishwa hadi kifurushi kipya na kutoa uwezo wa kusakinisha Python 2.7 na 3.6. Maelezo zaidi kuhusu mabadiliko na kwa nini yalifanywa yanaweza kupatikana katika uchapishaji katika Blogu ya Langdon White (Langdon White).

Kwa hivyo, ili kupata Python ya kufanya kazi, unahitaji tu kusakinisha vifurushi viwili, na python3-pip imejumuishwa kama utegemezi.

sudo yum install python36 python3-virtualenv

Kwa nini usitumie simu za moduli za moja kwa moja kama Langdon anapendekeza na usakinishe pip3? Kwa kuzingatia uwekaji otomatiki unaokuja, inajulikana kuwa Ansible itahitaji bomba iliyosakinishwa ili kuendesha, kwani moduli ya bomba haitumii virtualenvs na bomba maalum inayoweza kutekelezwa.

Ukiwa na mkalimani wa python3 unaofanya kazi, unaweza kuendelea na mchakato wa usakinishaji wa Django na kuwa na mfumo wa kufanya kazi pamoja na vifaa vyetu vingine. Kuna chaguzi nyingi za utekelezaji zinazopatikana kwenye Mtandao. Kuna toleo moja lililowasilishwa hapa, lakini watumiaji wanaweza kutumia michakato yao wenyewe.

Tutasakinisha matoleo ya PostgreSQL na Nginx yanayopatikana katika RHEL 8 kwa chaguo-msingi kwa kutumia Yum.

sudo yum install nginx postgresql-server

PostgreSQL itahitaji psycopg2, lakini inahitaji kupatikana tu katika mazingira ya virtualenv, kwa hivyo tutaisakinisha kwa kutumia pip3 pamoja na Django na Gunicorn. Lakini kwanza tunahitaji kusanidi virtualenv.

Daima kuna mjadala mwingi juu ya mada ya kuchagua mahali pazuri pa kusakinisha miradi ya Django, lakini ukiwa na shaka, unaweza kurejea kwenye Kiwango cha Uongozi wa Mfumo wa Faili ya Linux. Hasa, FHS inasema kwamba /srv inatumiwa: "kuhifadhi data maalum ya mwenyeji-data ambayo mfumo hutoa, kama vile data ya seva ya wavuti na hati, data iliyohifadhiwa kwenye seva za FTP, na hifadhi za mfumo wa kudhibiti." matoleo (yanayoonekana katika FHS). -2.3 mwaka 2004).

Hii ndio kesi yetu haswa, kwa hivyo tunaweka kila kitu tunachohitaji ndani /srv, ambayo inamilikiwa na mtumiaji wetu wa programu (wingu-mtumiaji).

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

Kuweka PostgreSQL na Django ni rahisi: kuunda hifadhidata, kuunda mtumiaji, kusanidi ruhusa. Jambo moja la kukumbuka wakati wa kusanikisha PostgreSQL ni hati ya usanidi ya postgresql ambayo imewekwa na kifurushi cha seva ya postgresql. Hati hii hukusaidia kufanya kazi za kimsingi zinazohusiana na usimamizi wa kikundi cha hifadhidata, kama vile uanzishaji wa nguzo au mchakato wa kuboresha. Ili kusanidi mfano mpya wa PostgreSQL kwenye mfumo wa RHEL, tunahitaji kutekeleza amri:

sudo /usr/bin/postgresql-setup -initdb

Kisha unaweza kuanza PostgreSQL kwa kutumia systemd, kuunda hifadhidata, na kusanidi mradi huko Django. Kumbuka kuanzisha upya PostgreSQL baada ya kufanya mabadiliko kwenye faili ya usanidi ya uthibitishaji wa mteja (kawaida pg_hba.conf) ili kusanidi hifadhi ya nenosiri kwa mtumiaji wa programu. Ukikumbana na matatizo mengine, hakikisha kuwa umebadilisha mipangilio ya IPv4 na IPv6 katika faili ya 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

Katika faili /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

Katika faili /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 }}',
   }
}

Baada ya kusanidi faili ya settings.py kwenye mradi na kusanidi usanidi wa hifadhidata, unaweza kuanza seva ya ukuzaji ili kuhakikisha kuwa kila kitu kinafanya kazi. Baada ya kuanzisha seva ya ukuzaji, ni wazo nzuri kuunda mtumiaji wa msimamizi ili kujaribu muunganisho kwenye hifadhidata.

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

WSGI? Wai?

Seva ya usanidi ni muhimu kwa majaribio, lakini ili kuendesha programu lazima usanidi seva na proksi inayofaa kwa Kiolesura cha Lango la Seva ya Wavuti (WSGI). Kuna mchanganyiko kadhaa wa kawaida, kwa mfano, Apache HTTPD na uWSGI au Nginx na Gunicorn.

Kazi ya Kiolesura cha Lango la Seva ya Wavuti ni kusambaza maombi kutoka kwa seva ya wavuti hadi kwa mfumo wa wavuti wa Python. WSGI ni masalio ya zamani mbaya wakati injini za CGI zilipokuwa karibu, na leo WSGI ndio kiwango cha ukweli, bila kujali seva ya wavuti au mfumo wa Python uliotumika. Lakini licha ya matumizi yake yaliyoenea, bado kuna nuances nyingi wakati wa kufanya kazi na mifumo hii, na chaguo nyingi. Katika kesi hii, tutajaribu kuanzisha mwingiliano kati ya Gunicorn na Nginx kupitia tundu.

Kwa kuwa vipengele vyote viwili vimewekwa kwenye seva moja, hebu tujaribu kutumia tundu la UNIX badala ya tundu la mtandao. Kwa kuwa mawasiliano yanahitaji tundu kwa hali yoyote, hebu tujaribu kuchukua hatua moja zaidi na tusanidi uanzishaji wa tundu kwa Gunicorn kupitia systemd.

Mchakato wa kuunda huduma zilizoamilishwa za tundu ni rahisi sana. Kwanza, faili ya kitengo imeundwa ambayo ina mwongozo wa ListenStream unaoelekeza mahali ambapo tundu la UNIX litaundwa, kisha faili ya kitengo cha huduma ambayo maagizo Inahitaji itaelekeza kwenye faili ya kitengo cha tundu. Halafu, katika faili ya kitengo cha huduma, kilichobaki ni kupiga Gunicorn kutoka kwa mazingira ya kawaida na kuunda kifunga WSGI kwa tundu la UNIX na programu ya Django.

Hapa kuna mifano ya faili za kitengo ambazo unaweza kutumia kama msingi. Kwanza tunaweka tundu.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Sasa unahitaji kusanidi daemon ya 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

Kwa Nginx, ni jambo rahisi kuunda faili za usanidi wa wakala na kusanidi saraka ili kuhifadhi yaliyomo tuli ikiwa unatumia moja. Katika RHEL, faili za usanidi za Nginx ziko ndani /etc/nginx/conf.d. Unaweza kunakili mfano ufuatao kwenye faili /etc/nginx/conf.d/default.conf na uanze huduma. Hakikisha umeweka jina_la_seva ili kuendana na jina la mwenyeji wako.

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

Anzisha tundu la Gunicorn na Nginx ukitumia systemd na uko tayari kuanza majaribio.

Hitilafu mbaya ya Lango?

Ukiingiza anwani kwenye kivinjari chako, kuna uwezekano mkubwa utapokea hitilafu ya 502 Bad Gateway. Inaweza kusababishwa na ruhusa za tundu za UNIX zilizosanidiwa kimakosa, au inaweza kuwa kutokana na masuala magumu zaidi yanayohusiana na udhibiti wa ufikiaji katika SELinux.

Kwenye logi ya makosa ya nginx unaweza kuona mstari kama huu:

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"

Ikiwa tutajaribu Gunicorn moja kwa moja, tutapata jibu tupu.

curl β€”unix-socket /run/gunicorn.sock 8beta1.example.com

Wacha tujue kwa nini hii inatokea. Ukifungua logi, utaona uwezekano mkubwa kwamba tatizo linahusiana na SELinux. Kwa kuwa tunaendesha daemon ambayo hakuna sera imeundwa, imetiwa alama kama init_t. Wacha tujaribu nadharia hii kwa vitendo.

sudo setenforce 0

Yote hii inaweza kusababisha ukosoaji na machozi ya damu, lakini hii ni kurekebisha mfano tu. Wacha tuzima hundi ili kuhakikisha kuwa hii ndio shida, baada ya hapo tutarudisha kila kitu mahali pake.

Kwa kuburudisha ukurasa kwenye kivinjari au kurejesha amri yetu ya curl, unaweza kuona ukurasa wa jaribio la Django.

Kwa hiyo, baada ya kuhakikisha kuwa kila kitu kinafanya kazi na hakuna matatizo zaidi ya ruhusa, tunawezesha SELinux tena.

sudo setenforce 1

Sitazungumza kuhusu audit2allow au kuunda sera zenye msingi wa tahadhari na sepolgen hapa, kwa kuwa hakuna programu halisi ya Django kwa sasa, kwa hivyo hakuna ramani kamili ya kile ambacho Gunicorn anaweza kutaka kufikia na kile kinachopaswa kukataa ufikiaji. Kwa hiyo, ni muhimu kuweka SELinux kukimbia ili kulinda mfumo, wakati huo huo kuruhusu programu kukimbia na kuacha ujumbe kwenye logi ya ukaguzi ili sera halisi iweze kuundwa kutoka kwao.

Inabainisha vikoa vinavyoruhusu

Sio kila mtu amesikia kuhusu vikoa vinavyoruhusiwa katika SELinux, lakini sio kitu kipya. Wengi hata walifanya kazi nao bila hata kujua. Sera inapoundwa kulingana na ujumbe wa ukaguzi, sera iliyoundwa inawakilisha kikoa kilichotatuliwa. Hebu tujaribu kuunda sera rahisi ya kuruhusu.

Ili kuunda kikoa mahususi kinachoruhusiwa cha Gunicorn, unahitaji aina fulani ya sera, na pia unahitaji kuweka alama kwenye faili zinazofaa. Kwa kuongezea, zana zinahitajika ili kuunda sera mpya.

sudo yum install selinux-policy-devel

Utaratibu wa vikoa vinavyoruhusiwa ni zana nzuri ya kubainisha matatizo, hasa linapokuja suala la programu maalum au programu ambazo husafirishwa bila sera ambazo tayari zimeundwa. Katika hali hii, sera ya kikoa inayoruhusiwa ya Gunicorn itakuwa rahisi iwezekanavyo - tangaza aina kuu (gunicorn_t), tangaza aina ambayo tutatumia kuashiria utekelezaji mwingi (gunicorn_exec_t), na kisha usanidi mpito ili mfumo uweke alama kwa usahihi. michakato inayoendesha. Mstari wa mwisho huweka sera kama inavyowezeshwa na chaguo-msingi wakati inapopakiwa.

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;

Unaweza kukusanya faili hii ya sera na kuiongeza kwenye mfumo wako.

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

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

Wacha tuangalie ikiwa SELinux inazuia kitu kingine isipokuwa kile daemon yetu isiyojulikana inapata.

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 inazuia Nginx kuandika data kwa tundu la UNIX linalotumiwa na Gunicorn. Kwa kawaida, katika hali kama hizi, sera huanza kubadilika, lakini kuna changamoto nyingine mbeleni. Unaweza pia kubadilisha mipangilio ya kikoa kutoka kwa kikoa cha kizuizi hadi kikoa cha ruhusa. Sasa hebu tuhamishe httpd_t kwa kikoa cha ruhusa. Hii itaipa Nginx ufikiaji unaohitajika na tunaweza kuendelea na kazi zaidi ya utatuzi.

sudo semanage permissive -a httpd_t

Kwa hivyo, mara tu umeweza kuweka SELinux ikilindwa (haupaswi kuacha mradi wa SELinux katika hali iliyozuiliwa) na vikoa vya ruhusa vimepakiwa, unahitaji kujua ni nini hasa kinahitaji kuwekwa alama kama gunicorn_exec_t ili kufanya kila kitu kifanye kazi vizuri. tena. Hebu tujaribu kutembelea tovuti ili kuona ujumbe mpya kuhusu vikwazo vya ufikiaji.

sudo ausearch -m AVC -c gunicorn

Utaona ujumbe mwingi ulio na 'comm="gunicorn"' ambao hufanya mambo mbalimbali kwenye faili katika /srv/djangoapp, kwa hivyo ni wazi kuwa hii ni mojawapo ya amri zinazofaa kualamishwa.

Lakini kwa kuongeza, ujumbe kama huu unaonekana:

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

Ukiangalia hali ya huduma ya gunicorn au kukimbia amri ya ps, hutaona michakato yoyote inayoendesha. Inaonekana kama bunduki inajaribu kupata mkalimani wa Python katika mazingira yetu ya virtualenv, ikiwezekana kuendesha hati za wafanyikazi. Kwa hivyo sasa tuweke alama kwenye faili hizi mbili zinazoweza kutekelezwa na tuangalie ikiwa tunaweza kufungua ukurasa wetu wa jaribio la Django.

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

Huduma ya gunicorn itahitaji kuanzishwa upya kabla ya lebo mpya kuchaguliwa. Unaweza kuanzisha upya mara moja au kuacha huduma na kuruhusu tundu lianze wakati unafungua tovuti kwenye kivinjari. Thibitisha kuwa michakato imepokea lebo sahihi kwa kutumia ps.

ps -efZ | grep gunicorn

Usisahau kuunda sera ya kawaida ya SELinux baadaye!

Ukiangalia ujumbe wa AVC sasa, ujumbe wa mwisho una permissive=1 kwa kila kitu kinachohusiana na programu, na permissive=0 kwa mfumo mzima. Ikiwa unaelewa ni aina gani ya ufikiaji ambayo programu halisi inahitaji, unaweza kupata haraka njia bora ya kutatua shida kama hizo. Lakini hadi wakati huo, ni vyema kuweka mfumo salama na kupata ukaguzi wa wazi, unaoweza kutumika wa mradi wa Django.

sudo ausearch -m AVC

Imetokea!

Mradi unaofanya kazi wa Django umeonekana ukiwa na mandhari ya mbele kulingana na Nginx na Gunicorn WSGI. Tulisanidi Python 3 na PostgreSQL 10 kutoka hazina za Beta za RHEL 8. Sasa unaweza kusonga mbele na kuunda (au kutuma kwa urahisi) programu za Django au kuchunguza zana zingine zinazopatikana katika RHEL 8 Beta ili kubinafsisha mchakato wa usanidi, kuboresha utendakazi, au hata kuweka usanidi huu kwenye chombo.

Chanzo: mapenzi.com

Kuongeza maoni