Bare Metal - Aplicação¶
Usando a infraestrutura: Django em Nuvem Bare-Metal¶
Vamos realizar um deploy manual de uma aplicação simples em Django em nossa nuvem MaaS.
Antes de começar
Realize um pequeno ajuste no DNS server:
No Dashboard do MaaS, vá em Subnets, clique na subnet 172.16.0.0/20 e edite o Subnet summary, colocando o DNS do Insper:
172.20.129.131
Primeira parte: Banco de Dados - PostgreSQL¶
Postgres é um servidor de banco de dados versátil e amplamente usado em projetos Open Source.
Passos:
- No Dashboard do MaaS, realize o deploy do Ubuntu 22.04 no server1.
- Acesse o terminal do server1 via SSH.
- Instale o PostgreSQL:
Crie o usuário da aplicação:
(Senha: cloud25+letra)
Crie o banco de dados:
Exponha o serviço para acesso remoto:
- Edite o
postgresql.conf:
Altere:
- Edite o
pg_hba.conf:
Adicione:
Saia do usuário postgres Finalize:
Lab1.1. Tarefa 1
Link para o Prairielearn - Tarefa 1
Importante:
Não deixe para fazer a tarefa depois para não perder o estado atual do ambiente.
Parte II: Aplicação Django¶
Agora vamos subir uma aplicação Django no server2.
Passos:
- No MaaS, deploy do Ubuntu 22.04 no server2.
- SSH no server2:
sudo apt update
sudo apt upgrade -y
sudo apt install python3-pip python3-full
python3 -m venv venv
source venv/bin/activate
pip install Django
django-admin --version
django-admin startproject my_<kit+letra>_project
python manage.py startapp members
Sobre Visualizações no Django
Visualizações são funções Python que recebem requisições HTTP e retornam respostas HTTP (HTML, JSON, etc).
Uma página da web que usa Django está cheia de visualizações com diferentes tarefas e missões.
As visualizações geralmente são colocadas em um arquivo chamado views.py localizado na pasta do seu aplicativo.
Criando a View:¶
Edite o views.py:
Sobre urls no Django
Mas como podemos executar a visualização? Bem, precisamos chamar a visualização por meio de uma URL. Ele define quais funções (views) serão executadas quando um usuário acessar uma determinada URL no navegador. Em outras palavras: Ele mapeia um caminho da URL para uma função específica do seu código.
Crie um urls.py dentro de members:
from django.urls import path
from . import views
urlpatterns = [
path('members/', views.members, name='members'),
]
No urls.py raiz:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('', include('members.urls')),
path('admin/', admin.site.urls),
]
Execute o servidor Django:
Teste no navegador:
http://localhost:8000
Modelos -> Criando Templates¶
Sobre modelos
Já aprendemos que o resultado da requisicão deve estar em HTML e deve ser criado em um modelo, então vamos fazer isso.
Crie uma pasta templates dentro da pasta members e crie um arquivo HTML chamado myfirst.html
Estrutura esperada:
my_<kit+letra>_project/
├── manage.py
├── my_<kit+letra>_project/
└── members/
└── templates/
└── myfirst.html
Se quiser, use o comando:
Conteúdo do HTML:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>{% block title %}Minha Aplicação Django{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Estilo básico -->
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
}
header, footer {
background-color: #003366;
color: white;
padding: 1rem;
text-align: center;
}
nav {
background-color: #005599;
padding: 0.5rem;
text-align: center;
}
nav a {
color: white;
margin: 0 15px;
text-decoration: none;
font-weight: bold;
}
main {
padding: 2rem;
}
.container {
background-color: white;
border-radius: 10px;
padding: 2rem;
max-width: 900px;
margin: 0 auto;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<header>
<h1>Projeto Django – Engenharia do Insper</h1>
<p>Desenvolvido com Django por {{ user.username|default:"Visitante" }}</p>
</header>
<nav>
<a href="#">Início</a>
<a href="#">Sobre</a>
<a href="#">Membros</a>
{% if user.is_authenticated %}
<a href="#">Sair</a>
{% else %}
<a href="#">Login</a>
{% endif %}
</nav>
<main>
<div class="container">
{% block content %}
<h2>Bem-vindo à sua aplicação Django!</h2>
<p>Esta é uma estrutura inicial para construir funcionalidades.</p>
{% endblock %}
</div>
</main>
<footer>
<p>© {{ year }} Insper - Engenharia da Computação</p>
</footer>
</body>
</html>
Modificar a Visualização para carregar o Template¶
Em members/views.py:
from django.http import HttpResponse
from django.template import loader
def members(request):
template = loader.get_template('myfirst.html')
return HttpResponse(template.render())
Alterar INSTALLED_APPS:¶
Em settings.py:
Rodar:
O que produzirá uma saída parecida com esta:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
Teste no navegador:
http://localhost:8000
Sobre o banco de dados SQLite
Quando criamos o projeto Django, um banco SQLite vazio (db.sqlite3) é criado na raiz.
Porém o nosso objetivo será migrar para PostgreSQL!
Migrar Modelos para o SQLite inicial¶
Agora você tem uma tabela Member em seu banco de dados!
- Tudo deve estar funcionando corretamente, porem o banco que queremos, NÃO é o SQlite, queremos conectar nossa aplicação Django ao Banco Postgresqs instalado no server1 !!!
Conectando o Django ao PostgreSQL¶
Instale os drivers:
Edite settings.py:
De:
Para:
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': '<usuario criado>',
'PASSWORD': '<senha>',
'HOST': '<IP do server1>',
'PORT': '5432',
Depois:
E:
Criando o Superuser:¶
Login: cloud25
Senha: cloud25
Expondo a Aplicação Externamente (SSH Tunnel):¶
Note
Para acessar o serviço no seu browser seria necessário fazer um NAT no roteador. Porém podemos considerar utilizar um TUNEL SSH, com esse serviço temporário podemos expor o serviço para fora do kit enquanto o terminal que o tunnel estiver utilizando esteja ativo.
Feche o terminal, com o acesso a partir do seu notebook, faça o comando SSH da rede do Insper (Wi-fi), apontando para o servidor MAIN:
Acesse:
http://localhost:8001/admin/
Lab1.2. Tarefa 2
Tarefa 2 - Prairielearn
Faça agora para não perder o estado!
Lab1.3. Tarefa 3
Tarefa 3 - Prairielearn
Não deixe para depois!
Utilizando o Ansible - deploy automatizado de aplicação¶
Até agora temos 1 aplicação Django (server2) conectada a um banco de dados, agora vamos melhorar esta arquitetura, criaremos mais uma aplicação django (server3) compartilhando o mesmo banco de dados (server1).
Os motivos para fazermos isso são dois:
- Alta disponibilidade: se um node cair o outro está no ar, para que nosso cliente acesse.
- Load Balancing: podemos dividir a carga de acesso entre os nós.
Vamos realizar a instalação da mesma aplicação de forma automática.
Vamos então utilizar novos conceitos e ferramentas: Exemplo - gerenciador de deploy Ansible (https://www.ansible.com/)
Características:
- Idempotente no sentido de conseguir repetir todos os procedimentos sem afetar os estados intermediários da instação.
- Fácil de se lidar com um pool de máquinas simultaneamente.
- Consegue realizar o provisionamento automático de VMs e Containers (mas não metal).
Fazer agora:
- Peça o deploy no server3 para o maas via cli
- Agora no SSH do MAIN:
sudo apt install ansible
wget https://raw.githubusercontent.com/Takahacker/my_kitq_project/main/my_kitq_project-install-playbook.yaml
ansible-playbook tasks-install-playbook.yaml -\-extra-vars server=[IP server3]
- Confirme que o Django foi instalado automaticamente no server3, sem que você precise alterar nada!!!
Lab1.4. Tarefa 4
Vá para a plataforma do prairielearn e faça a atividade Tarefa 4.
Obs: NÃO deixe para fazer a tarefa depois para não perder o "estado" atual do seu ambinete
Balancamento de carga usando Proxy Reverso¶
Seria ideal que tivéssemos apenas um ponto de entrada, ao invés de escolher manualmente ou chavear os IPs dos nós.
Para montar o ponto único de entrada, utilizaremos uma aplicação de proxy reverso como load balancer.
Vocês devem conseguir instalar o NGINX no nó server4 como loadbalancer ...
Então monte este proxy.
- Tutorial para fazer manual: https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-load-balancing
Dicas
Loadbalancing é um mecanismo útil para distribuir o tráfego de entrada por vários servidores privados virtuais capazes. Ao distribuir o mecanismo de processamento por várias máquinas, a redundância é fornecida à aplicação - garantindo tolerância a falhas e maior estabilidade. O algoritmo Round Robin para balanceamento de carga envia visitantes para um conjunto de IPs. Em seu nível mais básico, o Round Robin, que é relativamente fácil de implementar, distribui a carga do servidor sem considerar fatores mais matizados como o tempo de resposta do servidor e a região geográfica dos visitantes.
Configuração: Antes de configurar o loadbalancing do nginx, você deve ter o nginx instalado no seu VPS. Você pode instalá-lo rapidamente com o apt-get:
$ sudo apt-get install nginx
Módulo Upstream
Para configurar um loadbalancer round robin, precisaremos usar o módulo upstream do nginx. Incorporaremos a configuração nas definições do nginx.
Prossiga e abra a configuração do seu site (neste exemplo, trabalharei com o host virtual padrão genérico):
$ sudo nano /etc/nginx/sites-available/default
Precisamos adicionar a configuração de balanceamento de carga ao arquivo.
Primeiro, precisamos incluir o módulo upstream, que se parece com isto:
upstream backend { server backend1.exemplo.com; server backend2.exemplo.com; server backend3.exemplo.com; }
Depois, devemos referenciar o módulo mais adiante na configuração:
server { location / { proxy_pass http://backend; } }
Reinicie o nginx:
$ sudo service nginx restart
Contanto que você tenha todos os servidores privados virtuais no lugar, agora você deve encontrar que o balanceador de carga começará a distribuir os visitantes igualmente para os servidores vinculados.
Dicas
No arquivo de tasks/views.py de cada Django modifique a mensagem "Hello World ..." para conseguir identificar cada server (coloque uma mensagem diferente em cada)
Código:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the tasks index.")
No arquivo de urls.py customize o seu path no urlpatterns:
urlpatterns = [path( ' ', views.index, name='index'),]
Lab1.5. Tarefa 5
Vá para a plataforma do prairielearn e faça a atividade Tarefa 5.
Obs: NÃO deixe para fazer a tarefa depois para não perder o "estado" atual do seu ambinete
Limpeza do ambiente
Agora que você utilizou um gerenciador de deploy, vamos retormar a criação de nuvem utilizando este novo conceito.!!!!
Remova o deploy (release) de todos nós no kit.