RHEL 8 Beta, geliştiricilere birçok yeni özellik sunuyor; bunların listesi sayfalar sürebilir, ancak pratikte yeni şeyler öğrenmek her zaman daha iyidir; bu nedenle aşağıda, Red Hat Enterprise Linux 8 Beta'yı temel alan bir uygulama altyapısı oluşturmaya yönelik bir atölye çalışması sunuyoruz.
Geliştiriciler arasında popüler bir programlama dili olan Python'u temel olarak, uygulamalar oluşturmak için oldukça yaygın bir kombinasyon olan Django ve PostgreSQL'in bir kombinasyonunu alalım ve RHEL 8 Beta'yı bunlarla çalışacak şekilde yapılandıralım. Daha sonra birkaç (sınıflandırılmamış) malzeme daha ekleyeceğiz.
Test ortamı değişecek çünkü otomasyonun, konteynerlerle çalışmanın ve birden fazla sunucunun bulunduğu ortamları denemenin olanaklarını keşfetmek ilginç olacak. Yeni bir projeye başlamak için, elle küçük, basit bir prototip oluşturarak başlayabilir, böylece tam olarak ne olması gerektiğini ve nasıl etkileşime girdiğini görebilir ve ardından otomatikleştirmeye ve daha karmaşık konfigürasyonlar oluşturmaya geçebilirsiniz. Bugün böyle bir prototipin yaratılmasından bahsediyoruz.
RHEL 8 Beta VM görüntüsünü dağıtarak başlayalım. Sıfırdan bir sanal makine kurabilir veya Beta aboneliğinizle birlikte sunulan KVM misafir görüntüsünü kullanabilirsiniz. Konuk imajı kullanırken, bulut başlatma (cloud-init) için meta veriler ve kullanıcı verilerini içerecek bir sanal CD yapılandırmanız gerekecektir. Disk yapısı veya mevcut paketler ile özel bir şey yapmanıza gerek yoktur; herhangi bir konfigürasyon işe yarayacaktır.
Tüm sürece daha yakından bakalım.
Django'yu Yükleme
Django'nun en yeni sürümüyle birlikte Python 3.5 veya sonraki sürümlere sahip bir sanal ortama (virtualenv) ihtiyacınız olacak. Beta notlarında Python 3.6'nın mevcut olduğunu görebilirsiniz, durumun gerçekten böyle olup olmadığını kontrol edelim:
[cloud-user@8beta1 ~]$ python
-bash: python: command not found
[cloud-user@8beta1 ~]$ python3
-bash: python3: command not found
Red Hat, Python'u RHEL'de bir sistem araç seti olarak aktif olarak kullanıyor, peki bu neden ortaya çıkıyor?
Gerçek şu ki, birçok Python geliştiricisi hala Python 2'den Python 2'ye geçişi düşünüyor, Python 3'ün kendisi ise aktif geliştirme aşamasında ve sürekli olarak daha fazla yeni sürüm ortaya çıkıyor. Bu nedenle, kullanıcılara Python'un çeşitli yeni sürümlerine erişim sunarken kararlı sistem araçları ihtiyacını karşılamak için Python sistemi yeni bir pakete taşındı ve hem Python 2.7 hem de 3.6'yı kurma yeteneği sağlandı. Değişiklikler ve bunların neden yapıldığı hakkında daha fazla bilgiyi adresindeki yayında bulabilirsiniz.
Dolayısıyla, Python'u çalışmaya başlamak için bağımlılık olarak python3-pip içeren yalnızca iki paket yüklemeniz gerekir.
sudo yum install python36 python3-virtualenv
Neden Langdon'ın önerdiği gibi doğrudan modül çağrılarını kullanıp pip3'ü yüklemiyorsunuz? Yaklaşan otomasyonu akılda tutarak, pip modülü özel bir pip yürütülebilir dosyasına sahip virtualenv'leri desteklemediğinden Ansible'ın çalışması için pip'in kurulu olmasını gerektireceği bilinmektedir.
Çalışan bir python3 yorumlayıcısı hizmetinizdeyken Django kurulum işlemine devam edebilir ve diğer bileşenlerimizle birlikte çalışan bir sisteme sahip olabilirsiniz. İnternette birçok uygulama seçeneği mevcuttur. Burada sunulan bir sürüm var, ancak kullanıcılar kendi süreçlerini kullanabilirler.
Yum'u kullanarak varsayılan olarak RHEL 8'de bulunan PostgreSQL ve Nginx sürümlerini yükleyeceğiz.
sudo yum install nginx postgresql-server
PostgreSQL psycopg2 gerektirecektir, ancak yalnızca sanalenv ortamında mevcut olması gerekir, bu yüzden onu Django ve Gunicorn ile birlikte pip3 kullanarak kuracağız. Ama önce virtualenv'i kurmamız gerekiyor.
Django projelerini yüklemek için doğru yeri seçme konusunda her zaman çok fazla tartışma vardır, ancak şüpheye düştüğünüzde her zaman Linux Dosya Sistemi Hiyerarşi Standardına başvurabilirsiniz. FHS özellikle /srv'nin şu amaçlarla kullanıldığını söylüyor: "ana makineye özgü verileri - web sunucusu verileri ve komut dosyaları, FTP sunucularında depolanan veriler ve kontrol sistemi depoları gibi sistemin ürettiği veriler." versiyonları (FHS'de görünür) 2.3'te -2004)."
Bizim durumumuz da tam olarak bu, bu yüzden ihtiyacımız olan her şeyi uygulama kullanıcımızın (bulut kullanıcısı) sahip olduğu /srv'ye koyuyoruz.
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 ve Django'yu kurmak kolaydır: bir veritabanı oluşturun, bir kullanıcı oluşturun, izinleri yapılandırın. PostgreSQL'i ilk kez kurarken akılda tutulması gereken bir şey, postgresql-server paketiyle birlikte yüklenen postgresql-setup betiğidir. Bu komut dosyası, küme başlatma veya yükseltme işlemi gibi veritabanı kümesi yönetimiyle ilişkili temel görevleri gerçekleştirmenize yardımcı olur. RHEL sisteminde yeni bir PostgreSQL örneğini yapılandırmak için şu komutu çalıştırmamız gerekir:
sudo /usr/bin/postgresql-setup -initdb
Daha sonra Systemd'yi kullanarak PostgreSQL'i başlatabilir, bir veritabanı oluşturabilir ve Django'da bir proje oluşturabilirsiniz. Uygulama kullanıcısı için parola depolamayı yapılandırmak üzere istemci kimlik doğrulama yapılandırma dosyasında (genellikle pg_hba.conf) değişiklik yaptıktan sonra PostgreSQL'i yeniden başlatmayı unutmayın. Başka zorluklarla karşılaşırsanız pg_hba.conf dosyasındaki IPv4 ve IPv6 ayarlarını değiştirdiğinizden emin 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 dosyası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 dosyasında:
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '{{ db_name }}',
'USER': '{{ db_user }}',
'PASSWORD': '{{ db_password }}',
'HOST': '{{ db_host }}',
}
}
Projede settings.py dosyasını yapılandırıp veritabanı yapılandırmasını ayarladıktan sonra her şeyin çalıştığından emin olmak için geliştirme sunucusunu başlatabilirsiniz. Geliştirme sunucusunu başlattıktan sonra veritabanı bağlantısını test etmek için bir yönetici kullanıcı oluşturmak iyi bir fikirdir.
./manage.py runserver 0.0.0.0:8000
./manage.py createsuperuser
WSGI'mi? Vay?
Geliştirme sunucusu test için kullanışlıdır, ancak uygulamayı çalıştırmak için Web Sunucusu Ağ Geçidi Arayüzü (WSGI) için uygun sunucuyu ve proxy'yi yapılandırmanız gerekir. Birkaç yaygın kombinasyon vardır; örneğin, uWSGI ile Apache HTTPD veya Gunicorn ile Nginx.
Web Sunucusu Ağ Geçidi Arayüzünün görevi, web sunucusundan gelen istekleri Python web çerçevesine iletmektir. WSGI, CGI motorlarının ortalıkta olduğu korkunç geçmişin bir kalıntısıdır ve bugün WSGI, kullanılan web sunucusu veya Python çerçevesinden bağımsız olarak fiili standarttır. Ancak yaygın kullanımına rağmen, bu çerçevelerle çalışırken hala birçok nüans ve birçok seçenek vardır. Bu durumda Gunicorn ile Nginx arasındaki etkileşimi bir soket üzerinden kurmaya çalışacağız.
Bu bileşenlerin her ikisi de aynı sunucuya kurulduğundan ağ soketi yerine UNIX soketi kullanmayı deneyelim. İletişim her durumda bir soket gerektirdiğinden, bir adım daha atıp Gunicorn için soket aktivasyonunu systemd aracılığıyla yapılandırmaya çalışalım.
Soketle etkinleştirilen hizmetler oluşturma süreci oldukça basittir. Öncelikle, UNIX soketinin oluşturulacağı noktaya işaret eden ListenStream direktifini içeren bir birim dosyası oluşturulur, ardından Requires direktifinin soket birim dosyasına işaret edeceği hizmet için bir birim dosyası oluşturulur. Daha sonra hizmet birimi dosyasında geriye kalan tek şey sanal ortamdan Gunicorn'u çağırmak ve UNIX soketi ve Django uygulaması için bir WSGI bağlaması oluşturmaktır.
Burada temel olarak kullanabileceğiniz bazı birim dosyaları örnekleri verilmiştir. İlk önce soketi kuruyoruz.
[Unit]
Description=Gunicorn WSGI socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Şimdi Gunicorn arka plan programını yapılandırmanız gerekiyor.
[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 için bu, proxy yapılandırma dosyaları oluşturmak ve kullanıyorsanız statik içeriği depolamak için bir dizin ayarlamak basit bir meseledir. RHEL'de Nginx yapılandırma dosyaları /etc/nginx/conf.d konumunda bulunur. Aşağıdaki örneği /etc/nginx/conf.d/default.conf dosyasına kopyalayıp servisi başlatabilirsiniz. Sunucu_adı'nı ana bilgisayar adınızla eşleşecek şekilde ayarladığınızdan emin 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;
}
}
Gunicorn soketini ve Nginx'i systemd kullanarak başlatın; teste başlamaya hazırsınız.
Kötü Ağ Geçidi hatası mı?
Adresi tarayıcınıza girerseniz büyük ihtimalle 502 Bad Gateway hatası alırsınız. Yanlış yapılandırılmış UNIX soket izinlerinden kaynaklanabilir veya SELinux'taki erişim kontrolüyle ilgili daha karmaşık sorunlardan kaynaklanabilir.
Nginx hata günlüğünde şöyle bir satır görebilirsiniz:
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 doğrudan test edersek boş bir cevap alırız.
curl —unix-socket /run/gunicorn.sock 8beta1.example.com
Bunun neden olduğunu anlayalım. Günlüğü açtığınızda büyük ihtimalle sorunun SELinux ile ilgili olduğunu göreceksiniz. Kendisi için hiçbir politika oluşturulmamış bir arka plan programı çalıştırdığımız için, bu init_t olarak işaretlendi. Bu teoriyi pratikte test edelim.
sudo setenforce 0
Bütün bunlar eleştirilere ve kanlı gözyaşlarına neden olabilir, ancak bu yalnızca prototipte hata ayıklamadır. Sorunun bu olduğundan emin olmak için kontrolü devre dışı bırakalım, ardından her şeyi yerine geri koyacağız.
Tarayıcıda sayfayı yenileyerek veya curl komutumuzu tekrar çalıştırarak Django test sayfasını görebilirsiniz.
Böylece her şeyin çalıştığından ve artık izin sorunu olmadığından emin olduktan sonra SELinux'u tekrar etkinleştiriyoruz.
sudo setenforce 1
Şu anda gerçek bir Django uygulaması olmadığından, burada denetim2allow veya sepolgen ile uyarı tabanlı politikalar oluşturma hakkında konuşmayacağım, dolayısıyla Gunicorn'un neye erişmek isteyebileceği ve neye erişimi reddetmesi gerektiğine dair tam bir harita yok. Bu nedenle, sistemi korumak için SELinux'u çalışır durumda tutmak gerekir, aynı zamanda uygulamanın çalışmasına ve denetim günlüğünde mesajlar bırakmasına izin vererek gerçek politikanın onlardan oluşturulabilmesini sağlamak gerekir.
İzin verilen alanları belirtme
Herkes SELinux'ta izin verilen alan adlarını duymamıştır, ancak bunlar yeni bir şey değildir. Hatta birçoğu farkına bile varmadan onlarla çalıştı. Denetim mesajlarına dayalı olarak bir politika oluşturulduğunda, oluşturulan politika çözümlenen etki alanını temsil eder. Basit bir izin politikası oluşturmaya çalışalım.
Gunicorn için izin verilen belirli bir alan adı oluşturmak için bir tür politikaya ihtiyacınız var ve ayrıca uygun dosyaları işaretlemeniz gerekiyor. Ayrıca yeni politikaların oluşturulması için araçlara ihtiyaç vardır.
sudo yum install selinux-policy-devel
İzin verilen etki alanları mekanizması, özellikle özel bir uygulama veya önceden oluşturulmuş politikalar olmadan gönderilen uygulamalar söz konusu olduğunda sorunları tanımlamak için harika bir araçtır. Bu durumda, Gunicorn için izin verilen etki alanı politikası mümkün olduğu kadar basit olacaktır - bir ana tür (gunicorn_t) bildirin, birden fazla yürütülebilir dosyayı işaretlemek için kullanacağımız bir tür bildirin (gunicorn_exec_t) ve ardından sistemin doğru şekilde işaretlemesi için bir geçiş ayarlayın süreçleri çalıştırıyor. Son satır, politikayı yüklendiği anda varsayılan olarak etkin olarak ayarlar.
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;
Bu politika dosyasını derleyip sisteminize ekleyebilirsiniz.
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 bilinmeyen arka plan programımızın eriştiğinden başka bir şeyi engelleyip engellemediğini kontrol edelim.
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 tarafından kullanılan UNIX soketine veri yazmasını engeller. Tipik olarak bu gibi durumlarda politikalar değişmeye başlar ancak ileride başka zorluklar da vardır. Ayrıca etki alanı ayarlarını kısıtlama etki alanından izin etki alanına değiştirebilirsiniz. Şimdi httpd_t'yi izinler alanına taşıyalım. Bu, Nginx'e gerekli erişimi sağlayacaktır ve daha fazla hata ayıklama çalışmasına devam edebiliriz.
sudo semanage permissive -a httpd_t
Dolayısıyla, SELinux'u korumayı başardıktan sonra (bir SELinux projesini kısıtlı modda bırakmamalısınız) ve izin alanları yüklendikten sonra, her şeyin düzgün çalışmasını sağlamak için tam olarak neyin gunicorn_exec_t olarak işaretlenmesi gerektiğini bulmanız gerekir. Tekrar. Erişim kısıtlamalarıyla ilgili yeni mesajları görmek için web sitesini ziyaret etmeyi deneyelim.
sudo ausearch -m AVC -c gunicorn
/srv/djangoapp içindeki dosyalarda çeşitli şeyler yapan 'comm='gunicorn'' içeren çok sayıda mesaj göreceksiniz, dolayısıyla bu açıkça işaretlemeye değer komutlardan biridir.
Ancak buna ek olarak şöyle bir mesaj belirir:
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 hizmetinin durumuna baktığınızda veya ps komutunu çalıştırdığınızda çalışan herhangi bir işlem görmezsiniz. Gunicorn'un, muhtemelen çalışan komut dosyalarını çalıştırmak için virtualenv ortamımızdaki Python yorumlayıcısına erişmeye çalıştığı anlaşılıyor. Şimdi bu iki yürütülebilir dosyayı işaretleyelim ve Django test sayfamızı açıp açamayacağımızı kontrol edelim.
chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6
Yeni etiketin seçilebilmesi için gunicorn hizmetinin yeniden başlatılması gerekecektir. Siteyi tarayıcıda açtığınızda hemen yeniden başlatabilir veya hizmeti durdurup soketin başlatmasını sağlayabilirsiniz. İşlemlerin doğru etiketleri aldığını ps kullanarak doğrulayın.
ps -efZ | grep gunicorn
Daha sonra normal bir SELinux politikası oluşturmayı unutmayın!
Şimdi AVC mesajlarına bakarsanız, son mesajda uygulamayla ilgili her şey için permissive=1 ve sistemin geri kalanı için permissive=0 ifadesi yer alıyor. Gerçek bir uygulamanın ne tür bir erişime ihtiyaç duyduğunu anlarsanız bu tür sorunları çözmenin en iyi yolunu hızlı bir şekilde bulabilirsiniz. Ancak o zamana kadar sistemi güvende tutmak ve Django projesinin net, kullanılabilir bir denetimini elde etmek en iyisidir.
sudo ausearch -m AVC
Çıktı!
Nginx ve Gunicorn WSGI tabanlı bir ön yüze sahip, çalışan bir Django projesi ortaya çıktı. Python 3 ve PostgreSQL 10'u RHEL 8 Beta depolarından yapılandırdık. Artık ilerleyebilir ve Django uygulamaları oluşturabilir (veya yalnızca dağıtabilir) veya yapılandırma sürecini otomatikleştirmek, performansı artırmak ve hatta bu yapılandırmayı kapsayıcı hale getirmek için RHEL 8 Beta'daki diğer mevcut araçları keşfedebilirsiniz.
Kaynak: habr.com