はじめに
私が運用している Kubernetes クラスタでは、公開されている Helm Chart を使っていくつかのサービスを立てています。
しかし、これらすべての Chart に対して、定期的にアップデートが来ていないかを確認して手動で設定を更新するのは非常に手間です。
そこで今回は、Flux の公式が紹介しているHelm Promotionの方法に従って、新しいバージョンの Helm Chart がリリースされたら「ステージング環境で動作確認をして」本番環境でも自動でバージョンを更新する仕組みを整えていこうと思います。
実装
実装しないといけないのは主に次の 4 つです。
- ステージング環境の Helm
- 本番環境の Helm
- Flux Alert
- GitHub Action
ステージング環境の Helm
ステージング環境では、マイナーバージョンのアップグレードが勝手に行われるよう、バージョン指定のマイナーバージョンを x で指定しておきます。
# staging.helm.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: release-name
spec:
chart:
spec:
version: 19.x
test:
enable: true
本番環境の Helm
本番環境の Helm では、通常通りマイナーバージョンまで指定しておきます。
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: release-name
spec:
chart:
spec:
version: 19.0.1
Flux Alert
Staging 環境で Helm に変更が加えられたら、GitHub Actions をトリガーするように設定します。
Staging 環境で次のように Flux の Provider, Alert を設定します。
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: githubdispatch
namespace: flux-system
spec:
type: githubdispatch
address: <repo address>
secretRef:
name: github-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: helm-promotion
namespace: flux-system
spec:
providerRef:
name: githubdispatch
summary: "Trigger promotion"
eventMetadata:
env: staging
eventSeverity: info
inclusionList:
- ".*.test.*succeeded.*"
eventSources:
- kind: HelmRelease
name: "*"
namespace: monitoring
- kind: HelmRelease
name: "*"
namespace: prometheus
- kind: HelmRelease
name: "*"
namespace: vault
全 namespace に対して指定をしないといけないのは面倒ですが、仕方ないですね
Flux の issue を見てみたら、一応改善する意思はあるみたいなので今後のリリースを待ちましょう
Github Action
最後に、Flux が GitHub Action をトリガーしたら、本番環境の Helm のバージョンが更新されるように GitHub Action を作成します。
name: helm-promotion
on:
repository_dispatch:
types:
- HelmRelease/*
permissions:
contents: write
pull-requests: write
jobs:
promote:
runs-on: ubuntu-latest
if: |
github.event.client_payload.metadata.env == 'staging' &&
github.event.client_payload.severity == 'info'
steps:
- uses: actions/checkout@v4
with:
ref: main
# Parse the event metadata to determine the chart version deployed on staging.
- name: Get chart info from staging
id: staging
run: |
NAME=${{ github.event.client_payload.involvedObject.name }}
VERSION=$(echo ${{ github.event.client_payload.metadata.revision }} | cut -d '@' -f1)
echo NAME=${NAME} >> $GITHUB_OUTPUT
echo VERSION=${VERSION} >> $GITHUB_OUTPUT
# Patch the chart version in the production Helm release manifest.
- name: Set chart version in production
id: production
env:
CHART_VERSION: ${{ steps.staging.outputs.version }}
run: |
echo "set chart version to ${CHART_VERSION}"
FILE_PATH=$(find ./kubernetes/apps/*/production/*helm*.yaml -type f -print | xargs grep "name: ${{ steps.staging.outputs.name }}$" | cut -d':' -f1)
yq eval '.spec.chart.spec.version=env(CHART_VERSION)' -i $FILE_PATH
# Open a Pull Request if an upgraded is needed in production.
- name: Open promotion PR
uses: peter-evans/create-pull-request@v6
id: open_pr
with:
branch: fluxcd/helm-promotion/${{ steps.staging.outputs.name }}/${{ steps.staging.outputs.version}}
delete-branch: true
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update ${{ steps.staging.outputs.name }} to v${{ steps.staging.outputs.version }}
title: Promote ${{ steps.staging.outputs.name }} release to v${{ steps.staging.outputs.version }}
body: |
Promote ${{ steps.staging.outputs.name }} release on production to v${{ steps.staging.outputs.version }}
- name: Enable auto-merge for FluxCD PRs
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{ steps.open_pr.outputs.pull-request-url }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
以下の部分で、該当する Helm ファイルを探し出しています。
FILE_PATH=$(find ./kubernetes/apps/*/production/*helm*.yaml -type f -print | xargs grep "name: ${{ steps.staging.outputs.name }}$" | cut -d':' -f1)
これで Helm の新しいバージョンがリリースされたら自動でステージング・プロダクションに更新が入るようになりました!
まとめ
今回は Flux の Alert を使って Helm の自動アップグレードを実現しました。ステージング環境を使って新しいバージョンの Helm の動作確認をした上で Production 環境に自動で反映させる、という一連の流れを実装することができて満足しています。
参考資料