APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

AKSでGitOps(Flux v2)を使う (1)

GitOpsとは

GitOpsというのをご存知でしょうか。 GitOpsはWeaveworks社が提唱した、Kubernetesへのワークロードの 継続的デプロイ(CD)方法です(Git to GitOps) 。

GitOpsは4つの原則があります

  1. システムを宣言的に記述する
  2. 望ましいシステム状態をGitでバージョン管理する
  3. 承認された変更は自動的にシステムに適用される
  4. ソフトウェアエージェントで正確性を確保し、相違を警告する

では、通常のデプロイと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をデプロイする方法として、標準で KustomizeHelmをサポートしています。 また、監視対象とするソースは GitリポジトリHelm ChartHelmリポジトリをサポートしています。

実際の設定例

細かい説明は公式ドキュメントや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コンフィグレーションリポジトリ

それでは次回もまたよろしくおねがいします。