<![CDATA[ Lucas Santos ]]> https://blog.lsantos.dev https://blog.lsantos.dev/favicon.png Lucas Santos https://blog.lsantos.dev Qui, 21 Jan 2021 22:05:11 -0300 60 <![CDATA[ Podcast #FalaDev - Vamos falar de Microsserviços ]]> https://blog.lsantos.dev/podcast-faladev-vamos-falar-de-microsservicos/ 5ff8955368fe9d21e9e66ab5 Sex, 08 Jan 2021 14:42:39 -0300 Tive o enorme prazer de ser convidado para fazer parte do incrível podcast #FalaDev, da RocketSeat, juntamente com o Wesley Willians para podermos falar sobre Microsserviços!

Neste podcast falamos sobre como podemos entender microsserviços, como eles funcionam, quais são os casos clássicos, como podemos melhorar nossas arquiteturas e como podemos ser muito mais eficientes em termos de custo e também de projetos usando microsserviços!

]]>
<![CDATA[ Somos 4k! Muito obrigado! ]]> https://blog.lsantos.dev/somos-4k-muito-obrigado/ 5fc9622b82fe71827326670f Qua, 09 Dez 2020 14:33:25 -0300 Eu gostaria de agradecer a todas as pessoas que fizeram parte desta conquista! Somos 4.000 pessoas no Twitter que adoram tecnologia e gostam de conversar e descobrir cada vez mais conteúdo!

Muito obrigado!

Quando comecei a escrever, por volta de 2016, não esperava que fosse atrair ninguém, eu nem sequer imaginava que um dia alcançaria tantas pessoas que se interessariam pelo meu conteúdo. Agora, trabalhando integralmente com conteúdo e aprendendo cada vez mais para poder levar mais conhecimento a todos eu entendo que esta é de fato a profissão que eu quero seguir!

Vai ter bolo?

Para comemorar este marco, eu vou estar realizando um sorteio! Para cada mil seguidores vou sortear um livro da casa do código a sua escolha, ou seja, vou sortear 4 livros físicos para 4 pessoas além de um pack de 5 stickers aleatórios! E mais um pack de 10 stickers para outras 4 pessoas sorteadas!

Para participar é muito simples, você so precisa ser uma das pessoas inscritas na newsletter! Para fazer isso é muito simples:

  1. No canto inferior direito da tela existe um botão "Assine a Newsletter" é só clicar nele!
  2. Coloque seu nome e e-mail
  3. Clique em "Enviar"

É simples assim! Se você já é assinante, então não precisa fazer mais nada!

Como funciona?

O sorteio vai acontecer no dia 15 de Janeiro de 2021, assim todos vão ter tempo para poder se cadastrar na lista e receber os emails! Você pode se cadastrar na newsletter até o dia do sorteio!

Os resultados do sorteio serão postados no meu Twitter e em todas as minhas outras redes sociais, bem como em uma newsletter especial. Assim que as pessoas ganhadoras forem anunciadas, vou enviar um email pessoal para cada uma delas pedindo informações sobre o livro que quer ganhar e também o endereço para entrega!

Se a pessoa não foi sorteada para os livros mas sim para o pack de stickers, vou entrar em contato da mesma forma para requisitar o endereço de entrega!

Assim que os livros forem enviados, eu estarei entrando em contato novamente para informar os códigos de rastreio e as últimas novidades :D

E se eu não ganhei :(

Não tem problema! Aqui todos vão ganhar! Todas as pessoas inscritas na newsletter vão receber códigos de descontos surpresas para facilitar ainda mais o aprendizado!

Vai ter mais?

Claro! A cada marco de 1000 novos seguidores vou fazer uma pequena ação para podermos comemorar o crescimento da nossa comunidade! A cada vez tentarei conseguir novas parcerias e novos sorteios!

Se você é parte ou conhece alguém que poderia ajudar a fazer os sorteios ainda mais legais! É só entrar em contato comigo através do meu email!

Obrigado!

Eu gostaria de agradecer a todas as pessoas que me acompanharam desde o início até aqui, este blog, todo o meu conteúdo e tudo que eu faço não seria nada sem alguém para discutir e ler minhas ideias. Então

MUITO OBRIGADO!

]]>
<![CDATA[ gRPC com Node.js no EnterJS 2020 ]]> https://blog.lsantos.dev/grpc-com-node-js-no-enterjs-2020/ 5fc945b782fe7182732666e3 Qui, 03 Dez 2020 17:55:44 -0300 Em setembro tive o prazer de participar de uma conferência online feita na Alemanha onde falei um pouco mais sobre gRPC com Node.js na parte teórica e dei alguns exemplos de como podemos codar a nossa aplicação utilizando o modelo gRPC de comunicação.

Aproveitando que o DoWhile vem ai! Veja a parte teórica antes da parte prática nessa palestra!

]]>
<![CDATA[ Entenda a comunicação entre serviços com gRPC no DoWhile 2020 ]]> https://blog.lsantos.dev/entenda-a-comunicacao-entre-servicos-com-grpc-no-do-while-2020/ 5fc5044482fe718273266672 Seg, 30 Nov 2020 11:52:51 -0300 Estou super feliz de anunciar que fui convidado pela RocketSeat para fazer parte do grupo de palestrantes no maior evento deles, o DoWhile 2020!

O evento é totalmente gratuito e acontece nos dias 14 e 15 de Dezembro, então já sabe, deixa sua agenda pronta para não esquecer! O evento é totalmente online e tem como objetivo reunir todo o ecossistema de desenvolvimento em busca do aprendizado contínuo!

Quem quiser se inscrever, lembrando que é gratuito, é só acessar o link abaixo.

Lucas Santos | DoWhile 2020
Junte-se a Lucas Santos no DoWhile, um evento online que vêm com a missão de reunir todo o ecossistema de programação em busca de um mesmo propósito: o aprendizado contínuo.

Junto comigo vão estar outros profissionais incríveis do mundo da tecnologia, entregando conteúdos em forma de palestras, workshops, painéis e muito mais!

Neste evento vou estar ensinando a fazermos comunicações entre microsserviços utilizando gRPC de forma simples e prática em um workshop totalmente prático e hands on, então quem estiver curioso para saber como você pode parar de usar o ReST em suas APIs e começar a tipar todo o seu ecossistema, então esta é a talk!

Vejo vocês por lá!

]]>
<![CDATA[ Por Que Black Fridays Dão Errado? - Hipsters.talks ]]> https://blog.lsantos.dev/por-que-black-fridays-dao-errado/ 5fc4647482fe718273266646 Seg, 30 Nov 2020 00:21:41 -0300 Tive o enorme prazer de ser o convidado surpresa neste quadro do Hipsters que adoro! O Gabs Ferreira me chamou para participar de um papo super descontraído para discutirmos junto com o Mário e a Patrícia sobre histórias de Black Friday.

Foi um papo super bacana e ele está totalmente disponível de graça neste link! Assista e dê seus comentários!

E você? Tem alguma história de black friday para contar?

]]>
<![CDATA[ Entendendo Threading no Node.js com Rodrigo Branas ]]> https://blog.lsantos.dev/entendendo-threading-no-node-js-com-rodrigo-branas/ 5fb7e5fa82fe71827326661f Sex, 20 Nov 2020 13:31:32 -0300 No dia 9 de Novembro tive o prazer de ser convidado pelo excelente Rodrigo Branas para participar de uma live super animada no canal dele.

Nesta live, ficamos mais de 2 horas falando sobre como funcionam os processos em threading no Node.js e também como podemos tirar vantagem da API de clusters e Worker Threads!

Mostramos códigos, falamos da nossa experiência e também tiramos muitas duvidas sobre como threading funciona nos computadores em geral! Veja a live na íntegra logo abaixo!

]]>
<![CDATA[ Atualização Automática de SO com Unattended Upgrades ]]> https://blog.lsantos.dev/atualizacao-automatica-de-so-com-unattended-upgrades/ 5fabfbb382fe7182732665b8 Qua, 11 Nov 2020 13:10:23 -0300 Quando estamos criando máquinas virtuais, um dos maiores problemas que temos é manter os nossos sistemas operacionais atualizados e livres de bugs e falhas de segurança.

Na maioria dos casos, o SO já possui um sistema interno para atualização automática, porém, quando estamos usando um sistema operacional baseado em pacotes como, por exemplo, o Linux, digamos um Ubuntu 18.4 Server, temos que constantemente rodar comandos como apt update e apt upgrade para instalar as últimas versões dos pacotes do sistema e assim atualizar para a última versão e corrigir possíveis falhas de segurança.

O problema

O grande problema com estas abordagens é que precisamos constantemente entrar na máquina, rodar o comando e sair. Para solucionar isso, temos as famosas crontabs. Podemos por exemplo executar o seguinte comando:

crontab -e

Para editar a nossa crontab, e ai podemos cadastrar a seguinte linha:

0 3 */5 * * sudo apt update && sudo apt upgrade -y

Esta linha vai fazer com que executemos os comandos de atualização a cada 5 dias as 3 da manhã. É uma boa prática realizar a atualização sempre fora dos horários de utilização da máquina, então esta hora pode ser definida por você sem problemas.

Da mesma forma, a frequência de execução fica a critério de quem está configurando a máquina, eu costumo executar o processo a cada 5 dias porque geralmente não temos grandes atualizações diariamente.

Porém, se tivermos outras atualizações que necessitam de um reboot, por exemplo, atualizações de Kernel, então vamos ter que entrar e reiniciar a máquina manualmente... Deve haver um jeito mais simples de fazer isso, não?

Unattended Upgrades

O Ubuntu (e acredito que a maioria dos sistemas baseados no Debian), possuem um pacote chamado unattended-upgrades, que pode ser combinado com alguns outros pacotes para prover uma funcionalidade sensacional em termos de segurança e atualização de SO.

Para começar, vamos remover a nossa crontab criada anteriormente e deixar o sistema limpo de novo. Depois, vamos instalar os seguintes pacotes:

sudo apt install -y unattended-upgrades apt-listchanges bsd-mailx

O bsd-mailx irá pedir algumas configurações iniciais para setar o seu email, estas configurações são específicas de máquina para máquina, mas o ideal é que você escolha a opção Internet Site para poder configurar o FQDN do seu próprio domínio. Se você precisar realizar alguma reconfiguração do pacote pois ele não está funcionando, use o comando a seguir:

sudo dpkg-reconfigure -plow postfix

Isto fará com que a janela de configuração seja aberta novamente, se você prefere reconfigurar utilizando o arquivo de configuração, basta editar o arquivo /etc/postfix/main.cf, não se esqueça de executar um restart do postfix depois de salvar o arquivo com o comando:

sudo systemctl restart postfix

Agora, vamos ativar o pacote para as atualizações estáveis usando o seguinte comando:

sudo dpkg -plow unattended-upgrades

Então podemos abrir o arquivo de configuração, use o seu editor preferido para editar o arquivo /etc/apt/apt.conf.d/50unattended-upgrades. Este arquivo contém todas as configurações necessárias para definirmos a funcionalidade de atualização do pacote, primeiro, vamos configurar nosso email para recebermos notificações de atualizações importantes, para isso vamos setar a chave Unattended-Upgrade::Mail com o nosso email escolhido, ficando Unattended-Upgrade::Mail "hello@lsantos.dev";.

Agora vamos configurar uma série de outras chaves para podermos obter o máximo do pacote:

Unattended-Upgrade::Automatic-Reboot "true";  # Para reiniciar o sistema após uma atualização de Kernel
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00"; # Que horas queremos que o sistema reinicie

Agora podemos rodar o comando sudo unattended-upgrades --dry-run para poder testar se as nossas configurações estão corretas. Este comando não deve ter nenhuma saída, se este é o resultado então está tudo certo!

Conclusão

Com a instalação destes pacotes podemos ficar mais tranquilos em relação a atualizações de sistemas operacionais e também podemos manter as nossas VMs atualizadas de forma mais concisa.

Se você leu o último artigo sobre criar uma VPN própria, a aplicação desta técnica e também 2FA usando SSH podem ser uma boa pedida para deixar a sua VM rodando tranquilamente!

Até mais!

]]>
<![CDATA[ Aplicando Two Factor Authentication no SSH ]]> https://blog.lsantos.dev/aplicando-two-factor-authentication-no-ssh/ 5fa45a4f82fe7182732664fa Qui, 05 Nov 2020 19:07:56 -0300 Já estamos muito acostumados com SSH para logarmos em máquinas virtuais, como fizemos no nosso post onde criamos uma VPN. Porém, sabemos que o SSH aceita diversos níveis de segurança quando se trata de acesso local.

O primeiro nível de segurança – e o mais fraco – é uma senha alfanumérica, este é o meio mais fraco porque a comunicação entre o seu computador e o servidor, mesmo sendo pelo protocolo do SSH, ainda transmite sua senha em texto plano, um ataque bem direcionado poderia capturar a sua senha e utilizá-la, se você não estiver utilizando nenhum túnel.

O segundo nível de segurança, e também o que mais utilizamos, é a combinação de chaves RSA, este tipo de segurança permite que você tenha mais facilidade para gerenciar acessos, por exemplo:

  • Podemos permitir o acesso de várias pessoas à mesma máquina sem ter uma senha trafegada por elas.
  • Podemos revogar as credenciais de uma única pessoa sem precisar alterar as demais.
  • Sendo sincero, é muito melhor não ter que lembrar uma senha do que ter que lembrar uma, não é?

A grande vantagem das chaves assimétricas é que você pode provar que você é o dono de uma chave privada sem precisar, de fato, mostrar a chave para ninguém, ou seja, você pode dar uma chave pública ao servidor e, quando você for logar, o servidor irá perguntar se você possui a chave privada que faz a contraparte daquela chave pública, se você possuir, então você está dentro.

Apesar disso, muitas pessoas ainda tem um grande problema porque precisam gerenciar estas chaves em algum lugar, manter a sua chave privada em segredo e segura é uma tarefa muito complicada. Então podemos adicionar uma nova camada de segurança para aumentar ainda mais a resiliência de um servidor importante. O 2FA, ou, Two-Factor Authentication.

Two Factor Authentication

O TFA (ou 2FA) é uma técnica de segurança que exige que você utilize um outro dispositivo (geralmente um celular) para confirmar um código de uso único, chamado de OTP, o One-Time Password.

Este código é gerado seguindo algumas implementações matemáticas que não vamos discutir aqui, mas ele está baseado em tempo, ou seja, desde que o seu relógio e o relógio do servidor estejam sincronizados, vocês dois irão gerar o mesmo código que valerá por um determinado tempo. Se você digitar o mesmo código que o servidor gerar, então você é o dono do OTP.

Por que usar TFA?

O uso de senhas se tornou algo comum e a principal forma de autenticação. Utilizar algo que só você sabe de forma que só você tenha acesso a um determinado tipo de dado é um conceito muito simples e todos podem entender. Porém, com o tempo, o uso de senhas se tornou muito comum com a Internet, tudo que temos pede uma conta com uma senha ou então algum tipo de autenticação.

O ideal seria que você gerasse senhas diferentes para serviços diferentes, porém é impossível lembrar todas essas senhas,  por isso temos serviços como o 1Password, Dashlane ou LastPass, para que possamos gerar senhas aleatórias que não precisamos lembrar, pois eles se encarregarão de logar para a gente no momento correto e também de manter os dados seguros.

O que acontece é que muitas pessoas não sabem ou não tem como utilizar estes serviços pelos mais variados motivos e acabam utilizando a mesma senha para diversos serviços. Desta forma, se você usa a sua senha em um serviço que tem uma boa segurança, digamos a Azure, mas também usa a mesma senha para serviços de qualidade duvidosa, quando o elo mais fraco se romper, os hackers só precisarão de uma senha para acessar todas as suas contas.

E é por isso que o TFA é tão importante. No geral, o TFA tenta melhorar a segurança adicionando uma camada extra de autenticação, que pode ser uma entre três fatores:

  • Algo que você sabe
  • Algo que você tem
  • Algo que você é

Algo que você sabe seria a sua senha, o que não é interessante. Algo que você tem seria um celular ou um outro dispositivo, portanto utilizar a combinação "Algo que eu sei + Algo que eu tenho" se tornou muito popular. Ultimamente estamos vendo também a combinação "Algo que eu sei + Algo que eu sou" com autenticações biométricas ou por identificação de face.

Por que usar TFA em um servidor

Pelo mesmo motivo que você utiliza TFA para proteger suas contas de e-mail: aumentar a segurança.

Imagine que você tenha uma empresa e esta empresa tenha uma tecnologia que valha milhões, ou então possua dados muito sensíveis armazenados em um servidor. Automaticamente este se torna um alvo muito cobiçado por hackers, então é importante adicionar camadas extras de proteção.

Aplicando TFA em um servidor

Chega de conceitos, vamos colocar a mão na massa! Para começar, vou assumir que você já tem um servidor rodando, pode ser uma VM da Azure, uma VM local, um Raspberry Pi, você que escolhe.

Além disso é importante que este servidor já esteja configurado para utilizar chaves SSH como meio de entrada. Desta forma não temos como logar através de uma senha, a maioria dos provedores cloud hoje permitem que você coloque sua chave pública como meio de autenticação na VM.

Configurando o SSH

Antes de começarmos, preciso dizer que não podemos executar os comandos como sudo su , sempre utilize sudo quando for necessário dentro do usuário que você irá logar.

Primeiramente, vamos abrir o arquivo /etc/ssh/sshd_config com o nosso editor de texto preferido. Você vai ver um arquivo com várias configurações. A primeira delas é a configuração da porta, que deve estar como #Port 22, você pode mudar a configuração para aumentar ainda mais a segurança, uma vez que a porta padrão do SSH é bem conhecida, basta remover o #. Esta porta pode ser qualquer uma que você escolher, você so precisa lembrar de abri-la no seu provedor e no seu firewall.

Procure a linha PermitRootLogin, ela deve estar com o valor padrão #PermitRootLogin prohibit-password. Altere este linha para PermitRootLogin no.

Agora, vamos alterar a linha #PubkeyAuthentication yes, removendo o # para ativar a configuração.

Não vamos reiniciar o servidor ainda, vamos primeiro garantir que conseguimos instalar o nosso sistema de TFA corretamente.

Instalando o TFA

Se você estiver utilizando qualquer tipo de sistema baseado em Debian, no meu caso estou usando o Ubuntu Server 18.4, basta instalar o pacote libpam-google-authenticator com o comando:

sudo apt install -y libpam-google-authenticator
Se você não está usando uma distro baseada no Debian, ou não está conseguindo instalar a biblioteca, procure por "libpam-google-authenticator <suadistro>" para obter instruções corretas de instalação.

Execute o script digitando google-authenticator na linha de comando, ele vai te fazer várias perguntas, as quais você pode só responder yes para todas, com exceção de duas.

Para a pergunta:

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n)

Responda n. Esta pergunta está perguntando se queremos desativar o login com tokens iguais ao mesmo tempo, se sim, você só poderá logar uma vez que um novo token for gerado a cada 30s, se não, poderá logar a qualquer momento. Se este é um servidor muito importante, recomendo que você digite y, no nosso caso estamos ignorando esta opção.

Para a pergunta:

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n)

Vamos digitar n, ela permite que  utilizemos o mesmo token anterior até alguns segundos depois que ele perdeu a validade para compensar a diferença de tempo entre o servidor e o cliente, enquanto isso ajuda a manter as coisas simples, ele também reduz a segurança.

No final, você terá uma imagem parecida com esta:

Resultado da criação de um autenticador

Basta apontar um aplicativo de TFA como o Authy, 1Password ou até mesmo o Google Authenticator para o QR Code para poder cadastrar a nova senha, ou então utilizar a Secret Key para poder gerar a mesma em aplicativos que não possuem leitura de QR Codes.

Lembre-se de anotar os códigos de emergência e o código de verificação e mantê-los em locais seguros!

Vamos agora editar o arquivo de configuração do pacote para podermos habilitar o uso de TFA no login, vamos abrir o arquivo /etc/pam.d/sshd. Este arquivo vai ter um código já pronto, vamos fazer as seguintes alterações:

  1. Comente a linha que diz @include common-auth, isto significa que o TFA não vai perguntar uma senha além do OTP.
  2. No final do arquivo, adicione a seguinte linha: auth required pam_google_authenticator.so
  3. Salve e feche o arquivo

Agora volte no arquivo de configuração do SSH em /etc/ssh/sshd_config, vamos deixar o SSH a par do novo método de autenticação.

Procure a linha ChallengeResponseAuthentication no e mude-a para ChallengeResponseAuthentication yes. Depois procure a linha UsePAM no e mude para UsePAM yes.

Agora vamos setar os métodos de entrada para o SSH, para isso procure a linha AuthenticationMethods, se ela não existir, adicione-a logo após a linha UsePAM. Nesta linha escreva:

AuthenticationMethods publickey,keyboard-interactive

Vamos reiniciar o serviço do SSH para poder ativar as alterações com o comando a seguir:

sudo systemctl restart sshd

Agora, em um outro terminal, tente fazer login no seu servidor, você deverá ver algo assim:

Agora basta digitar o seu código de autenticação e então você estará logado!

Conclusão

Aplicar TFA nos seus servidores pode parecer uma medida drástica, porém ela ajuda a manter toda a sua infraestrutura mais segura de forma que você poderá ter certeza de que seus dados estarão mais seguros do que somente com uma autenticação simples com chaves ou senhas!

]]>
<![CDATA[ Tenha privacidade total com sua própria VPN hospedada na cloud ]]> https://blog.lsantos.dev/criando-uma-vpn/ 5f92ee1a82fe718273266332 Ter, 27 Out 2020 14:51:53 -0300 Quer estejamos trabalhando ou simplesmente navegando na Internet, um dos principais questionamentos que temos é se o nosso tráfego de rede está realmente seguro ou se estamos sendo espionados pelos nossos próprios provedores de Internet.

Com base nisso, decidi utilizar uma VPN paga há alguns anos, a PIA VPN, porém eu acabei cancelando o uso desta VPN por dois fatores simples:

  • Depois de um tempo eles pararam de ter servidores brasileiros por conta de políticas internas do país com relação a retenção de logs, então o servidor mais próximo era o dos EUA, o que adicionava um ping de 120ms para cada requisição
  • A PIA foi recentemente adquirida por uma companhia israelense que tem um histórico que é, digamos... Um pouco duvidoso em relação a espionagem

Obviamente estes motivos foram totalmente pessoais, a PIA é uma ótima VPN porém, para mim, não estava mais funcionando. Então por um tempo fiquei sem nenhuma VPN até ter uma ideia de tentar construir a minha própria, já que não haviam outros servidores que não guardavam logs aqui no Brasil.

Iniciando o processo

Para começar o processo, eu comecei a pesquisar alguns tipos de tutoriais e ideias de de como começar a criar minha própria VPN, juntando alguns deles consegui um processo bastante rápido e bastante conciso para poder criar a minha própria VPN e ter total certeza que não há alguém espionando os logs por trás.

Aqui estão alguns dos artigos que utilizei para poder criar a VPN, alguns deles explicam muito bem as razões por trás de tudo, outros simplesmente são tutoriais passo a passo:

Por que eu deveria construir minha própria VPN

Assim como já falamos no parágrafo anterior, a principal razão para você querer setar a sua VPN própria é justamente a questão de que você está no controle de todos os logs e todas as ações dentro do servidor. Então não há como ter alguém espionando suas ações no meio do caminho.

Além disso, ter uma VPN própria – principalmente para os brasileiros – implica que, se você estiver utilizando uma VPN por pura segurança, você vai conseguir acesso a redes públicas e até mesmo sem senha sem precisar se preocupar com segurança no geral, porque você vai ter um servidor local que adiciona pouquíssimo de latência a sua conexão, ou seja, essencialmente, o túnel criptografado que você irá criar entre seu computador e a sua VPN vai atuar somente como uma camada de criptografia extra.

Menos importante do que isso também, é a capacidade que você terá de permitir que outras pessoas tenham acesso a sua rede através do mesmo túnel, então você poderá compartilhar arquivos locais ou até mesmo jogar jogos desenhados para a LAN através da Internet.

Problemas de criar sua própria VPN

O maior uso de VPNs atualmente infelizmente não é para se proteger de olhos alheios, mas sim para poder trocar a sua localização geográfica de forma que você aparentará estar em outros países, quebrando assim algumas travas de Geo-IP que alguns sites possuem, que impedem você de consumir algum conteúdo que será destinado a um país específico, por exemplo.

Enquanto é possível criar um servidor utilizando provedores de cloud como a Azure, que providenciam várias máquinas virtuais em diversos locais do mundo, ainda sim o custo que você terá para criar um servidor de VPN em cada região é extremamente alto comparado ao custo de você contratar um serviço de VPN pronto, como a NordVPN ou a TunnelBear. Embora seja completamente possível se você estiver disposto a gastar algumas centenas de reais por mês.

Você também pode criar diversos servidores e deixar os mesmos desalocados (parados), o que consome muito menos recursos e gasta muito menos, ligando o servidor somente quando for utilizar ou agendando um auto desligamento.

Criando sua própria VPN

Com isso tudo dito, vamos partir para a criação da nossa própria VPN, o primeiro passo é criar um servidor onde possamos acessar a VPN a partir da Internet, existem várias maneiras de se fazer isso, uma delas (que vou postar aqui assim que terminar) é utilizar um RaspberryPI como servidor e o serviço do No-IP para poder expor o mesmo para a Internet.

Como vamos criar o nosso próprio servidor e não vamos armazenar logs, não há problema em criarmos em serviços de cloud como a Azure, então vamos começar criando um servidor por lá.

Você pode utilizar outros serviços cloud também, como a DigitalOcean, Linode ou qualquer outro que você se sinta mais a vontade utilizando.

Criando o servidor

Para criarmos o nosso servidor, você primeiro precisa ter uma conta na Azure, se é a sua primeira vez então você vai ganhar alguns créditos que vão te ajudar a não precisar pagar pelo servidor, pelo menos nos primeiros meses.

Ao entrar no portal da Azure, pesquise no topo por "Virtual Machines", clique no ícone e você deverá cair em uma lista de máquinas virtuais, que provavelmente estará vazia, clique no botão "Add" logo abaixo do título:

Adicionando uma máquina virtual

Selecione "Virtual Machine":

Clique em "Add" e então em "Virtual Machine"

Quando você selecionar a opção, vamos ter um formulário para ser preenchido, é importante que você preste atenção no que vamos colocar por aqui. Primeiro, vamos ter uma ideia de como este formulário se divide.

A primeira seção são dados gerais do projeto:

Agora atente-se ao que vamos colocar em cada campo:

  • Subscription: isto vai vir preenchido automaticamente se você só tiver uma conta da Azure, se não, é a conta que você deseja ser cobrado.
  • Resource Group: É uma boa prática criar um novo resource group para armazenar os dados da VPN, você pode clicar no link "Create New" logo abaixo para poder criar o novo RG.
  • Virtual Machine Name: É o nome da sua máquina, aqui você pode ser uma pessoa criativa e escrever o que achar mais conveniente, só é preciso lembrar dele depois.
  • Region: Aqui é a parte mais importante, onde você vai criar o seu servidor, lembrando que você precisa levar em consideração as leis locais de cada país, então se você quer acessar conteúdo disponível nos EUA, crie um servidor nos EUA, se você quer baixar algum torrent, evite países presentes na lista dos 14 eyes, vamos de Brasil mesmo.
  • Availability Options: Neste campo definimos a redundância de rede, não vamos precisar disso então vamos manter como está.
  • Image: Vamos usar o Ubuntu por comodidade em instalar os scripts e a VPN, mas se você tiver habilidade com Linux, pode usar qualquer distro que quiser.
  • Azure Spot Instance: Há uma categoria de VMs na Azure que utilizam a capacidade não utilizada da cloud a um preço bem menor, as chamadas Spot Instances, porém o problema é que elas não tem garantia de disponibilidade, e seu servidor pode ser desalocado se a capacidade for necessária, queremos que o servidor seja o mais disponível possível, certo? Então vamos deixar isso aqui como "No".
  • Size: Essa é a parte onde teremos que decidir o tamanho da nossa máquina, a Azure te dá vários tipos e tamanhos diferentes de máquinas, a mais comum é a DS2_V3, porém ela é um canhão para o que queremos fazer, vamos selecionar então a máquina B1s que possui somente 1 núcleo e 1 Gb de RAM.
Escolha o tamanho apropriado de máquina

Na próxima seção, vamos ter as configurações de autenticação.

Aqui temos um disclaimer importante. Vou utilizar o "password" para que todos saibam o que fazer quando para trocar para um acesso via chave SSH, uma vez que a senha é trafegada em texto puro, portanto pode ser um meio de ataque para hackers.

O que vamos fazer é setar uma senha inicial para fazer o login, porém a primeira alteração no servidor será alterar o SSH para que possamos acessar em portas diferentes e também através de uma chave SSH ao invés da senha.

Se você já é familiarizado com os métodos de login do SSH e já sabe como fazer a alteração, então você pode marcar "SSH Public Key" para evitar um retrabalho.

Por fim temos as configurações de portas. Vamos deixar somente uma das portas habilitadas, a 22 que é a porta padrão do SSH:

Ao clicar em "Next" vamos para a seção de discos, não vamos incluir nenhum disco novo, vamos apenas trocar o disco que vem por padrão de "Premium SSD" para "Standard HDD", pois não precisamos de velocidade e o HD é muito mais barato:

Vamos dar um "Next" e passar batido pela seção de rede, pois não vamos mudar nada, na seção "Management", vamos desativar todas as opções:

Desativamos todas as opções na seção de gerenciamento

Então clicamos no botão azul do lado esquerdo inferior "Review + Create". Após uma rápida revisão de configurações, seu servidor será criado, o processo em si demora alguns minutos, mas assim que estiver finalizado você poderá navegar para a tela do recurso, e verá algo parecido com isto:

Painel de controle da VM

Protegendo o servidor

Como comentamos anteriormente, acessar um servidor de segurança utilizando senha é uma hipocrisia, então vamos gerar as nossas chaves SSH para podermos acessar o servidor de forma segura.

Se você estiver usando o Windows, abra o PowerShell e instale o OpenSSH com o seguinte comando:

PS C:\> Add-WindowsCapability -Online -Name OpenSSH.Client*

Se você estiver em Mac ou Linux, basta abrir o terminal que o OpenSSH deverá estar instalado por padrão. Se não estiver, busque como instalar o OpenSSH para a sua distro antes de continuar.

Vamos usar o seguinte comando para gerar uma chave:

ssh-keygen -t rsa -b 4096

Pressione ENTER quando for perguntado aonde você quer salvar a chave para salvar no diretório padrão (que é geralmente ~/.ssh), se não selecione um local aonde você terá acesso para deixar as suas chaves (você pode ter problemas no futuro se não colocar no diretório padrão).

Você será questionado por uma senha na sua chave, ela é completamente opcional, mas adiciona um nível extra de segurança, se quiser adicionar, pode ficar a vontade.

Vamos logar no servidor para poder realizar as alterações, para isso é só utilizar o comando:

ssh usuario@ip

Lembrando que o usuário é o mesmo usuário que você colocou quando criou o servidor, e o IP é o endereço de IP público que aparece como um link no seu painel da VM na Azure.

Uma vez dentro do servidor vamos atualizar o sistema operacional e todo o sistema com os clássicos:

sudo apt-get update && sudo apt-get upgrade

Depois vamos instalar um editor de texto para que possamos editar os arquivos que vamos precisar, aqui a escolha é pessoal, eu gosto de utilizar o Vim, mas você pode instalar o que for melhor para você.

sudo apt-get install -y vim

Vamos criar um novo usuário não root para podermos utilizar como login:

sudo useradd -G sudo -m nomedousuario -s /bin/bash

Depois vamos criar uma senha para este usuário:

passwd nomedousuario

Agora, não desconecte do SSH do seu servidor e abra um novo terminal local, vamos transferir a nossa chave pública para dentro do servidor para que ele possa realizar o login.

Para isso, no Linux ou Mac vamos executar o seguinte comando:

ssh-copy-id usuario@ip

No Windows você precisará utilizar outro comando

type $env:USERPROFILE\.ssh\id_rsa.pub | ssh seuip "cat >> .ssh/authorized_keys"

Mantenha os dois terminais abertos, vamos agora restringir o acesso a quem está usando senha, e também vamos atualizar a porta do SSH para que ele não fique exposto na porta 22, que é padrão.

A primeira coisa que vamos fazer é abrir o arquivo /etc/ssh/sshd_config dentro do servidor da VPN. Vamos então procurar a linha Port 22 e vamos alterá-la, aqui estou usando a porta 78, mas você pode utilizar qualquer porta que queira e não esteja utilizada por outro serviço:

# Port 22
Port 78

No painel da Azure, vamos entrar nas configurações de rede para abrir a nova porta. Para isso, no painel da VM, vá na barra lateral e clique em "Networking":

Você verá uma lista com todas as portas que estão abertas e todas as regras de rede para o seu IP ordenadas por prioridade. Clique no botão azul "Add inbound port rule":

Preencha as informações alterando o "Destination port ranges" para o número da porta que você escolheu, defina a "priority" como 100 e dê um nome identificável para esta regra de rede. Salve.

Já vamos aproveitar também e abrir a próxima porta que vamos utilizar, que vai ser a porta 443 UDP, que é utilizada pelo OpenVPN para poder realizar a conexão e o tráfego de dados. Clique novamente no botão para adicionar outra regra:

Desta vez, vamos setar o "Destination port ranges" para 443 e selecionar o "protocol" como UDP, deixamos a prioridade do jeito que está e damos um nome identificável. Agora temos o acesso liberado para as duas portas principais, não feche esta aba ainda, nós vamos ter que voltar aqui em instantes.

Voltando ao servidor, vamos continuar alterando o nosso arquivo de configurações. Agora vamos procurar por PasswordAuthentication e vamos desativar o login através de senha:

PasswordAuthentication no

Vamos também desabilitar o login como root:

PermitRootLogin no

Vamos salvar o arquivo e reiniciar o serviço utilizando:

sudo systemctl restart sshd

Não feche o terminal que está logado no servidor ainda, pois se tivermos problemas, não queremos ficar trancados para fora não é mesmo? Abra um novo terminal e vamos tentar logar na máquina com o novo usuário através da nova porta:

ssh -i ~/.ssh/id_rsa novousuario@ip -p porta

Se você conseguir logar sem digitar nenhuma senha, ou então um prompt para digitar a senha da sua chave, então está tudo certo. Você pode tentar fazer um teste para saber se podemos também logar sem uma chave:

ssh novousuario@ip -p porta

Isto deve te dar um "Permission Denied"

Agora sim podemos fechar o terminal anterior que tínhamos logado como root, vamos voltar ao portal da Azure e remover a regra padrão de acesso à porta 22 que foi criada. Para isso, é só clicar nos três pontos no final da linha correspondente e selecionar o botão "Delete".

(Opcional) Criando um alias

O SSH permite que você crie um alias para se conectar mais facilmente ao servidor sem precisar digitar o IP, usuário, chave e porta todas a vezes. Para isso, na sua máquina local, encontre o arquivo config, que está na pasta .ssh no seu diretório $HOME (ou ~/.ssh), abra com o seu editor preferido e crie um registro novo:

Host minhavpn # pode ser qualquer nome
    User novousuario # usuario de login
    Port porta # a porta que você escolheu
    IdentityFile ~/.ssh/id_rsa # Se você salvou a chave em outro local, escolha coloque este local aqui
    HostName ip # endereço de IP do servidor

Agora você pode logar no servidor com o comando ssh minhavpn

Isso é totalmente opcional, você não precisa executar este passo se não quiser.

Criando a VPN

A criação da VPN é um processo bastante complexo, que exige que você instale todos os pacotes do OpenVPN, crie IPTables, configure o firewall, crie as chaves de acesso e os certificados que serão utilizados para acessar o endereço e tudo mais.

Todo o processo é muito complexo e é fácil de errar em algo e ter que começar tudo de novo. Então, graças ao open-source, temos um usuário no GitHub chamado Nyr que criou um script chamado OpenVPN Road Warrior Installation, que será o que vamos utilizar para instalar, ele vai te fazer algumas perguntas simples e, na maioria das vezes, você vai selecionar a resposta padrão.

Vamos instalar o wget primeiro no nosso servidor com:

sudo apt-get install -y wget

Agora vamos baixar o script no nosso caminho atual (que provavelmente será ~):

wget https://git.io/vpn -O openvpn-controller.sh

Vamos dar permissão de execução com chmod +x openvpn-controller.sh e então vamos executar o script com ./openvpn-controller.

Alguns pontos importantes durante a instalação:

  • Porta do servidor: A porta padrão do OpenVPN é a 1194 UDP, porém como é uma porta padrão, vamos escolher outra, no nosso caso é a 443 UDP que abrimos na Azure
  • Servidor de DNS: O servidor de DNS pode ser qualquer um de sua preferência, eu geralmente utilizo 1.1.1.1 ou 8.8.8.8
  • Nome do cliente: Este será o nome do arquivo que você vai gerar com a configuração, eu geralmente separo as configurações por dispositivo, então se você vai usar em um computador Windows, ele pode se chamar VPN_WIN

No final do processo de instalação, você vai obter um arquivo .ovpn de configuração. Este arquivo é o arquivo mais importante de todos porque ele possui as credenciais de acesso para que você possa entrar na sua VPN, bem como os certificados e chaves do cliente.

Removendo Logs

Por fim, vamos fazer o que a maioria dos serviços de VPN não fazem, que é desativar os logs.

Para isso vamos acessar o arquivo de configuração do OpenVPN com:

sudo vim /etc/openvpn/server/server.conf

Lembrando que o vim pode ser qualquer editor. Mude a linha que tem escrito verb 3 para verb 0, salve o arquivo e reinicie o serviço com:

sudo systemctl restart openvpn-server@server.service
É possível que o nome do serviço seja um pouco diferente dependendo da máquina que você instalou o OpenVPN e a sua versão, então talvez você precise encontrar o nome do serviço para reiniciá-lo

Agora não temos nenhum log sendo mantido pela nossa VPN!

Baixando as credenciais

Por padrão o script posiciona o arquivo no diretório do root (porque ele precisa ser executado como administrador), então vamos mover o arquivo para o nosso diretório e mudar o dono para que possamos alterá-lo:

sudo mv /root/nomedoarquivo.ovpn ~
sudo chown novousuario nomedoarquivo.ovpn

Vamos agora baixar o arquivo. Para isso, vá em um terminal local e abra uma conexão sftp com o seu servidor de VPN através do comando sftp minhavpn (ou qualquer que seja o nome que você colocou no seu alias), depois execute os seguintes comandos:

get nomedoarquivo.ovpn pasta/de/destino
exit

Lembrando que você pode acessar por outros meios também, o sftp é só um deles, mas você pode usar o scp ou até mesmo clientes de SFTP como o FileZilla.

Agora o seu arquivo está localizado na sua máquina local e a VPN está instalada, chegou a hora de testar!

Testando a VPN

Para testar a VPN, se você estiver em um Mac e quiser que todo o seu tráfego passe pela sua VPN, que é o que eu faço por aqui, você vai precisar de um software gratuito chamado TunnelBlick.

Painel do TunnelBlick

Basta baixar o software e clicar duas vezes sobre o arquivo .ovpn que você baixou e ele será importado para o sistema. A partir daí você poderá usar a VPN como qualquer outra.

Se você estiver no Windows ou em qualquer outro dispositivo (até mesmo no iOS, Android e afins) você vai precisar do OpenVPN Connect, e a partir daí a configuração é a mesma, basta um duplo clique no arquivo para importar, se isto não funcionar, ambos os programas possuem um botão de importação.

Gerenciando a VPN

A partir da primeira instalação você já vai ter o script de conexão completo, porém, algo que notei é que utilizar o mesmo script para todos os seus dispositivos acaba sendo ruim porque a VPN parece não lidar muito bem com o tráfego vindo do mesmo cliente, então a solução é criar um cliente novo para cada dispositivo que você usa.

Para isso você pode acessar o servidor da VPN novamente e executar o mesmo comando que usou para instalar a VPN, ou seja, utilizamos o mesmo script de instalação porque ele é inteligente o suficiente para saber quando ele já foi instalado e quando você está querendo apenas gerenciar.

Basta o comando sudo ./openvpn-controller.sh (ou qualquer nome que você tenha dado ao arquivo) e ele vai mostrar uma lista de comandos possíveis:

Nele você pode adicionar novos clientes para poder dar a outras pessoas a capacidade de conexão à sua VPN ou então para adicionar novos dispositivos a ela. Assim como você também pode revogar um cliente existente e remover a VPN completamente.

Conclusão

O artigo ficou um pouco longo, porém ele contém tudo que é necessário para você criar a sua própria VPN! Nos próximos artigos vou mostrar como você pode aumentar ainda mais a segurança do seu servidor com Two-Factor Authentication e também adicionar upgrades automáticos para manter o sistema sempre atualizado.

Fiquem ligados para os próximos capítulos!

]]>
<![CDATA[ Que tal aprender AKS com este curso GRATUITO? ]]> https://blog.lsantos.dev/que-tal-aprender-aks-com-este-curso-gratuito/ 5f92e81282fe7182732662f9 Sex, 23 Out 2020 11:34:51 -0300 Na semana passada divulguei em meu Twitter que tinha acabado de lançar um curso gratuito de Kubernetes com AKS como vocês podem ver no tweet aqui a seguir

Não poderia estar mais feliz de divulgar este curso porque, além de ele ser gratuito, ele também é super completo. A grade que criei para o desenvolvimento dele cobre desde Docker até o seu primeiro deploy com Kubernetes passando por quase todos os workloads mais importantes!

Além disso, estou super feliz de que ele tenha sido publicado em um canal tão sensacional como o Channel9! O canal de cursos e vídeos da própria Microsoft!

Maratona AKS: Tudo sobre Kubernetes de A a Z | Channel 9
Neste bootcamp, aprenderemos os conceitos básicos de contêineres, Docker, Kubernetes, Helm e outras ferramentas para permitir que você assuma o controle de seus aplicativos criando, gerenciando e mant

Se você quiser ir lá aprender mais sobre Kubernetes, aproveita e já assiste este curso e me dê os feedbacks através dos comentários deste artigo ou então nas minhas redes sociais (você pode encontrar todas elas no topo do blog ou então no meu site) eu vou ficar super feliz em saber o que está certo e o que posso mudar para continuar produzindo um conteúdo de cada vez mais qualidade para todos!

Muito obrigado pessoal!

]]>
<![CDATA[ Tornando o VSCode o seu único ambiente de desenvolvimento com Docker e Kubernetes ]]> https://blog.lsantos.dev/tornando-o-vscode-o-seu-unico-ambiente-de-desenvolvimento-com-docker-e-kubernetes/ 5f7a64d982fe718273266212 Dom, 04 Out 2020 21:34:43 -0300 No dia 3 de outubro participei da BrazilJS.live() um evento completamente online organizado pela já conhecida equipe da BrazilJS!

Neste dia decidi ser um pouco mais ousado e trazer para vocês uma palestra completamente Hands On sobre como podemos transformar o nosso editor do coração, o VSCode no único ambiente de desenvolvimento quando estamos tratando de Azure, Docker e Kubernetes.

Nesta palestra de mais ou menos 30 minutos, abro meu VSCode e mostro as incríveis extensões do Docker e do Kubernetes que permitem que você faça a gestão completa de qualquer cluster Kubernetes diretamente de dentro do editor, além disso, temos também a capacidade de fazer qualquer modificação e manipular o Docker em si diretamente de dentro do Code!

Dá uma olhada como foi:

Você pode encontrar as duas extensões nestes links:

]]>
<![CDATA[ Será este o fim da carreira em desenvolvimento de software? ]]> https://blog.lsantos.dev/sera-este-o-fim-das-pessoas-desenvolvedoras-chegamos-ao-limite-do-desenvolvimento-de-software/ 5f76112582fe718273266156 Sex, 02 Out 2020 18:47:10 -0300 Recentemente li um post bastante interessante no Medium que dizia que a "Era de Ouro da programação" estava chegando ao fim. Que, assim como todas as coisas, quem hoje sabe escrever código e entende das minúcias do mundo digital, amanhã será somente outra pessoa qualquer. Assim como aconteceu no passado com a leitura e a escrita.

Primeiramente, o que seria a Era de Ouro da programação?

A era de ouro

Se você dissesse para qualquer pessoa em meados de 1600 que daqui há algumas centenas de anos teríamos redes sociais onde todas as pessoas do mundo iriam postar conteúdo escrito, você provavelmente seria taxado de herege ou então de maluco.

Isto porque, como todas as habilidades do mundo, qualquer tipo de nova ciência começa como um conhecimento especializado, vindo de uma necessidade de poucas pessoas e pesquisada por poucas pessoas. Depois, este conhecimento trazido de especialistas é aprofundado e abstraído por outros especialistas para que conceitos novos, mais simples, utilizem esta base sem que as pessoas que os usem sequer saibam das suas origens.

Um exemplo clássico. Você, programador ou programadora, já escreveu ou sequer leu uma linha de código em Assembly? Fortran? As poucas pessoas que já fizeram isso são pessoas que são muito entusiastas do mundo digital ou então tiveram um contato, mesmo que passageiro, com estas tecnologias. Isto porque, hoje, a desenvolvedora comum não precisa saber que MOV ax, cs é uma instrução essencial de um processador moderno.

E esta é considerada a Era de Ouro da programação. A era que estamos vivendo agora. Onde saber codar, entender de código, de "computadores", do digital é algo que está além da capacidade da maioria das pessoas do mundo. Isto porque, para aprender essas capacidades, você precisaria se desviar do caminho "comum" de uma escola padrão. Tanto é que cursos de informática são considerados extracurriculares.

Como Tim O'Reilly - fundador da O'Reilly media, que toda pessoa dev já deve ter visto - citou neste mesmo artigo:

"Eu acho que a era de ouro das últimas duas décadas onde você pode se tornar um programador e você vai ter um emprego está meio que no fim... Programar hoje é mais como saber ler e escrever. Você simplesmente precisa saber isso."

Mas, será que, com o aumento da demanda por devs, saber programar deixará de ser um diferencial e se tornará um requisito? Não só para quem é dev, mas para todas as pessoas do mundo?

E será que, com isso, a quantidade de pessoas que saberiam programar no futuro seria tão alta que a demanda não acompanharia? Então estaríamos ao mesmo tempo ajudando a área de desenvolvimento quanto matando o que nos torna valiosos? Seria esse o fim da carreira em tecnologia como conhecemos?

A viralidade da ciência

Esta não é a primeira vez que vemos uma nova especialidade surgindo com este boom, antigamente as pessoas pensavam exatamente a mesma coisa sobre cientistas. Havia até uma promessa de que a ciência seria um conhecimento de todos o que, claramente, não aconteceu. Hoje vemos pessoas utilizando infinitas tecnologias baseadas em ciências naturais sem entender como elas funcionam.

O mesmo vale para a "arte da programação", muitas pessoas estão usando computadores e não sabem absolutamente nada do funcionamento dos mesmos. E isso é completamente normal... Hoje eu e você utilizamos o Waze, que é um GPS e nenhum de nós sabe a fundo sobre relatividade geral - provavelmente nem os criadores do Waze sabem sobre isso.

O que estou tentando dizer é que, para que possamos tornar a programação plausível para todos, a fim de que as pessoas comecem a entender as máquinas que as cercam, precisamos parar de afastar as pessoas que querem aprender. A área de desenvolvimento, assim como literalmente qualquer outra área, é super tóxica se pegarmos alguns pontos de vista.

Mas não podemos deixar a toxicidade de algumas pessoas afetarem a experiência de todas as demais pessoas que querem entrar na área e serem programadoras. Algo que me surpreendeu bastante está sendo o avanço de empresas como a Microsoft em plataformas no-code.

Como falamos no primeiro parágrafo, as pessoas que são mais versadas e especialistas na área de software conseguem abstrair conceitos mais complexos para conceitos mais simples a fim de formar uma fundação para outras pessoas poderem codar também. No discurso do Satya Nadella no Microsoft Ignite, a empresa apresentou uma proposta muito interessante para o futuro da Power Platform .

Para quem nunca ouviu falar, a Power Platform é uma solução no-code, ou seja, não é necessário saber programar, para criar automação em tarefas genéricas. Dentre elas temos várias ferramentas como o Power BI, que permite a melhor visualização de dados para quem está trabalhando com BI.

A ideia de que, no futuro, a disseminação da programação venha não por uma forma mais "pura" de código, mas sim através de plataformas desenvolvidas por empresas parece interessante, uma vez que mantemos a necessidade de haverem pessoas especializadas, e ainda sim buscamos reduzir o abismo que existe entre saber as pessoas que sabem e as que não sabem programar.

A Gangorra da Especialidade

Para quem está pensando que seu emprego pode acabar nos próximos cinco anos, há muito tempo, em 2016, escrevi o que viria a ser o meu primeiro artigo publicado. Neste artigo eu abordo justamente este tema. E, veja que, apesar de ter quatro anos de idade, estou ainda citando o artigo por aqui, porque ele ainda está atual!

Em determinado momento deste artigo eu comento sobre a diferenciação de devs generalistas e especialistas. Enquanto a oferta de empregos vai sim ficar menor para pessoas que estiverem no nível mais iniciante, outras ofertas para desenvolvedores mais avançados ainda continuarão existindo.

Isto acontece por causa do efeito gangorra. Este é um efeito bastante observado em todos os tipos de mercado de trabalho. Quando temos uma determinada tecnologia nova, não temos muitas pessoas que se destacam nela, portanto o mercado pende para a área de especialistas. Mas, no momento que esta tecnologia se tornar mais comum, e estas pessoas serão substituídas pelas generalistas, mais baratas, porém mais rasas no assunto. E aí a gangorra pende para o outro lado em um movimento perpétuo.

A área de tecnologia não irá acabar, muito menos a carreira de desenvolvimento. O que irá mudar muito é a quantidade de habilidade necessária para se manter no mercado de trabalho. Hoje, podemos estar falando de aplicações distribuídas como se fosse ciência avançada, daqui a dez anos isso pode ser tão comum quando um formulário.

O mercado futuro não ficará defasado de pessoas desenvolvedoras, mas sim de pessoas desenvolvedoras com a habilidade necessária. Hoje temos infinitos cursos iniciais sobre vários assuntos, porém estes cursos não passam muito do básico e muitas pessoas não tem a noção de que precisam estar estudando constantemente para se manter no mercado, portanto, estas pessoas formarão a base da carreira no futuro, onde hoje já há e no futuro haverá ainda mais concorrência para pouca demanda.

Precisamos investir em um conhecimento contínuo, que perpetua o conhecimento desde o básico até o avançado, ou pelo menos o intermediário, de forma que todos nós possamos estar presentes no mercado de trabalho no futuro, pois ele vai ser mais exigente. Lembre-se, a ciência de hoje é comum amanhã.

O futuro do mercado de tecnologia

A minha opinião sincera é de que, além da tecnologia, o futuro reserva uma oportunidade especial para quem se destacar em uma área que existe há mais ou menos 10 mil anos. As relações interpessoais.

Atualmente estamos tão focados na parte técnica do nosso trabalho que não temos tempo para focar nas pessoas e no que elas representam para a gente. Como eu sempre falo em todas as palestras que eu já fiz sobre o assunto:

Nós fazemos código, criado por pessoas, para pessoas. Não estamos codando para máquinas, mas sim para outras pessoas

Algo que muita gente hoje parece esquecer. No futuro isso será importantíssimo, pois além dos conhecimentos técnicos é muito importante que saibamos lidar uns com os outros.

Além disso, a técnica tende a ser abstraída para algo mais simples. Hoje temos intellisense, temos IDEs, temos várias ferramentas que pessoas há 30 anos não tinham. Atualmente é muito mais fácil desenvolver um software de qualidade e muito mais complexo do que era há 30 anos.

Então, assim como este artigo que li há um tempo também fala. Se escolhermos chamar de "Era dourada" a era que tiver a menor fricção possível para aprender algo novo e mostrar para o mundo, então estamos na maior era de ouro possível.

Nunca foi tão fácil criar um software quanto é hoje. Mas temos que tomar cuidado, pois o futuro não está tendendo para quem não pretende acompanhar as tendências, pelo que temos visto hoje, o futuro é daquelas pessoas que estarão constantemente evoluindo e buscando entender não só sobre suas próprias áreas, mas também sobre as áreas que as cercam.

Conclusão

Espero que tenham gostado deste artigo, ele foi uma tentativa mais pessoal de mostrar minha visão do mercado de tecnologia para o futuro embasando em outras visões que já havia visto no passado.

Eu acredito que ainda temos muito a mostrar e que a área de técnologia está só começando sua jornada!

]]>
<![CDATA[ Microsoft Reactor: Workshop de AKS com Virtual Nodes e AKS Com GitHub Actions ]]> https://blog.lsantos.dev/microsoft-reactor-workshop-de-aks-com-virtual-nodes-e-aks-com-github-actions/ 5f76080d82fe718273266112 Qui, 01 Out 2020 14:17:34 -0300 No dia 29 participei de uma live sensacional do Microsoft Reactor com o grande Caio Calado como host!

Nesta live fizemos um workshop prático de como podemos criar um cluster no Azure Kubernetes Service e utilizar o poder dos Virtual Nodes para ter escalabilidade infinita, essa é a nossa primeira demonstração.

Depois, partimos para uma criação prática de um repositório no GitHub para utilizar o GitHub Actions de forma a podermos criar e fazer os deploys de aplicações completas para o AKS sem precisar sequer tocar nelas

Tudo isso você encontra de forma gratuita no vídeo abaixo!

Não esqueça de curtir e compartilhar para que outras pessoas também possam ter acesso a este conteúdo! Se inscreva na newsletter aqui embaixo e deixe suas impressões nos comentários. Todos os feedbacks são bem vindos 🤓

]]>
<![CDATA[ Deploy de imagens Docker: Do VSCode para a Azure ]]> https://blog.lsantos.dev/deploy-de-imagens-docker-do-vscode-para-a-azure/ 5f6e825b82fe7182732660bc Sex, 25 Set 2020 20:54:57 -0300 Comentamos neste post que o Docker estaria ganhando uma integração nativa com a Azure! Com essa integração o deploy de uma imagem docker direto para o Azure Container Instances (ACI) seria tão fácil quando um único  comando no Docker CLI.

A integração já estava presente no Docker Edge, que é a versão beta do Docker. Agora temos a excelente notícia de que esta integração chegou para todos os usuários do Docker! E, junto com ela, agora temos a mesma integração direto no VSCode!

E como podemos ter acesso a essa facilidade?

Habilitando a integração com VSCode

Primeiramente, precisamos ter o Docker instalado na máquina. Se você ainda não possui então vá até o site oficial e baixe a versão stable para o seu sistema operacional.

Assim que você baixar e instalar o Docker, faça login na Azure utilizando o seguinte comando:

docker login azure

E depois crie um novo contexto usando o comando docker context create aci <nome>, o nome do contexto fica por sua conta!

Agora, vá até o marketplace do VSCode, baixe e instale a extensão oficial do Docker para o Code. Ela deve aparecer no seu canto esquerdo da tela, conforme a imagem a seguir.

Baixe e instale a extensão do Docker

Perceba que, no final da barra lateral, teremos um menu chamado Contexts. Abra-o e clique com o botão direito sobre o contexto que você acabou de criar. Selecione Use:

Selecione o contexto que vamos operar
Use o contexto criado

Com o contexto selecionado, já temos tudo o que precisamos para fazer nosso deploy.

Fazendo um deploy para o ACI

Com a extensão, podemos fazer login em nosso DockerHub ou Azure Container Registry:

Clique no botão de conexão para fazer o login
Clique no botão de conexão para logar em um registro

A partir daí podemos selecionar o tipo de registro que estamos usando

Selecione o serviço
Selecione o tipo de CR que quer logar

E então teremos a listagem das nossas imagens hospedadas nestes serviços:

Veja as imagens
Veja as imagens listadas

Agora podemos abrir e selecionar uma das imagens, clicar com o botão direito, e selecionar "Deploy Image to Azure Container Instances":

Selecione a imagem e faça o deploy

Veja o processo como um todo:

A partir daí você terá prompts para fazer o input do nome do seu ACI ou se quer usar um já existente, e também poderá trazer os logs, abrir portas e muito mais!

Conclusão

A integração nativa do Docker com o ACI é uma das ferramentas mais interessantes que temos quando estamos nos referindo à cloud. Essa capacidade de integração direta faz com que fique muito mais fácil realizar nossos deploys e também gerenciar nossos containers.

Se você quiser saber mais, veja a documentação oficial sobre a integração e também leia a documentação no site do Docker.

Até mais!

]]>
<![CDATA[ Conheça o GitHub Container Registry ]]> https://blog.lsantos.dev/conheca-o-github-container-registry/ 5f65116782fe718273265f94 Sex, 18 Set 2020 19:59:27 -0300 Há algum tempo atrás, o GitHub anunciou que estavam criando os GitHub Packages. Esta era mais uma ferramenta desta incrível rede para que a vida dos desenvolvedores e desenvolvedoras ficasse ainda mais fácil.

Você pode acessar os packages através do seu próprio perfil, e lá você vai ver uma série de opções, desde pacotes do NPM até, mais recentemente, imagens do Docker!.

Acesse seu perfil para poder ver seus pacotes

Isso mesmo! Agora, além do Docker Hub, você também pode armazenar suas imagens diretamente no GitHub, mas o que isso muda?

GitHub Container Registry

O GH Container Registry é uma forma de você conseguir unir o seu código com a imagem que ele representa, ou seja, deixar a infraestrutura e o código em si no mesmo ambiente.

Isso facilita muito quando você precisa direcionar algum usuário para uma página de downloads, ou então informar que você pode também baixar a imagem de um determinado container diretamente do seu próprio perfil!

Inicialmente, essa ferramenta estava em um beta fechado, porém, no dia 1 de setembro, a equipe liberou um beta aberto para todos os usuários testarem o novo modelo de pacotes.

Quanto custa

Comparando com o Docker Hub, que não cobra para repositórios públicos, mas sim para repositórios privados, o GH Container Registry é a mesma coisa. Quando essa funcionalidade for para a sua versão pública - a famosa GA (General Availability) - o custo para imagens públicas será zero, enquanto imagens privadas terão um custo a parte.

Por enquanto, no entanto, durante todo o beta, tanto os pacotes públicos quanto privados serão gratuitos. Então aproveita para fazer aquele teste e colocar suas imagens lá!

Mas, espera um pouco... Como a gente faz isso?

Criando uma imagem

Para criarmos e armazenarmos uma imagem no registro do GitHub é super simples. Podemos fazer de duas maneiras.

Através do Docker

Podemos logar no GitHub com nosso Docker local e enviar a imagem para o registro, da mesma forma que logamos em outros registros privados, como o ACR.

Para isso vamos seguir os seguintes comandos:

  1. Execute o login em seu terminal de preferência:
docker login docker.pkg.github.com -u <usuario do github>

2. O prompt vai pedir sua senha, é gerar um novo access token nesta página

É importante que o token tenha as permissões de escrita e leitura de packages

Tenha certeza que as permissões estão corretas

3. Utilize este token gerado como senha para logar

4. Faça um push de qualquer imagem utilizando docker push docker.pkg.github.com/username/repositório/nome-da-imagem:tag

Através de GitHub Actions

Já falamos em outro artigo sobre como podemos automatizar uma série de coisas utilizando GH Actions (e mais artigos vão vir por ai 😎), então como podemos utilizar as actions para enviar nossas imagens para o CR do GitHub?

Para este exemplo eu vou usar um repositório que mantenho, chamado Zaqar. Isto porque este projeto já é em sua natureza um microsserviço e precisa do Docker para funcionar, então podemos utiliza-lo de forma mais real.

Primeiramente vou criar um novo access token para que eu possa usar como minha senha na nossa action

Dentro do nosso repositório, vamos na aba settings e depois na guia secrets. Lá, vamos criar um novo secret chamado PACKAGES_PASSWORD e vamos colocar o conteúdo do nosso access token dentro dele:

Depois, vamos na aba actions dentro do repositório:

Clicaremos em new workflow (no meu caso, porque eu já tinha um workflow existente), quando formos direcionados para a tela onde seremos apresentados com os mais diversos workflows, vamos clicar no link abaixo do título que diz "Set up a workflow yourself".

Não vamos trabalhar com templates

Lá vamos ter um pequeno documento padrão com algumas linhas, vamos fazer uma alteração para que tenhamos a nossa action sendo executada somente em pushes para a branch master e também em tags que comecem com v, assim podemos ter v1.0.0 e assim por diante.

Veja como nosso arquivo base vai ficar

# This is a basic workflow to help you get started with Actions

name: Publish to GitHub Container Registry

on:
  push:
    branches: [ master ]
    tags: v*

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

Agora, vamos no menu do lado direito e iremos procurar a action da própria Docker chamada "Build and push Docker images"

Iremos copiar o código clicando no botão de cópia do lado direito:

Copiando o código de uso

E vamos colar logo abaixo da nossa action anterior, dentro de steps, depois vamos apagar algumas das linhas que estão colocadas como parâmetros, porque não vamos utilizar todos eles.

# This is a basic workflow to help you get started with Actions

name: Publish to GitHub Container Registry

on:
  push:
    branches: [ master ]
    tags: v*

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Build and push image
        uses: docker/build-push-action@v1.1.1
        with:
          # Username used to log in to a Docker registry. If not set then no login will occur
          username: khaosdoctor
          # Password or personal access token used to log in to a Docker registry. If not set then no login will occur
          password: ${{ secrets.PACKAGES_PASSWORD }}
          # Server address of Docker registry. If not set then will default to Docker Hub
          registry: docker.pkg.github.com
          # Docker repository to tag the image with
          repository: khaosdoctor/zaqar/zaqar
          # Automatically tags the built image with the git reference as per the readme
          tag_with_ref: true

Vamos passar parte por parte deste arquivo para que possamos entender o que está acontecendo. Primeiramente, estamos dizendo para o workflow na chave name que vamos nomear esse passo do nosso processo com um novo nome além do nome da action, isto é apenas para organização.

Depois, estamos dizendo que vamos utilizar a action da Docker como uma base, estamos passando o nome do repositório e o nome da action, bem como sua versão.

Depois estamos passando pelos parâmetros que queremos setar:

  • username é o nome do nosso usuário do github
  • password é o nosso secret que acabamos de criar, contendo o nosso access token para podermos fazer o login no registry
  • Depois temos a chave registry que é onde vamos definir para que registro vamos mandar o nosso container. Neste caso, como estamos usando o próprio GitHub, vamos fixar esse valor em docker.pkg.github.com
  • Na chave repository vamos colocar o nome da nossa imagem, ela deve ser sempre neste formato que comentamos acima, onde temos nomedeusuario/repositorio/imagem:tag
  • E então temos a última configuração, que é a mais interessante e é a que mais poupa trabalho para quem está desenvolvendo. A chave tag_with_ref faz algumas coisas interessantes, a principal delas é que ela faz o taggeamento automático da imagem para nós, quando estamos enviando um push para a branch master diretamente, nossa imagem vai receber a tag latest quando enviamos para uma tag do git, a tag da imagem vai ser o nome da nossa tag do git. Você pode checar mais sobre as peculiaridades e como cada uma das configurações funciona na página da action

Depois de terminarmos, vamos dar um nome ao nosso arquivo e então salvá-lo. A partir daí uma nova build irá rodar e vamos ter uma nova imagem no nosso repositório:

A nova imagem no nosso repositório, pronta para ser baixada

Você pode checar a página deste pacote individual nesta URL

Conclusão

Juntando o GitHub com os container registries, temos uma capacidade muito maior de poder unir o nosso código e nossa infraestrutura em um único lugar. Essa unificação faz com que nossa complexidade diminua, pois vamos ter que lidar com menos ambientes, portanto podemos pensar em outras funcionalidades que tirem proveito destas facilidades no futuro!

Espero que tenham gostado do artigo, deixe seu comentário, curta e compartilhe! Não se esqueça de se inscrever na newsletter para mais conteúdo exclusivo!

Até mais!

]]>
<![CDATA[ Saiba de tudo sobre seus serviços com Jaeger e Linkerd ]]> https://blog.lsantos.dev/saiba-de-tudo-sobre-seus-servicos-com-jaeger-e-linkerd/ 5f5f889182fe718273265ea9 Seg, 14 Set 2020 14:16:46 -0300 Já falamos um pouco sobre o Linkerd no último post, agora, para podermos estender ainda mais o nosso conhecimento sobre service mesh, vamos falar de um conceito interessante que vamos explorar com mais calma em outros artigos. Mas aqui vamos ter um exemplo prático! O Tracing.

Tracing

Tracing é um dos elementos da tríade que compõe o que vamos tratar mais a frente como Observabilidade, porém, no momento vamos focar nesse aspecto.

O tracing é a capacidade de poder acompanhar uma request de ponta a ponta verificando a ordem das chamadas dos serviços, o payload enviado e recebido por cada um, as respostas de cada serviço e também o tempo que cada request demorou.

Implementar um tracing simples em uma aplicação não é uma tarefa complexa, basta fazermos um log de tudo que recebemos e enviamos. Porém, existe um outro conceito chamado deep tracing ou distributed tracing que é justamente voltado à aplicações distribuídas.

E é ai que as coisas começam a ficar complicadas...

Deep Tracing

Deep Tracing é o nome que se dá à técnica de ligar logs de uma chamada a outra, formando uma linha do tempo do que foi feito. A cada log, damos o nome de um span e uma request pode desencadear múltiplos spans, ainda mais quando estamos tratando com microsserviços que chamam uns aos outros em sequencia.

Sendo muito simplista, o que o Deep Tracing faz é adicionar um header na request inicial que é chamado de Request ID – cada implementação da técnica tem seu próprio nome para isso. A cada nova request, esse ID é passado para frente e, combinada com a data da requisição, essas informações são utilizadas para construir um histórico de tudo que foi feito.

O problema é que, para fazer a implementação manual disso tudo, temos que:

  • Ter uma noção muito boa da nossa aplicação
  • Interceptar todas as chamadas HTTP e colocar um header em cada uma delas

O que não é uma tarefa fácil, por isso existem ferramentas como o Jaeger.

Jaeger

O Jaeger é uma ferramenta open source hospedada pela CNCF que serve justamente para evitar a complicação de ter que faz o deploy e implementação de todas as partes móveis que compõem um sistema de tracing distribuído.

Ele também utiliza o Open Telemetry um projeto que visa simplificar a telemetria de aplicações através de um conjunto padrão de ferramentas para obtenção de métricas.

O Jaeger é escrito em Golang, o que torna ele super rápido e muito útil para sistemas que estão distribuídos ou então possuem uma malha complexa de serviços. Sabe o que mais vai bem com essa arquitetura? O Linkerd!

Linkerd e Jaeger

Service Mesh e Observabilidade são conceitos que andam lado a lado, porém nem sempre você tem a capacidade de implementar ambos de forma simples. E é ai que tanto o Linkerd quanto o Jaeger brilham individualmente, mas, além de serem incríveis por si só, eles são ainda melhores juntos.

Usar o Linkerd com o Jaeger é uma excelente forma de obter todas as informações e métricas possíveis de sua aplicação de forma rápida e prática, até porque o próprio Linkerd suporta add-ons que incluem tanto o Jaeger como o OpenCensus Collector, uma ferramenta de coleta de métricas.

Mas chega de conceitos! A melhor forma de explicar o que é o Jaeger é através da prática! Então vamos colocar a mão na massa!

Aplicando Tracing

Para começar, vou assumir que você já está com o cluster criado e com o Linkerd Instalado, se você ainda não instalou tudo, volta para o artigo anterior e siga o tutorial até o final

Com o nosso cluster configurado e o Linkerd já instalado, vamos começar instalando a configuração all-in-one, que provê uma única imagem que contém todos os elementos necessários para que o tracing do Jaeger funcione tranquilamente.

Para instalar essa configuração, vamos criar um novo arquivo chamado config.yaml e colocar o seguinte conteúdo nele:

tracing:
  enabled: true

Então, vamos executar um comando do Linkerd para adicionar o novo add-on, na pasta aonde você criou o novo arquivo execute o seguinte comando:

linkerd upgrade --addon-config config.yaml | kubectl apply -f -

Assim que terminarmos, devemos ter dois novos deploys, um chamado linkerd-collector e outro chamado linkerd-jaeger no namespace linkerd:

Temos dois novos deployments dentro do namespace Linkerd

Anotações

Para detectar as mudanças e começar a realizar o tracing, o Linkerd utiliza duas anotações novas nos nossos deployments, sempre que precisarmos fazer essa modificação vamos incluir estas linhas juntamente com a anotação linkerd.io/inject: enabled, ficando assim:

spec:
  template:
    metadata:
      annotations:
      	linkerd.io/inject: enabled
        config.linkerd.io/trace-collector: linkerd-collector.linkerd:55678
        config.alpha.linkerd.io/trace-collector-service-account: linkerd-collector

Instrumentação

O tracing, diferentemente da maioria das técnicas do DevOps, exige uma instrumentação na aplicação, ou seja, temos que manualmente inserir o código do coletor de métricas no nosso sistema para que ele possa identificar e adicionar os headers e o ID para o trace.

Isso pode ser feito de forma manual na nossa aplicação usando Node através deste pacote, porém, para mantermos o processo mais simples, vamos utilizar a aplicação padrão do Linkerd para testar.

Primeiramente instalamos a aplicação com o comando

kubectl apply -f https://run.linkerd.io/emojivoto.yml

Depois executamos o seguinte comando para que possamos incluir a anotação que mostramos anteriormente

kubectl -n emojivoto patch -f https://run.linkerd.io/emojivoto.yml -p '
spec:
  template:
    metadata:
      annotations:
        linkerd.io/inject: enabled
        config.linkerd.io/trace-collector: linkerd-collector.linkerd:55678
        config.alpha.linkerd.io/trace-collector-service-account: linkerd-collector
'

Esperamos o deployment terminar de ser finalizado. Você pode executar o comando a seguir para acompanhar:

kubectl -n emojivoto rollout status deploy/web

Para finalizar, vamos ativar o tracing setando uma nova variável de ambiente no deployment com o seguinte comando

kubectl -n emojivoto set env --all deploy OC_AGENT_HOST=linkerd-collector.linkerd:55678

Explorando o Jaeger

Vamos ter certeza de que nossa implementação funcionou quando rodarmos o comando linkerd dashboard e virmos o ícone do Jaeger ao lado dos nossos namespaces

Veja o ícone do logo do Jaeger ao lado do Grafana

Se clicarmos nele, teremos todas as chamadas feitas dentro da aplicação e poderemos acompanhar o histórico de tudo que foi chamado via HTTP

Cada círculo é uma chamada

Se clicarmos em uma das linhas, conseguiremos ver por onde todas as requisições passaram e quais serviços foram chamados, bem como seus payloads e tempos

Outra funcionalidade interessante é a capacidade do Jaeger identificar a possível arquitetura do sistema. Basta clicar na guia "System Architecture" e selecionar entre o grafo direcionado e o DAG:

Diagrama de número de requisições
Grafo direcionado

Podemos também explorar cada uma das requisições individualmente através do mesmo ícone do Jaeger em cada uma das linhas quando iniciamos o "Live View" de uma rota.

Conclusão

Vamos falar mais de observabilidade por aqui no futuro, mas tenha em mente que o tracing é uma das principais razões pelo qual o service mesh é tão cobiçado. O poder que é possível extrair quando você sabe exatamente o que está acontecendo em seu sistema permite que você resolva bugs e trate erros de forma muito mais simples e rápida.

Espero que tenham gostado do artigo, deixe seu comentário, curta e compartilhe! Vamos ajudar todo mundo a entender o que é tracing! Não se esqueça de se inscrever na newsletter para mais conteúdo exclusivo!

Até mais!

]]>
<![CDATA[ Uma Introdução à Service Mesh com Linkerd ]]> https://blog.lsantos.dev/uma-introducao-a-service-mesh-com-linkerd/ 5f58d59282fe718273265cac Qui, 10 Set 2020 18:26:02 -0300 Conversamos recentemente sobre Service Mesh e como este padrão de arquitetura pode salvar seu projeto de forma que ele ganhe mais observabilidade e facilidade de utilização.

Falamos de Service Mesh de forma muito conceitual. Agora vamos colocar a mão na massa e criar nossa própria mesh utilizando o Linkerd!

Linkerd

Uma breve história do Linkerd

O Linkerd é um projeto criado dentro do Twitter em 2013, quando a rede estava migrando sua arquitetura de uma plataforma de camadas para uma arquitetura de microsserviços. O projeto Linkerd foi transformado em open source em 2016 no que ficou conhecida como  a versão 0.1.

Em 2017, o projeto foi doado a CNCF (Cloud Native Computing Foundation), que é um braço da Linux Foundation dedicado a cuidar de projetos open source. Alguns projetos como o Kuberntes, Helm, Brigade, Harbor, Envoy e o CoreDNS fazem parte dessa incrível fundação.

Recentemente, em 2018, o Linkerd chegou a versão 2.0. O Linkerd v2 foi lançado corrigindo uma série de problemas e tendo como base as lições aprendidas na v1. O projeto inicial tinha a intenção de ser altamente configurável, poderoso e multiplataforma. Já a v2 tinha como objetivo ser muito mais simples. Os principais objetivos de design da versão dois eram:

  • Zero configuração
  • Simples e leve
  • Pensado para Kubernetes

Por padrão, o Linkerd já nos proporciona uma série de funcionalidade nativas:

  • Detecção de protocolos: O Linkerd pode, além de fazer um proxy para protocolos TCP e gRPC, detectar se o tráfego é do tipo HTTP ou gRCP automaticamente.
  • Proxy HTTP 1.1/2 e gRPC: Se qualquer um destes protocolos for usado, o Linkerd pode, nativamente, extrair métricas, fazer proxies, lógicas de tentativas e load balancing.
  • Injeção automática e zero configuração: Como vamos ver mais adiante, o Linkerd é super simples de se instalar, mesmo em clusters com aplicações existentes. Portanto isso facilita muito a adoção da ferramenta
  • mTLS automático por padrão: Por padrão, toda comunicação interna é criptografada usando mTLS
  • Observabilidade: Além de logs e métricas, o Linkerd pode construir um grafo de serviços baseado somente nos tráfegos de entrada e saída. Tudo com métricas e dados.
  • Divisão de tráfego: Uma técnica bastante comum para aplicações distribuídas é chamada de Canary Deployment. Que é quando fazemos o deploy de aplicações parcialmente, através do redirecionamento de parte do tráfego gradualmente para a aplicação nova enquanto a aplicação antiga ainda está funcionando. O Linkerd nativamente proporciona essa funcionalidade.

Arquitetura

Para entendermos melhor o que estamos fazendo, vamos tentar entender como o Linkerd funciona e qual é a arquitetura que ele segue. Para isso temos dois conceitos que são inerentes de service mesh.

  • Control Plane: Responsável por coletar e armazenar todas as informações de requisições e também controlar o fluxo de informações
  • Data Plane: Aonde sua aplicação está localizada e aonde estamos tendo transferências de dados
Overview da arquitetura do Linkerd

Não vou passar por todas as camadas do sistema de forma completa, pois não é o intuito do artigo, mas vou falar um pouco de cada uma para podermos entender como todas as partes se comunicam.

Proxy

A única parte que existe no data plane. É a responsável por capturar informações e métricas dos containers onde suas aplicações estão rodando.

Isto é feito através da injeção de dois containers dentro dos seus pods do Kubernetes:

  • Init Container: Vai ser executado antes do container do pod e vai configurar as regras de acesso, IP e rotas para que toda a comunicação passe primeiro pelo proxy do Linkerd
  • Proxy Container: É a camada que vai capturar as requisições e extrair métricas para análise.

Controller

É a parte com mais responsabilidades. Ela contém o core do Linkerd e possui diversas funcionalidades:

  • Host do servidor de API
  • Atua como CA (autoridade certificadora) para o mTLS
  • Informação de service discovery e balanceamento de carga para o proxy
  • Permite o tap, que é a inspeção em tempo real do tráfego de rede em uma ou mais rotas/aplicações
  • Injeta os proxies automaticamente nos containers iniciados

Web

Uma das grandes facilidades do Linkerd é a existencia de uma interface web que mostra e controla todos os aspectos da malha.

Interface web do Linkerd

Prometheus

Serviço de coleta de métricas do proxy. Busca e armazena temporariamente as métricas coletadas das suas aplicações.

Muitas vezes o cluster do Kubernetes já vem com um serviço do Prometheus, o serviço do Linkerd não é configurado para análise, somente para performance, então ele não armazena mais do que 6h de métricas.

Grafana

Busca métricas e as exibe em forma de gráficos e dashboards

Dashboard do Grafana

E o Istio?

Uma das principais perguntas que as pessoas fazem quando olham o Linkerd é:

Qual é a diferença entre o Linkerd e o Istio?

Basicamente, temos algumas diferenças de foco da plataforma em si e também na arquitetura. Porém, em suma, o Linkerd é uma ferramenta mais focada em performance do que o Istio.

O Istio é mais focado em prover mais ferramentas e funcionalidade e, por isso, é mais complexo do que o Linkerd. Em minha opinião, o uso do Linkerd é muito mais fácil para quem está começando com Service Mesh do que o Istio.

Criando um service mesh

Chegou a hora de sair da teoria e entrar na prática! Vamos colocar a mão na massa e entender como podemos criar um service mesh usando Linkerd.

Para realizar esse hands on eu vou criar um cluster no AKS, mas você pode escolher realizar em qualquer cluster Kubernetes que você tiver, inclusive em um cluster já em produção visto que o Linkerd não é destrutivo e instala suas informações em outro namespace.

Você também pode utilizar soluções para executar o K8S de forma local com o minikube, Docker ou outras opções

Dentro deste cluster vou fazer o deploy da aplicação presente no repositório abaixo

Azure-Samples/aks-bootcamp-sample
Demo repository for the AKS Bootcamp course. Contribute to Azure-Samples/aks-bootcamp-sample development by creating an account on GitHub.

Esta é uma aplicação de demonstração que utiliza um front-end e um backend para comunicação. Você também pode seguir utilizando outra aplicação como, por exemplo, a aplicação de exemplo do Linkerd.

Vou assumir que o cluster já está criado e que a aplicação já está rodando para podermos pular diretamente para a parte que importa.

Instalação

Para rodarmos o Linkerd, primeiramente precisamos instalar a linha de comando da ferramenta com o comando:

curl -sL https://run.linkerd.io/install | sh

E adicionar no nosso path com o comando:

export PATH=$PATH:$HOME/.linkerd2/bin
Se você usa Mac, então você pode instalar o Linkerd com o Homebrew através do brew install linkerd

Validação

Antes de instalarmos o Linkerd no cluster propriamente dito, vamos realizar uma validação executando o comando:

linkerd check --pre

Isso vai garantir que todos os nomes e serviços estão disponíveis para que o Linkerd seja instalado

Saída com sucesso do comando

Então rodamos o comando:

linkerd install | kubectl apply -f -

Perceba que este comando, na verdade é uma junção, pois o Linkerd não faz nenhuma instalação no cluster, ele somente gera um output de um arquivo YAML que pode ser usado pelo cluster para criar seus workloads, por isso que damos um pipe para o kubectl apply -f -. Experimente rodar somente linkerd install e veja os arquivos sendo mostrados na tela.

Depois, vamos rodar o comando a seguir para podermos checar se todo o processo foi executado com sucesso:

linkerd check

Se tudo correu bem, você deverá ter uma saída como esta:

Saída de sucesso do linkerd check

Todos os workloads do Linkerd são instalados dentro de um namespace próprio chamado linkerd, então você pode buscar todos os recursos que comentamos através do kubectl pelo comando:

kubectl get all -n linkerd

Primeiras impressões

Para começarmos a entender como o Linkerd funciona, você pode digitar o comando linkerd dashboard & e aguardar alguns segundos para a abertura do painel web.

Painel web do Linkerd

Por este painel você será capaz de realizar executar todas as funcionalidades do Linkerd, bem como verificar o estado do seu cluster, ele também pode agir como uma forma de dashboard para o Kubernetes, de certa forma. Basta vermos a seção Workloads no menu lateral:

Veja que estamos trabalhando no namespace default. Isso pode ser trocado através do menu de seleção.

Control Plane

Se clicarmos na seção Control Plane, iremos ter uma visão geral de todo o nosso Service Mesh.

Painel de visualização do Control Plane

Veja que este painel nos mostra todo o status do sistema e também a quantidade de componentes que temos instalados.

Mais abaixo, podemos ver a quantidade de namespaces que estão "meshed", ou seja, que estão injetados pelo proxy do Linkerd de forma que estão gerando métricas:

Perceba que apenas um namespaces está gerando métricas

Adicionando métricas

Nossa aplicação está no namespace default, como fazemos para incluí-la no Service Mesh? Simples! Vamos executar o seguinte comando:

kubectl get deploy -o yaml

Veja que temos todos os arquivos YAML dos nossos deployments, então vamos criar um pipe deste comando para o comando linkerd inject:

kubectl get deploy -o yaml | linkerd inject -

Agora veja a diferença entre os dois arquivos. O arquivo injetado terá uma annotation no template do pod desta forma:

Anotação do Linkerd no pod

Esta é a única mudança que é feita em seus deployments, ou seja, é muito fácil injetar o Linkerd em serviços que já estão em produção sem causar muitos efeitos colaterais.

Vamos aplicar as mudanças através de um outro pipe para o comando apply:

kubectl get deploy -o yaml | linkerd inject - | kubectl apply -f -

Assim que aplicarmos a mudança poderemos ver uma movimentação no Control Plane de forma que ele estará carregando os nossos pods novamente para incluí-los nas métricas:

O namespace está entrando no mesh

Veja que não temos um dos pods enviando métricas... O pod do MongoDB está fora do Mesh, mas por que?

Pois, neste exemplo, ele é um StatefulSet e não um deployment! Então vamos executar o mesmo comando que executamos anteriormente, mas vamos substituir deploy por sts.

kubectl get sts -o yaml | linkerd inject - | kubectl apply -f -
Importante: Para este exemplo estou utilizando uma versão simples do MongoDB dentro do cluster local, você pode utilizar uma versão hosteada por qualquer provedor – como o Mongo Atlas, por exemplo – ou então outras soluções. A aplicação só precisa de um MongoDB para funcionar.

Agora temos todos os detalhes:

Ferramentas

O Linkerd nos dá uma série de ferramentas interessantes, vamos conhecer algumas delas.

Grafana

Clique no nome do namespace na aba Control Plane.

Além de conseguirmos verificar as métricas dentro do painel do Linkerd, também podemos encontrar um dashboard do Grafana ao clicarmos no pequeno ícone laranja no canto direito

Vamos abrir o painel para o deployment porto-backend:

Nosso dashboard está vazio

Veja que o dashboard não apresenta nenhum dado... Por que? Pois ainda não fizemos nenhuma requisição que possa ser capturada! Vamos entrar na nossa aplicação e criar alguns acessos. Para achar a URL da sua aplicação utilize o comando kubectl get ing para buscar os ingresses e assim as URLs.

Assim que começarmos a fazer alguns acessos podemos ver alguns dados chegando:

E podemos ver o que está acontecendo nos gráficos do grafana também!

Temos também métricas de tráfego TCP:

Além deste dashboard, temos outros dashboards já internos que o próprio Linkerd criou.

Visão em tempo real

Ao clicarmos no nosso deployment dentro da visão do namespace, podemos ver em tempo real as chamadas que estão sendo feitas.

Também podemos ver um mapa da aplicação que nos mostra quais são os serviços conectados.

Top

Se clicarmos no menu Top na seção Tools do menu lateral. Vamos poder selecionar um namespace ou recurso para podermos acompanhar em tempo real. Selecione o namespace default e faça algumas requisições para a aplicação. Veja que começamos a ter um acompanhamento de métricas:

Tap

Ainda na mesma visualização, veja que temos o ícone de um microscópio, este ícone permite que observemos aquela rota específica para mais detalhes.

Vamos abrir a aba Tap no menu lateral. Selecionar o namespace default no topo e clicar em start. Assim que fizermos algumas requisições, poderemos ver todas elas em tempo real

Ao clicarmos na seta esquerda, teremos uma visualização da request em detalhes

Grafo de serviços

Na minha opinião, uma das funcionalidades mais legais do Linkerd é a do grafo de serviços. Para podermos representar bem como ela funciona, vamos voltar para a visualização de namespaces no menu esquerdo e clicar sobre o namespace linkerd

No topo da tela teremos uma representação dos serviços que estão conversando entre si e quais deles estão enviando requisições. Isto é muito útil quando estamos falando de meshes muito grandes.

Removendo o Linkerd

Para removermos o linkerd de um namespace basta executar o comando

kubectl get deploy -o yaml | linkerd uninject - | kubectl apply -f -

Ou seja, da mesma forma que executamos o inject, executamos também o uninject.

Conclusão

O Linkerd pode facilitar muito a vida de quem esta desenvolvendo aplicações distribuídas, por ser simples e fácil de instalar, ele tem uma grande vantagem sobre os demais sistemas de Service Mesh e pode provar ser um excelente adendo à sua infraestrutura.

Não se esqueça de se inscrever na newsletter para receber esse conteúdo e também notícias semanais! Curta e compartilhe seus feedbacks nos comentários!

Até mais!

]]>
<![CDATA[ Otimização de custos com Kubernetes e AKS ]]> https://blog.lsantos.dev/otimizando-custos-com-kubernetes-e-aks/ 5f4d3b5c82fe7182732659ec Qui, 03 Set 2020 12:41:57 -0300 Desde os primórdios da computação distribuída e da chegada da cloud, todas as pessoas já tiveram que lidar, de alguma forma, com otimização de custos. Seja esta otimização em forma de redução de uso de espaço, ou até mesmo em redução de tráfego de rede!

Uma das ferramentas mais caras quando falamos em computação distribuída é o Kubernetes. Isto é um pouco óbvio por dois motivos bastante simples:

  1. O Kubernetes trabalha é um cluster de máquinas
  2. Por ser um cluster, temos mais recursos para gerenciar

Infelizmente, este problema faz com que muitas soluções incríveis deixem de estar rodando em seu ambiente ideal, que é um ambiente distribuído e altamente escalável, para rodarem em ambientes menores por pura questão de custo.

Mas isso não precisa ser assim!

Modelos de cobrança

Para entendermos como podemos otimizar os custos dentro de uma arquitetura cloud com computação distribuída – usando Kubernetes – primeiro precisamos entender os modelos de cobrança.

Cada cloud tem seu modelo de cobrança individual, aqui vamos trabalhar somente com o AKS (Azure Kubernetes Service) que roda na Microsoft Azure.

Se você usa outro provedor cloud, busque no site do fornecedor o preço e as opções de cobrança para cada serviço oferecido. No entanto, as opções de otimização que vou mostrar por aqui servem para todas as clouds, claro, com algumas mudanças na linha de comando.
Descrição das formas de cobrança para o AKS

Como podemos ver, no caso do AKS, a cobrança é feita somente pelos recursos utilizados, sendo que o o gerenciamento do cluster como um todo não possui nenhuma cobrança extra. Isso quer dizer que, em uma arquitetura Kubernetes padrão, o que chamamos de Control Plane, ou o plano de controle onde todos os recursos de sistema são criados, não é cobrado. Ao invés disso, todos os demais recursos que o Kubernetes usa para poder funcionar são.

Esta é uma prática bastante comum em vários provedores cloud. Alguns outros provedores cobram também pela alocação do control plane, geralmente porque não são totalmente gerenciados e abrem espaço para que as pessoas que os administram possam modificar uma parte do seu conteúdo, ou seja, oferecem uma capacidade maior de customização.

E quais recursos seriam estes?

Recursos de cobrança

No geral, criar um cluster Kubernetes exige uma série de pequenos recursos que vão desde máquinas virtuais – que suportam os nodes – até interfaces de rede e controladores de tráfego. Dependendo do tipo de funcionalidades que você está escolhendo para seu cluster, você pode ter zonas de DNS e outros recursos nessa lista.

No caso do AKS, quando criamos um cluster, selecionamos o que é chamado de Resource Group. Neste resource group, a Azure irá criar um recurso de controle chamado Kubernetes Service, como podemos ver a seguir:

Criamos um demo-cluster em um resource group

Porém, aonde estão todos os recursos cobrados que falei no início do parágrafo? Para isto, por conta de gerenciamento interno, a Azure cria um outro resource group que começa com o nome MC_<resource-group>-<cluster>_<região>. E nele serão colocados todos os recursos cobrados:

Recursos cobrados por um cluster

Veja que temos oito recursos diferentes, porém podemos ser cobrados por mais que isto porque o que é chamado de Virtual Machine Scale Set é, na verdade, uma lista de VMs que podem ser escaladas de acordo com o precisamos.

Otimizando custos com AKS

Para construir este artigo, estou usando como base um excelente material disponibilizado gratuitamente no Microsoft Learn. O curso "Otimização de Custos com AKS e Node Pools".

Neste artigo, vamos passar pelo material completo, porém vou dar alguns exemplos fora do contexto e explicar algumas coisas além do que está sendo mostrado. Porém, é fortemente recomendado que você complete o módulo, ele é gratuito e leva apenas alguns minutos.

Criando o ambiente

Para começar, vamos precisar de três itens importantes:

  1. Você precisa ter o Azure CLI instalado em sua máquina
  2. Você precisa ter o Kubectl instalado em sua máquina
  3. Você precisa ter uma conta na Azure

Como uma segunda opção, se você já tiver uma conta na Azure, você pode entrar no Azure Cloud Shell e rodar todos os comandos por lá, pois o Cloud Shell já possui tanto o Azure CLI quando o Kubectl instalados. Se for a sua primeira vez usando o Cloud Shell, então selecione o Bash como shell principal.

Execute o comando a seguir para habilitar o modo de preview no seu CLI da Azure:

az extension add --name aks-preview

Depois execute o seguinte comando para registrar as funcionalidades de permissão que vamos precisar:

az feature register --namespace "Microsoft.ContainerService" --name "spotpoolpreview"

Este comando demora alguns minutos para rodar, para checar o progresso, rode periodicamente o comando abaixo:

az feature list -o table --query "[?contains(name,'Microsoft.ContainerService/spotpoolpreview')].{Name:name,State:properties.state}"

Enquanto o resultado desta query for Registering, aguarde até que seja Registered. Uma vez registrado, rode o comando para atualizar o CLI:

az provider register --namespace Microsoft.ContainerService

Node Pools

Antes de podermos partir para a criação do nosso cluster, precisamos entender o que são as chamadas Node Pools, elas serão essenciais para podermos economizar durante o uso do AKS.

Basicamente, uma Node Pool descreve um grupo de nodes do Kubernetes que compartilham características em comum.

Por exemplo, podemos ter nodes que são VMs específicas para Machine Learning, ou então aqueles que possuem mais memória. O objetivo das Node Pools é justamente permitir que as pessoas que estejam operando o cluster possam ter uma opção de escolha para criar suas aplicações na infraestrutura que for mais adequada para o tipo de trabalho que está sendo realizado.

No AKS, temos dois tipo de Node Pools.

System Node Pools

São criadas automaticamente com o cluster e, geralmente, servem para armazenar pods e deployments do sistema do AKS e do Kubernetes no geral. Não é uma boa prática executar workloads personalizados usando a mesma node pool. Todo o cluster do AKS deve conter pelo menos uma Node Pool de sistema com pelo menos um node.

User Node Pools

Como podemos imaginar, são os grupos de nodes criados pelo usuário. Nestas pools temos algumas configurações interessantes, já que podemos especificar tanto Windows como Linux para as máquinas que são executadas, e também podemos alocar máquinas de tamanhos e categorias diferentes das do que foram definidas no AKS

Capacidade de execução

Cada node tem uma capacidade máxima de execução de pods, ou seja, conseguimos colocar uma quantidade máxima de pods dentro de uma VM antes que seus recursos sejam esgotados. Por isso, você pode especificar a quantidade de nodes dentro de uma pool até um limite de 100.

Em pools de usuário você pode setar a quantidade de nodes para zero, enquanto em pools de sistema o número mínimo é um.

Criando uma Node Pool

Você pode criar uma nova pool em um cluster existente usando o Azure CLI com o seguinte comando:

az aks nodepool add \
  -g <resource-group> \
  --cluster-name <nome do cluster> \
  --name <nome da pool> \
  --node-count <numero de nodes> \
  --node-vm-size <tamanho e tipo da VM> \

Escalabilidade

Quando um node atinge a sua capacidade máxima de execução, ou seja, quando já colocamos o número máximo de pods possível dentro daquela máquina, temos de aumentar – ou escalar – o número de nodes dentro da pool. Isso pode ser feito de forma manual, através do comando a seguir:

az aks nodepool scale \
  -g <resource-group> \
  --cluster-name <nome do cluster> \
  --name <nome da pool> \
  --node-count <novo numero de nodes>

A escalabilidade é uma das principais razões pelo qual seu cluster pode custar bem caro. Principalmente porque quanto mais máquinas, mais recursos. E, quanto mais recursos estamos usando, mais vamos ter que pagar. Por isso é altamente recomendável utilizarmos formas automáticas de escalar nossas pools, a principal delas é o Cluster Autoscaler.

Cluster autoscaler

Escalabilidade deve ser algo automático, pois é muito mais seguro e também economiza muito mais dinheiro porque ele sempre vai aumentar a quantidade de nodes quando for necessário e vai reduzir a quantidade de nodes quando estes nodes não precisarem mais serem utilizados. Você pode ativar o autoscaler em um cluster existente através do comando:

az aks update \
  -g <resource-group> \
  -n <nome do cluster> \
  --enable-cluster-autoscaler \
  --min-count <minimo de nodes> \
  --max-count <maximo de nodes>

Spot Instances com Node Pools

Uma das formas mais eficientes de se economizar dinheiro enquanto estamos utilizando instâncias do AKS é através do uso de múltiplas node pools com as chamadas Spot Instances.

Spot VMs

As VMs do tipo Spot são máquinas virtuais que oferecem todos os recursos de escalabilidade que uma VM normal teria, mas ainda sim reduzindo os custos através do uso de computação excedente. Isso significa que as Spot VMs usam poder computacional que não está sendo utilizado pela Azure no momento, garantindo descontos significativos no preço das mesmas.

Porém, isso tudo vem com um preço. As Spot Instances, por se aproveitarem de poder computacional não utilizado, podem ser desativadas ou interrompidas a qualquer momento. Isso significa que, durante o uso da VM, você terá uma notificação 30 segundos antes da máquina ser desalocada, depois deste tempo a máquina entrará em um estado de desalocação e sua computação será parada abruptamente.

Por este motivo, as Spot VMs são muito boas quanto utilizamos aplicações que não guardam estado e podem ser interrompidas a qualquer momento, reiniciando seus processos sempre que for necessário. Alguns casos de uso:

  • Processamento batch
  • Aplicações stateless
  • Ambientes de desenvolvimento
  • Pipelines de CI e CD

Juntando forças

Utilizar Spot VMs com node pools dá um grande poder para economizar um bom dinheiro na hora de processar dados de larga escala. Principalmente porque, quando usamos Spot VMs com node pools, temos a capacidade de escolher entre duas políticas de desalocação:

  • Desalocar: Quando a política é definida como desalocação, a máquina será parada e desalocada quando a VM chegar a um estado que não há mais poder computacional. Você pode fazer o deploy dela novamente quando a capacidade voltar a estar disponível, mas lembre-se de que todos os custos de alocação de CPU e discos continuam sendo contados.
  • Deletar: Neste caso, a máquina será completamente removida e você não irá pagar por mais nenhum recurso consumido.

Spot Node Pools

As Spot Node Pools permitem que você defina um valor máximo por hora para pagar, quando o valor for atingido, a máquina será desalocada ou removida, de acordo com a política selecionada.

Apesar de garantirem uma redução de custos. Spot node pools não são recomendadas para nenhum tipo de workload muito importante, pois a disponibilidade da mesma não é garantida.

Para criarmos uma spot node pool, podemos utilizar o seguinte comando:

az aks nodepool add \
  -g <resource-group> \
  --cluster-name <nome do cluster> \
  --name <nome da pool> \ 
  --enable-cluster-autoscaler \
  --min-count <numero minimo de nodes> \
  --max-count <numero maximo de nodes> \
  --priority Spot \
  --eviction-policy Delete \
  --spot-max-price -1 \

Quando setamos o valor do preço por hora para -1, os nodes não vão ser removidos com base no preço e as novas instâncias criadas serão baseadas no menor valor entre o valor atual das spot VMs ou então o valor padrão de um node

Criando recursos na nova pool

Para criarmos recursos nas nossas spot node pools, precisamos saber o conceito de Taints e Tolerations do Kubernetes (vamos ter um artigo aqui sobre isso logo mais). E também o conceito de Node Affinity.

Em suma, cada node tem uma taint. Essas taints repelem novos pods de serem criados nesses nodes a não ser que estes pods tenham uma toleration àquela taint específica. É uma forma de escolher em qual VM suas aplicações serão criadas.

Por padrão, todos os nodes criados dentro de uma spot node pool terão um taint do tipo kubernetes.azure.com/scalesetpriority=spot:NoSchedule, isso significa que, a não ser que o pod tenha uma toleration do mesmo tipo, nenhum outro pod poderá sofrer um schedule naquele node.

Para que possamos criar um pod – ou qualquer outro workload – dentro de um node que está presente em uma spot node pool, precisamos definir uma nova toleration no arquivo declarativo do pod, por exemplo:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    env: example
spec:
  containers:
  - name: example
    image: node
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "kubernetes.azure.com/scalesetpriority"
    operator: Equal
    value: spot
    effect: NoSchedule

Veja que definimos um operador para que ele seja igual a taint do node em questão, portanto novos pods serão criados neste node.

Conclusão

Apesar de ser um trabalho extenso, o uso de spot node pools pode ser um salvador de vidas em termos de recursos quando estamos trabalhando com otimização de custos no AKS, mas lembre-se sempre que as máquinas do tipo spot não são máquinas que garantem alta disponibilidade!

Recomendo fortemente a leitura da documentação sobre a baseline de otimização de custos do AKS, uma documentação incrível sobre como você pode definir polícias e melhores práticas para clusters AKS em produção

Neste artigo falamos bastante sobre conceitos mais avançados do Kubernetes, como taints e tolerations. Estou preparando um artigo somente sobre estes conceitos e também sobre uma outra ferramenta super interessante desse orquestrador de containers, então não se esqueça de se inscrever na newsletter para receber esse conteúdo e também notícias semanais! Curta e compartilhe seus feedbacks nos comentários!

Até mais

]]>
<![CDATA[ O que há de novo no TypeScript 4.0 ]]> https://blog.lsantos.dev/o-que-ha-de-novo-no-typescript-4-0/ 5f4d515f82fe718273265a94 Seg, 31 Ago 2020 17:45:39 -0300 No dia 20 de Agosto de 2020, o TypeScript anunciou a sua mais nova versão, a 4.0! Então, neste artigo, me preparei para apresentar para vocês as últimas mudanças e novidades da versão!

Apesar de ser uma major version as alterações que foram introduzidas nesse release não são muito substanciais e, pode se acalmar, não temos nenhuma breaking change :D

Tuplas nomeadas

Para começar, temos a resolução de um problema relativamente antigo do superset mais amado por todos. Quando temos tuplas (elementos que são compostos de pares de dados), antigamente tínhamos uma definição como esta:

function tupla (...args: [string, number]) {}

Veja que não temos nenhum nome para nenhum dos parâmetros que ocupam tanto a posição da string quanto a posição do number. No que diz respeito à inferência de tipos e à checagem no geral, isso não faz diferença alguma, mas é muito útil quando estamos documentando nosso código.

Por conta da checagem de tipos, a função anterior seria traduzida para algo semelhante a isto:

function tupla (args_0: string, args_1: number) {}

Que é essencialmente a mesma coisa, porém, na hora de fazermos o código, o nosso intellisense – que é uma das grandes vantagens do uso do TypeScript, no geral – vai nos dar uma nomenclatura que não ajuda ninguém, como podemos ver no gif abaixo

Nomenclatura como args_0 e args_1

Agora, com a versão 4.0, podemos incluir nomes nas nossas tuplas para que elas sejam nomeadas durante o intellisense:

function tupla (...args: [nome: string, idade: number]) {}

E ai conseguimos um resultado como o seguinte:

Conseguimos ver a nomenclatura de cada parâmetro

É importante notar que: Se você está nomeando qualquer elemento de uma tupla, você precisa nomear os dois. Caso contrário você terá um erro:

type Segment = [first: string, number];
//                             ~~~~~~
// error! Tuple members must all have names or all not have names.

Inferência de propriedades a partir do construtor

A partir de agora, quando configuramos o TypeScript com a configuração noImplicitAny, podemos usar a análise de fluxo que é feita no tempo de compilação para determinar os tipos de propriedades em classes de acordo com as atribuições em seu construtor.

class Test {    
   public x   
   constructor (b: boolean){      
     this.x = 42
     if (b) this.x = 'olá'
   }
}

Em versões anteriores, como não estamos especificando o tipo da propriedade, isto faria o compilador atribuir o tipo any, mas como checamos que não queremos any de forma implícita, então o compilador nos daria um erro dizendo que não podemos ter nenhum tipo de any implícito.

Na versão mais atual, o TypeScript consegue inferir, a partir do construtor, que x é do tipo string | number.

Short-Circuit em operadores compostos

Poucas pessoas conhecem esta funcionalidade do JavaScript, mas muitas outras linguagens também possuem o que é chamado de compound assignment operator, ou, operadores de atribuição compostos.

O que eles fazem é resolver a expressão do lado direito e atribuir o valor para a variável do lado esquerdo. Os mais famosos são os operadores algébricos:

let b += 2
let c /= 3

Todos funcionam muito bem e existem para a maioria das operações lógicas. Porém, de acordo com o próprio time do TS, existem três notáveis exceções à esta regra. Os operadores lógicos &&, || e o operador de coalescencia nula ??. No 4.0 temos a adição de três novos operadores:

a ||= b
// que é igual a
a || (a = b)

Além disso temos os operadores &&= e ??=.

Catch com unknown

Desde os primórdios do TypeScript, sempre que tínhamos uma cláusula catch, o valor do argumento de erro era sempre definido como any, pois não havia como saber qual era o tipo de retorno.

Portanto, o TypeScript simplesmente não checava os tipos destes parâmetros, mesmo se o noImplicitAny estava ativo.

try {
  throw 'Alguma coisa'
} catch (err) { // Este 'err' é Any
  console.log(err.foo()) // não vai dar erro
}

Isso era pouco seguro uma vez que podíamos chamar qualquer função dentro do catch. A partir do 4.0, o TS vai tipar os erros como unknown.

O tipo unknown é um tipo especificamente voltado para tipar coisas que não sabemos o que são. Portanto elas precisam de um type-casting antes de poderem ser usadas. É como se um dado do tipo unknown fosse um papel em branco e você pudesse pinta-lo da cor que quiser. Neste caso, o unknown pode ser convertido para qualquer tipo.

Outras mudanças

Além de mudanças na linguagem, a velocidade de compilação com a flag --noEmitOnError ficou mais rápida quando usamos junto com a flag --incremental. O que a última flag faz é dar a possibilidade de compilarmos uma aplicação mais rapidamente a partir de uma outra aplicação que já foi compilada, a chamada compilação incremental.

Quando utilizávamos --incremental com --noEmitOnError, se compilássemos um programa pela primeira vez e ele der um erro, isso significa que ele não emitira nenhuma saída, portanto não há um arquivo .tsbuildinfo onde o --incremental poderá olhar, o que tornava tudo super devagar.

Na versão 4.0 este problema foi corrigido. E, além disso, agora é permitido o uso da flag --noEmit juntamente com --incremental, o que não era permitido antes pois --incremental precisava da emissão de um .tsbuildinfo.

Algumas outras mudanças menores foram feitas no que diz respeito à edição e editores no geral. Você pode conferir a postagem do blog aqui.

Conclusão

E fechamos por aqui a nossa atualização deste superset sensacional! Lembrando que estamos precisando de ajuda na tradução para português no site do TypeScript, nos ajude a traduzir!

Não se esqueça de se inscrever na newsletter para mais conteúdo exclusivo e notícias semanais! Curta e compartilhe seus feedbacks nos comentários!

]]>
<![CDATA[ Maratona Full Cycle 4.0 ]]> https://blog.lsantos.dev/maratona-full-cycle-4-0/ 5f49c03082fe718273265982 Sex, 28 Ago 2020 23:48:18 -0300 Tive o prazer imenso de ser convidado pelo Wesley a participar da Maratona Full Cycle 4.0!

O objetivo dessa maratona é mostrar que é possível ser uma pessoa desenvolvedora completa que vai desde o desenvolvimento até o deploy e monitoramento da aplicação!

Nesta talk de mais de 2h, falamos sobre cloud no geral, sobre suas diferenças e como podemos tirar o máximo proveito delas através de publicações com containers utilizando Docker e Azure Container Registry, também usamos o Azure Container Instances, App Services, passamos por Azure Functions e o tão famoso Azure Kubernetes Service para mostrar que você pode fazer o deploy da sua aplicação sem esforço!

]]>
<![CDATA[ Elevando o nível de microsserviços com service meshes ]]> https://blog.lsantos.dev/service-mesh-1/ 5f3bdab482fe718273265869 Sex, 21 Ago 2020 17:42:36 -0300 Desde que o Docker foi lançado – e até mesmo antes disso – pessoas desenvolvedoras se preocupam em como vão desacoplar suas aplicações das suas configurações e também da sua infraestrutura, de forma que elas possam ser facilmente migradas e possam facilmente se comunicar umas com as outras.

O advento do Kubernetes facilitou muito a implementação de melhores camadas de serviços, principalmente quando falamos de serviços distribuídos utilizando a arquitetura de microsserviços.

O grande problema é que, mesmo com todas essas facilidades, ainda enfrentamos muitas dificuldades quando o assunto é migrar uma aplicação ou até mesmo fazer com que ela seja mais independente. Principalmente por conta do modelo de comunicação que utilizamos.

O problema dos microsserviços

Quando estudamos microsserviços, vemos que o ideal é que tenhamos aplicações individuais que se comunicam com seus próprios bancos de dados e são independentes o suficiente a ponto de não precisarem de nenhuma outra aplicação externa para funcionarem.

A representação de um microsserviço versus um monólito (Fowler, 2015)

Além disso sempre estamos ouvindo frases como esta:

Um microsserviço é uma aplicação independente, que é auto-contida e pode utilizar seu próprio banco de dados para não depender de nenhuma outra parte do sistema.

O grande problema é que nem sempre conseguimos criar uma aplicação neste modelo, isso pode estar relacionado a diversos problemas mais impeditivos:

  • Grande aumento de complexidade
  • Custo para manter todos os bancos de dados
  • Dispersão dos dados
  • Duplicação de dados
  • Segurança

E outro grande problema que muitas empresas enfrentam quando utilizam microsserviços são os clássicos problemas da observabilidade (que vamos falar em outro artigo) e do Service Discovery. Apesar deste último ter sido resolvido em grande parte pelo uso de ferramentas de orquestração como o Kubernetes.

Então entramos em um assunto bastante interessante, o Service Mesh.

Service Mesh

Em palavras bastante simples, service mesh pode ser considerada uma nova "camada" que abstrai os problemas de rede quando estamos falando de comunicação entre serviços.

Porém, quando falamos de abstrações, não estamos falando apenas de algo passivo. Uma camada de service mesh também proporciona uma série de benefícios, entre eles os principais são:

  • Telemetria
  • Canary Deployments
  • Testes A/B
  • Roteamento de tráfego
  • Descoberta de rede (Service Discovery)
  • Monitoramento
  • Tracing

Estes pontos são os principais problemas que temos em arquiteturas distribuídas, perguntas do tipo "como posso monitorar todos os meus serviços de forma completa?", "como posso saber o número de requisições que estou recebendo?" geralmente exigem a existência de um recurso compartilhado, o API Gateway, que é um recurso muito comum em arquiteturas distribuídas como um ponto de entrada e controle para toda a malha de serviços por trás.

Em geral, chamar Service Mesh de camada está um pouco errado, porque ela não é uma camada no topo dos demais serviços, mas sim uma rede embutida diretamente na estrutura das aplicações.

Uma das principais vantagens de se utilizar um modelo de mesh é, por exemplo, não termos este recurso compartilhado, como teríamos com um API Gateway se tivermos que rotear as nossas requisições através de um único ponto de entrada, pois a implementação do roteamento já está dentro da aplicação em si.

Além disso, o uso de Service Mesh permite a implementação de um padrão chamado Circuit Breaker, que isola instâncias quebradas de uma aplicação até gradualmente trazê-las de volta à vida.

As implementações mais famosas de Service Mesh hoje são o Istio e o Linkerd.

Definições

Por se tratar de um novo padrão que permeia todo o ecossistema de serviços, algumas nomenclaturas se fazem necessárias.

Instâncias e serviços

Por padrão, todas as aplicações dentro de um service mesh são chamadas de serviços, cada uma delas é uma instância de um serviço.

Especificação de um pod do Kubernetes

Basicamente todo serviço é uma cópia em execução de algum microsserviço, algumas vezes essa instância é um único container, outras vezes pode ser uma aplicação constituída de mais de um container, que é o conceito de Pod que temos no Kubernetes.

Sidecar

O grande trunfo do Service mesh é o uso de sidecars. Sidecars são proxies em containers que vivem lado a lado com os serviços que estão suportando. Quando estamos falando em um Pod no Kubernetes, um sidecar é outro container que vive dentro do mesmo pod.

O sidecar é o responsável por receber o tráfego de rede e rotear este tráfego para sua aplicação irmã. O sidecar se comunica com os demais sidecars em outros microsserviços e são gerenciados pelo orquestrador de containers em uso. Além disso, o sidecar é um dos maiores responsáveis por obter métricas de uso de rede da aplicação.

Este é o grande trunfo porque um sidecar é basicamente uma implementação distribuída de um API Gateway. Ao invés de termos um único ponto de comunicação, temos vários pontos que permitem à rede saber como chegar do serviço A ao serviço B.

Data Plane

O Data Plane é o responsável pelo tráfego de rede entre as instâncias, isso é chamado de "Tráfego Leste-Oeste", como podemos ver na imagem anterior, este tipo de tráfego é aquele que está se movendo horizontalmente dentro da mesma rede. Ou seja, o data plane é o próprio sidecar.

Explicação de um tráfego norte-sul para um leste-oeste

O tráfego Norte-Sul, como mostrado na imagem acima, é a comunicação entre diferentes redes, ou seja, a comunicação interna para uma rede externa é um tipo de tráfego N-S, enquanto um serviço se comunicando com outro dentro do mesmo cluster é um exemplo de tráfego L-O.

Control Plane

O plano de controle, ou Control Plane, é somente utilizado pelas pessoas operando o service mesh, ou seja, é o plano que contém as ferramentas de controle para a malha de serviços.

Visão geral da arquitetura de um Service Mesh

Esta camada inclui, na maioria dos casos, uma API de comunicação com o Service Mesh e também pode incluir um CLI e/ou uma interface visual para controle da aplicação, com podemos ver na imagem abaixo.

Imagem do dashboard do Linkerd

Como um service mesh pode melhorar a comunicação de serviços

É difícil entender como uma simples malha de serviço pode melhorar a comunicação de uma rede inteira. Pois bem, vamos ver uma situação prática onde podemos tirar proveito das métricas e da visibilidade do service mesh para melhorar nossas aplicações.

Imagine que você possua um serviço que falhe constantemente, isso já é conhecido mas não se sabe uma possível solução, então sua aplicação implementa um sistema de tentativas que faz um retry da chamada a cada 5, 8, 10 e 15 segundos respectivamente a cada tentativa. Porém isso está causando um gargalo de requisições visto que, em horários de pico, sua aplicação está segurando o usuário por até 15 segundos.

Por conta da natureza inerentemente transparente das métricas do service mesh, toda a comunicação é documentada, incluindo as métricas de tráfego entre serviços. Com estas métricas em mãos, podemos ver o tempo médio que nosso serviço está falhando – ou até mesmo se é este serviço que está falhando e não um outro – e ajustar o nosso tempo de retry para ser equivalente.

Vamos supor que o tempo médio de falha é de 6 segundos, então nosso retry não está sendo efetivo, pois temos que fazer duas tentativas antes de poder ter uma terceira que está válida. Podemos fixar nosso tempo de retry para 6 segundos então, evitando uma carga desnecessária de requisições do serviço.

Conclusão

Nos próximos artigos vamos explorar ainda mais como podemos criar e manipular service meshes e também seus conceitos! Por isso se inscreva na newsletter para receber notícias semanais de todos os artigos e também outras notícias do mundo da tecnologia!

Até mais!

]]>
<![CDATA[ Um Mergulho em Imagens de Containers - Parte 3 ]]> https://blog.lsantos.dev/um-mergulho-em-imagens-de-containers-parte-3/ 5f36b6a482fe7182732657a9 Sex, 14 Ago 2020 14:34:25 -0300 No artigo anterior falamos como podemos criar uma imagem Docker da melhor maneira para linguagens consideradas estáticas, como o C ou o Go. Neste artigo vamos explorar um pouco mais a criação de imagens utilizando linguagens dinâmicas, como o Python ou o JavaScript.

Adeus Imagens Scratch

Como falamos lá no primeiro artigo, temos um tipo de imagem chamada scratch, que é uma imagem completamente vazia, realmente so um filesystem vazio. Utilizamos este tipo de imagem para construir nosso container no artigo anterior.

Porém, a péssima notícia é que não podemos utilizar este tipo de imagem para poder criar nossos containers dinâmicos, pois vamos precisar do runtime da linguagem instalado no sistema operacional, então vamos estar utilizando somente as imagens full, slim e alpine.

Builds de múltiplos estágios

Assim como fizemos no artigo anterior, é possível tirar vantagem de um processo de build de múltiplas fases, ou seja, temos um container que contém todos os recursos e ferramentas de desenvolvimento para construir a nossa aplicação, mas não utilizamos este container para produção, mas sim um outro container que conterá o mínimo possível.

Isto também é válido para linguagens dinâmicas, porém temos algumas modificações que precisamos fazer para que estas builds sejam mais eficientes. Como não vamos ter um único binário para copiar, o ideal seria copiar o diretório todo. Algumas linguagens como o Python possuem um bom relacionamento com este tipo de build porque esta linguagem possui o VirtualEnv, que permite que separemos logicamente os ambientes que estamos trabalhando.

Vamos fazer este teste com uma aplicação simples, uma API em JavaScript que envia emails – o código fonte pode ser visto aqui – Para começar, vamos analisar o Dockerfile com a imagem de build:

FROM node:12 AS builder

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

## Install dependencies
COPY ["./package.json", "./package-lock.json", "/usr/src/app/"]

RUN npm install

## Add source code
COPY ["./tsconfig.json", "/usr/src/app/"]
COPY "./src" "/usr/src/app/src/"

## Build
RUN npm run build

A imagem do Node:12 pode variar de espaço utilizado, mas a imagem crua possui cerca de 340Mb.  Como você pode observar, as imagens base de linguagens dinâmicas são bem maiores do que imagens de linguagens compiladas porque temos a necessidade do runtime estar junto.

Porém, vamos fazer uma alteração já que as imagens full podem ter muitas vulnerabilidades, vamos mudar para a imagem slim que tem aproximadamente 40mb

FROM node:12-slim AS builder

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

## Install dependencies
COPY ["./package.json", "./package-lock.json", "/usr/src/app/"]

RUN npm install

## Add source code
COPY ["./tsconfig.json", "/usr/src/app/"]
COPY "./src" "/usr/src/app/src/"

## Build
RUN npm run build

Podemos deixar ainda melhor se alterarmos a nossa imagem para uma imagem alpine!

FROM node:12-alpine AS builder

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

## Install dependencies
COPY ["./package.json", "./package-lock.json", "/usr/src/app/"]

RUN npm install

## Add source code
COPY ["./tsconfig.json", "/usr/src/app/"]
COPY "./src" "/usr/src/app/src/"

## Build
RUN npm run build

Agora a imagem de build tem somente 28mb iniciais para serem baixados.

Imagem de produção

Já criamos o nosso builder, vamos agora criar a nossa imagem de produção. Para isso, vamos utilizar a imagem alpine que é bem menor!

# PRODUCTION IMAGE

FROM node:12-alpine

RUN mkdir -p /usr/app
WORKDIR /usr/app

COPY --from=builder [\
  "/usr/src/app/package.json", \
  "/usr/src/app/package-lock.json", \
  "/usr/app/" \
  ]

COPY --from=builder "/usr/src/app/dist" "/usr/app/dist"
COPY ["./scripts/install_renderers.sh", "/usr/app/scripts/"]

RUN npm install --only=prod

EXPOSE 3000

ENTRYPOINT [ "npm", "start" ]

Estamos copiando apenas a pasta de saída do TypeScript para dentro da nossa imagem de produção e estamos apenas instalando as dependências necessárias para uma aplicação de produção com o npm install --only=prod.

Da mesma forma estamos expondo as portas necessárias e criando o script de inicialização somente nesta imagem e não na imagem de build, já que ela não vai ser utilizada.

Colocando todas juntas temos:

FROM node:12-slim AS builder

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

## Install dependencies
COPY ["./package.json", "./package-lock.json", "/usr/src/app/"]

RUN npm install

## Add source code
COPY ["./tsconfig.json", "/usr/src/app/"]
COPY "./src" "/usr/src/app/src/"

## Build
RUN npm run build

# PRODUCTION IMAGE

FROM node:12-alpine

RUN mkdir -p /usr/app
WORKDIR /usr/app

COPY --from=builder [\
  "/usr/src/app/package.json", \
  "/usr/src/app/package-lock.json", \
  "/usr/app/" \
  ]

COPY --from=builder "/usr/src/app/dist" "/usr/app/dist"
COPY ["./scripts/install_renderers.sh", "/usr/app/scripts/"]

RUN npm install --only=prod

EXPOSE 3000

ENTRYPOINT [ "npm", "start" ]

A imagem final tem aproximadamente 120mb, mas a imagem alpine do Node tem 28Mb, ou seja, temos aproximadamente 90mb de aplicações e dependências nesta imagem. Se estivéssemos utilizando uma imagem full, este tamanho seria facilmente maior do que 1gb.

Conclusão

Saber criar as suas imagens é uma habilidade importante, pois com ela podemos reduzir o tamanho e transformar nossa aplicação em algo muito mais conciso e leve que facilite muito mais o download e uso das nossas imagens.

Não se esqueça de se inscrever na newsletter para mais conteúdo exclusivo e notícias semanais! Curta e compartilhe seus feedbacks nos comentários!

Até mais!

]]>
<![CDATA[ Faça código em qualquer lugar com os Codespaces ]]> https://blog.lsantos.dev/faca-codigo-em-qualquer-lugar-com-os-codespaces/ 5f358fec82fe71827326564f Qui, 13 Ago 2020 19:20:32 -0300 O sonho de qualquer pessoa que trabalha com tecnologia é estar sempre com o seu melhor amigo, o seu computador. Existem diversas soluções que transformam pequenos dispositivos como Raspberry Pis em computadores completos, outras soluções criam pequenos computadores de bolso que podem ser acessados a todo o momento.

Existem vários motivos para alguém precisar – ou apenas gostar – de estar com um computador ao seu lado o tempo todo. Muitas vezes a pessoa prefere ter uma ferramenta super poderosa sempre a mão para eventuais problemas ou até mesmo desenvolver aquela ideia que teve no meio da rua. Em outros casos mais especiais, a pessoa pode ser uma das mantenedoras de projetos críticos e precisa estar sempre disposta a resolver eventuais problemas, isto tira a liberdade de locomoção, possuir um dispositivo destes faz com que a pessoa possa ganhar sua mobilidade de volta.

Podemos ter as melhores máquinas portáteis, porém nenhum computador se iguala ao nosso próprio, com nossos ambientes e com nossas configurações.

Codespaces

Tela de abertura do site do GitHub Codespaces

Recentemente o GitHub em seu evento Satellite 2020 o lançamento de uma nova funcionalidade na plataforma, os Codespaces. No momento, ela está disponível somente mediante a requisição de acesso antecipado pelo site. Porém, você pode ser um dos que recebeu acesso recentemente e poderá acessar essa incrível facilidade!

Por enquanto o Codespaces do GitHub está em beta e você pode não ter a funcionalidade habilitada. Então você não conseguirá ver o que mostrarei a seguir, porém você poderá se cadastrar diretamente no site para receber um acesso antecipado.

Os codespaces são uma implementação online do Visual Studio Code. Por ser um editor baseado em tecnologias web, o VSCode tem a incrível facilidade de ser um dos poucos projetos que podem ser portados entre plataformas de forma extremamente fácil.

Isso já havia sido feito antes com o Code Server – nós até chegamos a utilizar uma implementação interessante criada pelo Alejandro Oviedo, nosso colega da Argentina, no Nodeschool SP – porém um dos grandes problemas do Code Server eram que a loja de extensões não suportava todas as extensões existentes para o VSCode e também que o editor se confundia quando utilizávamos teclados com layouts diferentes.

A grande vantagem que o GitHub Codespaces (GH Codespaces ou GHC) trouxe é que ele é integrado diretamente ao GitHub, ou seja, você pode abrir qualquer repositório que você tenha permissão de escrita em um editor pronto na web! Veja um exemplo do meu repositório GotQL:

Tela de clonagem de um repositório do GitHub mostrando o botão "Open with Codespaces"

E tudo isso é grátis, tanto para repositórios pagos quanto para privados.

Como funciona

Os Codespaces são construídos em cima de uma outra solução já existente da Microsoft chamada Visual Studio Codespaces (VSC), que é uma excelente alternativa paga ao GH Codespaces quando você está procurando algo mais aberto, isto porque os VS Codespaces criam uma máquina virtual na Azure e conectam-se a ela através da funcionalidade nativa do VSCode chamada Remote Development.

O Remote Development se conecta a um outro computador rodando um pequeno servidor do outro lado. Ou seja, você consegue separar o processamento do editor, da interface. Dessa forma você consegue praticamente rodar o VSCode em qualquer lugar, porque todo o browser que suporte JavaScript mais recente consegue executar a interface do editor.

E então unimos outra tecnologia sensacional que são os containers. Como você já deve ter visto aqui mesmo no blog, os containers são uma tecnologia incrível que permite que você rode praticamente todas as aplicações de forma auto contida sem dependender de bibliotecas externas. Os Codespaces tiram muitas vantagens disso principalmente para que eles possam construir as imagens das máquinas que vão executar.

Dessa forma podemos ter um container que contém todas as ferramentas necessárias para o nosso projeto rodar, porque ele é completamente customizável.

Visual Studio Codespaces

Tela de abertura do Visual Studio Codespaces

Antes de mergulharmos no GitHub Codespaces, vou mostrar como podemos utilizar os VS Codespaces para criar um ambiente de desenvolvimento remoto, para que possamos entender com o que estamos lidando

Depois de fazer o login e criar sua instância do VSC, vamos criar um novo codespace:

Botão de criação para um Visual Studio Codespace

E, após clicarmos no botão "Create Codespace", as coisas começam a ficar interessantes, pois começamos a ter uma série de opções sensacionais que podem ser ativadas:

Tela de opções do Visual Studio Codespaces

A primeira opção é bem simples, temos que dar um nome para nosso codespace, será o nome que vamos identificar essa máquina, então precisa ser um nome bem descritivo.

Depois, temos a opção mais interessante, o próprio VSC já permite que começemos um Codespace a partir de outro repositório do GitHub, ou seja, o próprio GH Codespaces é uma interface diferente para os VSCs.

A partir daí temos a configuração das nossas VMs, então podemos escolher o quão forte a nossa máquina remota vai ser e também quanto tempo de ociosidade ela pode ter antes de se suspender para não gastar.

E então entramos na parte mais legal! Podemos definir o que são chamados de dotfiles, que são os arquivos de configuração do nosso shell. Dessa forma, nós podemos ter um repositório separado de dotfiles – como eu tenho – e um script para instalar estes dotfiles na nossa máquina online, ou seja, podemos replicar exatamente o que temos no nosso computador local em uma interface web!

Visual Studio Codespace online

GitHub Codespaces

Com o GHC é exatamente a mesma coisa! A única ação diferente que você terá de fazer será entrar em um repositório – como o GotQL – clicar no botão verde que seria o "clonar". Então clicar em "open with codespace":

Abrindo um novo repositório com codespace

Todos os usuários beta tem direito a 2 codespaces gratuitos. Ou seja, você pode manter até 2 máquinas de desenvolvimento sem pagar absolutamente nada. Depois, você precisará remover as antigas para criar novas. No exemplo do GotQL, temos a opção de abrir com o Codespaces, esta ação já vai criar um ambiente pronto para desenvolvimento, com todas as dependências instaladas

Mas como fazemos isso?

Personalização

Uma das funcionalidades mais legais dos codespaces é o fato de que eles são completamente personalizáveis.

No caso dos dotfiles, você pode configurar tanto o seu VSCode local (o editor instalado na sua máquina) para buscar uma série de arquivos conforme esta documentação explica ou, no caso do GitHub, você pode ter diretamente um repositório chamado dotfiles, como a documentação do GitHub explica.

Porém você pode fazer mais do que isso com uma pasta chamada .devcontainer. O que esta pasta faz é agrupas as configurações possíveis para um codespace. Nela podemos ter um arquivo Dockerfile, um arquivo chamado devcontainer.json e um arquivo sh que seria a configuração da shell do nosso ambiente. Quando criarmos um codespace a partir de um repositório, o GitHub irá buscar esta pasta no repositório e irá criar o codespace de acordo com ela.

Vamos ver o exemplo do .devcontainer do GotQL. Nós temos um Dockerfile, ele é o responsável por dizer qual tipo de container, ou qual tipo de ambiente vamos ter, será nele que vamos instalar pacotes, criar usuários e etc. Bem como escolher a imagem do nosso sistema operacional base.

FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:14

# The javascript-node image includes a non-root node user with sudo access. Use 
# the "remoteUser" property in devcontainer.json to use it. On Linux, the container 
# user's GID/UIDs will be updated to match your local UID/GID when using the image
# or dockerFile property. Update USER_UID/USER_GID below if you are using the
# dockerComposeFile property or want the image itself to start with different ID
# values. See https://aka.ms/vscode-remote/containers/non-root-user for details.
ARG USERNAME=node
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Alter node user as needed, install tslint, typescript. eslint is installed by javascript image
RUN if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
        groupmod --gid $USER_GID $USERNAME \
        && usermod --uid $USER_UID --gid $USER_GID $USERNAME \
        && chmod -R $USER_UID:$USER_GID /home/$USERNAME \
        && chmod -R $USER_UID:root /usr/local/share/nvm /usr/local/share/npm-global; \
    fi \
    #
    # Install tslint, typescript. eslint is installed by javascript image
    && sudo -u ${USERNAME} npm install -g tslint typescript gitmoji-cli

Então, quando um codespace do GotQL for criado, será esse o ambiente que vamos ter, um ambiente com um usuário não root com acesso ao sudo e o tslint e TypeScript já instalados. Também adicionei o gitmoji-cli que é o padrão de commits que uso neste projeto.

Depois, temos o arquivo devcontainer.json, que é o responsável não só por setar as configurações do nosso editor mas também por dar as direções para o construtor do codespace. Nele definimos o nome do codespace, as extensões que nosso VSCode online terá logo que for iniciado, qual é o Dockerfile que ele precisará usar para construir a base do sistema e também podemos sobrescrever as configurações do próprio VSCode.

{
  "name": "TypeScript website codespace",
  "extensions": [
    "emmanuelbeziat.vscode-great-icons",
    "dbaeumer.vscode-eslint",
    "oderwat.indent-rainbow",
    "vtrois.gitmoji-vscode",
    "dracula-theme.theme-dracula",
    "2gua.rainbow-brackets",
    "ms-vscode.vscode-typescript-tslint-plugin"
  ],
  "dockerFile": "Dockerfile",
  // Set *default* container specific settings.json values on container create.
  "settings": { 
    "terminal.integrated.shell.linux": "/bin/bash",
    "window.autoDetectColorScheme": true,
    "workbench.preferredDarkColorTheme": "Dracula",
    "editor.renderWhitespace": "boundary",
    "workbench.colorTheme": "Dracula",
    "workbench.iconTheme": "vscode-great-icons"
  },
  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "npm install"
}

Além disso temos a adição de um postCreateCommand, que é extremamente útil para rodar comandos depois que o codespace foi criado, neste caso estamos rodando o comando npm install, pois assim já teremos todos os pacotes instalados quando abrirmos.

Também temos um excelente repositório de exemplos de codespaces que podem servir de base para que você possa criar os seus. Vamos buscar o arquivo setup.sh do exemplo de codespace para Node

## update and install some things we should probably have
apt-get update
apt-get install -y \
  curl \
  git \
  gnupg2 \
  jq \
  sudo \
  zsh

## set-up and install yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn -y

## install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

## setup and install oh-my-zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
cp -R /root/.oh-my-zsh /home/$USERNAME
cp /root/.zshrc /home/$USERNAME
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc

Este arquivo é referenciado dentro do Dockerfile, sendo executado assim que é iniciado.

Conclusão

Os codespaces podem se tornar uma das principais tecnologias que temos atualmente, principalmente pelo fato de que eles permitem uma edição ou então até mesmo um desenvolvimento mais complexo utilizando aparelhos móveis como o celular.

Muitos programadores já utilizavam soluções baseadas no Docker para programar no ipad, porém estas soluções acabavam sempre sendo mais como "gambiarras" do que soluções propriamente ditas.

Com o surgimento de tecnologias e funcionalidades como estas, temos a capacidade de levar nosso ambiente de trabalho para qualquer lugar. Fiquem ligados nos próximos artigos onde vou explicar como montei meu ambiente de trabalho remoto usando o GHC!

Até mais!

]]>
<![CDATA[ Hipsters.tech #212 - Tecnologias Cloud na Microsoft ]]> https://blog.lsantos.dev/hipsters-tech-212/ 5f297e2982fe7182732655c1 Ter, 04 Ago 2020 17:21:26 -0300 Esta semana tive o prazer imenso de participar mais uma vez do meu podcast de tecnologia favorito! O Hipsters.tech.  Já acompanho o Hipsters há anos, praticamente desde que o projeto começou e poder participar dele é uma das coisas que tenho mais orgulho!

Neste podcast comentamos sobre tecnologias cloud da Microsoft, como funciona a cloud, como a Azure surgiu e como você pode criar aplicações utilizando o que já existe por lá!

Além do que comentamos no podcast, falamos de várias coisas super legais! Vou deixar a lista de todos os links que chegamos a puxar o assunto!

Temos o Microsoft Learn! Um serviço completamente gratuito que você pode usar para aprender qualquer tecnologia cloud Microsoft:

Microsoft Learn
The skills required to advance your career and earn your spot at the top do not come easily. Now there’s a more rewarding approach to hands-on learning that helps you achieve your goals faster. Earn points, levels, and achieve more!

O curso de introdução à Azure gratuito do Microsoft Learn:

Deploy a website to Azure with Azure App Service learning path - Learn
In this learning path, get acquainted with using Azure App Service to create and deploy your website without underlying servers, storage or network assets.

Toda a documentação da Microsoft sobre a Azure:

Azure documentation
Learn how to build and manage powerful applications using Microsoft Azure cloud services. Get documentation, example code, tutorials, and more.

Visual Studio Codespaces, que permite a você criar uma instância do seu VSCode e utilizá-lo online!

Visual Studio Codespaces
]]>
<![CDATA[ Executando Containers no Azure Container Instancies com Docker ]]> https://blog.lsantos.dev/executando-containers-no-azure-container-instancies-com-docker/ 5f230a1c82fe71827326548d Seg, 03 Ago 2020 10:00:00 -0300 Se você já utiliza Docker então, provavelmente, já executou um container em sua máquina. Porém, já imaginou como seria se você pudesse executar diretamente um container em uma infraestrutura cloud sem precisar fazer nada novo?

No mês passado o time do Docker anunciou que as novas versões do Docker para desktop (chamadas de versões Edge) estariam ganhando o suporte nativo aos Azure Container Instances, ou seja, poderíamos rodar containers da nossa máquina diretamente para um ambiente cloud sem precisar baixar nenhuma imagem localmente!

Azure Container Instances

Os Azure Container Instances (ACI) é um dos produtos oferecidos pela Azure que permitem que você faça o deploy de uma aplicação em um container sem se preocupar com máquinas virtuais ou qualquer outro tipo de infraestrutura.

Já cheguei a utilizar o ACI quando realizamos uma talk para o #CodeInQuarentena. No vídeo abaixo você pode ver o vídeo onde criamos uma API completa utilizando Mongoke e ACI

Vídeo do Code In Quarentena sobre como fazer um deploy no ACI

Essencialmente, o ACI é uma forma de você rodar sua aplicação como um container online. Dessa forma a única coisa que você precisa ter é uma conta na Azure e uma aplicação que já esteja dentro de um container. O melhor é que isso é tudo cobrado pelo segundo de uso, então você realmente não para por computação ociosa. O que é excelente para aplicações que precisam ser criadas e destruídas rapidamente.

Mas como o ACI pode ser integrado com o Docker?

Integrando o ACI com o Docker

Vamos realizar a nossa integração entre o Docker e o ACI. Assumindo que você já possua uma conta na Azure e já conheça um pouco sobre Docker, o que você precisa fazer é baixar o Docker Edge.

Docker Edge

O Docker Edge é uma versão experimental do Docker que recebe todas as atualizações que ainda não foram disponibilizadas na versão de disponibilidade geral. Para que a integração com o ACI aconteça, como ela ainda é uma flag experimental, temos que baixar a versão Edge do Docker, este repositório tem todos os links necessários para instalação em várias plataformas.

Se você tem o Docker instalado na sua máquina, você precisará remover a versão CE oficial e instalar o Docker Edge. Não é possível ter ambas as versões instaladas na mesma máquina.

Uma vez que o Docker estiver instalado, você deverá ver esta tela:

Imagem mostrando a página principal de preferências do Docker Edge

Veja na aba Command Line se você possui a opção Enable Cloud Experience ativada:

Imagem mostrando a opção "Enable Cloud Experience" ativa nas ferramentas do Docker

Com isto você já tem a integração ativa, agora o que precisamos fazer é criar um contexto!

Docker Context

Os contextos do Docker não são uma funcionalidade nova. O objetivo dos contextos é permitir que você possa alterar o local de onde você está trabalhando. Isto é muito interessante depois do advento do Kubernetes para Docker, pois com os contextos você pode alterar entre o uso do Docker engine, do Kubernetes dentro do Docker ou até mesmo de um contexto do Docker Swarm.

Com o ACI não é diferente, temos que criar um contexto para a integração com a cloud! Isso é bastante simples, primeiro temos que logar na Azure através do seguinte comando:

$ docker login azure

Após isto, você será levado ao site da Azure para realizar o login, uma vez que ele for completado, você poderá voltar para o CLI e executar o seguinte comando:

$ docker context create aci nome-do-contexto

Em seguida você terá de escolher a sua subscription e depois o resource group que será utilizado para subir as imagens. Uma vez terminado, você poderá rodar o comando docker context ls para ver todos os contextos existentes e a sua integração está completa!

Criando um container

Para podermos executar este exemplo, vamos usar uma imagem pública que tenho no Docker Hub, chamada Simple Node API.

Vamos começar trocando o nosso contexto para o novo contexto criado através do comando docker context use <nome-do-contexto>.

Para fazermos o deploy, podemos rodar o comando que estamos acostumados, o docker run:

$ docker run -d -p 80:80 --name node-api -e PORT=80 khaosdoctor/simple-node-api

Veja o output que vamos ter:

Para conseguirmos buscar o caminho que devemos acessar para vermos a nossa API online, vamos executar um docker ps e buscar os conteúdos de PORTS.

Veja que tenho que acessar o IP 13.86.141.148 para poder ver o resultado da API no browser, vamos lá!

Imagem mostrando o browser acessando o IP anterior e o resultado da API com a frase "Hello World"

Veja que, se acessarmos o portal da Azure, vamos ter o nosso recurso criado como se tivéssemos criado manualmente!

Imagem do portal da Azure com o nosso recurso "node-api" criado

Para removermos, basta executar o comando docker rm <nome>, veja que não é possível executar o comando docker stop porque este tipo de integração não permite que paremos o container remotamente. Se digitarmos docker rm node-api vamos ter o nosso ACI removido da azure e o nosso container parado!

Outras aplicações

Podemos utilizar também o ACI para criar aplicações multi-container usando o Docker Compose. Para isto, vamos utilizar o próprio exemplo que a Docker nos dá do site da DockerCon! Temos o seguinte arquivo YAML:

# docker-conpose.yaml
version: '3.3'

services:
  db:
    image: bengotch/acidemodb
  
  words:
    image: bengotch/acidemowords
  
  web:
    image: bengotch/acidemoweb
    ports:
      - "80:80"

Fazemos o mesmo processo. Porém, ao invés de rodar o comando docker run vamos rodar o comando docker compose up -d.

Note que não temos um - entre o docker e o compose como era de se esperar quando estamos rodando o comando localmente. Porque o compose é um comando da integração em si!

Depois podemos utilizar o comando docker ps normalmente para pegar o IP público e ver o site no ar:

Site da DockerCon no ar utilizando a integração com ACI

Limitações

  • O ACI não suporta mapeamento de portas, portanto você precisa ter certeza de que seu container está rodando na mesma porta no host e no container através da flag -p porta:porta (veja esta issue)
  • Nem todos os comandos presentes no docker estão presentes na integração (veja esta outra issue para mais detalhes)

Conclusão

Com a integração do ACI podemos integrar muito mais rápido com a Azure e isso facilita muito o desenvolvimento de aplicações voltadas para a cloud! Experimente você também!

Não se esqueça de se inscrever na newsletter aqui embaixo para mais conteúdo exclusivo e notícias semanais! Curta e compartilhe seus feedbacks nos comentários logo após o post!

Até mais.

]]>
<![CDATA[ Imersão Alura React Live #02 - Usando TypeScript no nosso projeto ]]> https://blog.lsantos.dev/imersao-react-live-02-usando-typescript-no-nosso-projeto/ 5f21fc6a82fe7182732653e2 Qua, 29 Jul 2020 20:28:30 -0300 Hoje tive o prazer de participar junto com o Mario Souto da #ImersãoAlura uma live super animada sobre como podemos utilizar TypeScript no nosso projeto React!

Veja como foi a live no vídeo abaixo:

Veja o vídeo da imersão React live!

Durante a live tivemos várias perguntas super pertinentes sobre como funcionava o TypeScript, quais eram as diferenças entre um tipo e uma interface, além de muitos outros conteúdos muito legais!


Conteúdo Comentado

Para facilitar o seu aprendizado, estou agrupando aqui todo o conteúdo relacionado que comentamos durante o vídeo!

Symbol.Iterator

Logo no início da live comentamos sobre a evolução do JavaScript e como o Node.js e o CoffeeScript foi essencial para que o ecossistema evoluísse. Então comentamos um pouco sobre Iterators e Downleveling.

Para que você entenda um pouco sobre Iterators, separei um artigo que escrevi há um tempo:

Javascript— Entendendo Iterators
Com certeza você já ouviu falar sobre iterators em outras linguagens como o C++ e o C#, mas aposto que você não sabia que o Javascript também era um adepto deste protocolo.

E, para complementar, um artigo sobre Symbols:

Javascript Symbols: Decifrando o mistério
Neste artigo conheça o mundo obscuro do Javascript, os Symbols, saiba que eles são estruturas extremamente poderosas e para que você pode utiliza-las!

Node.js Por baixo dos Panos

O Mário comentou sobre uma série de artigos que produzi ao longo de um ano sobre os fundamentos do Node.js, estes artigos podem ser encontrados aqui:

Node.js Por Baixo dos Panos #1 - Conhecendo nossas ferramentas
Esta é uma tradução do meu artigo original Recentemente eu fui convidado para fazer uma palestra em...

Além disso, você pode encontrar também uma palestra minha sobre este tema (em inglês) no The Conf 2019:

Veja os slides aqui:

Deno

Tivemos muitas perguntas sobre Deno também! Por isso vou deixar aqui o Hipsters que participei sobre a tecnologia!

Deno, o novo Node? - Hipsters #203 - Hipsters Ponto Tech

E aproveito para deixar um tutorial de como fazer o deploy de uma aplicação Deno para a Azure!

Deploy Deno apps to Azure App Service from the Azure CLI
Tutorial part 1, introduction and prerequisites.

Promises

Uma pergunta bastante comum e um grande problema para quem está aprendendo JavaScript é o entendimento do fluxo assíncrono de mensagens usando Promises! Por isso vou deixar aqui um artigo que escrevi sobre o assunto

Entendendo Promises de uma vez por todas
Promises sempre foram o calcanhar de Aquiles de muitos programadores. Com este guia vamos desmistificar o que é uma Promise e como ela funciona

Juntamente com a Live que participei sobre o tema:

Ajude a traduzir o site do TypeScript!

Estou, em conjunto com meu colega Orta – que coordena a criação e desenvolvimento do site do TypeScript – coordenando a tradução para a língua portuguesa do site do TypeScript. Você pode nos ajudar traduzindo os arquivos!

Tenha seu código no repositório oficial do website 😱

Portuguese Localization Coordination · Issue #233 · microsoft/TypeScript-Website
tsconfig intro.md allowJs.md allowSyntheticDefaultImports.md allowUmdGlobalAccess.md allowUnreachableCode.md allowUnusedLabels.md compilerOptions.md top_level.md watchOptions.md Additional_Checks_6...

Outros conteúdos relacionados

O TypeScript é um mundo imenso, então estou linkando alguns outros posts e conteúdos sobre o universo TypeScript que podem abrir a sua mente para as coisas que você pode realizar

Padrões de projeto com TS

Escrevi um guia de algumas partes sobre como podemos aplicar padrões de projetos com TypeScript lá no iMasters!

Artigo novo: Design Patterns com JavaScript & TypeScript
Os Design Patterns fazem parte do dia-a-dia de uma pessoa desenvolvedora de software quer ela queira ou não, muitas vezes nem sabemos

Arquitetura de projetos com TS

Em conjunto com outras pessoas produzi alguns vídeos sobre como podemos aplicar diversas arquiteturas como Event Sourcing:

Event Sourcing - A arquitetura que pode salvar seu projeto - iMasters - We are Developers
No seguinte artigo, Lucas Santos apresenta os conceitos do Event Sourcing e explica suas principais vantagens e desvantagens.

Juntamente com o vídeo explicativo:

E os slides para esta palestra:

E, para finalizar, o conteúdo sobre como podemos criar uma aplicação em camadas usando TS!


Espero que tenham gostado da live!

Não deixe de acompanhar mais do meu conteúdo no meu blog e se inscreva na newsletter para receber notícias semanais!

Até mais!

]]>
<![CDATA[ Um Mergulho em Imagens de Containers - Parte 2 ]]> https://blog.lsantos.dev/um-mergulho-em-imagens-de-containers-parte-2/ 5f2074cc82fe718273265324 Qua, 29 Jul 2020 10:00:00 -0300 No último post da nossa série falamos um pouco sobre o que são as imagens de containers e como elas se dividem. Passamos sobre o que é uma imagem slim, uma imagem full e falamos sobre as imagens alpine. Mas, o que isso impacta para a sua aplicação?

A aplicação

Vamos construir uma aplicação simples utilizando Go que serve um arquivo estático em HTML para descrever como podemos otimizar a nossa imagem para a nossa aplicação.

Não vamos desenvolver esta aplicação aqui, vamos apenas imaginar a seguinte situação:

  • Temos uma aplicação em Go que serve um arquivo estático HTML
  • Esta aplicação compila sem erros, é pequena e rápida

Otimizando a build

Para linguagens compiladas como: Go, C#, Java e outras, uma boa prática antes até de escolher qualquer tipo de sistema operacional base é otimizar a compilação, ou build da aplicação. Para isso, o que é geralmente utilizado, porém não muito divulgado, é o que é chamado de builds de múltiplos estágios.

Quando realizamos a compilação de alguma aplicação, geralmente o container que está fazendo esta compilação possui todas as ferramentas necessárias para que a compilação seja feita. Isso inclui ferramentas que não são necessárias no ambiente de execução. Por exemplo, com o Go, não temos que possuir o runtime inteiro instalado, pois ele já é capaz de rodar como um binário único, então não faz sentido termos todo esse ferramental instalado no nosso container que vai ser executado em produção.

E é isso que as builds de múltiplos estágios fazem. Começamos com um container – que contém todo o ferramental para a build da aplicação, geralmente um container próprio para aquela linguagem – e depois movemos somente o binário gerado no final para um novo container vazio. Neste container vazio não temos nenhuma dessas ferramentas que não vamos precisar utilizar em produção.

Este tipo de build é utilizado para manter as imagens de produção as menores possíveis, assim não temos problemas com entrada e saída de rede e também temos menos dados para baixar! E a grande vantagem é que podemos fazer isso direto do nosso Dockerfile!

Criando uma build otimizada

Para começarmos, vamos criar o Dockerfile, dentro dele vamos criar os passos responsáveis por fazer com que a aplicação seja construída:

FROM golang:1.11-stretch as build

WORKDIR /go/src/github.com/khaosdoctor/webapp

COPY web.go web.go

RUN CGO_ENABLED=0 GOOS=linux go build -o ./bin/webapp github.com/khaosdoctor/webapp

FROM debian:stretch

RUN mkdir -p /web/static/ 

COPY --from=build /go/src/github.com/khaosdoctor/webapp/bin/webapp /usr/bin
COPY index.html /web/static/index.html

WORKDIR /web

EXPOSE 3000

ENTRYPOINT ["webapp"]

Veja que estamos dando um nome ao primeiro container como FROM <imagem>:<tag> as build, o as build é o que dá o nome ao nosso container intermediário e diz que este container não será o passo final da nossa esteira de construção.

Veja que estamos usando uma imagem full na construção. Isso é ok porque esse container vai ser descartado.

Vamos pular uma linha e criar o nosso próximo container, que será o container final com nossa aplicação já construída para produção:

# Começo do container de build
FROM golang:1.11-stretch as build

WORKDIR /go/src/github.com/khaosdoctor/webapp

COPY web.go web.go

RUN CGO_ENABLED=0 GOOS=linux go build -o ./bin/webapp github.com/khaosdoctor/webapp

# Começo do container de produção
FROM debian:stretch-slim

RUN mkdir -p /web/static/ 

COPY --from=build /go/src/github.com/khaosdoctor/webapp/bin/webapp /usr/bin
COPY index.html /web/static/index.html

WORKDIR /web

EXPOSE 3000

ENTRYPOINT ["webapp"]

Perceba uma instrução importante. Estamos usando COPY --from=build, ou seja, estamos dizendo para o Docker copiar os arquivos não do nosso filesystem, mas sim de outro container intermediário! Isso é o que define uma build de múltiplos estágios.

Reduzindo o tamanho da imagem

Agora veja que estamos utilizando uma imagem debian:stretch-slim, como já vimos, essa imagem é menor do que uma imagem full, portanto tem menos vulnerabilidades e ocupa menos espaço. Um teste de construção das duas imagens mostra que a imagem full tem mais ou menos 110mb contra 62mb da imagem slim.

Além das duas imagens, temos mais um tipo de imagem que comentamos, a alpine, que é baseada no Alpine Linux. Para isso a gente só precisa mudar a imagem base para o alpine:3.8

# Começo do container de build
FROM golang:1.11-stretch as build

WORKDIR /go/src/github.com/khaosdoctor/webapp

COPY web.go web.go

RUN CGO_ENABLED=0 GOOS=linux go build -o ./bin/webapp github.com/khaosdoctor/webapp

# Começo do container de produção
FROM alpine:3.8

RUN mkdir -p /web/static/ 

COPY --from=build /go/src/github.com/khaosdoctor/webapp/bin/webapp /usr/bin
COPY index.html /web/static/index.html

WORKDIR /web

EXPOSE 3000

ENTRYPOINT ["webapp"]

Agora temos uma imagem de 11mb e sem nenhuma vulnerabilidade ou dependência externa. Então podemos ver que mover uma imagem para o Alpine é uma excelente pedida quando estamos trabalhando com aplicações compiladas que já possuem seu runtime junto com seu binário.

Otimizando do zero

Para finalizar, vamos tentar colocar nossa aplicação em uma imagem scratch. Se lembrarmos bem, uma imagem scratch, na verdade, não possui absolutamente nada instalado, ou seja, ela é uma imagem "from scratch". Aqui vamos poder ver duas principais mudanças.

A primeira será no nosso container de build:

# Começo do container de build
FROM golang:1.11.2-alpine3.8 as build

WORKDIR /go/src/github.com/khaosdoctor/webapp

COPY web.go web.go

RUN CGO_ENABLED=0 GOOS=linux go build -o ./bin/webapp github.com/khaosdoctor/webapp

Veja que estamos utilizando o Alpine para buildar nossa aplicação, uma vez que o scratch não possui absolutamente nada. Então vamos construir a imagem em um container Alpine e copiar o binário para o container de produção scratch.

Podemos fazer isso também com a imagem de build no container Slim. Isso fará com que a build seja ainda mais rápida porque a imagem de build será menor.

Agora vamos copiar o binário do Go para dentro da imagem scratch:

# Começo do container de build
FROM golang:1.11.2-alpine3.8 as build

WORKDIR /go/src/github.com/khaosdoctor/webapp

COPY web.go web.go
COPY index.html /web/static/index.html

RUN CGO_ENABLED=0 GOOS=linux go build -o ./bin/webapp github.com/khaosdoctor/webapp

# Começo do container de produção
FROM scratch

RUN mkdir -p /web/static/ 

COPY --from=build /go/src/github.com/khaosdoctor/webapp/bin/webapp /usr/bin
COPY --from=build /web/static/index.html /web/static/index.html

EXPOSE 3000

ENTRYPOINT ["/usr/bin/webapp"]

Perceba que fizemos duas mudanças principais:

  1. Tiramos a instrução WORKDIR, porque o scratch não tem um sistema de arquivos inicial, então tudo está no mesmo diretório
  2. O ENTRYPOINT agora é um caminho completo, pois o container scratch não possui um PATH para olhar uma vez que ele não tem um SO

Com isso, reduzimos ainda mais o tamanho da imagem para 7mb. E, além disso, temos a melhor segurança possível, já que não temos nenhum tipo de pacote instalado na nossa imagem.

Conclusão

Aprendemos como melhor construir uma imagem para uma linguagem compilada, neste caso foi Go, mas você pode transpor essa criação para qualquer outra linguagem que precise de compilação prévia!

Não se esqueça de se inscrever na newsletter aqui embaixo para mais conteúdo exclusivo e notícias semanais! Curta e compartilhe seus feedbacks nos comentários logo após o post!

Até mais.

]]>
<![CDATA[ Meetup: 1º Meetrybe - Arquitetura de código ]]> https://blog.lsantos.dev/1-meetrybe-arquitetura-de-codigo/ 5f1c583282fe718273265245 Sáb, 25 Jul 2020 14:01:16 -0300 Hoje participei do Meetrybe, o primeiro evento online da Trybe junto com um monte de gente de peso como: Elton Minetto, Rogério Munhoz e Igor Halfeld.

Depois de palestras sensacionais do Elton e da Ana Cardoso, montamos uma roda de perguntas e respostas sobre arquitetura de software. Tiramos diversas dúvidas super legais e ainda criamos frases icônicas como:

Todo o legado um dia já foi um hype

Foi uma conversa super descontraída! Dá uma olhada como rolou!

1º Meetrybe

Leitura recomendada

Dois excelentes livros clássicos sobre clean code e arquitetura clean:

Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin Series) (English Edition) - eBooks em Inglês na Amazon.com.br
Compre Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin Series) (English Edition) de Martin, Robert C. na Amazon.com.br. Confira também os eBooks mais vendidos, lançamentos e livros digitais exclusivos.
Livro Clean Code
Arquitetura Limpa: o Guia do Artesão Para Estrutura e Design de Software | Amazon.com.br
Compre online Arquitetura Limpa: o Guia do Artesão Para Estrutura e Design de Software, de Martin, Robert C., Henney, Kevlin, Gorman, Jason na Amazon. Frete GRÁTIS em milhares de produtos com o Amazon Prime. Encontre diversos livros escritos por Martin, Robert C., Henney, Kevlin, Gorman, Jason com ó…
Livro Clean Architecture

Você consegue também encontrar os dois livros acima em um pacote:

The Robert C. Martin Clean Code Collection (Collection) (Robert C. Martin Series) (English Edition) - eBooks em Inglês na Amazon.com.br
Compre The Robert C. Martin Clean Code Collection (Collection) (Robert C. Martin Series) (English Edition) de Martin, Robert C. na Amazon.com.br. Confira também os eBooks mais vendidos, lançamentos e livros digitais exclusivos.
Pacote clean architecture

O clássico livro do GoF sobre padrões de projeto, que estão inspirando meu conteúdo no iMasters:

Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos | Amazon.com.br
Compre online Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos, de Gamma, Erich, Helm, Richard, Johnson, Ralph, Vlissides, John, Salgado, Luiz A. Meirelles, Paulo, Fabiano Borges na Amazon. Frete GRÁTIS em milhares de produtos com o Amazon Prime. Encontre diversos livros …

Uma série de livros sensacional sobre gestão e aplicação de projetos

O Projeto Fênix: um Romance Sobre TI, DevOps e Sobre Ajudar o seu Negócio a Vencer | Amazon.com.br
Compre online O Projeto Fênix: um Romance Sobre TI, DevOps e Sobre Ajudar o seu Negócio a Vencer, de Kim, Gene, Spafford, George, Behr, Kevin na Amazon. Frete GRÁTIS em milhares de produtos com o Amazon Prime. Encontre diversos livros de Computação, Informática e Mídias Digitais com ótimos preços.
The Unicorn Project: A Novel about Developers, Digital Disruption, and Thriving in the Age of Data (English Edition) - eBooks em Inglês na Amazon.com.br
Compre The Unicorn Project: A Novel about Developers, Digital Disruption, and Thriving in the Age of Data (English Edition) de Kim, Gene na Amazon.com.br. Confira também os eBooks mais vendidos, lançamentos e livros digitais exclusivos.

Este livro sensacional sobre OOP com Java:

Design Patterns com Java: Projeto orientado a objetos guiado por padrões eBook: Guerra, Eduardo: Amazon.com.br: Loja Kindle
Design Patterns com Java: Projeto orientado a objetos guiado por padrões eBook: Guerra, Eduardo: Amazon.com.br: Loja Kindle

O livro clássico do Erick Evans sobre DDD:

Domain-Driven Design: Atacando as Complexidades no Coração do Software | Amazon.com.br
Compre online Domain-Driven Design: Atacando as Complexidades no Coração do Software, de Evans, Eric, Fowler, Martin na Amazon. Frete GRÁTIS em milhares de produtos com o Amazon Prime. Encontre diversos livros escritos por Evans, Eric, Fowler, Martin com ótimos preços.

Conclusão

É isso ai pessoal! Espero que gostem do conteúdo! Não deixem de curtir e compartilhar o post e se inscrever na newsletter para conteúdos exclusivos por email!

Valeu!

]]>
<![CDATA[ Um Mergulho em Imagens de Containers - Parte 1 ]]> https://blog.lsantos.dev/um-mergulho-em-imagens-de-containers-parte-1/ 5f183ff2f1911484af3ab9b0 Sex, 24 Jul 2020 10:00:00 -0300

Recentemente li uma série de artigos do Scott Coulton[1][2][3] no Medium sobre como escolher as imagens base para seus containers. Decidi então escrever estes artigos para que outras pessoas também possam entender como escolher melhor como começar a criar seus containers usando Docker da melhor forma possível!


  1. I Chose You Container Image - Part 1 ↩︎

  2. I Chose You Container Image - Part 2 ↩︎

  3. I Chose You Container Image - Part 3 ↩︎

Imagens Base

Quando começamos a criar nossas imagens, a primeira coisa que temos que nos preocupar é: Qual será a imagem base que vamos utilizar para a nossa aplicação?

Por exemplo, eu crio muitas imagens que utilizam o Node.js, portanto minha escolha natural seria utilizar uma imagem base do próprio Node, como a node:14 que é uma imagem oficial presente no DockerHub.

Porém eu poderia tranquilamente criar minha própria imagem tendo o Node como uma ferramenta instalada ao invés de tê-la nativamente a partir da minha imagem base. Para isso, basta que eu escolha uma outra imagem base que contenha apenas o sistema operacional, poderíamos utilizar a imagem do Debian e então criar um Dockerfile parecido com o seguinte:

FROM debian:buster 
RUN sudo apt update \ 
    && sudo apt upgrade -y \ 
    && sudo apt install -y curl \ 
    && curl -sL https://deb.nodesource.com/setup_14.x | bash - \ 
    && sudo apt install -y nodejs

O que não é muito diferente do que é feito na imagem oficial. Mas será que estamos criando uma imagem que possui os requisitos básicos para que ela seja utilizada por outras pessoas?

O que quero dizer com esta introdução é que temos que pensar muito além da imagem base. Qualquer imagem do Docker precisa ser pensada para obter a melhor escalabilidade e usabilidade possível. Isto é feito com os seguintes requisitos:

  • O tamanho da imagem é pequeno o suficiente
  • A aplicação que executará dentro da imagem possui uma boa performance
  • A segurança está garantida dentro da imagem base

Para podermos atacar todas as partes, vamos trabalhar com linguagens compiladas – como Golang – na próxima parte deste artigo e, na última parte, vamos trabalhar com linguagens dinâmicas – como JavaScript ou Python.

Tipos de imagens base

Para deixar a escolha diretamente a quem lê, não vou dizer se um sistema operacional é melhor que outro, afinal isto é uma escolha completamente pessoal. Ao invés disso, vamos trabalhar com três tipos de nomenclaturas:

  • Imagens full
  • Imagens slim
  • Imagens alpine

Imagens Full

departure from Euromax terminal, 400 meters long
Foto de um navio carregado de containers Andrey Sharpilo / Unsplash

As imagens full (ou completas), são imagens que contém toda a extensão de um sistema operacional, por exemplo, uma imagem debian-full é uma imagem que possui a distribuição Debian do Linux por completo, com todos os pacotes e módulos carregados.

Este tipo de imagem é o melhor tipo de imagem para se começar e, provavelmente, o jeito mais simples de colocar uma aplicação no ar. Isto porque elas possuem todas as ferramentas e pacotes já instalados por padrão.  Neste artigo vamos apenas comparar as imagens e não vamos nos preocupar muito com as aplicações que vamos rodar dentro delas.

Um dos grandes problemas de imagens full é que, por terem muitos pacotes instalados por padrão, isso significa que existem muitos pacotes com vulnerabilidades comprovadas que também vem instalados por padrão. Isto abre portas para que um ataque possa ocorrer.

O próprio Docker Hub possui uma ferramenta de análise de vulnerabilidades que pode ser utilizada diretamente do site, através da aba Tags. Como mostra a imagem a seguir.

Detecção de vulnerabilidades do Docker Hub

Como você pode ver, a própria imagem tem vulnerabilidades que você está "herdando" antes mesmo de fazer qualquer deploy do seu código.

Imagens Slim

Foto de uma etiqueta escrito "the slim" Mat Reding / Unsplash

Uma imagem slim é uma imagem um pouco menor. Toda a imagem slim só possui os pacotes necessários para que o sistema operacional funcione, é esperado que você instale todos os pacotes extras para que sua aplicação possa funcionar. Atualmente, só o Debian possui uma imagem slim.

Um dos benefícios diretos do uso de imagens slim é que, por ter menos pacotes, você tem menos dependências que podem estar sujeitas a vulnerabilidades. Veja um exemplo.‌

Vulnerabilidades de uma imagem slim

Outro ganho interessante é que, justamente por serem mais "limpas", imagens slim são muito menores em tamanho do que uma imagem full. Em casos mais extremos, uma imagem slim pode ser até 50% menor do que uma imagem full. Veja o exemplo da comparação do debian:buster com o debian:buster-slim.

Tamanho da imagem slim do Debian Buster

Agora veja o tamanho da imagem completa

Tamanho da imagem full do Debian Buster

Veja que, se pegarmos a arquitetura amd64, que é a mais comum para processadores de 64 bits, e compararmos as versões full com 48.06MB contra os 25.84MB da mesma imagem, só que na versão slim. Isso é uma redução de 47% no tamanho da imagem. Tudo isso só removendo pacotes não utilizados.

Imagens Alpine Linux

Foto dos Alpes por Benni Asal / Unsplash

As imagens Alpine Linux são o tipo de imagem mais otimizada possível. Este tipo de OS foi construído do zero para ser um sistema operacional já nativo de containers. A principal diferença entre esse tipo de imagem para uma imagem tradicional é que esse sistema não utiliza a glibc. O Alpine depende de uma outra biblioteca chamada musl libc. Além disso, por padrão, o Alpine só vem com os pacotes base instalados, ou seja, qualquer outra coisa que sua aplicação precisar, você vai ter que instalar manualmente.

Isso pode parecer um pouco complicado, mas veja como reduzimos a quantidade de vulnerabilidades só por reduzir os pacotes. Perceba que não há nenhuma vulnerabilidade crítica.

Vulnerabilidades de uma imagem Alpine

Além disso, uma imagem alpine tem menos de 6MB de tamanho total. No caso das imagens mais novas, esse tamanho pode chegar a pouco mais de 2MB. Isso é uma redução de mais 95% no tamanho geral da imagem.

Tamanho de uma imagem Alpine Linux

Os contras de se trabalhar com uma imagem Alpine é que é um sistema completamente diferente, você terá de aprender a lidar com seu package manager nativo, como ele não usa as bibliotecas padrões do Linux, provavelmente a grande maioria dos sistemas precisarão ser recompilados utilizando as ferramentas do Alpine.

Imagens Scratch

Foto de um papel preto sem nada escrito com um lápis branco em cima por Kelly Sikkema / Unsplash

Por último, vamos dar uma olhada nas imagens do tipo scratch. Quando usamos scratch como imagem base, estamos dizendo ao Docker que queremos que o próximo comando no nosso Dockerfile seja a primeira camada do nosso sistema de arquivos dentro dessa imagem.

Isso significa que não temos nenhum gerenciador de pacotes, nem mesmo pacotes. Somente um sistema de arquivos vazio. Você pode começar utilizando FROM scratch, já que este é um namespace reservado no DockerHub e não possui nenhum tipo de vulnerabilidade ou pacote instalado.

FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]

A maioria das imagens de sistemas operacionais começam deste modo, pois a maioria delas são consideradas imagens vazias. Que começam do absoluto zero.

Conclusão

Vamos explorar um pouco mais sobre imagens e colocar esses conceitos em prática nos próximos artigos escrevendo uma aplicação em Go.

Fique ligado para mais novidades! Se inscreva na newsletter para receber todo o conteúdo diretamente no seu e-mail!

]]>
<![CDATA[ Olá, Mundo! ]]> https://blog.lsantos.dev/ola-mundo/ 5f173a2ef1911484af3ab995 Qua, 22 Jul 2020 21:23:11 -0300 Olá pessoal! Este é o primeiro artigo deste blog!

Quem já me conhece e acompanha meu trabalho sabe que sou um grande fã de escrita de conteúdo escrito e já escrevo há algum tempo sobre tecnologia. Nos últimos 4 anos venho escrevendo bastante para publicações como o Medium e o Dev.to, mas chegou a hora de evoluir para uma nova fase da minha carreira como criador de conteúdo.

Neste post vou descrever tudo que me motivou a criar este blog, bem como vou descrever as tecnologias utilizadas e o que há de novo! Vamos lá!

Uma nova fase

The most powerful word in the world pops up everywhere. Ironically, this is on Sandown Pier on the Isle of Wight (UK) — a place that has not changed for 30 years.
Letreiro neon escrito "change" por Ross Findon / Unsplash

Nos últimos anos sempre pensei em criar um local próprio para compartilhar meu conteúdo, não que eu não considere as outras publicações boas o suficiente, muito pelo contrário, elas são excelentes locais para se publicar conteúdo no geral. O que me fez mudar foram dois simples fatores: controle e presença

Controle

O controle pelo simples fato de que eu gosto de ter o controle das minhas publicações para que eu possa criar integrações, modificar ou migrar o conteúdo, fazer backups seguros e manter o conteúdo de livre acesso. Além do controle do conteúdo em si, para mim é importante ter o controle sobre o meio onde eu estou publicando.

Plataformas como o Medium ou o Dev.to, por mais incríveis que sejam, ainda são limitadas em alguns casos. E você, como autor, não tem controle sobre o que você pode fazer com o sistema, nem sobre quais integrações pode criar, além disso todo o seu conteúdo está nas mãos das pessoas que controlam essas redes e, se um dia quiserem, podem simplesmente sumir da mesma forma que apareceram.

Além disso, ter um local próprio para publicar os meus conteúdos faz com que eu possa não só buscar novas formas de apresentar esse conteúdo, mas também que eu possa evoluir o site para ter novas funcionalidades bacanas e aplicar a minha marca pessoal. E ai entramos na presença.

Presença

Um dos pontos que mais me deixava incomodado era que eu tinha que mostrar uma lista de redes sociais para as pessoas quando eu queria que elas encontrassem meu conteúdo, isso dilui um pouco a sua presença e o seu impacto porque fica muito mais difícil para que as pessoas achem você na rede.

Outro ponto que me levou a criar este blog foi que eu poderia transformá-lo em um lugar "com a minha cara". Aplicar a marca que foi feita com carinho por várias pessoas que me ajudaram a transformar tudo isso que vocês estão vendo em realidade. Tendo poder sobre o front-end e podendo adicionar novas ferramentas, eu posso criar uma experiência diferente para algum tipo de post ou então até mesmo transformar o blog em um hub ou um agregador, em suma, eu posso fazer o que eu quiser!

Por isso decidi que criar um blog seria a melhor alternativa, pois assim posso centralizar o conteúdo de forma que todos os meus artigos sairão deste único ponto e posso pedir para que as pessoas me encontrem somente por aqui também.

E agora? Como vai ser?

A partir de agora, todos os conteúdos novos serão publicados primeiro neste blog. Eles também serão automaticamente replicados no meu Dev.to através do feed RSS.

Todos os conteúdos antigos continuarão existindo onde sempre estiveram. A única coisa que muda é que, a partir de agora, todos os novos conteúdos vão ser postados somente aqui no meu blog.

Criar um blog próprio também me permitiu criar uma página exclusiva para todas as pessoas que desejarem me apoiar o meu trabalho e me ajudar nesta empreitada através de doações ou contribuições.

Só artigos?

Em resumo: NÃO 😌

Como eu disse anteriormente, esta é uma nova fase de produção de conteúdos, ou seja, além do blog estarei também investindo em outros formatos de publicação de conteúdo. No momento o blog é o primeiro passo, porém já estou elaborando um canal do YouTube e também pensando em outras formas de compartilhar conteúdo de qualidade para ainda mais pessoas.

Todos os vídeos serão publicados no canal e terão um post dedicado no blog! Assim fica fácil saber de tudo o que ocorreu! Mas não é só isso. A ideia é que o blog se torne um arquivo de todo o meu conteúdo, tanto escrito quando não escrito.

Portanto, todas as minhas futuras palestras – que já podem ser encontradas no meu SpeakerDeck – ficarão também disponíveis aqui com uma pequena descrição de como ocorreram, e os detalhes sobre aquele evento em si, ou seja, todo o conteúdo que eu já participei ou vou participar ficará guardado aqui em segurança para que todos possam encontrar!

Sempre alerta!

Um dos grandes motivos que me influenciaram fortemente a criar um blog foi a possibilidade de ter uma newsletter!

Uma das coisas que eu sinto mais falta em conteúdo escrito é que não temos a possibilidade de atingir as mesmas pessoas sempre, de estar em contato constante mesmo após quem leu já ter saído do blog.

Meu objetivo com esta newsletter é enviar mensalmente (ou semanalmente, ainda não decidi) um resumo de todas as postagens que foram feitas, destacar postagens importantes, avisar quem está acompanhando sobre eventos, códigos de desconto e outras coisas legais que vão acontecer por aqui!

Então, se você está lendo isso, considere se inscrever na lista de emails e fique por dentro de todas as novidades, você também vai receber códigos de desconto e conteúdos exclusivos. Prometo que não vou lotar a sua caixa de emails!

Por baixo dos panos

Sei que provavelmente você é uma pessoa desenvolvedora e quer saber quais foram as tecnologias que eu utilizei para fazer este site não é mesmo? Vamos lá então!

A saga pelo CMS

Desde que comecei a trabalhar com tecnologia o WordPress é uma das ferramentas mais utilizadas para a criação de blogs. O problema é que ele é muito pesado e eu, pessoalmente, não gosto muito de utilizá-lo, pois já tive muitos problemas no passado.

Minha primeira opção seria criar um blog simples utilizando um gerador estático chamado Hugo, que é escrito em Golang. A ideia era simples: criar o blog, escrever o conteúdo em markdown e publicar tudo pelo GitHub Pages. Cheguei até a montar um repositório com uma pequena prova de conceito, porém infelizmente acabei não o usando justamente porque eu tinha mais planos para este blog do que simplesmente um blog. E o Hugo não é tão simples para criar algo mais complexo.

Passei para o Gatsby, que é essencialmente a mesma coisa, porém escrito em JavaScript usando React. A ideia surgiu quando vi um projeto chamado Ghost, isso resolveria todos os meus problemas!

O Ghost é um CMS Headless, isso significa que você pode plugar qualquer tipo de front-end nele e utilizar somente sua API para gerenciar e criar o conteúdo. Em suma, é como se você tivesse um WordPress sem o front-end, somente com a API aberta e o painel administrativo. Então eu teria um painel de gerenciamento de posts, login e senha, controle de acesso, a possibilidade de ter mais de uma pessoa escrevendo o mesmo artigo e muitas outras funções que qualquer CMS já tem de fábrica.

Mas o que me ganhou foi a possibilidade nativa do Ghost integrar com um sistema de envio de newsletters, que era algo que eu já queria fazer há um tempo. Comecei o desenvolvimento usando Gatsby, mas depois que analisei e estudei o tema percebi que o que o Gatsby fazia não era nada mais nada menos do que puxar as postagens do Ghost remotamente.

O Ghost já possuía um tema que vinha pré instalado, chamado Casper e um outro tema com a newsletter já implementada chamado Lyra, portanto não tinha necessidade de ter ainda outra camada só para servir o front-end. Acabei largando o Gatsby e usando apenas o Ghost por completo

A infraestrutura

O Ghost é o clássico projeto open source com suporte pago. Você pode baixar e instalar ele na sua própria máquina sem custo – que foi o que eu fiz – ou então pagar para usar a cloud deles já pré instalada.

Meu objetivo era não gastar nenhum dinheiro para manter o blog em si, então utilizei os crédito da Azure que possuo por ter sido um Microsoft MVP para criar os recursos que precisei na cloud e instalar o Ghost localmente.

Portanto, este blog está rodando exclusivamente na Azure.

O front-end

Eu não sou um front-end. Na verdade é uma das funções que menos desempenho no mundo de desenvolvimento. Então eu não tenho um vasto conhecimento em frameworks como o Vue, React, Angular ou qualquer outro. Portanto, a ideia era ser algo simples.

Peguei o tema padrão, Lyra, como um início. Fiz um fork para um novo repositório para armazenar somente o tema do blog e todas as alterações que foram feitas nele.

O Ghost trabalha com temas renderizados no lado do servidor utilizando o Handlebars como template engine. Então a partir daí foi simples, tive apenas que alterar o HTML, CSS e JavaScript das páginas para montar o meu layout em cima do layout padrão do blog. E este é o resultado.

O futuro

Enquanto esse é o primeiro de muitos artigos que vão aparecer por aqui, este não é tudo que este blog pode ser!

Para o futuro estou com a ideia de abrir este meio de conteúdo para que outras pessoas também possam escrever seus conteúdos por aqui! Assim criando um hub de ensino e colaboração! Mas isso fica para uma próxima!

Conclusão

Carta escrito "thanks" por Kelly Sikkema / Unsplash

Muito obrigado por acessar e por ler meu conteúdo, se você tiver qualquer feedback tanto sobre conteúdo quanto também sobre o site em si, por favor, entre em contato comigo em qualquer uma das minhas redes sociais (que podem ser encontradas no menu e no rodapé) ou então através do meu site. Sempre estou disponível para responder!

Se alguma coisa quebrou para você enquanto estava passeando por aqui, acesse a página de issues do blog e descreva seu problema que vou tentar corrigir o mais rápido possível.

Muito obrigado por ler e acreditar em meu conteúdo! 😍

]]>