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: [email protected] 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.
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.
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:
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.