A Product-minded and Results-oriented Software Engineer | Empowering DevTestOps Culture
Walkthroughs, tutorials, guides, and tips. This story will teach you how to do something new or how to do something better.
The code in this story is for educational purposes. The readers are solely responsible for whatever they build with it.
As implantações manuais não são propensas a erros. Além disso, consistem em um conjunto de tarefas repetitivas e complexas. As equipes de desenvolvimento têm medo da complexidade de implantar uma nova versão de um aplicativo e das dores de cabeça que isso traz. Às vezes, a implantação de um aplicativo requer conhecimentos avançados de plataforma. É um processo tedioso depurar problemas de implantação.
FluxCD ajuda você a reduzir o esforço dedicado a tarefas manuais e repetitivas. Também minimiza os erros de implantação e as interações humanas. Ele oferece ferramentas para rastrear e atualizar o estado de suas implantações usando arquivos declarativos, facilitando o processo de implantação e depuração para suas equipes de desenvolvimento.
Este artigo explora a automação de seus processos de implantação para transformá-los em processos de implantação contínua usando FluxCD , Flagger e Grafana .
Verifique o primeiro artigo para saber mais sobre a entrega contínua de um aplicativo:
Prática de CI/CD: um fluxo de trabalho de integração contínua simples, mas funcional [Parte 1] .
Exemplo do GitHub: https://github.com/joan-mido-qa/continious-deployment-example
Use KinD e Terraform para configurar o cluster Kubernetes. Primeiro de tudo, crie o cluster e exporte a configuração do Kubernetes para definir o provedor Kubernetes:
$ kind create cluster --name develop $ kind export kubeconfig --name develop --kubeconfig kubeconfig
Crie um novo repositório GitHub e um token de desenvolvedor com permissões de repositório. O Terrafom exige isso para configurar o FluxCD. Inicialize o Terraform e aplique as alterações:
$ terraform init $ terraform apply -var="github_owner=owner_name" -var="github_repository=repo_name" # Introduce your GitHub token
Assim que o Terraform terminar o processo de instalação, você deverá ter o FluxCD em execução em seu cluster KinD e uma nova pasta chamada cluster em seu repositório.
Nos bastidores, o Terraform instala o MetalLB e configura o intervalo de IP. Você pode ler mais sobre a configuração do MetalLB na primeira parte do artigo :
resource "helm_release" "metallb" { name = "metallb" repository = "https://metallb.github.io/metallb" chart = "metallb" } data "docker_network" "kind" { name = "kind" } resource "kubectl_manifest" "kind-address-pool" { yaml_body = yamlencode({ "apiVersion" : "metallb.io/v1beta1", "kind" : "IPAddressPool", "metadata" : { "name" : "kind-address-pool" }, "spec" : { "addresses" : [replace(tolist(data.docker_network.kind.ipam_config)[0].subnet, ".0.0/16", ".255.0/24")] } }) depends_on = [helm_release.metallb] } resource "kubectl_manifest" "kind-advertisement" { yaml_body = <<YAML apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind-advertisement YAML depends_on = [helm_release.metallb] }
Em seguida, ele instala o FLuxCD Helm Chart e configura o repositório GitHub para usar o FluxCD:
resource "helm_release" "flux" { repository = "https://fluxcd-community.github.io/helm-charts" chart = "flux2" name = "flux2" namespace = "flux-system" create_namespace = true version = "2.9.2" } resource "tls_private_key" "flux" { depends_on = [helm_release.flux] algorithm = "ECDSA" ecdsa_curve = "P256" } resource "github_repository_deploy_key" "flux" { depends_on = [tls_private_key.flux] title = "Flux" repository = var.github_repository key = tls_private_key.flux.public_key_openssh read_only = "false" } resource "flux_bootstrap_git" "this" { depends_on = [github_repository_deploy_key.flux] path = "clusters/develop" }
Sugestões de ganchos pré-confirmados:
FluxCD é uma ferramenta GitOps para manter um cluster Kubernetes com as alterações de controle de origem mais recentes (como repositórios Git). Flux automatiza a implantação de novo código.
Assim que o Flux estiver rodando no cluster, vamos ver como funciona. Implantaremos o ingress-nginx como um provedor de ingresso. O Flux não impõe a estrutura de pastas do projeto. Você pode configurá-lo como desejar ou seguir o padrão de sua preferência.
Crie uma pasta chamada base dentro de uma pasta chamada infraestrutura . A pasta base contém a configuração básica da infraestrutura para todos os seus clusters. Em seguida, crie uma pasta chamada ingress-nginx . Use o nome do namespace como nome da pasta.
--- apiVersion: v1 kind: Namespace metadata: name: ingress-ngnix --- apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: HelmRepository metadata: name: ingress-nginx spec: interval: 2h url: https://kubernetes.github.io/ingress-nginx --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: ingress-nginx spec: interval: 15m chart: spec: chart: ingress-nginx version: 4.7.1 sourceRef: kind: HelmRepository name: ingress-nginx interval: 15m --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ingress-ngnix resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Use vários arquivos para definir seus objetos: helmrelease.yaml , helmrepository.yaml , namespace.yaml , kustomization.yaml , etc.
O Kustomization lê e processa os recursos para aplicá-los. Por último, mas não menos importante, você precisa criar um objeto Kustomization para sincronizar a configuração do seu cluster. Crie um arquivo YAML chamado infraestrutura.yaml dentro da pasta cluster/cluster_name :
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: infra-base namespace: flux-system spec: interval: 1h retryInterval: 1m timeout: 5m sourceRef: kind: GitRepository name: flux-system path: ./infrastructure/base prune: true wait: true
Depois de confirmar e enviar suas alterações para seu repositório, o Flux reconciliará o status do cluster para instalar o Helm Chart ingress-nginx.
Flagger é um operador Kubernetes que entrega progressivamente seu aplicativo usando implantações azul/verde, lançamento canário ou testes A/B.
Você pode usar a pasta base para instalar sua pilha em todos os clusters ou usar uma pasta diferente para personalizar sua instalação dependendo do cluster. Por exemplo, queremos instalar o Flagger apenas no cluster de desenvolvimento.
Crie uma nova pasta usando o nome do cluster dentro da pasta de infraestrutura . Em seguida, crie um arquivo chamado i nfrastructure.yaml em seu cluster/cluster_name :
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: infra-cluster-name namespace: flux-system spec: dependsOn: - name: infra-base interval: 1h retryInterval: 1m timeout: 5m sourceRef: kind: GitRepository name: flux-system path: ./infrastructure/cluster_name prune: true
O FluxCD sincronizará o status do cluster após aplicar o Kustomization infra-base. Instale o Flagger, criando o seguinte arquivo YAML dentro da pasta infraestrutura/cluster_name/flager-system :
--- apiVersion: v1 kind: Namespace metadata: name: flagger-system --- apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository metadata: name: flagger spec: interval: 1h url: https://flagger.app --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: flagger spec: interval: 1h install: crds: CreateReplace upgrade: crds: CreateReplace chart: spec: chart: flagger version: 1.xx interval: 6h sourceRef: kind: HelmRepository name: flagger --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: flagger-loadtester spec: interval: 1h chart: spec: chart: loadtester version: 0.xx interval: 6h sourceRef: kind: HelmRepository name: flagger --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flagger-system resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Para construir o pipeline de implantação contínua do aplicativo Podinfo , crie o arquivo YAML de instalação em apps/cluster_name/podinfo *:*
--- apiVersion: v1 kind: Namespace metadata: name: podinfo --- apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository metadata: name: podinfo spec: interval: 5m url: https://stefanprodan.github.io/podinfo --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: podinfo spec: releaseName: podinfo chart: spec: chart: podinfo version: 6.5.0 sourceRef: kind: HelmRepository name: podinfo interval: 50m install: remediation: retries: 3 values: ingress: enabled: true className: nginx hpa: enabled: true --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Você pode usar o script Python update hosts para atualizar seus hosts de ambiente local, conforme explicado na primeira parte do artigo .
Em seguida, crie o arquivo Kustomization na pasta cluster/cluster_name para sincronizar seus aplicativos:
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: apps namespace: flux-system spec: interval: 10m0s dependsOn: - name: infra-cluster-name sourceRef: kind: GitRepository name: flux-system path: ./apps/cluster_name prune: true wait: true timeout: 5m0s
A seguir, podemos configurar o FluxCD para atualizar automaticamente a versão do Helm Chart da imagem Podinfo. Para configurar a atualização automática da imagem, precisamos criar um repositório de imagens para procurar novas tags de imagem, uma política de atualização de imagem para definir o padrão de versão a ser atualizado e uma atualização automática de imagem para configurar o repositório para enviar a alteração.
--- apiVersion: image.toolkit.fluxcd.io/v1beta2 kind: ImageRepository metadata: name: podinfo-chart spec: image: ghcr.io/stefanprodan/charts/podinfo interval: 5m --- apiVersion: image.toolkit.fluxcd.io/v1beta2 kind: ImagePolicy metadata: name: podinfo-chart spec: imageRepositoryRef: name: podinfo-chart policy: semver: range: 6.xx --- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImageUpdateAutomation metadata: name: podinfo-chart spec: interval: 30m sourceRef: kind: GitRepository name: flux-system namespace: flux-system git: checkout: ref: branch: main commit: author: email: fluxcdbot@users.noreply.github.com name: fluxcdbot messageTemplate: 'chore(develop): update podinfo chart to {{range .Updated.Images}}{{println .}}{{end}}' push: branch: main update: path: ./apps/cluster_name/podinfo strategy: Setters --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - imagepolicy.yaml - imagerepository.yaml - imageautoupdate.yaml
Por fim, aplique a política de atualização de imagem à imagem ou tag que deseja atualizar:
apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: podinfo spec: releaseName: podinfo chart: spec: chart: podinfo version: 6.5.0 # {"$imagepolicy": "podinfo:podinfo-chart:tag"} sourceRef: kind: HelmRepository name: podinfo interval: 50m install: remediation: retries: 3
Sempre que o Podinfo Chart tiver uma nova versão na faixa 6.xx, o FluxCD enviará um commit para o repositório, atualizando a versão atual com a mais recente.
FluxCD. https://fluxcd.io/flux/components/image
Lançar uma nova versão do aplicativo para um pequeno subconjunto de usuários para garantir que a funcionalidade, o desempenho e a segurança do aplicativo sejam os esperados. O FluxCD atualiza automaticamente a versão do gráfico e a disponibiliza aos usuários. Em caso de falha, o FluxCD reverte automaticamente a versão da imagem para a anterior.
O Flagger entrega progressivamente a nova versão do aplicativo a um subconjunto de usuários e monitora o status do aplicativo. Ele cria uma nova implantação para as novas versões do aplicativo e redireciona progressivamente o tráfego de entrada para a nova implantação. Ele promoverá a implantação canário após uma análise bem-sucedida das métricas. Em caso de falha, o Flagger exclui a nova implantação e restabelece o fluxo de tráfego para a implantação antiga. Este processo pretende detectar defeitos, problemas e erros antes de entregar a aplicação a todos os seus usuários.
Sinalizador. https://docs.flagger.app/tutorials/nginx-progressive-delivery
Primeiro, crie um modelo de métrica para informar ao Flagger qual é o status do aplicativo. Usamos o Prometheus para medir a taxa de sucesso da solicitação:
--- apiVersion: flagger.app/v1beta1 kind: MetricTemplate metadata: name: podinfo-request-success-rate spec: provider: type: prometheus address: http://loki-stack-prometheus-server.loki-stack:80 query: | 100 - sum( rate( http_requests_total{ app_kubernetes_io_name="podinfo", namespace="{{ namespace }}", status!~"5.*" }[{{ interval }}] ) ) / sum( rate( http_requests_total{ app_kubernetes_io_name="podinfo", namespace="{{ namespace }}", }[{{ interval }}] ) ) * 100 --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - metrictemplate.yaml
Em seguida, defina o processo de lançamento canário. Usamos o nginx como provedor para moldar o tráfego de entrada. Flagger oferece várias maneiras e ferramentas para configurar seus lançamentos.
--- apiVersion: flagger.app/v1beta1 kind: Canary metadata: name: podinfo spec: provider: nginx targetRef: apiVersion: apps/v1 kind: Deployment name: podinfo ingressRef: apiVersion: networking.k8s.io/v1 kind: Ingress name: podinfo autoscalerRef: apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler name: podinfo progressDeadlineSeconds: 60 service: port: 9898 targetPort: 9898 analysis: interval: 10s threshold: 10 maxWeight: 50 stepWeight: 5 metrics: - name: podinfo-request-success-rate thresholdRange: min: 99 interval: 1m webhooks: - name: acceptance-test type: pre-rollout url: http://flagger-loadtester.flagger-system/ timeout: 30s metadata: type: bash cmd: curl -sd 'test' http://podinfo-canary.podinfo:9898/token | grep token - name: load-test url: http://flagger-loadtester.flagger-system/ timeout: 5s metadata: cmd: hey -z 1m -q 10 -c 2 http://podinfo-canary.podinfo:9898/healthz --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - canary.yaml
O sinalizador requer referências à sua implantação, entrada e escalonador automático de pod. Sempre que o Flagger detectar uma nova versão, ele aumentará a implantação, criará um serviço primário e secundário e configurará o nginx para enviar o tráfego de entrada para o serviço correspondente. Use as propriedades maxWeight e stepWeight para configurar a porcentagem máxima de redirecionamento de tráfego e a porcentagem de etapa incremental.
Teste de carga seu aplicativo usando ganchos Flagger. Possui vários ganchos. Os ganchos de aceitação verificam a prontidão da implantação canário e o gancho de teste de carga gera tráfego de entrada constante.
O Flagger monitorará o status de lançamento do canary usando a métrica de taxa de sucesso predefinida para decidir o caso de promoção da implantação do canary. Flagger espera uma taxa de sucesso de solicitação de 99% para promover a implantação canário. Use a propriedade limite para configurar um número máximo de verificações de métricas com falha antes da reversão.
Use a pilha Loki para monitorar o status dos recursos do cluster usando Grafana + Loki + Prometheus. Instale a pilha Loki criando o seguinte arquivo YAML dentro da pasta infraestrutura/cluster_name/loki-stack :
--- apiVersion: v1 kind: Namespace metadata: name: loki-stack --- apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: HelmRepository metadata: name: grafana spec: interval: 2h url: https://grafana.github.io/helm-charts --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: loki-stack spec: interval: 1h chart: spec: chart: loki-stack version: v2.9.11 sourceRef: kind: HelmRepository name: grafana interval: 1h values: grafana: enabled: true ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: - grafana.local prometheus: enabled: true nodeExporter: enabled: true --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: loki-stack resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
A instalação da pilha Loki permite que o Grafana Ingress acesse o Grafana, o Prometheus para coletar as métricas do seu ambiente e o Node Exporter para exportar as métricas do seu nó.
Você pode usar o script Python update hosts para atualizar seus hosts de ambiente local, conforme explicado na primeira parte do artigo
Faça login no Grafana usando o nome de usuário e senha de administrador. Você pode definir a senha do administrador usando os valores de instalação. Por padrão, o gráfico cria um segredo do Kubernetes para armazenar uma senha aleatória. Descreva o segredo para obter o valor da senha base64 e decodificá-lo.
Você pode importar seu painel favorito usando seu ID ou copiando o JSON bruto:
Grafana - Painel do Prometheus K8s
Grafana - Painel Prometheus FluxCD
Grafana - Registros de Loki
O primeiro artigo explorou como entregar um aplicativo bem testado. Este artigo explora como implantar continuamente um produto final e monitorar o status da implantação.
FluxCD e Flagger oferecem vários recursos para testar, implantar e monitorar continuamente o status de seu aplicativo. Este artigo usa alguns deles, mas não vimos os webhooks e recursos de notificações. Use os recursos de notificações para saber quando uma implantação falhou ou o recurso web-hooks para promover a implantação em um novo ambiente ou iniciar seus testes em novas versões. Integre o FluxCD junto com outras ferramentas para enriquecer seu pipeline de implantação.
Evite implantações manuais. Eles são complexos e não sujeitos a erros. Incentive as equipes de desenvolvimento a manterem suas aplicações, facilitando o processo de implantação. As implantações automáticas reduzem o tempo de espera, o ciclo de feedback e os custos gerais. Os desenvolvedores podem se concentrar no que realmente importa.