sexta-feira, 30 de junho de 2017





Minha ideia é fazer uma série de posts sobre a implementação e as possibilidades de uso do Docker Swarm nas novas versões do Docker. Nesse primeiro post vou mostrar um Quickstart de como iniciar um cluster de testes local utilizando o Docker-Machine com o driver do Virtualbox. Ao decorrer das postagens, vou mostrar o mesmo processo utilizando demais drivers e provedores de Cloud, como AWS, Digital Ocean e etc.

Post migrado do Medium, desculpa galera... 

Dependências 

Inicialmente, nosso cluster de teste será composto por 3 hosts. Um master e dois workers.

Para isso, iremos utilizar o Docker Machine e a Virtualbox.
É importante que você possua os dois instalados localmente. 


Nossos Hosts serão:
  • master — Manager do Cluster 
  • minion01 — Worker do Cluster 
  • minion02 — Worker do Cluster 


Criando o Host Master

Com todas as dependências instaladas, vamos criar nossa docker-machine com o nome de master especificando o driver virtualbox.

$ docker-machine create -d virtualbox master


1. Utilizar o EVAL para importar as variáveis de ambiente para a shell local. 

A primeira que você criar uma máquina pelo docker-machine vai demorar consideravelmente, pois toda a resolução de dependências como o boot2docker serão instaladas de primeiro momento. Depois todas as outras tentativas vão ficar bala.


Depois de ter instalado e configurado o nosso host master, podemos listar nossos hosts e verificar mais informações de ambiente dos mesmos executando:


$ docker-machine ls // Lista os hosts ativos 
$ docker-machine env master // Exibe as configuracoes do host informado


Acabamos de criar um container chamado ‘master’. Para conseguirmos realizar uma ‘conexão’ com esse host para iniciar o cluster temos duas alternativas bem tranquilas.
Na primeira opção, vamos exportar as variáveis de ambiente do host para nossa sessão do shell.

Caso esteja utilizando o Bash ou Zsh:

$ eval "$(docker-machine env master)"

Caso esteja utilizando o Fishshell:

$ eval (docker-machine env master)


2. Pilotar os hosts via SSH.

Quando criamos a docker-machine ele já se encarrega de fazer a troca de chaves RSA entre nossa máquina e o host. Isso é bem bacana. 
Nos próximos posts vamos entrar mais a fundo nesse assunto e vamos ver que isso pode ser um ‘Power Up’ de segurança e flexibilidade em demais hosts com Amazon, DigitalOcean e etc.


$ docker-machine ssh master



Iniciando o Cluster do Swarm no Master

Com as variáveis de ambiente importadas para sua sessão do shell, vamos iniciar o swarm mode gerando um Token de Auth e Discovery.

Agora só precisamos iniciar o serviço. De costume, nosso IP externo da rede do Docker fica na interface eth1 em modo Bridge, enquanto a eth0 está configurada com um IP interno da rede do Virtualbox. Fica a sua preferência iniciar o serviço em qualquer uma delas.
As questões de segurança devem ser revisadas aqui.

Para exemplificar, vamos utilizar a interface de rede com IP externo a rede eth1. Então com a shell importada, ou via SSH no host master, execute:

$ docker swarm init --advertise-addr eth1


Após iniciar o cluster, a máquina já vai estar ingressada automaticamente como master do cluster. E irá nos mostrar o comando já pronto para ingressar novos hosts com o IP do host master e um Auth Token de discovery como o abaixo:

docker swarm join \
  --token SWMTKN-1-2e95hldkj5o49adkdz469fvlq311z1ral971gchs32hyol6rpn-57mr3rif9iy4mj54a29uekch0 \
 192.168.99.100:2377



Criando e Ingressando novos Hosts ao Cluster

Como combinamos nosso cluster será composto de 3 hosts simples:

Um master (que já criamos) e dois minions. Vamos trabalhar os mesmos agora. O processo de criação será parecido com o do master.

Também temos duas possibilidades:

1. Criar o host já ingressado no Cluster

Diretamente na criação do host no Docker Machine podemos informar alguns parâmetros do Swarm, como o  -- swarm-discovery informando o token que geramos acima.

$ docker-machine create -d virtualbox --swarm \
   --swarm-discovery token://SWMTKN-1-2e95hldkj5o49adkdz469fvlq311z1ral971gchs32hyol6rpn-57mr3rif9iy4mj54a29uekch0 \
minion01

$ docker-machine create -d virtualbox --swarm \
   --swarm-discovery token://SWMTKN-1-2e95hldkj5o49adkdz469fvlq311z1ral971gchs32hyol6rpn-57mr3rif9iy4mj54a29uekch0 \
minion02


2. Criar os hosts individualmente e ingressar via SSH

Podemos fazer o processo de criar os hosts um a um e ingressar os mesmos manualmente de forma individual com aquele comando que o swarm init nos gerou

$ docker-machine create -d virtualbox minion01 
$ docker-machine create -d virtualbox minion02

Criamos duas máquinas limpas utilizando o docker-machine. Agora podemos conectar nelas via SSH e ingressar no cluster

Ingressando o minion01

$ docker-machine ssh minion01

$ docker swarm join \
  --token SWMTKN-1-1rpipju4gbyqccce8gmbq1r5cwbqiyeg3zj3k7ikx0tjgq4mm0-abi0matsvro32s4oxzo00dpid \
  192.168.99.100:2377

Ingressando o minion02

$ docker-machine ssh minion02

$ docker swarm join \
  --token SWMTKN-1-1rpipju4gbyqccce8gmbq1r5cwbqiyeg3zj3k7ikx0tjgq4mm0-abi0matsvro32s4oxzo00dpid \
  192.168.99.100:2377


Listando os hosts ingressados no cluster e suas responsabilidades:

Podemos ter um controle em tempo real de todos os hosts ingressados e quais são suas responsabilidades dentro do cluster do swarm. Esse controle é muito bom caso você trabalhe diretamente com load balances e Auto Scaling dentro de algum provedor de cloud. Vamos abordar isso fielmente na continuidade dessa série de Swarm. Localmente não é tão importante, mas é um treino pro jogo da final.

Para listar todos os hosts ingressados:


$ docker node ls


Gerando redundância para o host Master

Todas as tarefas administrativas, como subir e descer containers, gerenciar comportamentos do cluster, rede, NAT, balance, deploys e criação de services devem ser feitos direto por um host manager (nosso master). Sem contar o ingress de novos hosts. Caso ele caia, essa tarefa se torna um pouco desastrosa.

Caso seja necessária uma manutenção programada, ou a máquina por algum motivo precisar morrer, podemos promover os demais hosts dentro do cluster como manager, tendo dois, três e até promover todos os hosts como master.

$ docker node promote minion01

Ou podemos promover vários hosts para manager

$ docker node promote minion01 minion02


Fazendo Deploy de uma Stack de Serviços no Cluster

Para fins de teste, podemos fazer um deploy simples de uma imagem de API que eu criei para testes educacionais e demonstrar o funcionamento de Load Balances e Auto Scaling. 
Vamos abordar mais a fundo esses conceitos nos próximos posts.

Link do Github: https://github.com/msfidelis/docker-api-demo
Link do Dockerhub: https://hub.docker.com/r/msfidelis/example-api/

Basicamente, o que importa é só nosso arquivo yml de deploy onde utilizaremos o Composer V3 para fazer o deploy do nosso serviço.

docker-compose-prodswarm.yml 

Para fazer o deploy é simples!


$ docker stack deploy -c docker-compose-prodswarm.yml app


Criamos um deploy da stack do docker-compose-prodswarm.yml com o nome de app. Nesse caso fizemos o deploy de 4 containers contendo nossa API. Você pode conferir isso rodando

$ docker stack ps app



Escalando Services do Cluster

Toda a Stack Docker nos oferece uma flexibilidade muito alta no aspecto de scaling. O modo Swarm, mais ainda! Com o docker, podemos listar todos os services que estão criados e rodando na nossa Stack que acabados de dar deploy. 

Para listá-los basta executar:

$ docker stack services app

Para escalar os serviços que estão rodando no cluster, em quantidade, devemos executar a partir de um host manager o seguinte comando:


$ docker service scale app_api=10

Onde app_api é o nome do serviço e 10 é a quantidade de novos containers que vamos fazer deploy no cluster. Depois podemos acompanhar a vida dos containers e a distribuição deles nos nossos hosts nodes normalmente.

$ docker stack ps app


Testando nossa API

Para testar a API, podemos pegar o IP do host master e acessar o Endpoint que nos mostra o hostname da máquina que está atendendo a requisição. Essa demonstração vai também nos provar que o load balance está acontecendo dentro do service da API. O correto é as requisições serem distribuídas entre todos os containers.$ docker-machine ip master

Agora acesse várias vezes:

http://ip-do-master/whoami




No próximo post iremos abordar um quickstart da criação de clusters com a Amazon AWS, usando EC2 e pois ECS.

:)

Docker Swarm :: Quickstart do seu Cluster Local com Docker-Machine e Virtualbox.


A dica de hoje é bem interessante. Na verdade é mais um dos life hacks que podem ser executados através de uma conexão SSH. Há bastante tempo eu fiz um post exemplificando como criar um simples túnel utilizando SSH para acessar recursos bloqueados na rede local, esse post aqui, recomendo que leia ele também. Hoje vamos criar um túnel HTTP utilizando Socks, para que seja possível acessar a internet a partir do seu navegador através do seu servidor SSH. Coisas muito úteis pra quando se estuda em uma faculdade com filtro de internet.

Para executar o processo, será necessário um servidor com SSH previamente configurado. Eu tenho uma instância na AWS dedicada pra isso que eu só paro nas férias (rs), mas pode ser qualquer máquina. Devemos realizar uma conexão SSH  silenciosa nessa máquina em Backgroud apontando uma porta para escutar nossa conexão. É através dela que vamos fazer nosso tunelamento HTTP.

$ ssh matheus@123.312.12.21 -D 7777 -f -C -q -N

Onde:

-D 8080 : A porta que a conexão SSH será criada.
-f : Faz o processo rodar em Backgroud. Parâmetro opcional
-C : Habilita a compressão SSH. Legal para internet lenta, tipo faculdade. 
-q : Quiet mode. 
-N : Parâmetro que diz que nenhum comando será enviado nessa sessão. (O -f solicita isso)

Configuração do Firefox

No firefox, vá nas opções de REDE

Selecione:

  • Configuração manual de proxy
  • APENAS em SOCKS coloque o endereço de localhost 127.0.0.1 e a porta que definimos que iremos escutar, no caso 7777
  • Selecione a opção "SOCKS v5"
  • Selecione a opção "Proxy DNS ao usar SOCKES v5"

Feche as configurações e acesse algum site que te entregue seu IP atual de dois navegadores, o nosso Firefox de Proxy e o Chrome por exemplo. Dica

Firefox de Proxy

Navegador com IP normal


Espero ter ajudado :)


Criando um HTTP Proxy seguro utilizando SSH e o Firefox

segunda-feira, 5 de junho de 2017



Sábado passado, 03/06/2017 participei do NodeSchool Campinas pra falar um pouco sobre API's REST com HapiJS, um framework muito poderoso para criação de API's e Web Services mais robustos voltados a alta disponibilidade e microservices.

Site HapiJS: https://hapijs.com/tutorials

Repositório dos exemplos da Talk: https://github.com/msfidelis/hapijs-demo

Confira a transmissão Ao Vivo que rolou no Superlógica Labs:



Confira os Slides:



Entra lá no Meetup do pessoal do NodeSchool!

:)

TALK :: API's com HapiJS no NodeSchool Campinas

domingo, 21 de maio de 2017



Hoje o Nginx tá rolando solto aqui. Recomendo que veja o primeiro artigo onde montamos de maneira simplista um Port Foward utilizando o Nginx com proxy reverso.

Dessa vez, vamos utilizar o Nginx para fazer o que ele faz de melhor utilizando alguns recursos mais avançados que do ultimo post: Ser um proxy reverso de alta performance para servir conteúdo estático e fazer caching dos mesmos para acelerar a navegação de sites e etc. O Nginx é uma ferramenta muito versátil que pode trabalhar em conjunto com vários outros Web Servers e ferramentas.

As estratégias de caching são quase que obrigatórias quando falamos de web hoje em dia, e viver sem isso quando sua aplicação cresce, pode causar diversos problemas de performance e até mesmo impactar nos custos de cloud, com scaling de máquinas de forma não pertinente. Uma solução pra isso é criar um proxy gateway utilizando o Nginx como primeiro contato para que ele se encarregue de cachear todo conteúdo estático como HTML, CSS, JS e imagens da nossa aplicação para diminuir ou evitar um Overhead dos nosso servidores.

Vou exemplificar esse artigo com um case parecido com o do anterior, mas dessa vez vamos trabalhar servindo uma Dashboard qualquer na porta 1234 do Apache.



Vamos seguir os passos iniciais para a instalação.


Instalação do Nginx 

Neste exemplo, como de costume, eu estarei utilizando o Debian 8 Jessie para os testes, mas o procedimento de instalação será o mesmo para todas as distribuições Debian Like.
Após a instalação vamos confirmar se o serviço está Ok.


$ sudo apt-get install nginx 
$ sudo systemctl enable nginx
$ sudo systemctl start nginx 
$ sudo systemctl status nginx

A saída deve ser parecida com essa:

● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
   Active: active (running) since Sun 2017-05-21 20:12:44 GMT; 9min ago
 Main PID: 1642 (nginx)
   CGroup: /system.slice/nginx.service
           ├─1642 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─1643 nginx: worker process
           ├─1644 nginx: worker process
           ├─1645 nginx: worker process
           └─1646 nginx: worker process

May 21 20:12:44 jessie systemd[1]: Started A high performance web server and a reverse proxy server.
May 21 20:21:19 jessie systemd[1]: Started A high performance web server and a reverse proxy server.
vagrant@jessie:~/teste$


Configuração do Proxy Reverso com Cache de conteúdo estático

Edite o arquivo de configuração do Nginx e adicione a linha do proxy_cache_path

$ vim /etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##
        
        # Adicione essa linha 
        proxy_cache_path  /data/nginx/cache  levels=1:2    keys_zone=STATIC:10m inactive=24h  max_size=1g;

...

Agora vamos criar a pasta de armazenamento do Cache e o arquivo que vamos utilizar para separar as configurações do nosso servidor.


$ mkdir -p /data/nginx/cache
$ touch /etc/nginx/sites-enabled/proxy-cache.conf

No arquivo que acabamos de criar, vamos adicionar as seguintes linhas:

/etc/nginx/sites-enabled/proxy-cache.conf

    server {
        listen       80;

        # Location do conteúdo estático - Aqui vamos cachear tudo
        location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {

            # PROXY CACHE CONFIGS
            proxy_pass             http://127.0.0.1:1234;
            proxy_set_header       Host $host;
            proxy_cache            STATIC;
            proxy_cache_valid      200  1d;
            proxy_cache_use_stale  error timeout invalid_header updating http_500 http_502 http_503 http_504;

            #CORS - Conteúdo estático libere somente o GET
            add_header 'Access-Control-Allow-Origin' *;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
            add_header 'Access-Control-Allow-Methods' 'GET';

            #CACHE - Informações do Cache no Header
            add_header Cache-Control "public";
            add_header X-Proxy-Cache $upstream_cache_status;

            # Tempo de expiração
            expires 30d;
        }

        # Location do Proxy reverso - Aqui rodando o Apache convencional
        location / {

            # PROXY CACHE CONFIGS
            proxy_pass             http://127.0.0.1:1234;
            proxy_set_header       Host $host;
            proxy_cache            STATIC;
            proxy_cache_valid      200  1d;
            proxy_cache_use_stale  error timeout invalid_header updating http_500 http_502 http_503 http_504;

            # CORS
            add_header 'Access-Control-Allow-Origin' *;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';

            # Status do Cache como Header no response
            add_header Cache-Control "public";
            add_header X-Proxy-Cache $upstream_cache_status;

            # Tempo de expiração do conteúdo cacheado - Aqui você pode pegar leva no cache
            expires 1d;
        }
    }

O que fizemos aqui:

Primeiramente nós criamos dois locations parecidos que vão bater na nossa configuração de proxy reverso.  As únicas diferenças são o tempo de cache, no caso 30 dias para o conteúdo estático e 1dia para o restante das solicitações.

No caso de você prover o uso de alguma API, recomendo retirar as configurações de cache do proxy_cache do location / ou diminuir o tempo de cache.

Também um pequeno detalhe do CORS que permite somente solicitações GET para o nosso conteúdo estático e liberamos os outros (mais utilizados) verbos HTTP para o restante da aplicação.

No proxy_pass, devemos informar o IP e a porta do nosso servidor original.
No exemplo eu estou provendo cache para uma aplicação que está na mesma máquina, porém rodando na porta 1234. Informe seu servidor ou load balance aqui.
Adicionamos um Header no response chamado X-Proxy-Cache, onde ele vai nos informar o status daquela solicitação mediante ao cache. No caso, as mais conhecidas vão ser HIT (veio do cache) e MISS (Não veio do cache, normalmente as primeiras solicitações após a limpeza ou vencimento do cache).

Agora vamos reiniciar o serviço e testar a aplicação:


$ rm -rf /data/nginx/cache/*
$ systemctl restart nginx

Acessando nossa Dashboard via navegador, podemos ver algo diferente das demais solicitações:

Nos conteúdos estáticos, podemos ver os Headers que adicionamos, o CORS o vencimento do cache (30 dias depois da sua solicitação) e o X-Proxy-Cache como HIT, dizendo que veio do cache (A primeira solicitação virá MISS).




Olhando mais de perto as solicitações de conteúdo fora dos assets, no caso o HTML da página podemos ver o mesmo resultado, porém com o cache para 1 dia.


Podemos testar com mais detalhes com o curl, para visualizar somente os headers com o parâmetro -I



$ curl -I http://192.168.1.53



$ curl -I http://192.168.1.53/style.css


Limpando o cache do Nginx

Para limpar o cache que o Nginx vai gerar, basta apagar o conteúdo da pasta que criamos anteriormente.

$ rm -rf /data/nginx/cache/*


Espero ter ajudado! :)

Nginx :: Criando um servidor de Proxy Reverso e Caching de Conteúdo




Esse artigo vai mostrar a maneira mais simples de fazer um proxy reverso com intuito de Port Forward utilizando o servidor de alta performance Nginx.

Site do Nginx: https://nginx.org/en/
Documentação: https://www.nginx.com/resources/wiki/

Vamos supor que nós criamos um serviço que rode na porta 1234 de uma máquina qualquer, e precisar fazer com o Nginx crie um proxy reverso da porta 80 para a porta 1234, fazendo com que o mesmo funcione como uma ponte de ligação entre o cliente e o serviço. Para exemplificar, vamos supor que tenhamos um servidor Apache 2.4 rodando na porta 1234 do servidor.



Instalação do Nginx


Para fazer a instalação do Nginx, você deverá acessar a documentação para mais detalhes. Neste exemplo eu estarei utilizando o Debian 8 Jessie para os testes, mas o procedimento de instalação será o mesmo para todas as distribuições Debian Like. Após a instalação vamos confirmar se o serviço está Ok.


$ sudo apt-get install nginx 
$ sudo systemctl enable nginx
$ sudo systemctl start nginx 
$ sudo systemctl status nginx

● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
   Active: active (running) since Sun 2017-05-21 20:12:44 GMT; 9min ago
 Main PID: 1642 (nginx)
   CGroup: /system.slice/nginx.service
           ├─1642 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─1643 nginx: worker process
           ├─1644 nginx: worker process
           ├─1645 nginx: worker process
           └─1646 nginx: worker process

May 21 20:12:44 jessie systemd[1]: Started A high performance web server and a reverse proxy server.
May 21 20:21:19 jessie systemd[1]: Started A high performance web server and a reverse proxy server.
vagrant@jessie:~/teste$

Pra verificar se está tudo Ok, vamos acessar a porta 80 do servidor


Criando o proxy reverso 

Vamos criar um arquivo chamado apache-proxy.conf onde vamos configurar nosso proxy reverso para fazer nosso redirect inicial do Nginx para o Apache

sudo vim /etc/nginx/sites-available/apache-proxy.conf

/etc/nginx/sites-available/apache-proxy.conf


    server {
        listen       80;
        server_name  localhost;
        access_log  /var/log/nginx/proxy-apache.log;

        location / {
                proxy_pass      http://127.0.0.1:1234;
        }
    }

Como vamos utilizar a porta 80 do servidor, devemos deletar o arquivo de configuração /etc/nginx/sites-enabled/default  que contém algumas configurações que ocupam essa porta. Em seguida vamos criar um link simbólico da do arquivo de configuração do proxy reverso para dentro da pasta sites-enabled antes de reiniciar o serviço.

$ sudo rm /etc/nginx/sites-enabled/default
$ sudo ln -s /etc/nginx/sites-available/apache-proxy.conf /etc/nginx/sites-enabled/apache-proxy.conf

$ sudo systemctl restart nginx 

Agora com o serviço reiniciado, vamos acessar a porta 80 do servidor.


Essa é a forma mais simples de fazer o serviço de redirecionamento de portas entre serviços utilizando o Nginx.

Espero ter ajudado :)

Nginx :: Criando um serviço de proxy reverso rapidamente

segunda-feira, 10 de abril de 2017


Aqui vai minha Stack básica de PHP 7.0. Apenas mais um daqueles posts que eu mato uma nota no meu Google Keep e faço nascer um post aqui pra comunidade. Essa é minha Stack default, ou seja, o general que fica ao meu lado na guerra. Uso esse esquema também nas minhas Dockerfiles também. Espero que ajude!

Instalação dos repositórios no Ubuntu Server 16.**

Instalação do Software Properties (Caso não houver) 
$ sudo apt-get install software-properties-common -y

Instalação do repositório do PHP 7.0 no Ubuntu

$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update 

Instalação dos repositórios no Debian Jessie

Instalação do repositório do PHP 7.0 no Debian
$ echo "deb http://packages.dotdeb.org jessie all" >> /etc/apt/sources.list 

$ wget https://www.dotdeb.org/dotdeb.gpg
$ sudo apt-key add dotdeb.gpg
$ sudo apt-get update

Instalação do PHP 7.0 no Debian Jessie e Ubuntu 16.xx

Instalação uniforme para ambos as distribuições
$ sudo apt-get install php7.0  php7.0-bcmath php7.0-bz2 \
php7.0-cli php7.0-common php7.0-curl php7.0-dev php7.0-fpm \
php7.0-gd php7.0-interbase php7.0-intl php7.0-json php7.0-mbstring \ 
php7.0-mcrypt php7.0-mysql php7.0-opcache \
php7.0-pspell php7.0-readline php7.0-recode \
php7.0-soap  php7.0-tidy php7.0-xml php7.0-xmlrpc php7.0-xsl php7.0-zip -y 


E caso necessite de mais algum pacote do PHP, você pode encontrá-lo facilmente

$ sudo apt-cache search php7

Espero ter ajudado :)

PHP :: Instalação do PHP 7.0 em Ambientes Ubuntu 16.04 e Debian Jessie

 
Nanoshots | Open Source Security, Linux e Tutoriais © 2015 - Designed by Templateism.com