Implementando microsserviços com Kubernetes na prática

Sobre mim

Vinícius Campitelli

Vinícius Campitelli

  • Membro do PHPSP
  • Entusiasta em cibersegurança
  • Desenvolvedor há 15 anos
  • Instrutor na Let's Code

Sobre mim

Preparação

Para acompanhar o Workshop, siga os passos a seguir:

  1. Clone esse repositório em
    
                                    $ git clone --recurse-submodules git@github.com:vcampitelli/workshop-kubernetes.git
                                
  2. Acesse os slides abrindo docs/index.html em seu navegador
  3. Instale o Docker em docs.docker.com/get-docker
  4. Instale o minikube em minikube.sigs.k8s.io
  5. Entre na pasta scripts e execute:
    
                                    $ minikube start
                                

Microsserviços

A variant of the soa structural style – arranges an application as a collection of loosely-coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight.
Wikipedia

Microsserviços

Containers

Containers are an abstraction at the app layer that packages code and dependencies together. Multiple containers can run on the same machine and share the OS kernel with other containers, each running as isolated processes in user space. Containers take up less space than VMs (container images are typically tens of MBs in size), can handle more applications and require fewer VMs and Operating systems.
Docker

Containers

O que são containers Docker
Docker

Kubernetes

Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications.
kubernetes.io

Kubernetes

Arquitetura do Kubernetes
C#Corner

Kubernetes

Pods

Pods are the smallest deployable units of computing that you can create and manage in Kubernetes.
Pod is a group of one or more containers, with shared storage and network resources, and a specification for how to run the containers. A Pod's contents are always co-located and co-scheduled, and run in a shared context.
kubernetes.io

Kubernetes

Deployment

A Deployment provides declarative updates for Pods and ReplicaSets.
You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.
kubernetes.io

Kubernetes

Service

An abstract way to expose an application running on a set of Pods as a network service.
In Kubernetes, a Service is an abstraction which defines a logical set of Pods and a policy by which to access them (sometimes this pattern is called a micro-service).
kubernetes.io

Kubernetes

HorizontalPodAutoscaler (HPA)

In Kubernetes, a HorizontalPodAutoscaler automatically updates a workload resource (such as a Deployment or StatefulSet), with the aim of automatically scaling the workload to match demand.
kubernetes.io

Kubernetes

HorizontalPodAutoscaler (HPA)

Horizontal scaling means that the response to increased load is to deploy more Pods. This is different from vertical scaling, which for Kubernetes would mean assigning more resources (for example: memory or CPU) to the Pods that are already running for the workload.
kubernetes.io

Kubernetes

HorizontalPodAutoscaler (HPA)

If the load decreases, and the number of Pods is above the configured minimum, the HorizontalPodAutoscaler instructs the workload resource (the Deployment, StatefulSet, or other similar resource) to scale back down. Horizontal pod autoscaling does not apply to objects that can't be scaled (for example: a DaemonSet.)
kubernetes.io

Kubernetes

HorizontalPodAutoscaler (HPA)

HorizontalPodAutoscaler
aws.amazon.com

Service Mesh

É uma camada dedicada de infraestrutura para facilitar a comunicação entre serviços usando um proxy
Wikipedia

Service Mesh

Propõe uma gestão mais eficaz das comunicações entre serviços, maior controle operacional e também o fornecimento de informações comportamentais
Wikipedia

Service Mesh

Funcionalidades

  • Encriptação;
  • Load balancing;
  • Observabilidade;
  • Rastreabilidade;
  • Circuit breaker;
  • Autenticação e autorização.

Service Mesh

Visão geral

Service Mesh nginx.com/blog/what-is-a-service-mesh

Service Mesh

Istio

is an open source Service Mesh that layers transparently onto existing distributed applications
istio.io

Service Mesh

Istio

Hands-on

Hands-on

1. Instalando minikube

Siga a documentação oficial em minikube.sigs.k8s.io para instalar o minikube de acordo com seu sistema operacional

Para ambientes Linux com arquitetura amd64, o comando é:


                            $ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
                            $ sudo install minikube-linux-amd64 /usr/local/bin/minikube
                        

Hands-on

2. Iniciando o cluster

Clone ou atualize este repositório:


                            $ git clone --recurse-submodules git@github.com:vcampitelli/workshop-kubernetes.git
                        

Entre na pasta scripts e inicialize o cluster com:


                            $ minikube start
                        

Hands-on

3. Instalando o Istio

Seguindo a documentação em istio.io:


                            $ curl -L https://istio.io/downloadIstio | sh -
                            $ cd istio-1.14.1
                            $ export PATH=$PWD/bin:$PATH
                        

Isso irá adicionar a pasta istio-1.14.1/bin em seu $PATH temporariamente.

Para fazer de forma permanente, você pode colocar o último comando (export ...) em algum arquivo de seu sistema que seja sempre carregado, como /etc/profile, ~/.bashrc, ~/.zshrc, entre outros.

Hands-on

3. Instalando o Istio

Instalando com o perfil demo (saiba mais sobre os outros perfis na documentação)


                            $ istioctl install --set profile=demo -y
                        

Adicionando a label istio-injection=enabled no namespace default, indicando que queremos injetá-lo automaticamente em nossas aplicações


                            $ minikube kubectl -- label namespace default istio-injection=enabled
                        

Hands-on

4. Deploy do cluster

O minikube cria um serviço separado do Docker, então sempre que iniciarmos um terminal e quisermos interagir diretamente com ele, devemos especificar que queremos executar os comandos nesse novo ambiente:


                            $ eval $(minikube -p minikube docker-env)
                        

Hands-on

4. Deploy do cluster

Execute os comandos abaixo para fazer o build das imagens do Docker:


                            $ docker build -t auth:latest auth
                            $ docker build -t comments:latest comments
                            $ docker build -t posts:latest posts
                            $ docker build -t users:latest users
                        

Hands-on

4. Deploy do cluster

Agora, vamos começar a subir a nossa aplicação:


                            $ minikube kubectl -- apply -f k8s/jwt_keys.yml
                            $ minikube kubectl -- apply -f k8s/auth.yml
                            $ minikube kubectl -- apply -f k8s/comments.yml
                            $ minikube kubectl -- apply -f k8s/posts.yml
                            $ minikube kubectl -- apply -f k8s/users.yml
                        

Hands-on

4. Deploy do cluster

Para acompanhar tudo que foi configurado:


                            $ minikube kubectl -- get pods
                            $ minikube kubectl -- get deployments
                            $ minikube kubectl -- get services
                        

Hands-on

5. Acessando os serviços

Como não há um serviço de Load Balancing no minikube, devemos expor os IPs dos serviços para eles serem acessados localmente

Execute o comando abaixo em um novo terminal e mantenha-o rodando:


                            $ minikube tunnel --cleanup
                        

Hands-on

5. Acessando os serviços

Volte ao terminal anterior e execute o comando a seguir até que os 4 EXTERNAL-IPs estejam alocados:


                            $ minikube kubectl -- get services
                            NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
                            auth-service          LoadBalancer   10.106.141.164   <pending>        3000:32110/TCP   1h
                            comments-service      LoadBalancer   10.107.141.217   <pending>        3000:31457/TCP   1h
                            kubernetes            ClusterIP      10.96.0.1        <none>           443/TCP          1h
                            posts-service         LoadBalancer   10.106.220.106   <pending>        3000:32532/TCP   1h
                            users-service         LoadBalancer   10.102.133.17    <pending>        3000:30921/TCP   1h
                        

Hands-on

5. Acessando os serviços

Volte ao terminal anterior e execute o comando a seguir até que os 4 EXTERNAL-IPs estejam alocados:


                            $ minikube kubectl -- get services
                            NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
                            auth-service          LoadBalancer   10.106.141.164   10.106.141.164   3000:32110/TCP   1h
                            comments-service      LoadBalancer   10.107.141.217   10.107.141.217   3000:31457/TCP   1h
                            kubernetes            ClusterIP      10.96.0.1        <none>           443/TCP          1h
                            posts-service         LoadBalancer   10.106.220.106   10.106.220.106   3000:32532/TCP   1h
                            users-service         LoadBalancer   10.102.133.17    10.102.133.17    3000:30921/TCP   1h
                        

Hands-on

5. Acessando os serviços

Para facilitar, vamos guardar os 4 IPs com as portas em variáveis:


                            $ IP_AUTH=10.106.141.164:3000
                            $ IP_COMMENTS=10.107.141.217:3000
                            $ IP_POSTS=10.106.220.106:3000
                            $ IP_USERS=10.102.133.17:3000
                        

Hands-on

5. Acessando os serviços

Para iniciar, vamos nos autenticar em nossa aplicação, executando o comando abaixo:


                            $ curl -X POST \
                              -u "admin:admin" \
                              "http://${IP_AUTH}/auth"
                        

Resultado:


                            {
                              "status": true,
                              "access_token": "eyJhbGciOiJFUzI1NiJ9.eyJzY29wZXMiOlsidXNlcnMiLCJwb3N0cyIsImNvbW..."
                            }
                        

Hands-on

5. Acessando os serviços

Salve o access_token em uma variável para facilitar as próximas chamadas:


                            $ TOKEN="eyJhbGciOiJFUzI1NiJ9.eyJzY29wZXMiOlsidXNlcnMiLCJwb3N0cyIsImNvbW..."
                        

Teste os outros serviços:


                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_COMMENTS}/comments"
                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_POSTS}/posts"
                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_USERS}/users"
                        

Hands-on

6. Criando o API Gateway

Vamos criar um API Gateway que irá fazer o roteamento dos nossos microsserviços:


                            $ minikube kubectl -- apply -f k8s/istio/gateway.yml
                        

Hands-on

6. Criando o API Gateway

Descubra o IP do API Gateway:


                            $ minikube kubectl -- -n istio-system get services
                            NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                AGE
                            istio-egressgateway    ClusterIP      10.107.106.220   <none>        80/TCP,443/TCP         1h
                            istio-ingressgateway   LoadBalancer   10.101.22.8      10.101.22.8   15021:32023/TCP, ...   1h
                            istiod                 ClusterIP      10.111.73.255    <none>        15010/TCP, ...         1h
                        

E mais uma vez, vamos salvar em uma variável para facilitar o uso:


                            $ IP_GATEWAY=10.101.22.8
                        

Hands-on

6. Criando o API Gateway

Vamos testar o roteamento:


                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_GATEWAY}/comments"
                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_GATEWAY}/posts"
                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_GATEWAY}/users"
                        

Hands-on

7. Configurando o Autoscaling

Ative o plugin de Metrics para coletar dados do uso de recursos:


                            $ minikube addons enable metrics-server
                        

Abra um novo terminal e aplique a regra de Autoscaling:


                            $ minikube kubectl -- apply -f k8s/hpa.yml
                        
kubernetes.io/docs/tasks

Hands-on

7. Configurando o Autoscaling

Abra um novo terminal e execute o comando abaixo para acompanhar o status:


                            $ watch -n 1 "minikube kubectl -- get hpa"
                        

Também é possível rodar este comando para visualizar o histórico de ações:


                            $ minikube kubectl -- describe hpa posts
                        

Hands-on

7. Configurando o Autoscaling

Baixe o wrk para realizar requisições simultâneas e execute:


                            $ wrk -t8 -c400 -d30s \
                                -H "Authorization: Bearer ${TOKEN}" \
                                "http://${IP_POSTS}/posts"
                        

PS: esse comando irá abrir 400 conexões distribuídas em 8 threads durante 30 segundos.
Ajuste esses números para atender às especificações de sua máquina.

Hands-on

8. Dashboards do Istio

Instalando o Kiali (dashboard), Prometheus (métricas), Grafana (monitoramento) e Jaeger (tracing distribuído):


                            $ minikube kubectl -- apply -f <caminho-para-o-istio>/samples/addons
                            serviceaccount/grafana configured
                            configmap/grafana configured
                            service/grafana configured
                            deployment.apps/grafana configured
                            ...
                        

Para abrir o Kiali no navegador, execute o comando abaixo e acesse o endereço informado:


                            $ istioctl dashboard kiali
                            http://localhost:20001/kiali
                        

Hands-on

8. Chaos Engineering no Istio

Aplique a regra abaixo:


                            $ minikube kubectl -- apply -f k8s/istio/gateway-delay.yml
                        

E busque novamente os comentários, passando pelo API Gateway:


                            $ curl -H "Authorization: Bearer ${TOKEN}" "http://${IP_GATEWAY}/comments"
                        
Fault Injection: Delay

Referências