ISID テックブログ

ISIDが運営する技術ブログ

GitOpsを利用したAzure Kubernetes Serviceへのアプリケーションデプロイ

こんにちは、電通国際情報サービス(ISID)の上羽です。 私はクラウドイノベーションセンターという組織に所属し、社内におけるパブリッククラウドの活用推進やクラウドテクノロジーの研究開発を行っています。この記事は最近Azureでパブリックプレビューとして公開されたAzure Kubernetes Service(以下、AKS)の機能であるGitOpsについて解説します。本記事では、CI/CD、およびKubernetesの基本的な概念をある程度理解していることを前提としています。

GitOpsとは

CI/CDによるデプロイを実現する方法として、多くの人が思い浮かべるのはCIツール(GitHub ActionsやJenkinsなど)を使った方法ではないでしょうか。この方法では、ソースコードリポジトリへの変更をトリガーとしてCIツールが起動し、ビルドなどのCI(継続的インテグレーション)からCD(継続的デリバリー・デプロイ)までを手続き的に実行します。このようなデプロイ方法はCIOpsと呼ばれ、CIツールが中心となったシンプルで開発者にとってわかりやすい方法です。ただし、CIOpsによるデプロイはいくつか課題があります。

  • 意図したデプロイ状況になっているか把握しにくい

CIツールは変更をデプロイするだけです。デプロイ先の状態を管理したい場合は、状態を取得するために複雑なワークフローを組む必要があります。

  • CIツールの持つ権限が大きくなる

デプロイのために、デプロイ先環境の認証情報をCIツールが持つ必要があります。

このような課題へのアプローチとして、WeaveWorks社の提唱するGitOpsという方法が考えられました。GitOpsはCDの方法の1つで、誤解を恐れずに要約すると「Kuberenetesクラスタを構成するマニフェストのすべてをGitリポジトリで管理し、その情報を正としてデプロイする方法」です1。 CIOpsが持つ課題に対して、それぞれ以下のようなアプローチをとっています。

「Gitリポジトリに存在するマニフェストKubernetesクラスタの状態」とすることで、クラスタの状態を把握できるようにします。

  • CIとCDを分離する

CIツールがデプロイ先の認証情報を持つ必要もなくなり、ビルドやテストといったワークフローに注力できるようにします。CDツールをKubernetesクラスタ内に配置して、デプロイに注力します。CDツールがGitで管理されているマニフェストと自身の構成情報の差分を検知すると、マニフェストを自身にデプロイします。

ここまでの説明を簡単に図示したものが以下です。CIOpsではソースコードリポジトリから一方向に矢印が伸びている対して、GitOpsではマニフェストリポジトリを境として矢印が反対を向いています。先ほどGitOpsの特徴として述べた「唯一の情報源」がマニフェストリポジトリであり、このリポジトリを境に「CIとCDの分離」を実現していることがわかります。

GitOpsを実現するツールとしてFluxArgoCDがあります。AKSのGitOps機能にはFluxが利用されています。

AKSでGitOpsを使ってみる

ここからが本題です。冒頭で紹介したAKSのGitOps機能を使ってみます。 Azure CLIを利用して環境を構築します。

リソースプロバイダーの登録とAzure CLI拡張機能の有効化

今回利用するAKSのGitOps機能はそのままの状態で利用できず、リソースプロバイダーの登録が必要になります。また、CLIからGitOpsの構成を作成するためにCLI拡張機能も必要です。それらを以下コマンドにより登録します。

# リソースプロバイダの登録
az provider register --namespace Microsoft.Kubernetes
az provider register --namespace Microsoft.ContainerService
az provider register --namespace Microsoft.KubernetesConfiguration
# AKS拡張機能の有効化
az feature register --namespace Microsoft.ContainerService --name AKS-ExtensionManager
# Azure CLI拡張機能のインストール
az extension add -n k8s-configuration
az extension add -n k8s-extension

なお、これらの登録には数十分要することがあります。リソースプロバイダーの登録は非同期処理なので、コマンドaz provider show -n <名前空間> -o tableにより登録状況を確認してください。StateがRegisteredになれば登録完了です。

AKSクラスタの作成

以下コマンドによりAKSクラスタを作成します。今回作成するクラスタはGitOpsの検証利用想定のため、必要最小限の構成としています。

az aks create --resource-group <リソースグループ名> --name <クラスタ名> --node-vm-size Standard_B2s --node-count 1 --generate-ssh-keys

GitOpsの構成

以下コマンドを実行してGitOpsの構成をAKSに追加します。

az k8s-configuration flux create \
  --resource-group <リソースグループ名> \
  --cluster-name <クラスタ名> \
  --cluster-type managedClusters \
  --name gitops-test \
  --namespace gitops-test \
  --scope cluster \
  --url https://github.com/fluxcd/flux2-kustomize-helm-example \
  --branch main \
  --kustomization name=infra path=./infrastructure prune=true \
  --kustomization name=apps path=./apps/staging prune=true dependsOn=["infra"]

コマンドについて補足します。

--resource-group <リソースグループ名> --cluster-name <クラスタ名>

作成したAKSクラスタ名、およびAKSが存在するリソースグループ名を指定してください。

--cluster-type managedClusters

インストール対象のクラスタとして、managedClustersを指定してください。これはAKSのマネージドクラスタであることを意味します。ほかにはconnectedClustersというAzure Arc(Azureに接続したオンプレ環境)のクラスタも指定できます。

--name gitops-test --namespace gitops-test --scope cluster

nameはこのGitOpsの構成を識別するための名称です。 namespaceはこの構成を配置する名前空間を指定します。クラスタ内になければ新規作成されます。 scopeはこの構成のアクセススコープです。検証用なので、clusterに設定します。

--url https://github.com/fluxcd/flux2-kustomize-helm-example --branch main \

urlにはマニフェストが存在するリポジトリを指定します。 本記事においては、Fluxが公開しているサンプルリポジトリを利用します。 branchリポジトリに存在するブランチを指定します。ここで指定したブランチに変更があった場合、AKSにデプロイされます。ほかにコミット単位や、タグを指定できるオプションもあります。 また今回はパブリックなリポジトリを指定しましたが、プライベートなリポジトリを指定することも可能です。その場合は リポジトリに対する認証情報を入力する必要があります。

--kustomization name=infra path=./infrastructure prune=true --kustomization name=apps path=./apps/staging prune=true dependsOn=["infra"]

次にKustomizationの設定です。KustomizationとはFluxで利用するCRDの1つで、Gitで管理されているマニフェストのうちクラスタに適用するものを定義したファイルです。KubernetesのエコシステムであるKustomizeとも深く関係しますが、この記事では割愛します。

今回作成するKustomizationの設定は2つ(infraとapps)です。このうちの、infraインスタンスで設定したパスにあるディレクトリ構成を見てみます。

infra/
 ├ nginx/
 │ └ kustomization.yaml
 │ └ namespace.yaml
 │ └ release.yaml
 ├ sources/
 │ └ kustomization.yaml
 │ └ 複数マニフェスト
 ├ redis/
 │ └ kustomization.yaml
 │ └ 複数マニフェスト
 └ kustomization.yaml

infra/kustomization.yamlファイルを見てみます。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - sources
  - nginx
  - redis

Kustomizationのマニフェストで、リソースとして3つ定義されています。この3つのリソースはディレクトリ名を表していて、それぞれのディレクトリの中にさらにkustomization.yamlが存在します。一例としてnginxディレクトリにあるkustomization.yamlの中を見てみます。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: nginx
resources:
  - namespace.yaml
  - release.yaml

リソースとしてマニフェストyamlファイルが定義されています。このように定義されたマニフェストをFluxが検知しデプロイする、という仕組みになっています。 本記事ではinfraの構成を確認してみましたが、appsについても同様です。ただし、appsの依存関係にinfraが設定されています。infraのリソースがデプロイされた後にappsをデプロイするための設定です。

デプロイの確認

まずはFluxがクラスタにインストールされているかを確認します。ここからは視覚的にわかりやすくするためにAzure Portalを利用します。

AKSのリソースメニューから作成したクラスタを選択し、ブレードからワークロードを選択します。 名前空間flux-systemでフィルタすると、Fluxを構成するオブジェクトを確認できます。 Fluxに関するアーキテクチャは説明しません。興味のある方はこちらをご参照ください。

次にGitOpsの構成を確認します。 ブレードからGitOps(プレビュー)を選択します。 先ほどCLIから作成した構成を確認できます。構成名をクリックして詳細画面に移ります。

現在のデプロイ状況を表す「状態」、同期するリポジトリを表す「リポジトリ」、設定したKustomizationなどを表す「プロパティ」がそれぞれ確認できます。いくつか気になる項目をピックアップします。

コンプライアンスの状態

AzureにはAzure Policyというコンプライアンスを管理するサービスが存在します。そのAzure Policyによる検出結果がこれです。AKSが対象としているポリシーはこちらから確認できます。

種類

GitOpsを実現するためのツールが示されています。Flux v2であることがわかりますね。あえて表示しているということは今後ほかのツールにも対応予定なのかもしれません。(筆者個人の感想です)

構成オブジェクト インストールの状態

今回のデプロイ対象のオブジェクト、およびその状態を示しています。リポジトリにあるkustomization.yamlを展開した結果のオブジェクトです。インストールの状態がSucceedになっているので、もうデプロイは完了しているようです。リンクをクリックして中を見てみます。

設定したKustomization自体や、同期先のリポジトリを管理するGitRepositoryオブジェクト、リポジトリに管理されているマニフェストで指定したHelmReleaseなどが確認できます。今回指定したサンプルリポジトリからデプロイされるアプリケーションはpodinfoという軽量のWebアプリケーションです。CLIを利用して動作確認してみます。 次のコマンドでAKSに対する認証情報を取得します。

az aks get-credentials --resource-group <リソースグループ名> --name <クラスタ名>

podinfoアプリケーションが公開されているポートを手元にポートフォワードして、アプリケーションに接続してみます。

# ポートフォワード
kubectl -n nginx port-forward svc/nginx-ingress-controller 8081:80 &
# アプリケーションへのリクエスト
curl -H "Host: podinfo.staging" http://localhost:8081
{
  "hostname": "podinfo-6dddd646b6-7d8fb",
  "version": "6.0.3",
  "revision": "",
  "color": "#34577c",
  "logo": "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif",
  "message": "greetings from podinfo v6.0.3",
  "goos": "linux",
  "goarch": "amd64",
  "runtime": "go1.16.9",
  "num_goroutine": "9",
  "num_cpu": "2"
}

podinfoからのレスポンスが返ってきました。このhostnameはPodの名前と一致しているはずです。podを取得して確認してみます。

kubectl get pods -n podinfo
NAME                       READY   STATUS    RESTARTS   AGE
podinfo-6dddd646b6-7d8fb   1/1     Running   0          129m

デプロイコマンドなど一切なしにアプリケーションをデプロイできました。

おわりに

本記事ではAKSのGitOps機能を利用してアプリケーションをデプロイする手順を解説しました。Flux自体はどのKubernetesプラットフォームにおいても利用可能です。Azureにおいてはそれを拡張機能として利用でき、管理用のGUIが提供されていたり、Azureのサービス(Azure Policy)と組み合わせて利用できるのが利点であると筆者は考えています。 最後までお読みいただきありがとうございました。

執筆:@ueba.yuki、レビュー:@shibata.takaoShodoで執筆されました


  1. Kuberenetes以外でもGitOpsを実現するツール(PipeCD)はありますが、解説を簡潔にするために今回は説明を省きました