on
GKE Connection GatewayとArgoCD ApplicationSetによるアプリケーションデプロイ
GKE に欠かせない CD ツールの一つである ArgoCD。
クラスターが一台の時はいいのですが、これが複数台になった時にどのように管理しようか悩みました。
耐障害性観点から複数台に分けてインストールするのもありですが、一台にプロジェクト間を跨いだクラスター管理をして管理コストを下げたらいいなとも思いました。
調べる前は VPC のピアリングなど修正する必要があるなーと思いましたが、GCP で提供している Connection Gateway を参考にネットワーク依存せずに一括にクラスター管理ができそうだったのでこちらを試してた時の備忘録です。
Terraform で GKE リソースの作成
下記内容で GKE リソースを作成します。※Autopilot です。
locals {
name_prefix = "test"
project_id = "your-project"
}
data "google_client_config" "default" {}
data "google_project" "project" {
project_id = local.project_id
}
resource "google_container_cluster" "test-1" {
provider = google-beta
project = local.project_id
name = "test-1"
location = "asia-northeast1"
# Enable Autopilot for this cluster
enable_autopilot = true
ip_allocation_policy {}
release_channel {
channel = "REGULAR"
}
}
resource "google_container_cluster" "test-2" {
provider = google-beta
project = local.project_id
name = "test-2"
location = "asia-northeast2"
# Enable Autopilot for this cluster
enable_autopilot = true
ip_allocation_policy {}
release_channel {
channel = "REGULAR"
}
}
# Register to Fleet
resource "google_gke_hub_membership" "fleet-1" {
membership_id = "test11-fleet"
project = local.project_id
authority {
issuer = "https://container.googleapis.com/v1/${resource.google_container_cluster.test-1.id}"
}
endpoint {
gke_cluster {
resource_link = "//container.googleapis.com/${resource.google_container_cluster.test-1.id}"
}
}
}
resource "google_gke_hub_membership" "fleet-2" {
membership_id = "test12-fleet"
project = local.project_id
authority {
issuer = "https://container.googleapis.com/v1/${resource.google_container_cluster.test-2.id}"
}
endpoint {
gke_cluster {
resource_link = "//container.googleapis.com/${resource.google_container_cluster.test-2.id}"
}
}
}
クラスター、fleet の存在を確認する。
gcloud container clusters list
gcloud container hub memberships list
ArgoCD のインストール
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
ConnectionGateway の設定
Connection Gateway 用の Service Account,Workload Identity のリソース追加
module "sa_cluster_argocd_admin" {
source = "./modules/service_account"
project_id = local.project_id
account_id = "argocd-fleet"
display_name = "argocd-fleet"
description = "Argocd cluster"
roles = ["container.admin", "gkehub.gatewayEditor"]
}
module "workload_identity_argocd_server" {
source = "./modules/workload_identity_iam"
project_id = local.project_id
gcp_service_account_id = module.sa_cluster_argocd_admin.name
k8s_service_accounts = [
"argocd/argocd-server",
"argocd/argocd-application-controller"
]
}
modules/resource の内容
resource "google_service_account" "service_account" {
project = var.project_id
account_id = var.account_id
display_name = var.display_name
description = var.description
disabled = var.disabled
}
resource "google_project_iam_member" "service_account_iam" {
project = var.project_id
for_each = toset(var.roles)
role = "roles/${each.key}"
member = "serviceAccount:${google_service_account.service_account.email}"
}
locals {
annotations = formatlist(
"serviceAccount:${var.project_id}.svc.id.goog[%s]",
var.k8s_service_accounts,
)
}
data "google_service_account" "serviceaccount" {
account_id = var.gcp_service_account_id
}
resource "google_service_account_iam_binding" "wi_iam_binding" {
service_account_id = data.google_service_account.serviceaccount.name
role = "roles/iam.workloadIdentityUser"
members = local.annotations
}
Google Service Account の追加が確認できたら、Kubernetes Service Account リソースを追加します。
---
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
iam.gke.io/gcp-service-account: argocd-fleet@$PROJECT_ID.iam.gserviceaccount.com
name: argocd-application-controller
---
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
iam.gke.io/gcp-service-account: argocd-fleet@$PROJECT_ID.iam.gserviceaccount.com
name: argocd-server
ArgoCD で管理したいクラスター secret を記載します。
apiVersion: v1
kind: Secret
metadata:
name: test2-gke
labels:
argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
name: test2-gke
server: https://connectgateway.googleapis.com/v1beta1/projects/$PROJECT_ID/locations/global/gkeMemberships/$FLEET_NAME
config: |
{
"execProviderConfig": {
"command": "argocd-k8s-auth",
"args": ["gcp"],
"apiVersion": "client.authentication.k8s.io/v1beta1"
},
"tlsClientConfig": {
"insecure": false,
"caData": ""
}
}
内容に問題がなければkubectl apply
をします。
アプリケーションリソースと ApplicationSet の作成
アプリケーションリソースは Nginx コンテナ利用しています。
ディレクトリ構成はクラスタ別に分けて Kustomize で管理していることを前提にして、ApplicationSet を作成します。
※アプリケーションリソース省略
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: dev-backend
spec:
generators:
- list:
elements:
- cluster: test1-cluster
url: https://kubernetes.default.svc
- cluster: test2-cluster
url: https://connectgateway.googleapis.com/v1beta1/projects/$PROJECT_ID/locations/global/gkeMemberships/$FLEET_NAME
template:
metadata:
name: "-nginx"
spec:
project: default
source:
repoURL: https://github.com/$GITHUB_USERNAME/REPO_NAME.git
targetRevision: HEAD
path: "nginx//overlays/dev"
destination:
server: ""
namespace: default
問題なければkubectl apply
をします。
apply を行うと ArgoCD のダッシュボード UI にアプリケーションが二つ登録されていることが確認できます。
念のため、各クラスターからアプリケーションが作成されてるか確認しましょう。
kubectl config use-context test-1
➜ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 6m29s
kubectl config use-context test-2
➜ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 4m46s
Connection Gateway を利用してネットワークの設定いじらず、簡単に ArgoCD でプロジェク間クラスターの管理ができるようになりました。
この他にも手動 fleet 登録を活用することによって EKS,オンプレ K8s の管理もできるようになったので、積極的に活用していきたいですね。