GitOpsとは
GitOpsというのをご存知でしょうか。 GitOpsはWeaveworks社が提唱した、Kubernetesへのワークロードの 継続的デプロイ(CD)方法です(Git to GitOps) 。
GitOpsは4つの原則があります
- システムを宣言的に記述する
- 望ましいシステム状態をGitでバージョン管理する
- 承認された変更は自動的にシステムに適用される
- ソフトウェアエージェントで正確性を確保し、相違を警告する
では、通常のデプロイとGitOpsによるデプロイはどういった違いがあるでしょうか。 簡単に示したのが以下の図になります。
従来のCI/CDツールはツール側からKubernetes環境にコマンド等を実行して、 Gitリポジトリにある設定情報をPushしてデプロイします(こちらをCIOpsと呼ぶこともあります)。 この方式では、環境設定情報をGitで管理し変更を自動的に適用することはできますが、望ましい状態を維持することはできません (難しい)。
それに対してGitOps Productは管理エージェントをKubernetes側にインストールします。 管理エージェントがKubernetes内部からGitリポジトリおよびKubernetes上の状態を監視し、 差分があったらその情報をPullしてデプロイします。 GitリポジトリとKubernetes上の両方の状態を監視することで、望ましい状態を維持し正確性を確保し、相違を警告することが可能になります。
Fluxとは
FluxはそうしたGitOpsツールの1つです。 Azure Kubernetes Service(AKS)はFluxを標準でサポートしています。
FluxはKubernetes Workloadをデプロイする方法として、標準で Kustomizeと Helmをサポートしています。 また、監視対象とするソースは Gitリポジトリや Helm Chart、 Helmリポジトリをサポートしています。
実際の設定例
細かい説明は公式ドキュメントやMicrosoft Docsを参照していただくとして、実際の設定内容を見ていただいたほうが イメージを掴みやすいと思いますので早速紹介いたします。
まずは全体像です。
設定は今回の例では階層構造のコンフィグレーションをしています。最終的なデプロ対象は、Nginxなどのインフラストラクチャと 自身で開発するアプリケーションです。これらはKustomization ControllerやHelm Controllerで管理します。インフラストラクチャや アプリケーションは複数登録することが可能ですのでこれらをInfrastructureやAppsというフォルダにまとめKustomization Controllerで 管理しています。そしてInfrastructureとAppsというフォルダの登録を全体コンフィグレーションで登録しています。
では個別に見ていきましょう。
AKSでFlux Extensionの有効化
まずAKSででFlux Extensionを有効にします。
az feature register --namespace Microsoft.ContainerService --name AKS-ExtensionManager az provider register --namespace Microsoft.Kubernetes az provider register --namespace Microsoft.ContainerService az provider register --namespace Microsoft.KubernetesConfiguration
これらのコマンドは非同期で実行されますので、設定完了まで最長で10分ほど時間がかかることがあります。 登録が完了しているかどうかは以下のコマンドで確認できます。
az feature show --namespace Microsoft.ContainerService --name AKS-ExtensionManager -o table az provider show --namespace Microsoft.Kubernetes -o table az provider show --namespace Microsoft.ContainerService -o table az provider show --namespace Microsoft.KubernetesConfiguration -o table
BicepによるFluxのデプロイ
featureやproviderの有効化が完了したらFluxをデプロイします。
Bicepの内容は以下のようなものになります。
@description('AKS cluster name') param clusterName string @description('name for flux control plane') param fluxName string = 'flux' @description('namespace for flux control plane') param fluxNamespace string = 'flux-system' @description('auto upgrade minor version for flux') param autoUpgradeMinorVersion bool = true resource aks 'Microsoft.ContainerService/managedClusters@2022-04-01' existing = { name: clusterName } resource flux 'Microsoft.KubernetesConfiguration/extensions@2022-04-02-preview' = { name: fluxName scope: aks properties: { extensionType: 'microsoft.flux' scope: { cluster: { releaseNamespace: fluxNamespace } } autoUpgradeMinorVersion: autoUpgradeMinorVersion } }
サンプルでは上記を こちら のBicepから呼び出してデプロイしています。デプロイのコマンドは以下のとおりです。
az deployment group create -f deploy-flux.bicep --resource-group $RESOURCE_GROUP
こちらをデプロイするとfluxのPod等がデプロイされますので確認してみましょう。
kubectl get pods -n flux-system
Podがいくつか表示されれば完了です。
続いて全体コンフィグレーション部分をデプロイします。
@description('Application name') param appName string = 'flux-demo' @description('AKS cluster name') param clusterName string = appName @description('Flux extension name') param fluxName string = 'flux' @description('Flux configuration name') param fluxConfigName string = '${appName}-${fluxName}-config' @description('target repository url') param gitRepositoryUrl string @description('target repository branch name') param targetBranch string = 'main' @description('sync interval time') param syncIntervalInSeconds int = 120 // Flux configuration namespace - it must be same as flux infrastructure's configuration var fluxConfigNamespace = 'flux-config' resource aks 'Microsoft.ContainerService/managedClusters@2022-04-01' existing = { name: clusterName } resource fluxExtension 'Microsoft.KubernetesConfiguration/extensions@2022-04-02-preview' existing = { name: fluxName scope: aks } resource fluxConfig 'Microsoft.KubernetesConfiguration/fluxConfigurations@2022-03-01' = { name: fluxConfigName scope: aks properties: { scope: 'cluster' namespace: fluxConfigNamespace sourceKind: 'GitRepository' gitRepository: { url: gitRepositoryUrl repositoryRef: { branch: targetBranch } syncIntervalInSeconds: syncIntervalInSeconds } kustomizations: { infra: { path: './infrastructure' syncIntervalInSeconds: syncIntervalInSeconds prune: true } apps: { path: './apps/staging' syncIntervalInSeconds: syncIntervalInSeconds prune: true } } } }
デプロイコマンドは以下のとおりです。
az deployment group create -f deploy-flux-config.bicep --resource-group $RESOURCE_GROUP \ --parameters @flux-parameters.json
なおパラメータファイルは以下のような内容です
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "gitRepositoryUrl": { "value": "https://github.com/apc-kamezaki/flux-sample" } } }
こちらをデプロイすることで、GitRepositoryにあるinfrastructureフォルダのkustomizationファイル、app/stagingフォルダのkustomizationファイルを実行します。またこれらの設定が更新された場合自動的にその内容が反映されます。
Fluxコンフィグレーション
infrastructureフォルダの内容や、apps/stagingフォルダの内容はサンプルのGitHubリポジトリを参照ください。
ここではポイントとなる、nginx用のHelm ControllerとアプリケーションのKustomization Controllerの設定を確認します。
まずはHelm Controllerから
apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: HelmRepository metadata: name: bitnami spec: interval: 30m url: https://charts.bitnami.com/bitnami --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: nginx namespace: flux-config spec: targetNamespace: nginx releaseName: nginx chart: spec: chart: nginx version: 12.0.6 sourceRef: kind: HelmRepository name: bitnami namespace: flux-config interval: 1h0m0s install: remediation: retries: 3 # support values https://artifacthub.io/packages/helm/bitnami/nginx values: service: type: LoadBalancer replicaCount: 2
spec.chartにデプロイ対象のチャートの情報を指定し、spec.valuesでカスタマイズする設定値を指定します。 helmコマンドを使ったことがある方であればなんとなく理解できるのではないかと思います。
次にKustomization Controllerです。
apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: GitRepository metadata: name: sample-apps spec: interval: 5m0s url: https://github.com/apc-kamezaki/sample-apps ref: branch: main --- # base yaml apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: flux-config-timefeed spec: interval: 5m targetNamespace: production sourceRef: kind: GitRepository name: sample-apps path: ./deploy/timefeed/production prune: true --- # patch apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flux-config resources: - ../sources - ../base/timefeed patches: - target: group: kustomize.toolkit.fluxcd.io kind: Kustomization name: flux-config-timefeed patch: |- - op: replace path: /spec/path value: ./deploy/timefeed/staging - op: replace path: /spec/targetNamespace value: staging
こちらも kustomizeをご利用の方であれば、なんとなく見慣れた内容ではないかと思います。
これらが全体コンフィグレーションを登録したところから自動的に登録され、それぞれ内容が更新されると自動的にその内容が 反映されるようになります。
なお、「あれ?アプリケーションの設定の実体がない」と思った方もいるかも知れませんが、今回の指定は実はあえてKustomizeの設定ファイルを外部リポジトリ(サンプルアプリケーションリポジトリ)側に置いています。このように複数のリポジトリを監視対象にできるということがわかるかと思います。これによりFluxの全体管理と個々のアプリケーションごとのデプロイの管理とで管理主体を分離することができると思います。
終わりに
今回のサンプルはMicrosoftのサンプルを参考にさせていただきました。 最初いくつものコンフィグレーションが存在して何をしているのかぱっと理解できなかったのですが、階層構造でそれぞれ更新されたときに うまく自動反映されるようになっているんだな、そして最初の登録部分(全体コンフィグレーション)は極力変更内容にしているんだな(この部分だけ自動反映ではないため)とわかってからやっと自分でも内容を考えながら構成することができました。
今回ご紹介している環境はGitRepositoryもHelm Repositoryも公開(Public Access可)のもので行っているため、認証等の設定は登場しませんでしたが、もちろんそうしたPrivateなRepositoryにも対応しています。また、今回はGitRepositoryの特定のブランチが更新されたら実行されるようにしていますが、GitRepositoryのTagを監視する機能もあります。そうした機能はまた別の機会にご紹介できればと思います。
今回ご紹介したアプリケーションやAKSやFluxの設定のソースコードは以下のGitHubリポジトリで公開しています。
サンプルアプリケーションリポジトリ
AKS デプロイおよびFluxコンフィグレーションリポジトリ
それでは次回もまたよろしくおねがいします。