Skip to content

ortisan/kubernetes-istio-hands-on

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kubernetes e Istio Hands On

Kubernetes (K8s) é um produto Open Source utilizado para automatizar a implantação, o dimensionamento e o gerenciamento de aplicativos em contêiner -- https://kubernetes.io

Preparação do ambiente

Linux

  • Instale o k3d

  • Criar o cluster

# k3d Version < 5.0
k3d cluster create k8s-istio-handson --servers 1 --agents 1 --port 9080:80@loadbalancer --port 9443:443@loadbalancer --api-port 6443 --k3s-server-arg '--no-deploy=traefik'

# k3d Version >= 5.0
k3d cluster create k8s-istio-handson --servers 1 --agents 1 --port 9080:80@loadbalancer --port 9443:443@loadbalancer --api-port 6443 --k3s-arg "--disable=traefik@server:0"

Cria o kubeconfig e configura o contexto para o kubectl:

k3d kubeconfig merge k8s-istio-handson --kubeconfig-switch-context

Windows

Habilite o kubernetes no Docker desktop, conforme imagem abaixo:

image -- from author

Altere o contexto do kubectl para o docker-desktop:

kubectl config get-contexts
kubectl config use-context docker-desktop

Kubernetes

Client

kubectl é o client oficial do K8s. Através dele, interagimos com o cluster e objetos K8s, tais como pods, services, deployments...

Contextos

kubectl config get-contexts
kubectl config use-context k3d-k8s-istio-handson

Link com detalhes dos arquivos kubeconfig: https://kubernetes.io/pt-br/docs/concepts/configuration/organize-cluster-access-kubeconfig/

Cluster status

kubectl get componentstatuses

image -- from author

image -- from https://kubernetes.io/pt-br/docs/concepts/overview/components/

Um cluster Kubernetes consiste em um conjunto de servidores de processamento, chamados nós, que executam aplicações containerizadas. Todo cluster possui ao menos um servidor de processamento (worker node).

O servidor de processamento hospeda os Pods que são componentes de uma aplicação. O ambiente de gerenciamento gerencia os nós de processamento e os Pods no cluster. Em ambientes de produção, o ambiente de gerenciamento geralmente executa em múltiplos computadores e um cluster geralmente executa em múltiplos nós (nodes), provendo tolerância a falhas e alta disponibilidade.

-- from https://kubernetes.io/pt-br/docs/concepts/overview/components/

Control Plane

Os componentes do control plane são responsáveis em manter a saúde do cluster.

  • controler-manager: Responsável regular os componentes do cluster. Ex: Assegura que todas as réplicas de um serviço estão disponíveis e saudáveis.

  • scheduler: Responsável em escalonar os diferentes pods em diferentes nós.

  • etcd: banco de dados chave valor do cluster.

Nodes

Podemos pensar em node como uma máquina física ou virtual que irá rodar um conjunto de containers. Cada node possui alguns componentes pré instalados responsáveis por comunicação com outros nodes e com o Control Plane.

  • kubelet: Agente que controla e garante a disponibilidade dos pods.

  • kubernetes-proxy: Componente responsável em rotear o tráfego de rede para os serviços de load balancer no cluster.

  • container-runtime: agente responsável por executar os containers

kubectl get nodes

image -- from author

Addons

Componentes que complementam as funcionalidades do Cluster.

  • kubernetes-dns: Roda um DNS server e provê um serviço de nome e descoberta ao cluster.
kubectl get services --namespace=kube-system

image -- from author

Namespaces

O Kubernetes usa os namespaces para organizar os objetos no cluster. Uma analogia é pensar em namespaces como diretórios, onde cada diretório tenha seus respectivos objetos. Conforme imagem anterior, o Kubernetes tem seu próprio namespace chamado kube-system, e por default trabalhamos com o namespace default para nossas aplicações.

kubectl get pods --all-namespaces
#ou
kubectl get pods -A

Objetos

Os tipos de objetos são utilizados para diversas finalidades.

A seguir destaco os principais:

Pod

Menor unidade de deploy. Pode conter um ou mais containers. A configuração se faz através de um arquivo yaml chamado pod manifest.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
  labels:
    web: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.7.9
      ports:
        - containerPort: 80

Criação do pod:

kubectl apply -f k8s/nginx-pod.yaml

Listagem:

kubectl get pods --output=wide

image -- from author

Detalhes:

kubectl describe pods nginx-demo

image -- from author

Service

Os objetos serviços dão aos pods ou deployments, a capacidade de receber um dns e também terem o service-discovery automático.

Exposição para o mundo externo:

# List services
kubectl get services
# Expose pod
kubectl expose pod nginx-demo --port 80 --type=LoadBalancer
# List services again
kubectl get services

image -- from author

image -- from author

Após o teste, remover o service loadbalancer:

# Delete svc
kubectl delete svc nginx-demo

Deployment

Um Deployment é um objeto de recurso no Kubernetes que fornece atualizações declarativas para aplicações. Além disso, ela permite descrever o ciclo de vida das aplicações, incluindo quais imagens usar, o número de pods necessários e como devem ser feitas as atualizações.

Com um deployment Kubernetes, você pode:

  • Implantar um pod ou conjunto de réplicas
  • Atualizar pods e conjuntos de réplicas
  • Reverter para versões anteriores da implantação
  • Escalar implantações
  • Pausar ou continuar uma implantação

-- from https://www.redhat.com/pt-br/topics/containers/what-is-kubernetes-deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80

image -- from author

ReplicaSet

O propósito da ReplicaSet é configurar e manter estável o conjunto de réplicas dos pods.

-- from https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/

Helm

Helm é um gerenciador de pacotes para o kubernetes. Utilizaremos ele para instalação do Istio.

Instalação

Baixar a última versão e seguir o passo a passo.

Linux

# Environment Vars
export HELM_HOME=/home/marcelo/Documents/Ambiente/helm-v3.5.4
export PATH=$HELM_HOME:$PATH

Windows

Crie a variável de ambiente como HELM_HOME e inclua no PATH

Configuração

Seguir passo a passo. Configure o repo stable e o atualize:

# Add repo stable
helm repo add stable https://charts.helm.sh/stable
# Update repo
helm repo update

Istio

Os principais desafios quando trabalhamos monolitos e microservices estão relacionados com segurança, controle de tráfego, observabilidade e telemetria.

O Istio é uma ferramenta opensource que ajuda a resolver esses problemas através da disponibilização de uma malha de serviços(service mesh) em um cluster Kubernetes.

O termo service mesh é usado para descrever a rede de microservicos que compoem as aplicações e as interações entre elas. Os requisitos incluem service discovery, load balance, métricas e monitoração, teste A/B, implantações canário, limite de tráfego, controle de acesso e autenticação de ponta a ponta.

image

-- from https://istio.io/latest/docs/concepts/what-is-istio/

Componentes

Envoy

Istio usa uma extensão do Envoy Proxy. Envoy é um proxy de alta performance desenvovlido em C++ e é utilizado para mediar todo o tráfego de entrada e saida de todos os serviços na malha de serviços.

Envoy é implantado como sidecar, dando as seguintes funcionalidades aos serviços:

  • Service Discovery Dinâmico
  • Load balancing
  • TLS
  • HTTP/2 and proxies gRPC
  • Circuit breakers
  • Health checks
  • Rollout usando porcentagem de tráfego
  • Métricas

-- from https://istio.io/latest/docs/ops/deployment/architecture/

Istiod

Istiod provê service discovery (Pilot), configuração(Citadel) e gerenciamento de certificados(Galley).

Istiod também converte as regras de roteamente e controla o controle de tráfego para os sidecars em runtime.

-- from https://istio.io/latest/docs/ops/deployment/architecture/

Instalação com Helm

Seguir o passo a passo.

Baixar o Istio 1.14.0

Linux

# Environment Vars
export ISTIO_HOME=/home/marcelo/Documents/Ambiente/istio-1.9.3
export PATH=$ISTIO_HOME/bin:$PATH

Windows

Crie a variável de ambiente como ISTIO_HOME e inclua no PATH a configuração %ISTIO_HOME%\bin.

Configuração

# Create namespace for Istio components
kubectl create namespace istio-system

# Install Istio base chart
helm install istio-base $ISTIO_HOME/manifests/charts/base -n istio-system

# Install Istio discovery chart
helm install istiod $ISTIO_HOME/manifests/charts/istio-control/istio-discovery -n istio-system

# Install Istio ingress chart
helm install istio-ingress $ISTIO_HOME/manifests/charts/gateways/istio-ingress -n istio-system

# Install Istio egress chart
helm install istio-egress $ISTIO_HOME/manifests/charts/gateways/istio-egress -n istio-system

# Check installation
kubectl get pods -n istio-system

Obs: No ambiente Windows, troque o $ISTIO_HOME por %ISTIO_HOME%

image -- from author

Instalação manual

Seguir o passo a passo.

Configuração do Sidecar

O componente principal para o Istio é o Sidecar. Ele é responsável pelo controle, log e tráfego dos dados aos pods. A configuração se faz através do seguinte comando:

kubectl label namespace default istio-injection=enabled

O comando informa ao Istio para injetar automaticamente o sidecar aos pods do namespace default.

Demo

Essa demo possui a seguinte arquitetura:

image -- from author

Hello App

Possui webservice que retorna "Hello". Imagem já disponível no Docker Hub.

World App

Possui webservice que retorna "World". Um diferencial desta aplicação é que ela possui uma propriedade (application.percentual_erro=50) indicando a porcentagem de erros. A proposta é simular um deploy com algum problema. A v1 não contém erros e a v2 possui 50% de chances de dar erro. Ambas imagens já disponíveis no Docker Hub.

Hello World App

A aplicação orquestra as chamadas da Hello App e World App, concatenando o retorno das duas APIs. Imagem já disponível no Docker Hub.

Build das imagens (Opcional)

  • No arquivo apps/make.sh, substitua o valor da variável YOUR_DOCKER_HUB_USER pela sua conta.

  • execute o comando:

    Linux:

    sh make.sh

    Windows:

    make.bat

Deploy do Hello App

  • No arquivo k8s/app-hello.yaml, substitua o valor tentativafc pelo seu usuário do Docker Hub (Opcional).

  • execute o comando:

    kubectl apply -f k8s/app-hello.yaml

Deploy do World App

  • No arquivo k8s/app-world.yaml, substitua o valor tentativafc pelo seu usuário do Docker Hub (Opcional).

  • execute o comando:

    # Versão sem erros
    kubectl apply -f k8s/app-world-v1.yaml
    # Versão com 50% erros. Utilizaremos essa versão nos controles de deploys (Blue Green e Canary)
    kubectl apply -f k8s/app-world-v2.yaml

Deploy do Hello World App

  • No arquivo k8s/app-hello-world.yaml, substitua o valor tentativafc pelo seu usuário do Docker Hub (Opcional).

  • execute o comando:

    kubectl apply -f k8s/app-hello-world.yaml

Disponibilizando para acesso externo

No Istio, para o acesso externo, precisamos configurar o Gateway e os Virtual Servers

  • execute o comando:

    kubectl apply -f k8s/gateway.yaml

Obtendo o host e porta

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "Ingress Host: $INGRESS_HOST"
echo "Ingress Port: $INGRESS_PORT"
# Testando a chamada para hello-world app
echo "Url Test: http://$GATEWAY_URL/hello-world/say-hello-world"

Rodar o script jmeter

No arquivo csv app/jmeter_config.csv configure o host e a porta com os respectivos valores das variáveis $INGRESS_HOST e $INGRESS_PORT.

Execute o jmeter utilizando o script app/jmeter_config.jmx

image -- from author

Complementos Istio

O Istio já possui alguns complementos na sua pasta home. Os passos a seguir demonstram a instalação e visualização de cada um.

# Install addons (Prometheus, Grafana, Jaeger and Kiali):
kubectl apply -f $ISTIO_HOME/samples/addons

Kiali

Kiali é uma ferramenta de visualização de mesh do cluster. Para acessar o dashboard, execute o comando:

istioctl dashboard kiali

image -- from author

Jaeger

Jaeger é uma ferramenta de trace distribuído das aplicações. Através de um traceid, ele agrupa toda a stack de chamadas. Para visualizá-lo, utilize o seguinte comando:

istioctl dashboard jaeger

image -- from author

Grafana

Grafana é uma ferramenta de observality. Esse complemento já pré configura alguns dashboards com as métricas coletadas pelo sidecar Istio.

istioctl dashboard grafana

image -- from author

Horizontal Autoscaling

Através da análise de métricas dos pods, o K8S possui um recurso destinado ao scaling horizontal dos pods.

O Metric Server é um recurso instalado separadamente e funciona como um coletor de métricas. Através dessas métricas coletadas, podemos criar regras de autoscaling através da configuracao HPA.

Instalação Metric Server

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/metrics-server-helm-chart-3.8.2/components.yaml

kubectl get pods -n kube-system

Demo

# Instalação da aplicação de exemplo
kubectl apply -f k8s/hpa.yaml

# Criação manual do hpa para a aplicação de exeplo
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

# Listagem dos objetos hpa
kubectl get hpa

# Forcando uma carga
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"


kubectl get hpa

image -- from author

# Instalacao com podmanifest
kubectl apply -f ./k8s/hpa-v2.yaml

Controle de deploys

Um dos desafios do Countinous Delivery é garantir que o software com as novas features, funcionem corretamente. Há a necessidade portanto de estruturas de deployments que garantam a entrega das novas funcionalidades, que essas entregas não gerem indisponibilidade, que ocorram um teste pilotado em produção, e caso tudo esteja de acordo com os critérios de aceite, ocorra a liberaćão da nova versão para o restante do público.

Abordaremos aqui os dois modelos de deployments mais utilizados no mercado.

O Deployment Blue Green parte da premissa que devemos sempre ter disponíveis dois ambientes. O primeiro (chamaremos de Blue) com a versão atual da aplicação, e o segundo (Green) com a nova versão da aplicaćão. Após o deployment, todo o tráfego é direcionado para a nova aplicaćão (Green) e caso se identifique-se problemas, o tráfego é direcionado novamente para a versão anterior da aplicação (Blue).

image

-- from https://opensource.com/article/17/5/colorful-deployments

Com o Istio, podemos ter esse modelo de deployment através da disponibilização de pesos no tráfego para as versões da aplicação.

# virtual-service-blue-green.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: world-vs
spec:
  hosts:
    - "*"
  gateways:
    - demo-gateway
  http:
    - match:
        - uri:
            prefix: /world/
      route:
        - destination:
            host: world-app-svc
            port:
              number: 8080
            subset: v1
          weight: 0
        # Direcionará 100 do tráfego para a v2
        - destination:
            host: world-app
            port:
              number: 8080
            subset: v2
          weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: world-dr
spec:
  host: world-app-svc
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2

Aqui o importante são as regras de destino. Nessa versão da aplicação iremos direcionar 100% do tráfego para a v2 (Serviço world-app-svc com label v2 já instalado anteriormente).

Demo

Execute a instação do virtual service com a nova configuração:

# Instalação da aplicação de exemplo
kubectl apply -f k8s/virtual-service-blue-green.yaml

Canário

O Deployment Canário, também ocorre a dispobilização dos dois ambientes (Blue e Green), porém somente uma pequena parte do tráfego é direcionado para nova versão. Nesse modelo pode-se adotar uma porcentagem do tráfego ou também podemos utilizar outras informaćões como Http Headers para a utilizacão dos beta testers.

image

-- from https://opensource.com/article/17/5/colorful-deployments

Demo:

    gateway.yaml
    ...    
    route:
    - destination:
        host: world-app-svc
        port:
          number: 8080
        subset: v1
      weight: 100
    - destination:
        host: world-app-svc
        port:
          number: 8080
        subset: v2
      weight: 0

Flagger

Helm:

# Repo
helm repo add flagger https://flagger.app
# CRD
kubectl apply -f https://raw.githubusercontent.com/fluxcd/flagger/main/artifacts/flagger/crd.yaml
# Deploy with istio
helm upgrade -i flagger flagger/flagger \
--namespace=istio-system \
--set crd.create=false \
--set meshProvider=istio \
--set metricsServer=http://prometheus:9090

Manual:

kubectl apply -k github.com/fluxcd/flagger//kustomize/istio

Demo

Deletar todas as versões já instaladas.

V1

A V1 não possui taxa de erro. Por ela ser a primeira a ser instalada, ela será considerada primary(versão estável).

Para a instalação, execute os comandos abaixo:

# Install service and deployment. 
kubectl apply -f k8s/app-world-flagger-v1.yaml
# Install Flagger canary objects
kubectl apply -f k8s/app-canary-world-with-flagger.yaml
V2

A V2 também não lançará erros, pois foi configurada com taxa de erro em 0%. Note que as versões posteriores, são configuradas como canary. Elas serão testadas através das métricas definidas, e caso não apresente falhas, será promovida, tornando-se primary. O comando à seguir irá iniciar o deploy canário.

# Install deployment. 
kubectl apply -f k8s/app-world-flagger-v2.yaml

Checando Status

# Lista os logs das mensagens de deployment do flagger
kubectl -n istio-system logs deployment/flagger --tail=100 | jq .msg

# Lista todos os canários (Flagger CRD)
kubectl get canaries --all-namespaces

# Exibe os detalhes do canário word-app
kubectl -n default get canary/world-app -oyaml | awk '/status/,0'

# Pausa o comando até estar na condição promoted. Muito utilizado em esteiras CI/CD
kubectl wait canary/world-app --for=condition=promoted

image -- from author

image -- from author

image -- from author

V3

A V3 foi configurada com a taxa de erro de 50%. Por ser um taxa superior ao permitido (5%), o deploy não será evoluido, ocorrendo ao final o rollback.

# Install service and deployment. 
kubectl apply -f k8s/app-world-flagger-v3.yaml

image -- from author

image -- from author

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published