Alisson Machado
21 December 2020

Capítulo 4: Configuração de um proxy reverso com Nginx

Este capítulo tem como objetivo explicar como um proxy reverso é usado e o que ele faz, como criar uma página simples no Python usando o framework Flask e disponibiliza-la em um servidor web Gunicorn. 

 

Estrutura: 

Neste capítulo discutiremos os seguintes tópicos: 

  • Instalando o Nginx 
  • Instalando o Python 
  • Criando uma página simples usando Flask 
  • Configurando o proxy reverso 


Instalando o Nginx 


Nginx, este nome foi criado pelo som da pronuncia EngineX, ele também é um dos servidores web mais famosos, mais usado como um balanceador de carga ou como um proxy reverson, uma de suas melhores capacidades é trabalhar com Threads tendo assim uma alta performance ao responder requisições em paralelo, ele é frequentemente usado com aplicações Python, recendo as requisições e passando para outro servidor web como o Gunicorn que vamos ver nas páginas seguintes. 

 

Para começar, vamos instalar o Nginx executando o seguinte comando: 

 

root@devops:~# apt install nginx -y
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libnginx-mod-http-geoip libnginx-mod-http-image-filter
libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6 libxpm4 nginx-common nginx-core
Suggested packages:
libgd-tools fcgiwrap nginx-doc
The following NEW packages will be installed:
fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libnginx-mod-http-geoip libnginx-mod-http-image-filter
libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6 libxpm4 nginx nginx-common nginx-core
0 upgraded, 18 newly installed, 0 to remove and 72 not upgraded.

Need to get 2,461 kB of archives.

 

Após o término da instalação, você pode verificar todos os arquivos de configuração nesta pasta: 

 

root@devops:~# ls /etc/nginx/
conf.d fastcgi_params koi-win modules-available nginx.conf scgi_params sites-enabled uwsgi_params
fastcgi.conf koi-utf mime.types modules-enabled proxy_params sites-available snippets win-utf 


Provavelmente você viu algumas semelhanças com o Apache, por exemplo aqui também temos os sites-enabled e sites-available, assim, você já sabe o que esses diretórios fazem.

No entanto, o mais importante é o arquivo nginx.conf que armazena as configurações principais do servidor web, podemos usar o comando grep para verificar as linhas habilitadas, que correspondem as linhas não comentadas. 

 

root@devops:~# grep -v "#" /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 768;
}


http {

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

gzip on;

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

} 

 

Portanto, este arquivo pode mostrar-lhe as linhas importantes, como a quantidade de conexões por Worker, de modo que cada trabalhador será responsável por responder 768 conexões, por padrão o valor é 1, mas podemos ter pelo menos um worker por processador da CPU, se você quiser verificar quantos processadors você tem em sua CPU, você pode executar este comando: 

 

root@devops:~# cat /proc/cpuinfo | grep processor
processor : 0

 

O último comando mostra que você tem apenas um processador em sua CPU, este comando que eu executei dentro da minha Máquina Virtual, que eu tenho apenas um processador configurado (vCPU), se eu executar na minha máquina física, este é o resultado: 

 

alisson@avell:~$ cat /proc/cpuinfo | grep processor
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7

 

Então, neste caso eu posso configurar o meu Nginx para usar 8 Workers, se você quiser fazer isso, eu só tenho que adicionar esta linha abaixo. 

 

Worker_processes 8. 

 

Reinicie o servidor e a configuração sera ativada. 

 

Agora que já conhecemos alguns arquivos de configuração, é hora de testar nosso servidor web, no último capítulo instalamos o servidor web apache nesta máquina virtual, então provavelmente ele ainda está em execução, portanto verifique se há qualquer processo rodando na porta 80. 

 

root@devops:~# ss -ntpl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=1100,fd=21))
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=705,fd=13))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=942,fd=3))
LISTEN 0 128 *:80 *:* users:(("apache2",pid=3107,fd=4),("apache2",pid=3106,fd=4),("apache2",pid=3105,fd=4),("apache2",pid=3104,fd=4),("apache2",pid=3103,fd=4),("apache2",pid=3098,fd=4))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=942,fd=4))


O último comando imprimiu na tela, todos os serviços que estão ouvindo na minha VM, o Apache é um deles, então pare o serviço, desative-o e inicie o Nginx.  

root@devops:~# systemctl stop apache2
root@devops:~# systemctl disable apache2
Synchronizing state of apache2.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable apache2

 

Para iniciar e ativar o Nginx, execute esses comandos: 

 

root@devops:~# systemctl start nginx
root@devops:~# systemctl enable nginx
Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable nginx


Abra no endereço IP no navegador para verificar a página do índice: http://192.168.178.62/ 

 

 

 

É interessante, que está mostrando a página do exemplo apache, isso acontece porque o Nginx está usando a mesma pasta que o Apache para a raiz do documento.

Você pode verificar isso usando o seguinte comando: 

 

root@devops:~# grep -v "#" /etc/nginx/sites-enabled/default

server {

listen 80 default_server;
listen [::]:80 default_server;

root /var/www/html;

index index.html index.htm index.nginx-debian.html;

server_name _;

location / {

try_files $uri $uri/ =404;

}
} 


O comando grep mostrou que o DocumentRoot é definido como /var/www/html, que é o mesmo que do Apache.

Se você quiser ver a página Index padrão do Nginx, execute este comando: 

 

root@devops:~# cp -v /usr/share/nginx/html/index.html /var/www/html/ 
'/usr/share/nginx/html/index.html' -> '/var/www/html/index.html' 

 

E acesse novamente o enderenço de IP.

 

 

 

Agora você pode ver a página padrão Nginx. 

 

Instalação de Python 

 

O Python hoje em dia é uma das linguagens de programação mais famosas, principalmente em áreas como Data Science e DevOps, é frequentemente utilizado para automatizar Tarefas Linux e integrar sistemas usando APIs REST, há alguns anos, trabalhei em um sistema chamado BeavOps, que foi responsável por fazer a matrícula dos alunos para a empresa em que costumava trabalhar.  

 

Esse sistema estava basicamente recebendo um arquivo JSON do CRM com os dados do aluno, o respectivo curso, a data de início e término, e a missão foi com esses dados criar algumas rotinas que integrariam diversas ferramentas como Gitlab, Jenkins, Apache, MongoDB e etc, visando criar um ambiente de desenvolvimento para os alunos e com um pipeline de CI / CD. Esse sistema foi completamente escrito usando Python, Flask e MongoDB para armazenar os dados. 


Para instalar o Python, precisamos de dois pacotes basicamente. 

root@devops:~# apt install python3 python3-pip -y

Reading package lists... Done
Building dependency tree
Reading state information... Done
python3 is already the newest version (3.6.7-1~18.04).
python3 set to manually installed.

 

Após o término da instalação, instale o Framework Flask usando PIP. 

 

root@devops:~# python3 -m pip install flask

Collecting flask
Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
100% |████████████████████████████████| 102kB 1.4MB/s


 

Criando uma página simples usando Flask 

 

Flask é um MicroFramework para Python, perfeito para você criar suas APIs REST, agora vamos aprender como criar um simples Hello World usando este MicroFramework e Python, também todas as etapas para fazer p deploy da nossa aplicação usando Nginx e Gunicorn. 

 

Agora vamos criar um arquivo chamado app.py com o seguinte conteúdo. 

 

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
  return "DevOps with Linux"
    
     
if __name__ == "__main__":
  app.run(debug=True,host="0.0.0.0")

 

Execute agora o seguinte comando: 

 

root@devops:~# python3 app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 179-281-442

 

Agora você pode ver o servidor interno em execução, como fizemos usando PHP, o mesmo é aplicado ao Python, então você pode obter o seu endereço IP, acessar do seu Navegador e essa página. 

 

 

 

Como os logs do Flask exibem na tela, este servidor é apenas para fins de desenvolvimento, para ambientes de Produção devemos usar um servidor WSGI (Web Server Gateway Interface).

Se você quiser saber mais sobre isso, acesse a página PEP 333: https://www.python.org/dev/peps/pep-0333/ , está explicando se mais detalhes sobre esse tópico, mas agora nosso foco é fazer o deploy da nossa aplicação. 

 

O servidor WSGI que usaremos, será o Gunicorn, é apenas uma das muitas opções que estão disponíveis, para instalá-lo, executar este comando: 

 

root@devops:~# python3 -m pip install gunicorn
Collecting gunicorn
Downloading https://files.pythonhosted.org/packages/69/ca/926f7cd3a2014b16870086b2d0fdc84a9e49473c68a8dff8b57f7c156f43/gunicorn-20.0.4-py2.py3-none-any.whl (77kB)
100% |████████████████████████████████| 81kB 1.3MB/s
Requirement already satisfied: setuptools>=3.0 in /usr/lib/python3/dist-packages (from gunicorn)
Installing collected packages: gunicorn
Successfully installed gunicorn-20.0.4

 

 Agora podemos fazer o deploy da aplicacao, mas usando o servidor WSGI, execute o seguinte comando: 

root@devops:~# gunicorn --chdir /root/ app:app -b "0.0.0.0"
[2020-03-23 18:34:13 +0000] [23783] [INFO] Starting gunicorn 20.0.4
[2020-03-23 18:34:13 +0000] [23783] [INFO] Listening at: http://0.0.0.0:8000 (23783)
[2020-03-23 18:34:13 +0000] [23783] [INFO] Using worker: sync
[2020-03-23 18:34:13 +0000] [23786] [INFO] Booting worker with pid: 23786

 

Observe que a porta mudou, agora você deve usar a porta 8000. 

 

 

Simples assim, no entanto, também queremos executar este aplicativo atrás de um proxy reverso, então vamos ver como vamos configurar isso. 

 

Configurando o proxy reverso 

 

Já instalamos o Nginx em nossa VM e também aprendemos os arquivos de configuração, sabendo que, a configuração para as páginas pode ser encontrada nos arquivos de VHost que são encontrados no diretório: 

 root@devops:~# ls /etc/nginx/sites-available/default
/etc/nginx/sites-available/default


Então podemos abrir o arquivo e o seu arquivo deve ficar como mostrado abaixo. 

 server {

listen 80 default_server;

listen [::]:80 default_server;

server_name _;

location / {

proxy_pass http://localhost:8000/ ;

}

}

 

Reinicie o servidor para ativar a configuração. 

 

root@devops:~# systemctl restart nginx
root@devops:~#                                                                                                                                                    

 

Se você tentar acessar o servidor usando a porta padrão, 80, você verá esta mensagem: 

 

 

 

Isso acontece porque o servidor por trás do nosso proxy ainda não está sendo executado, então vamos fazê-lo executar e verificar as alterações. 

 

root@devops:~# gunicorn --chdir /root/ app:app
[2020-03-23 18:52:26 +0000] [24025] [INFO] Starting gunicorn 20.0.4
[2020-03-23 18:52:26 +0000] [24025] [INFO] Listening at: http://127.0.0.1:8000 (24025)
[2020-03-23 18:52:26 +0000] [24025] [INFO] Using worker: sync
[2020-03-23 18:52:26 +0000] [24028] [INFO] Booting worker with pid: 24028

 

Desta vez não precisamos passar a opção de bind. -b, que pode disponibilizar o servidor para todos os endereços IP, no caso atual, o servidor está apenas ouvindo localhost, portanto, o Nginx está aberto para o mundo recebendo as conexões e encaminhando-o para o Gunicorn. 

 

Se você tentar acessar novamente usando a porta padrão verá que agora podemos ver o serviço em execução. 

 

 


O ambiente está pronto, Proxy Reverso são usados em muitas estratégias, uma das mais comuns é o cache dos arquivos estáticos, como javascriptcss e html, portanto todas as conexões recebidas são respondidas pelo Nginx e apenas o conteúdo dinâmico é encaminhado para o Gunicorn, desta forma é menos caro para a CPU processar tudo, nos próximos capítulos veremos como aplicar a mesma lógica, mas usando Cloud Services que são mais comuns no momento, mas se você estiver usando a infraestrutura On Premises, isso pode ser uma estratégia para aumentar o desempenho.