paint-brush
CI/CD 실습: 간단하지만 기능적인 지속적 배포 워크플로 [2부]~에 의해@j04n
515 판독값
515 판독값

CI/CD 실습: 간단하지만 기능적인 지속적 배포 워크플로 [2부]

~에 의해 Joan Flotats14m2023/10/10
Read on Terminal Reader

너무 오래; 읽다

수동 배포에서는 오류가 발생하지 않습니다. 더욱이, 이는 반복적이고 복잡한 작업으로 구성됩니다. 이 기사에서는 FluxCD, Flagger 및 Grafana를 사용하여 배포 프로세스를 지속적인 배포 프로세스로 변환하는 자동화 방법을 살펴봅니다.
featured image - CI/CD 실습: 간단하지만 기능적인 지속적 배포 워크플로 [2부]
Joan Flotats HackerNoon profile picture
0-item
1-item


수동 배포에서는 오류가 발생하지 않습니다. 더욱이, 이는 반복적이고 복잡한 작업으로 구성됩니다. 개발 팀은 새 버전의 애플리케이션을 배포하는 데 따른 복잡성과 이로 인해 발생하는 골칫거리를 두려워합니다. 때로는 애플리케이션을 배포하려면 고급 플랫폼 기술이 필요합니다. 배포 문제를 디버깅하는 것은 지루한 프로세스입니다.


FluxCD는 수동적이고 반복적인 작업에 드는 노력을 줄이는 데 도움이 됩니다. 또한 배포 오류와 인간 상호 작용을 최소화합니다. 선언적 파일을 사용하여 배포 상태를 추적하고 업데이트하는 도구를 제공하므로 개발 팀의 배포 및 디버깅 프로세스가 더 쉬워집니다.


이 기사에서는 FluxCD , FlaggerGrafana를 사용하여 배포 프로세스를 지속적인 배포 프로세스로 변환하는 자동화 방법을 살펴봅니다.


애플리케이션을 지속적으로 제공하는 방법에 대해 자세히 알아보려면 첫 번째 문서를 확인하세요.

CI/CD 실습: 단순하지만 기능적인 지속적 통합 워크플로 [1부] .



소개

KinDTerraform을 사용하여 Kubernetes 클러스터를 설정합니다. 우선 클러스터를 생성하고 Kubernetes 구성을 내보내 Kubernetes 공급자를 설정합니다.


 $ kind create cluster --name develop $ kind export kubeconfig --name develop --kubeconfig kubeconfig


새로운 GitHub 저장소와 저장소 권한이 있는 개발자 토큰을 생성하려면 Terrafom에서 FluxCD를 설정해야 합니다. Terraform을 초기화하고 변경 사항을 적용합니다.


 $ terraform init $ terraform apply -var="github_owner=owner_name" -var="github_repository=repo_name" # Introduce your GitHub token


Terraform이 설치 프로세스를 완료하면 KinD 클러스터에서 FluxCD가 실행되고 저장소에 클러스터 라는 새 폴더가 있어야 합니다.


테라폼

내부적으로 Terraform은 MetalLB를 설치하고 IP 범위를 구성합니다. 기사의 첫 번째 부분 에서 MetalLB 구성에 대해 자세히 알아볼 수 있습니다.


 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] }


그런 다음 FLuxCD Helm Chart를 설치하고 FluxCD를 사용하도록 GitHub 저장소를 구성합니다.


 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" }


후크 사전 커밋 제안:

  1. Terraform ( https://github.com/antonbabenko/pre-commit-terraform ):
    • TFSec: 잠재적인 구성 오류를 찾아내기 위한 Terraform의 정적 분석
    • TFLint: Terraform용 정적 형식 검사기
  2. 비밀 감지 ( https://github.com/Yelp/Detect-secrets ): 새로운 비밀이 코드 베이스에 입력되는 것을 방지합니다.


플럭스CD

FluxCD 는 Git 리포지토리와 같은 최신 소스 제어 변경 사항으로 Kubernetes 클러스터를 유지하는 GitOps 도구입니다. Flux는 새로운 코드 배포를 자동화합니다.


Flux가 클러스터에서 실행되면 어떻게 작동하는지 살펴보겠습니다. ingress-nginx를 수신 공급자로 배포합니다. Flux는 프로젝트 폴더 구조를 강제하지 않습니다. 원하는 대로 구성하거나 선호하는 표준을 따를 수 있습니다.


인프라 라는 폴더 안에 base 라는 폴더를 만듭니다. 기본 폴더에는 모든 클러스터에 대한 기본 인프라 구성이 있습니다. 다음으로 ingress-nginx 라는 폴더를 만듭니다. 네임스페이스 이름을 폴더 이름으로 사용합니다.


 --- 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


여러 파일을 사용하여 객체를 정의합니다( helmrelease.yaml , helmrepository.yaml , 네임스페이스.yaml , kustomization.yaml 등).


Kustomization 은 리소스를 읽고 처리하여 적용합니다. 마지막으로 클러스터 구성을 동기화하려면 Kustomization 객체를 생성해야 합니다. Cluster/cluster_name 폴더 내에 industry.yaml 이라는 YAML 파일을 생성합니다.


 --- 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


변경 사항을 저장소에 커밋하고 푸시한 후 Flux는 클러스터 상태를 조정하여 ingress-nginx Helm 차트를 설치합니다.


신고자

Flagger 는 블루/그린 배포, Canary 릴리스 또는 A/B 테스트를 사용하여 점진적으로 애플리케이션을 제공하는 Kubernetes 운영자입니다.


기본 폴더를 사용하여 스택을 모든 클러스터에 설치하거나 다른 폴더를 사용하여 클러스터에 따라 설치를 사용자 지정할 수 있습니다. 예를 들어 개발 클러스터에만 Flagger를 설치하려고 합니다.


인프라 폴더 내에 클러스터 이름을 사용하여 새 폴더를 만듭니다. 그런 다음, i nfrastructure.yaml 이라는 파일을 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


FluxCD는 인프라 기반 Kustomization을 적용한 후 클러스터 상태를 동기화합니다. 인프라/cluster_name/flager-system 폴더 내에 다음 YAML 파일을 생성하여 Flagger를 설치합니다.


 --- 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


지속적인 배포

Podinfo 애플리케이션 지속적 배포 파이프라인을 빌드하려면 apps/cluster_name/podinfo *:*에 설치 YAML 파일을 생성합니다.


 --- 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


문서의 첫 번째 부분 에 설명된 대로 업데이트 호스트 Python 스크립트를 사용하여 로컬 환경 호스트를 업데이트할 수 있습니다.


그런 다음 Kustomization 파일을 Cluster/cluster_name 폴더에 생성하여 앱을 동기화합니다.


 --- 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


다음으로 Podinfo 이미지 Helm Chart 버전을 자동 업데이트하도록 FluxCD를 구성할 수 있습니다. 이미지 자동 업데이트를 구성하려면 새 이미지 태그를 검색하기 위한 이미지 저장소, 업데이트할 버전 패턴을 정의하기 위한 이미지 업데이트 정책, 변경 사항을 푸시하도록 저장소를 구성하기 위한 이미지 자동 업데이트를 생성해야 합니다.


 --- 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


마지막으로 업데이트하려는 이미지 또는 태그에 이미지 업데이트 정책을 적용합니다.


 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


Podinfo Chart에 6.xx 범위의 새 버전이 있을 때마다 FluxCD는 커밋을 저장소에 푸시하여 현재 버전을 최신 버전으로 업데이트합니다.


플럭스CD. https://fluxcd.io/flux/comComponents/image


카나리아 출시

애플리케이션 기능, 성능 및 보안이 기대한 수준인지 확인하기 위해 소수의 사용자 하위 집합에게 새 애플리케이션 버전을 출시합니다. FluxCD는 차트 버전을 자동으로 업데이트하여 사용자가 사용할 수 있도록 합니다. 오류가 발생하면 FluxCD는 자동으로 이미지 버전을 이전 버전으로 롤백합니다.

Flagger는 새로운 애플리케이션 버전을 사용자 하위 집합에 점진적으로 제공하고 애플리케이션 상태를 모니터링합니다. 새 애플리케이션 버전에 대한 새 배포를 생성하고 들어오는 트래픽을 새 배포로 점진적으로 리디렉션합니다. 측정항목을 성공적으로 분석한 후 카나리아 배포를 승격합니다. 오류가 발생하면 Flagger는 새 배포를 삭제하고 이전 배포에 대한 트래픽 흐름을 다시 설정합니다. 이 프로세스는 애플리케이션을 모든 사용자에게 제공하기 전에 결함, 문제 및 오류를 감지하는 척합니다.



플래거. https://docs.flager.app/tutorials/nginx-progressive-delivery


먼저, Flagger에게 애플리케이션 상태를 알리는 지표 템플릿을 만듭니다. Prometheus를 사용하여 요청 성공률을 측정합니다.


 --- 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


그런 다음 카나리아 릴리스 프로세스를 정의합니다. 우리는 nginx를 공급자로 사용하여 들어오는 트래픽을 형성합니다. Flagger는 릴리스를 구성하는 다양한 방법과 도구를 제공합니다.


 --- 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


Flagger에는 배포, 수신 및 Pod 자동 에스컬러에 대한 참조가 필요합니다. Flagger는 새 버전을 감지할 때마다 배포를 확장하고 기본 및 보조 서비스를 생성하며 들어오는 트래픽을 해당 서비스로 보내도록 nginx를 구성합니다. maxWeight 및 stepWeight 속성을 사용하여 최대 트래픽 리디렉션 비율과 증분 단계 비율을 구성합니다.

Flagger 후크를 사용하여 애플리케이션 부하 테스트를 수행하세요. 여러 개의 후크가 있습니다. 수락 후크는 카나리아 배포 준비 상태를 확인하고 부하 테스트 후크는 지속적인 수신 트래픽을 생성합니다.

Flagger는 사전 정의된 성공률 지표를 사용하여 Canary 릴리스 상태를 모니터링하여 Canary 배포 프로모션 사례를 결정합니다. Flagger는 Canary 배포를 촉진하기 위해 99%의 요청 성공률을 기대합니다. 롤백하기 전에 실패한 메트릭 확인의 최대 수를 구성하려면 임계값 속성을 사용하십시오.


모니터링

Loki 스택을 사용하면 Grafana + Loki + Prometheus를 사용하여 클러스터 리소스의 상태를 모니터링할 수 있습니다. 인프라/cluster_name/loki-stack 폴더 내에 다음 YAML 파일을 생성하여 Loki 스택을 설치합니다.


 --- 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


Loki 스택을 설치하면 Grafana Ingress가 Grafana에 액세스하고, Prometheus가 환경 측정항목을 수집하고, Node Importer가 노드 측정항목을 내보낼 수 있습니다.


문서의 첫 번째 부분 에 설명된 대로 업데이트 호스트 Python 스크립트를 사용하여 로컬 환경 호스트를 업데이트할 수 있습니다.


관리자 사용자 이름과 비밀번호를 사용하여 Grafana에 로그인합니다. 설치 값을 사용하여 관리자 비밀번호를 정의할 수 있습니다. 기본적으로 차트는 임의의 비밀번호를 저장하기 위해 Kubernetes 비밀을 생성합니다. base64 비밀번호 값을 가져오고 이를 디코딩하기 위한 비밀을 설명합니다.


ID를 사용하거나 원시 JSON을 복사하여 즐겨찾는 대시보드를 가져올 수 있습니다.


Grafana - Prometheus K8s 대시보드


Grafana - Prometheus FluxCD 대시보드


Grafana - Loki 로그


결론

첫 번째 기사에서는 잘 테스트된 애플리케이션을 제공하는 방법을 살펴보았습니다. 이 문서에서는 결과물을 지속적으로 배포하고 배포 상태를 모니터링하는 방법을 살펴봅니다.


FluxCD와 Flagger는 애플리케이션 상태를 지속적으로 테스트, 배포 및 모니터링할 수 있는 다양한 기능을 제공합니다. 이 문서에서는 그 중 일부를 사용하지만 웹후크 및 알림 기능은 확인하지 못했습니다. 알림 기능을 사용하여 배포가 실패한 시기를 확인하거나 웹후크 기능을 사용하여 배포를 새 환경으로 승격하거나 새 버전에 대한 테스트를 시작하세요. FluxCD를 다른 도구와 함께 통합하여 배포 파이프라인을 강화하세요.

수동 배포를 피하세요. 복잡하고 오류가 발생하기 쉽지 않습니다. 개발 팀이 애플리케이션을 유지 관리하도록 장려하여 배포 프로세스를 더 쉽게 만듭니다. 자동 배포는 리드 타임, 피드백 루프 및 전체 비용을 줄여줍니다. 개발자는 정말로 중요한 것에 집중할 수 있습니다.