segunda-feira, 21 de outubro de 2019

Definindo a arquitetura no início do projeto

Onde começa e onde termina a arquitetura de um Software?

Sempre defendi que arquitetura é arquitetura, independente da cenários que estamos abordando (não significa que vou sair por ai construindo prédios rsrs). Mas segue uma comparação que podemos fazer:

De acordo com o site significado. Significado de arquitetura é:
"Arquitetura é a arte e técnica de projetar uma edificação ou um ambiente de uma construção. É o processo artístico e técnico que envolve a elaboração de espaços organizados e criativos para abrigar diferentes tipos de atividades humanas.
A arquitetura é a disposição das partes ou dos elementos que compõem os edifícios ou os espaços urbanos em geral."

Em software podemos traduzir para:

"Arquitetura é a arte e técnica de projetar um software ou infraestrutura de um software. É o processo artístico e técnico que envolve a elaboração de componentes organizados e coesos para abrigar diferentes tipos de requisito funcionais e não funcionais de um projeto de software.
A arquitetura é a disposição das partes ou dos componentes que compõem o software ou os recursos de infraestrutura em geral."

Dito isso... gostaria de compartilhar algumas alterações que fiquei sabendo que ocorreram na Obra do meu apartamento (certamente você já passou por isso ou sabe de alguém que passou).

Assim que entrei em meu apartamento (onde estou morando a pouco mais de 4 anos), percebi algumas coisas diferentes do que foram apresentados na planta e outras que mudaram no meio do caminho. Duas dessas mudanças, lembro ter questionado:

1. Na planta, existia uma entrada no corredor para prateleiras (na mesma parede de um dos quartos). Mas ao longo da obra, perceberam que se tornaria um espaço de poucas opções e reduziria o quarto por um espaço que poucos utilizariam.

2. No banheiro, o teto do box não deveria ter saída de energia para lampada, mas tem. Pois a medida que a obra foi evoluindo, o arquiteto percebeu que o box poderia ficar escuro por conta de uma leve separação entre o box e o teto do banheiro. O que faria, dependendo da lampada que fosse usada, que o box não recebesse luz o bastante e então ele incluiu uma saída a mais para receber outra lampada, dentro do box.

Percebam que o que foi definido lá no inicio da obra, sofreu alterações (não apenas essa, mas deveríamos ter um espaço para visitantes estacionarem, mas se tivessem levado isso pra frente, hoje não teríamos vagas exclusivas, sem rodizio e totalmente separadas)

E o kiko?

Agora vou citar dois casos reais, onde alterei a abordagem que estava em uso, também por alguns motivos e também com o carro andando.

1. Uma aplicação web (front), utilizada apenas no horário comercial. Estávamos rodando no kubernetes, junto com outras aplicações (bacana, utilizando recursos já reservados, faz sentido).  Mas começamos a utilizar mais e mais recursos do kubernetes, então, eu poderia tomar duas ações: Fazer upgrade do cluster kubernetes para atender a necessidade, ou mover a aplicação (que só era usada poucas vezes no horário comercial), para serverless (pagando pelo uso apenas - ainda não saímos da faixa gratuita), garantindo liberação de recursos no kubernetes, para outras aplicações que necessitam executar 24/7.

2. Um service executa algumas tarefas de replicação de dados dentro do kubernetes, usando uma biblioteca para agendamento de baseado em cron. Porém, como o responsável por agendar as tasks está dentro da aplicação, somos obrigados a manter apenas uma instancia de POD (unidade de container), nessa apliação. Perdendo um dos grandes benefícios do kubernetes (escalabilidade vertical dos pods). E também somos obrigados a realizar novos deploys ou executar os endpoints dentro da rede manualmente para forçar ma atualização quando necessário. Para contornar isso, optamos por usar o cloud scheduler para chamar esse service. Permitindo auto scale, alteração direto pelo painel do cloud scheduler no intervalo das execuções ou até mesmo, solicitar uma imediata execução manual, sem ter que fazer nada na aplicação.

Humm, parecem abordagens semelhantes.

Se esse titulo não foi sua conclusão, desculpe!
Em ambas as situações, projetamos algo no inicio e isso foi alterado a medida que a aplicação ou a infraestrutura cresce. Nos forçando a tomar outras decisões e rever o que antes era visto como "adequado".

Em resumo, o que pretendo com isso, é mostrar que arquitetura é algo tão mutável, como o próprio projeto. Arrisco dizer que mais mutável que o próprio projeto, visto que geralmente os projetos recebem novas features e pouco se altera nas já implementadas, enquanto a arquitetura pode mudar drasticamente se um crescimento exponencial for identificado, por exemplo.

Enfim. Arquitetura nunca tem fim!

Se eu tivesse de escolher uma palavra para definir arquitetura, eu certamente escolheria Resiliência. 
Projetar um software, por mais simples ou inadequado que sejam as tecnologias elencadas, deixa de ser um problema se o software está desacoplado e distribuído o suficiente para tornar a refatoração não impactante para o projeto.

Então, respondendo a pergunta no titulo desse artigo: Arquitetura inicia junto com o projeto e nunca tem fim.

segunda-feira, 22 de julho de 2019

Usando secret tls para configurar https no kubernetes

Como configurar certificado https para  uma aplicação em um cluster Kubernetes?

Se você usa docker, mas nunca usou o Kubernetes (k8s). Então, você precisa conhecer :)
Dentre diversas vantagens em utilizar k8s, destaco a facilidade em ter uma aplicação sempre disponível, facilidade em recuperação nos casos de falhas e até mesmo, a simplicidade em ter uma aplicação escalando horizontal e verticalmente para atender a demanda no exato momento em que existe a necessidade.

É muito comum utilizar um cluster k8s para criar arquiteturas baseadas em micro serviços, onde, geralmente, temos um gateway exposto, fornecendo acesso a serviços e APIs que executam dentro da rede do cluster. Mas também é possível ter aplicações web ou scheduled jobs rodando nesse cluster. E em alguns momentos, como no caso de um gateway ou de uma aplicação web, queremos oferecer acesso externo a aplicação que está rodando dentro do cluster. E é ai que tratamos o assunto desse post!

Algo importante: Estou partindo da premissa de que você já tem o Ingress configurado e possui um endereço configurado no DNS com o IP do Ingress.


Mas porque diabos você faz uma introdução gigante ao invés de iniciar o assunto?

Puff!, sei lá =). Porque trabalhei com redatores por muito tempo?


Agora é sério...


Veremos abaixo os passos necessários para configurar uma secret TLS no k8s, montar o yaml da secret, executar no k8s e vincular a secret gerada no service do k8s para possibilitar acesso HTTPS em sua aplicação. 

O secret.yaml

Não necessariamente precisa ser "secret.yaml", só usei esse nome para simplificar. O importante é o conteúdo do arquivo.
apiVersion: v1
kind: Secret
metadata:
name: $nome_do_certificado
namespace: $namespace_do_seu_app_no_k8s
type: kubernetes.io/tls
data:
tls.crt: $hash_base64_extraido_do_seu_certificado_https tls.key: $hash_key_base64_extraido_do_seu_certificado_https
*Tudo que está com $, você preenche com seus dados 😙


O criando no Kubernetes

Bom, para criar a secret, basta conectar no seu cluster k8s (via cli - eu uso bash) e usar o comando abaixo:
- kubectl create -f secret.yaml

Após a mensagem de sucesso, a secret nome_do_certificado estará disponível e bastará apenas vincular a secret gerada a sua aplicação (aquela do namespace_do_seu_app_no_k8s), no campo tls.hosts.secretName.

Eu uso Google Cloud. Se esse for também seu caso, siga o caminho: kubernetes engine > services > acesse pod Entrada (Ingress) > YAML > tls.hosts.secretName = nome_do_certificado (ou via VI usando bash DeUXx mE livRe do VIMMM - É real, não gosto do vim, uso sei lá porque).

Feito isso, basta acessar sua aplicação pelo endereço vinculado ao IP do Ingress (espero que você já tenha configurado o DNS para o IP do Ingress).

Fica ai a referência que usei quando configurei: https://kubernetes.io/docs/concepts/configuration/secret/

Bom, é isso ai. Tem algumas coisas particulares aqui, como Google Cloud e Ingress. Mas creio que vá te ajudar caso esteja com o mesmo problema.


Ah, outra coisa...

Caso esteja se perguntando sobre vincular usar o HTTPS em diferentes aplicações para no mesmo cluster k8s, fique tranquilo. É um cluster e quem faz a magica de direcionar o endereço para a aplicação correta é o load balance, no meu caso o Ingress quebra essa :P.


Caso tenha alguma dificuldade, pergunta ae!

Abraços

quinta-feira, 27 de junho de 2019

Convertendo o appsettings em um objeto com c#

Como converter o appsettings.json em um objeto fortemente tipado no netcore e C#?

Antes de mais nada, vale pontuar que existem várias soluções para esse problema, mas, fui buscar esses dias, a forma mais adequada de trabalhar com os dados de um appsettings. Claro que dependendo do problema, isso não é necessário. Por exemplo, ler apenas uma chave, um texto ou um número. Mas esse caso que vou apresentar, é uma solução para caso você tenha um objeto grande, com uma estrutura de árvore que precise ser manipulado usando o System.Collection.Generic por exemplo.

Vou apresentar um problema para depois apresentar a solução.

Imagine a seguinte estrutura:
{
"Clients": [
{
"name": "pic",
"id": "2378sdkjsk"
},
{
"name": "poc",
"id": "f9d8sdkjsk"
},
{
"name": "pluc",
"id": "n323dj8"
}
]
}


Certo! imaginado... e agora?

Agora você deseja consultar o "client" com "name" = "poc". Blz?

To fazendo sentido? (assisti uma palestra onde o cara repetiu essa pergunta a palestra toda. Em algum número entre o 15 e 20 eu parei de contar).

Para "mapear" esses valores, precisamos primeiro de um objeto. Então criamos um:

namespace PicPocPluc.Models.Configuration
{
public class Clients
{
public string Name { get; set; }
public string Id { get; set; }
}
}

No nosso Startup.cs, geralmente temos as propriedades (se não tem, crie :P):


public IConfiguration Configuration { get; private set; }
public IHostingEnvironment Environment { get; private set; }

E também temos dois métodos:


public Startup(IHostingEnvironment env, IConfiguration configuration);
e
public void ConfigureServices(IServiceCollection services);

Nesses métodos, faremos 2 coisas. A primeira é carregar o appsettings de acordo com nosso ambiente e a segunda é carregar os valores do appsettings na classe "Clients" e oferecer essa classe para nossas controllers via injeção de dependência.

CUMA? Como?

Usando o System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), podemos descobrir qual ambientes estamos rodando e com um belo IFzão, vamos carregar o appsettings que queremos no método Startup():


if(System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "production"))
Configuration = new ConfigurationBuilder()
.AddJsonFile(Environment.ContentRootPath + @"/appsettings.production.json")
.Build();

Feito isso, teremos o appsettings de cada ambiente funcionando corretamente e o próximo passo é no método ConfigureServices(), carregar nosso objeto:


services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton(Configuration.GetSection("Clients").Get<List<Clients>>());

Objeto carregado, é hora de usá-lo via injeção de dependência em qualquer controller.

readonly List<Clients> _clients;
public PocController(List<Clients> clients) => _clients = clients;

E pronto ! É isso. Criamos o appsettings com dados, uma classe para mapea-lo, carregamos o appsettings de acordo com o ambiente, usamos a propriedade Configuration do Startup.cs para acessar a chave Clients do appsettings carregado e assim, via injeção de dependência (padrão no netcore), acessamos os dados já carregados no controller. 

Como mencionei no inicio, tem várias formas de fazer. Esse é o formato que usei e me pareceu mais adequado para esse problema. Se te ajudei de alguma forma, valeu escrever o post :)

Abraço!

domingo, 27 de janeiro de 2019

Publicando um aplicativo pelo gitlab

Como publicar uma branch do git, no gitlab usando o gitlab, Ingress e criando um apontamento DNS para um domino?

No artigo anterior apresentei o passo a passo que utilize para montar um pipeline completo no gitlab, criar uma instancia  de um container da imagem do meu aplicativo e colocar essa instancia em um cluster kubernetes usando google cloud. Para tornar acessivel o aplicativo, utilizamos um wildcard dns para responder para um IP através de um domínio não existente.

Link para o artigo: https://www.rcelebrone.com/2019/01/ci-cd-gitlab-google-cloud-kubernetes.html

Mas e se eu desejar publicar automaticamente em um domínio existente?

É perfeitamente simples e possível.
No artigo anterior, dentro do gitlab. Entre no projeto, em configurações, CI/CD e abra as configurações do recurso Auto DevOps. No campo domínio, no artigo anterior, utilizamos um serviço de wildcard DNS (o xip.io), para apontar para o IP do Ingress. É nesse campo domínio que temos que informar o domínio oficial por onde queremos servir nosso aplicativo.

* No gitlab, o IP do Ingress (caso tenha seguido o artigo anterior), está disponível dentro do projeto em Operações > Kubernetes > (clique no nome do cluster na lista) > O ip estará visível em aplicações > Ingress.


IP em mãos e domínio configurado no gitlab e agora?

Aqui tem uma observação. Existem diversas ferramentas de registro de domínio. No meu caso, trabalho com o uolhosts e diretamente no painel do uolhosts eu consigo fazer o apontamento que preciso. Para isso, basta criar no domínio um apontamento A Name para o endereço gerado pelo gitlab e o IP do Ingress.

Vale lembrar que por padrão (quando não definimos um arquivo gitlab-ci.yml), o gitlab utiliza uma junção do nome do seu grupo no gitlab com o nome do seu projeto. Então, por exemplo, se nossas informações são as seguintes:

  • Grupo do gitlab: universo
  • Nome do projeto: admin-jupiter
  • Ip do Ingress: 35.234.567.67
  • Domínio: nasa.com
Teremos o seguinte:

No serviço de configuração do domínio:
Crie um registro "A NAME" > com IP: 35.234.567.67 e endereço: universo-admin-juniper.nasa.com

No campo domínio do Ingress no gitlab:
Informe o domínio: nasa.com


* Para utilizar um endereço customizado, basta utilizar nas variáveis de ambiente: Dentro do projeto > Configurações > CI/CD > variáveis de ambiente. Então basta utilizar a variável: CI_PROJECT_PATH_SLUG e o nome do subdomínio. Ou seja, para o endereço xpto.exemplo.com, o valor dessa variável será xpto.

sexta-feira, 25 de janeiro de 2019

Integração e Entrega continua com gitlab, google cloud, kubernetes e café

Como criar um processo de teste, integração e deploy continuo usando o fantástico recurso de Auto DevOps do GitLab?

Hoje muito se fala em DevOps. Mas o que é DevOps?
DevOps é a junção das palavras "desenvolvimento" e "operação". Uma proposta que tomou força por diversos fatores. No lado técnico, as complexidades em entregar um software de forma ágil dependendo de outro time, ou talvez uma motivação natural pela gama de ferramentas e a tão difundida computação na nuvem, ou mesmo (para os que gostam de conspiração), uma força do mundo corporativo para reduzir os gastos com profissionais de TI centralizando os esforços em um mesmo time. Enfim, isso é meio que como aquela história do quem nasceu primeiro...

Fato que é DevOps está longe de ser uma novidade. Já amplamente praticado, principalmente por Startups que podem se dar ao luxo de criar seu software escolhendo entre centenas de softwares e hardwares gratuitos ou muito acessíveis e colocar seu negócio em produção quase que instantaneamente.

Falou, falou, falou e não disse nada!

É verdade! rsrs

Nos últimos dias estive avaliando uma serie de ferramentas e oportunidades de integração entre elas. Focando em 3 coisas: praticidade, custo e integração entre elas. Brinquei com bitbucket, github, docker hub, gitlab, docker registry, aws, jira, tfs, google cloud, jenkins, tfs e muitas outras. Meu objetivo era elencar ferramentas para montar um pipeline com no minimo teste automatizado, build, deploy e integração com uma ferramenta de projetos. Depois de muito teste e avaliação das ferramentas, cheguei a conclusão que o mais pratico, melhor custo beneficio e com ótimo custo seria trabalhar com gitlab integrado ao jira, utilizando o pipeline do próprio gitlab para o build e testes, bem como o container registry dele para armazenar as imagens e para o deploy uma integração bem bacana que o gitlab oferece dentro da ferramenta deles. O Gitlab Auto DevOps trabalha preferencialmente com Kubernetes no Google Cloud. Então, isso nos permite criar um pipeline completo sem muito trabalho. Abaixo vou descrever os passos de cada ferramenta e algumas observações que ninguém nos conta e acabamos por descobrir depois de apanhar um pouco.

Instalações. Não!

Tem um custo que não levamos em consideração, que é o custo para manter hardware e software. Então, resolvi me dar ao luxo de usar tudo na nuvem.

Então, vamos aos cadastros

  • Crie uma conta no http://gitlab.com
    • Crie um grupo (isso vai evitar que você tenha que configurar cluster kubernetes por projeto)
      • No menu superior "Grupos"
    • Crie um projeto (aqui não vou sugerir que usem algum pronto pois foi o que mais vi nos tutorias e quando montamos o nosso, não funciona)
      • Crie o projeto dentro do Grupo que você criou.
    • Clone o repositório do projeto criado na sua maquina, crie uma aplicação simples que possa ser compilada e em seguida, crie um Dockerfile para esse projeto. Única observação é que exporte a porta 5000 (vi isso em uma das documentações do Auto DevOps e no meu caso só funcionou quando usei a porta 5000)
      • Seria bacana criar também um teste dentro do projeto
  • Crie uma conta no http://cloud.google.com
    • Crie uma conta de pagamento na Google Cloud
    • Crie um projeto na Google Cloud
      • Acessando http://console.cloud.google.com na parte superior esquerdo da tela existe o menu pra criar projeto.
      • Na tela de criação do projeto basta informar o nome do projeto e selecionar a conta de pagamento (é necessário para o kubernetes engine api).
    • Projeto criado, clique no menu hamburger (superior esquerdo) e clique em APIs e serviços.
      • No painel, busque por Kubernetes Engine Api, clique e ative essa api no projeto

Vamos falar de coisa boa, vamos falar de gitlab

  • Novamente no gitlab, vá no menu grupos e clique no grupo que você criou.
  • Você perceberá que existe um menu Kubernetes. 
    • Clique nesse menu e na pagina que abrir, você deve utilizar a opção de criar Cluster Kubernetes no Google Cloud (clique no botão para autenticar pelo google). 
    • Preencha um nome para o cluster (como é o cluster onde estamos liberando produção, pode chamar o cluster de produção).
    • Escolha o projeto que você criou lá no Google Cloud no combo abaixo. 
  • Feito isso, clique em criar Cluster.
  • Aguarde criar completamente o cluster no Google Cloud e todas as instancias estarem executando.
    • Você pode acompanhar a criação lá no Google Cloud, novamente pelo menu hamburger, clicando agora na opção Kubernetes Engine > Clusters.
  • Assim que concluir a criação do cluster, no gitlab, ainda dentro de grupos > (seu grupo) > Kubernetes.
    • Instale o Helm Tiller e aguarde concluir a instalação.
    • Em seguida instale o Ingress e aguarde concluir a instalação e principalmente aparecer o IP no campo do Ingress (isso é importante).
  • Copie o IP do Ingress e entre no projeto que você criou no gitlab (o repositório).
    • Vá em configurações > CI/CD > Auto DevOps
    • Se não estiver ativo, ative a opção para tornar padrão o Auto DevOps
    • E no campo Dominio, cole o IP e concatene com xip.io
      • Fica algo assim: 35.123.654.23.xip.io
  • Clique em salvar alterações
Você poderá acompanhar as execuções das pipelines do gitlab acessando o seu grupo > o repositório > clicando no menu CI/CD > pipelines.

E que bruxaria é essa ai? 

O teste que você incluiu no projeto vai rodar, a aplicação vai compilar passando pelo build, qualidade de código também executa no projeto. "Production" faz toda a comunicação com o kubernetes subindo seu container a partir do registry.gitlab.com (um registry do gitlab que guarda as suas imagens, melhor do que pagar pelo docker hub e ainda não precisa se preocupar com integração) e por última, assim que a aplicação já está disponível. Acontece um teste de performance, que pelo log parece ser um crawler usando selenium para testar a velocidade da aplicação.

Simples não? 

Sim, é! Porém, tem muito material desatualizado que acaba complicando chegar nesses passos. Algumas coisas chatas ocorrem se seguirmos passos em outra ordem. Por exemplo não incluir o Kubernetes Engine Api no projeto do Google Cloud e tentar integrar no gitlab. De problema, ai você tem que atualizar a pagina da integração do gitlab e reiniciar o preenchimento. Ou o fato do Wildcard DNS não estar tão claro que deve ser usado a partir do IP do Ingress (eu usei o xip.io, mas tem outros, como o nip.io, por exemplo).

Enfim, é isso. Espero que ajude. 
Caso esteja implementando e usando essas mesmas ferramentas e algo der errado, entre em contato ou posta no stackoverflow e coloca o link nos comentários.


Ah, quase esqueci! 

É bem simples integrar o Jira, dentro do repositório no gitlab, vá em configurações > integrações > jira. E sobre o café no titulo desse post. Acredite, foram muitos cafés até chegar nesse resultado.

domingo, 9 de dezembro de 2018

Forma simples de criar e rodar uma aplicação react native no celular

Como criar uma aplicação react native e rodar em um aparelho android?


- Primeiro, execute no terminal o comando: 

lsusb

- Deve aparecer uma lista mais ou menos assim:

Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub 
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 
Bus 001 Device 003: ID 22b8:2e76 Motorola PCS 
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Na lista acima, identifique o ID correspondente ao seu aparelho e execute o comando abaixo com o ID identificado acima:

echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-android-usb.rules
*Isso permite incluir seu aparelho na lista de dispositivos disponiveis para debug

- E então, escolha onde quer criar seu projeto e crie o projeto base com o comando: 

react-native init AppTeste

- Entre na pasta do projeto criado:

cd AppTeste

-Execute o comando abaixo (com o aparelho ja conectado em modo debug):

react-native run-android

domingo, 25 de novembro de 2018

vscode salvar arquivo ou pasta como administrador

Como alterar um arquivo sem ter que usar privilegios de administrador no linux?

Bom, antes de mais nada tenho algo a dizer: Esse artigo não é um artigo oO? Isso mesmo, é mais uma dica para resolver de uma forma decente algo que é um pouco chato enquanto desenvolvemos no linux.

Ok, e?

Ocorre que quando criamos nossos projetos, dependendo de onde e como criamos nosso workspace, acabamos por ter um diretório onde o dono é o root e tudo que criamos dentro dele, acaba herdando a propriedade, grupo e permissões. E nós percebemos isso quando vamos alterar um arquivo e uma IDE ou editor de texto não altera a menos que executemos a ação de salvar como super usuário.

Para evitar problema com seus projetos (caso isso ocorra com você), faremos:

- Primeiro crie ou localize via terminal a pasta onde pretende colocar todos seus projetos (geralmente chamamos de workspace): Eu gosto de criar no /home/<USER>/workspace
- Pasta workspace criada, no terminal teremos: <USER>@<USER>: ~/workspace$
- Caso a pasta workspace já exista e tenha conteúdo, verifique quem é o dono usando: ls -al
- E para alterar para seu usuário, faça execute o comando na /home/<USER>sudo chown <USER>:<USER> -R workspace/

Dessa forma você garante que os projetos atuais e os próximos criados dentro de workspace, não lhe trarão problemas de permissão, pois são do próprio usuário que está editando.

Aeeeeee :D chuva de CTRL + S no vscode