はじめに
GitOpsは、開発者がコードをGitリポジトリにプッシュすることで自動的にインフラストラクチャーが更新される仕組みです。
Fluxは、GitOpsを実現するためのツールであり、KubernetesのmanifestファイルをGitリポジトリに保存し、変更があるたびに自動でデプロイすることができます。
本記事では、Terraformを用いてAKS上にFluxを導入する手順を説明し、GitOpsのデモを行います。
AKS上にFluxを導入する手順
連携先のGitHubリポジトリの準備
GitHubリポジトリが空だとTerraformの実行時にエラーになるため、mainブランチにreadmeか何かを入れておいてください。
続いてGitHubとの認証情報の準備です。
今回はDeploy keyを用いてFluxからGitHubに接続する方針で説明します。
Deploy keyの作成方法は下記です。
- 接続に使用するSSHキーを生成します
- 対象のリポジトリの「Setting」から、「Deploy keys」を開きます
- 「Add deploy key」をクリックします
- Titleに任意の名称を設定し、SSHキーの公開鍵をコピペし、「Allow write access」のチェックを入れて「Add key」します
SSHキーの秘密鍵はTerraformの実行時に必要になります。
AKSとFluxの導入
AKSの作成とFluxの導入はTerraformで実現しましょう。
主に azurerm_kubernetes_cluster と flux_bootstrap_git を利用します。検証時点ではflux_bootstrap_gitのバージョンは `1.0.0-rc.5` でした。
main.tf
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
}
flux = {
source = "fluxcd/flux"
version = "1.0.0-rc.5"
}
}
}
provider "azurerm" {
subscription_id = var.subscription_id
client_id = var.sp_client_id
client_secret = var.sp_client_secret
tenant_id = var.sp_tenant_id
features {}
}
provider "kubernetes" {
host = azurerm_kubernetes_cluster.this.kube_config.0.host
client_certificate = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.client_certificate)
client_key = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.client_key)
cluster_ca_certificate = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.cluster_ca_certificate)
}
provider "flux" {
kubernetes = {
host = azurerm_kubernetes_cluster.this.kube_config.0.host
username = azurerm_kubernetes_cluster.this.kube_config.0.username
password = azurerm_kubernetes_cluster.this.kube_config.0.password
client_certificate = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.client_certificate)
client_key = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.client_key)
cluster_ca_certificate = base64decode(azurerm_kubernetes_cluster.this.kube_config.0.cluster_ca_certificate)
}
git = {
url = "ssh://git@github.com/${var.github_organization_name}/${var.github_repository_name}.git"
ssh = {
username = "git"
private_key = file(var.gitops_ssh_private_key_file)
}
}
}
locals {
resource_group_name = "rg-gitops"
aks_name = "aks-gitops"
namespace_flux = "flux-system"
}
resource "azurerm_resource_group" "this" {
name = local.resource_group_name
location = "japaneast"
}
resource "azurerm_kubernetes_cluster" "this" {
name = local.aks_name
location = "japaneast"
resource_group_name = azurerm_resource_group.this.name
automatic_channel_upgrade = "patch"
dns_prefix = "dns"
default_node_pool {
name = "system"
node_count = 1
vm_size = "Standard_B2s"
type = "VirtualMachineScaleSets"
}
identity {
type = "SystemAssigned"
}
network_profile {
network_plugin = "azure"
}
}
resource "kubernetes_namespace" "flux" {
metadata {
name = local.namespace_flux
}
depends_on = [
azurerm_kubernetes_cluster.this
]
lifecycle {
ignore_changes = [
metadata
]
}
}
resource "flux_bootstrap_git" "this" {
namespace = kubernetes_namespace.flux.metadata[0].name
path = "clusters/${local.aks_name}"
}
variables.tf
variable "subscription_id" {
description = "AKS作成先のサブスクリプションのID"
type = string
}
variable "sp_tenant_id" {
description = "AzureのテナントのID"
type = string
}
variable "sp_client_id" {
description = "Azureに接続するサービスプリンシパルのID"
type = string
}
variable "sp_client_secret" {
description = "Azureに接続するサービスプリンシパルのシークレット"
sensitive = true
type = string
}
variable "github_organization_name" {
description = "GitHubリポジトリが所属する組織名またはユーザー名"
type = string
}
variable "github_repository_name" {
description = "GitHubリポジトリ名"
type = string
}
variable "gitops_ssh_private_key_file" {
description = "GitHubリポジトリのDeploy keyの秘密鍵が記載されたファイルパス"
type = string
}
terraform apply時は、variables.tfのdescriptionの説明を参考にパラメータを渡してあげてください。
providerの記述が特徴的かと思います。
namespaceの作成やFluxの導入時にkubernetesへの接続情報が必要になるのですが、 `provider "kubernetes"` や `
provider "flux"` の記載でazurerm_kubernetes_clusterのアウトプットから拾うようにしています。
他は各リソースのterraformドキュメントに記載されている内容とあまり差が無いと思います。
GitOpsのデモ
terraform applyが成功すると、GitOps用のGitHubリポジトリ内に `clusters/aks-gitops/flux-system` フォルダが作成され、ここにFluxの管理ファイルが保管されています。
mainブランチの `clusters/aks-gitops` フォルダ内がFluxにより監視されているので、ここに好きなファイル名.yamlでマニフェストファイルを追加してあげるとAKSにデプロイされます。
GitHubを監視する周期はデフォルト設定だと1分です。
試しに下記のマニフェストファイルを `clusters/aks-gitops/sample-namespace.yaml` としてmainブランチにコミット、プッシュしてみましょう。
sample-namespace.yaml
kind: Namespace
apiVersion: v1
metadata:
name: sample
labels:
name: sample
kubectl applyすると `sample` という名前のnamespaceが作成されるマニフェストファイルですね。
namespaceが作成されたかどうかは好きな方法で確認してOKですが、Azureポータルから見るのが気軽ですかね?
AzureポータルからTerraformで作成されたAKSの「Kubenetes リソース」→「名前空間」を選択してください。
kubectl applyせずに、マニフェストファイルをプッシュしてから1分以内にnamespaceが作成されたと思います!
ファイルの削除をコミットすればnamespaceが削除されます、素晴らしいー
まとめ
Terraformを使用することで、簡単にFluxを用いたGitOps環境が構築できることが分かりました。
GitOpsの実現手段としてはArgoCDもありますが、Fluxの利用もぜひ検討してみてください。