8 Mart 2018 Perşembe

Linux üzerinde Python web uygulaması yayına alma alternatifleri

Digital Ocean (DO) - Ubuntu üzerinde Python web uygulaması kurulumu / yayına alma ve güncelleme ile ilgili notlar.

Ubuntu 16.04
Nginx 1.10.3
Python 3.6.4


Problemler 

-Tüm kurulumlardan sonra çalışan sistemde güncellemelerde.

Bir paket güncellemesinde "pip install -U x" wheel üretilme adımında kurulum killed olarak sonlanıyorsa bellek yetmezliğinden kaynaklanıyor olabilir. örn: https://github.com/explosion/spaCy/issues/1586
Normalde 2GB kurulumlarda yetmişti linux güncellemelerinden yada yeni python package den kaynaklı sıkıntı olabilir.
Bu durumda uygulama başlamaz ve alttaki problem ortaya çıkabilir.
gunicorn connect() to unix:/*.sock failed (2: No such file or directory) while connecting to upstream,

Daha detay bilgi almak için systemd service dosyasında gunicorn için log gile parametreleri belirtilebilir.
ExecStart=/home/app/_env/bin/gunicorn --workers 2 --bind unix:lingoapi.sock -m 007 wsgi:flask_app -e LINGOAPPENV=PROD --error-logfile /home/app/logs/gunierr.txt, --log-file /home/app/logs/guni.log

Normalde yetmesi gereken 2GB yetmediğinde swap dosyası tanımı yapılabilir.
Yapmak için : https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-16-04

Swap tanımı yapıp güncellemeyi (pip install) yaptıktan sonra eğer sunucu reboot edilirse swap dosyası uçacaktır. Dolayısıyla güncelleme de aynı problem tekrar edecektir.

-Artan bellek problemine bir çözüm önerisi
gunicorn apps.wsgi:application -b 127.0.0.1:8080 --workers 8 --max-requests 1000
Her bin istekten sonra app pool recycle benzeri işlem
https://rayed.com/posts/2014/09/django-memory-leak-with-gunicorn/


-Bellek kullanım detaylarını görmek için kullanılabilecek bir script
https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py
>python3 ps_mem.py

-Memory leak tespiti için:
https://pypi.org/project/Dozer/
Dozer was originally a WSGI middleware version of Robert Brewer’s Dowser CherryPy tool that displays information as collected by the gc module to assist in tracking down memory leaks. It now also has middleware for profiling and for looking at logged messages.


Sistem kurulum adımları


1. Tanımlar / Configler
-non-root kullanıcı oluşturma - putty ile bağlanma
-Uygulama dizinler, dizin yazma hakkı, firewall vs güvenlik tanımları

2. Kurulumlar (nginx, python...)

3. Geliştirilen uygulamanın kurulum : virtual env, ...
Alternatifler: herşey manuel, docker, dokku, captainduckduck, rancher?)
---Deployment/Güncelleme (deploy, config change) / staging, live... > blue/green deployment

4. Diğer Konular
---SSL (Nginx üzerine)
---Güvenlik
---Kayıtlar / Loglar
---Performans
---Coğrafi dağıtık kurulum alternatifleri
----DNS, IP, istemci performans ölçümüne göre




1. Tanımlar

Digital ocean özelinde;
-Droplet oluştururken SSH public key tanımlanmazsa root password email ile gönderiliyor. (root user). Aksi halde root user password yok ve sadece SSH private key erişim var.
Console dan Password reset diyerek root user pass email ile alınır ve sonra ilk bağlantıda şifre değiştirilir.

DO için ilk kurulum yönergeleri


Genel olarak önerilen erişim yöntemi yeni bir kullanıcı oluşturma ve o kullanıcıya yönetim yetkisi verme. Dolayısıyla bağlantı yapılabiliyor ama yönetimsel işlemler için sudo anahtar kelimesi ile tanımlı şifreyi kullanmak gerekiyor.
Örn: sudo [username] apt-get nginx

Windows istemci ortamı için (geliştirme ortamı) sunucu linux ortamına bağlanma alternatifleri;
-Kullanıcı oluşturma ve geliştirme ortamından bağlanma (Putty)

Putty ile özet süreç (detay alttaki linklerde):
1. Dropleti (DO ortamında linux instance) ssh key (puttgen ile ) oluştur. 
2. root user ile bağlan ve non-root super user oluştur
3. /home/[username]/.ssh/authorized_key dosyasını oluştur ve permission tanımlarını yap
4. puttygen ile üstteki linkde anlatıldığı şekilde yeni kullanıcı için ssh key ker oluştur ve oluşan public key i yine üstteki anlatıldığı şekilde nano/vim ile authorized_key dosyasına yaz.
5. putty ye yeni ssh key tanımlarını yap ve bağlan




P.S. -Web console da karakter problemi (DO web ekranları console erişim): SHIFT and CTRL keys a few times

2. Kurulumlar


Nginx kurulumu ve genel bilgi:

nginx de sites-available den sites-enable a tanım için
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/$SITENAME $SITENAME
enable iptal
sudo rm /etc/nginx/sites-enabled/default

nginx config değişimden sonra restart: sudo systemctl restart nginx

nginx loglar (uygulamanın kendisi için oluşturulan ayrı config dosyasında özelleştirilebilir):
/var/log/nginx/error.log
/var/log/nginx/access.log



Python 3.6.4 kurulumu

Ubuntu 16.04 ile Python 3.5 geliyor. apt update ile güncellenemiyor.
-Bu nedenle alternatif yöntemlerden bu linkteki gösterilen yöntem ile güncelleme yapılabilir.
-pip kurulum ve upgrade : pip install --upgrade pip
-virtual environment kurulum : pip install venv & py -m venv [envname]
-virtual environment aktivasyon: source [venv-name]/bin/activate 



3. Uygulama Kurulumu


Farklı kurulum alternatifleri bulunmakta:
-El (manuel - el emeği göz nuru) ile kurulum
-Docker (kismi el ile)
-Captain Duck Duck (arka planda Docker, kısmi otomatik). 
-Dokku (kısmı otomatik)



Manuel kurulum çalışma şekli


Python ve Nginx kurulumu ve tüm güncellemeler yapıldıktan sonra:
-Nginx tanımları
-Uygulama tanımları (kod içinden ip/port tanımları)
-Linux service tanımları (crash yada reboot durumunda müdahaleye gerek olmaksızın çalışma)


Genel akış>
app (flask, bottle etc) <-> A Web Server Gateway Interface - WSGI  (gunicorn...) <-> Web server + reverse proxy server + load balancer (nginx, apache)

WSGI gerekliliği: Neden web framework ile gelen built in (development) web server kullanılmıyor? Örneğin flask aynı anda tek bir isteğe cevap verebiliyor.


Bu dev için gerekli. App interface (gunicorn etc) zaten çalıştırıyor.
if __name__ == '__main__':
app.run()

Uygulama kurulum dizinini oluşturma
aktif user a ilgili dizine ownership verme
sudo chown -R [user] /var/www/[appname]
yada
sudo chown -R [user] /home/[user]/www
kurulumlar vs. yapılmadan önce ilk bu yapılmalı

Nginx tanımlar:


-nginx site tanımları(dizin + config)
config check
sudo nginx -t
start
sudo systemctl restart nginx

!!!
nginx arkasında yayına alma
http://flask.pocoo.org/docs/0.12/deploying/#deployment
flask + gunicorn + nginx
>> https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04
>> https://simpleisbetterthancomplex.com/tutorial/2016/10/14/how-to-deploy-to-digital-ocean.html
uwsgi

nginx config
root config: /etc/nginx/nginx.conf
app config: /etc/nginx/sites-available/x-app


Nginx alternatifi:


WSGI kurulum ve tanımlar
Alternatifler: gunicorn, uwsgi...





Nginx ve WSGI arasındaki iletişim için
-Unix domain sockets oluşturma
Nginx site config de :
proxy_pass http://unix:/tmp/[yourappname].socket;
Uygulamayı sunması için
gunicorn --bind unix:/tmp/[yourappname].socket wsgi:[app_variable/flask_app etc..]

Service tanımında (systemd...)


Servisi yönetimi için:
supervisor, systemd
Sunucunun yeniden başlatıldığı yada servisin hata vs. nedenlerle durduğu durumda wsgi servisini ayakta tutmak için servis yönetimi aracı ile tanım yapılır.
Örnek:  /etc/systemd/system/[yourapname].service
Çalışır halde tutmak için:
sudo systemctl enable [yourappname]
sudo systemctl start [yourappname]
Güncellemerin aktif olması için:
sudo systemctl daemon-reload
Servis ile ilgili sistem loglarına erişim:
sudo journalctl -u [yourappname]
Servis tanımının doğruluğu kontrol etme:
systemd-analyze verify /etc/systemd/system/[yourappname].service

Detaylar
https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units

Deployment senaryosu:
local den DO ya upload yerine vsts git entegrasyonu.
linux sunucudan webhook vs yöntem ile deployment başlatılır..

https://zapier.com/apps/digital-ocean/integrations/visual-studio-online




Docker


Docker
system reboot da container in tekrar çalışır hale gelmesi için
docker run -p 88:80 --restart always  --name webxx -d httpd
alternatif olarak service lere eklenmesi
update running container config
docker update --restart=always webxx

digital ocean a docker kurma ve deploy etme

Docker alternatifi (lxd):


Captain Duck Duck

DO üzerinde Docker instance + CaptainDuck ile kurulumu.
Sağlanan arayüz üzerinden birden fazla uygulama+domain yayına alınabilir.
Yönetim kabiliyetleri kısıtlı.


Dokku

Dokku CaptainDuckDuck benzeri, arayüzü olmayan, uygulama kurulum servisi.
Ücretsiz Heroku alternatifi (servis anlamında) olarak gösteriliyor.
"Dokku - which is Docker-powered Heroku-like application. "

Deploymen diğer konular

Simple utility for graceful reloading of services
https://github.com/swistakm/hupwatch

uwsgi config > deploy dan sonra az bekletme

Deployment script


Python fabric ile linux üzerinde komut execution: Bu şekilde deployment script oluşturulabilir.
Fabric alternatifi (daha beta):

blue-green deployment

Blue/Green deployment için alternatifler:
Nginx load balancer kullanımı


api-eu-test.xdomain.com icin dns tanımlamak yerine localhost a yazılabilir.

baştan sona kurulum. sondaki git otomasyonu

4. Diğer Konular

-Firewall rule ekleme (http, https, ssh, sftp)
sudo ufw app list
sudo ufw allow 'ssh' (unutulmamalı)
sudo ufw allow 'http' veya sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'https'
sudo ufw status


-SSL Kurulumu

-Log yönetimi

-Performans

Güvenlik
http://tech.marksblogg.com/detect-bots-apache-nginx-logs.html
DO, Google gibi kaynaklardan gelen bot isteklerini engelleme örneği.

IP bazlı istek limit koyma:
https://lincolnloop.com/blog/rate-limiting-nginx/
Aşağıdaki şekilde IP bazlı limit uygulanabilir. Bu örnekte 10MB veri alanına kadar IP bilgisi için IP başına saniyede 1 saniye limit konuluyor. burst ile aynı IP'den belirli sayıda sıraya girmişse sonraki istekleri düşürmek için.
Genel tanımlarda:
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
location alanında
 # apply rate limiting
    limit_req zone=login burst=5;


Coğrafi dağıtık kurulum alternatifleri

IP tabanlı kontrol: Nginx üzerinde IP veritabanı ile ülkelere göre yönlendirme.

DNS üzerinden kontrol: DNS sağlayacı üzerinden yönlendirme. Alternatif servis: Amazon Route 53, https://www.cloudflare.com/dns/

Diğer alternatif istemci üzerinde javascript ile belirli aralıklarla var olan servislerin hepsine istek yapıp en hızlısını ön tanım olarak almak. Bu durumda çalışmayan servis için diğerine yönlendirme yapılabilir.

Örnek:
Javascript ile farklı bölgelerde var olan servisler çağırılır ve ilk cevap veren varsayılan olaran işaretlenir.
https://gist.github.com/mehmetilker/2f4c6f9ddb2f598ede749a1729504795

Ek

node kurulumu ve virtual env ile kullanımı

Hiç yorum yok: