Skip to content

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:
sudo apt update
sudo apt install postgresql postgresql-contrib -y

Crie o usuário da aplicação:

sudo su - postgres
createuser -s cloud -W

(Senha: cloud25+letra)

Crie o banco de dados:

createdb -O cloud tasks

Exponha o serviço para acesso remoto:

  • Edite o postgresql.conf:
sudo nano /etc/postgresql/<versão>/main/postgresql.conf

Altere:

listen_addresses = '*'
  • Edite o pg_hba.conf:
sudo nano /etc/postgresql/<versão>/main/pg_hba.conf

Adicione:

host    all    all    172.16.0.0/20    trust

Saia do usuário postgres Finalize:

exit
sudo ufw allow 5432/tcp
sudo systemctl restart postgresql

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:

from django.http import HttpResponse

def members(request):
    return HttpResponse("Hello world!")

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:

python manage.py runserver 0.0.0.0:8000

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:

sudo apt install tree
tree -L 2

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:

INSTALLED_APPS = [
    ...
    'members',
]

Rodar:

python manage.py migrate

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

python manage.py makemigrations members
python manage.py migrate

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:

pip install psycopg2-binary psycopg

Edite settings.py:

De:

'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',

Para:

'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': '<usuario criado>',
'PASSWORD': '<senha>',
'HOST': '<IP do server1>',
'PORT': '5432',

Depois:

python manage.py migrate

E:

python manage.py runserver 0.0.0.0:8000

Criando o Superuser:

python manage.py createsuperuser

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:

ssh cloud@10.103.1.X -L 8001:[IP server2]:8000

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

Roteiro 1 MAAS_APP

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.

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

Roteiro 1 MAAS_APP

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.