手動デプロイメントではエラーが発生しにくいです。さらに、それらは反復的で複雑なタスクの束で構成されています。開発チームは、アプリケーションの新しいバージョンの展開の複雑さと、それがもたらす頭痛の種を恐れています。場合によっては、アプリケーションのデプロイには高度なプラットフォーム スキルが必要になります。導入の問題をデバッグするのは面倒なプロセスです。
FluxCD は、手動タスクや反復的なタスクに費やされる労力を軽減するのに役立ちます。また、導入エラーや人的介入も最小限に抑えられます。宣言ファイルを使用してデプロイメントの状態を追跡および更新するツールが提供され、開発チームにとってデプロイメントとデバッグのプロセスが容易になります。
この記事では、 FluxCD 、 Flagger 、およびGrafanaを使用して、デプロイメント プロセスを自動化し、継続的なデプロイメント プロセスに変換する方法について説明します。
アプリケーションの継続的配信について詳しくは、最初の記事をご覧ください。
CI/CD ハンズオン: シンプルだが機能的な継続的インテグレーション ワークフロー [パート 1] 。
KinDとTerraform を使用して 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" }
事前コミットフックの提案:
FluxCD は、最新のソース管理変更 (Git リポジトリなど) を含む Kubernetes クラスターを維持するための GitOps ツールです。 Flux は、新しいコードのデプロイメントを自動化します。
Flux がクラスター内で実行されたら、それがどのように動作するかを見てみましょう。 ingress-nginx を Ingress プロバイダーとしてデプロイします。 Flux はプロジェクト フォルダー構造を強制しません。必要に応じて構成することも、好みの標準に従うこともできます。
Infrastructureという名前のフォルダー内に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 、 namespace.yaml 、 kustomization.yamlなどの複数のファイルを使用します。
Kustomizationは、リソースを読み取り、処理して適用します。最後に重要なことですが、クラスター構成を同期するために Kustomization オブジェクトを作成する必要があります。 Cluster/cluster_nameフォルダー内にインフラストラクチャ.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 Chart をインストールします。
Flaggerは、Blue/Green デプロイメント、カナリア リリース、または A/B テストを使用してアプリケーションを段階的に配信する Kubernetes オペレーターです。
ベースフォルダーを使用してスタックをすべてのクラスターにインストールすることも、別のフォルダーを使用してクラスターに応じてインストールをカスタマイズすることもできます。たとえば、開発クラスタにのみ Flagger をインストールしたいとします。
インフラストラクチャフォルダー内にクラスター名を使用して新しいフォルダーを作成します。次に、 i nfra Structure.yamlという名前のファイルをクラスター/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 を適用した後、クラスターのステータスを同期します。 Flagger をインストールし、インフラストラクチャ/クラスター名/flagger-systemフォルダー内に次の YAML ファイルを作成します。
--- 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アプリケーションの継続的デプロイメント パイプラインを構築するには、インストール YAML ファイルを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
この記事の最初の部分で説明したように、ホスト更新 Python スクリプトを使用してローカル環境ホストを更新できます。
次に、Kustomization ファイルをクラスター/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 はリポジトリにコミットをプッシュし、現在のバージョンを新しいバージョンで更新します。
新しいアプリケーション バージョンを少数のユーザーにリリースして、アプリケーションの機能、パフォーマンス、セキュリティが期待どおりであることを確認します。 FluxCD はチャートのバージョンを自動的に更新し、ユーザーが利用できるようにします。障害が発生した場合、FluxCD はイメージ バージョンを自動的に以前のバージョンにロールバックします。
Flagger は、新しいアプリケーション バージョンをユーザーのサブセットに段階的に配信し、アプリケーションのステータスを監視します。新しいアプリケーション バージョン用の新しいデプロイメントが作成され、受信トラフィックが新しいデプロイメントに徐々にリダイレクトされます。メトリクスの分析が成功した後、カナリアのデプロイメントが促進されます。障害が発生した場合、Flagger は新しいデプロイメントを削除し、古いデプロイメントへのトラフィック フローを再確立します。このプロセスは、アプリケーションをすべてのユーザーに配信する前に、欠陥、問題、エラーを検出するふりをします。
まず、アプリケーションのステータスを 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 には、デプロイメント、イングレス、ポッド自動エスケーラーへの参照が必要です。 Flagger が新しいバージョンを検出するたびに、デプロイメントをスケールアップし、プライマリ サービスとセカンダリ サービスを作成し、受信トラフィックを対応するサービスに送信するように nginx を構成します。 maxWeight プロパティと stepWeight プロパティを使用して、最大トラフィック リダイレクト パーセンテージと増分ステップ パーセンテージを構成します。
Flagger フックを使用してアプリケーションの負荷テストを行います。複数のフックが付いています。受け入れフックはカナリア展開の準備状況をチェックし、負荷テスト フックは継続的な受信トラフィックを生成します。
Flagger は、事前定義された成功率メトリクスを使用してカナリアのリリース ステータスを監視し、カナリア デプロイメントの推進ケースを決定します。 Flagger は、カナリア デプロイメントを促進するために 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 Exporter がノード メトリクスをエクスポートできるようになります。
記事の最初の部分で説明したように、ホスト更新 Python スクリプトを使用してローカル環境ホストを更新できます。
管理者のユーザー名とパスワードを使用して Grafana にログインします。インストール値を使用して管理者パスワードを定義できます。デフォルトでは、Chart はランダムなパスワードを保存するための Kubernetes シークレットを作成します。 Base64 パスワード値を取得してデコードするためのシークレットを記述します。
ID を使用するか、生の JSON をコピーして、お気に入りのダッシュボードをインポートできます。
最初の記事では、十分にテストされたアプリケーションを提供する方法について説明しました。この記事では、成果物を継続的にデプロイし、デプロイメントのステータスを監視する方法について説明します。
FluxCD と Flagger は、アプリケーションのステータスを継続的にテスト、デプロイ、監視するための複数の機能を提供します。この記事ではその一部を使用していますが、Webhook と通知機能については説明していません。通知機能を使用して、デプロイメントがいつ失敗したかを知るか、Web フック機能を使用して、新しい環境へのデプロイメントを促進したり、新しいバージョンに対するテストを開始したりできます。 FluxCD を他のツールと統合して、デプロイメント パイプラインを強化します。
手動による展開は避けてください。これらは複雑であり、エラーが発生しやすいものではありません。開発チームがアプリケーションを保守するよう奨励し、展開プロセスを容易にします。自動展開により、リード タイム、フィードバック ループ、および全体的なコストが削減されます。開発者は本当に重要なことに集中できます。