前回はAWS上にArgo CDを構築しました。今回はGCPにArgo CDをデプロイしていきたいと思います。
必要なもの
- Googleアカウント
- GCPプロジェクト
- gcloud CLI
- Terraform
- Helm
- kubectl
- argocd(CLI)
請求先アカウントが設定済みのGCPプロジェクトを用意してください。GKEを動かすためには請求先アカウントを設定しておく必要があります。
gcloud CLI, Terraform, Helm, kubectl, argocdは公式ドキュメントにインストール方法が記載されています。以下のドキュメントを参考にインストールをお願いします。
Terraformのバージョンはv1.3.3を使用しました。
gcloudコマンドでGCPプロジェクトを操作できるように、gcloud auth loginとgcloud config set project PROJECT_IDで対象のプロジェクトを設定してください。手順は以下です。
GCP
新しいGCPプロジェクトを作って試したところ、TerraformやExternalDNSでGCPのリソースを操作するには以下の権限が必要になりました。
gcloud services enable container.googleapis.com gcloud services enable dns.googleapis.com
GKE
以下のテキストをmain.tfというファイル名で保存してください。これはGKEクラスターを作るためのコードで、testという名前のGKEクラスターが起動してきます。
variable "project" {}
variable "region" {}
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.41.0"
}
}
}
provider "google" {
project = var.project
region = var.region
}
resource "random_id" "suffix" {
byte_length = 4
}
resource "google_service_account" "edns" {
account_id = "edns-${random_id.suffix.hex}"
}
resource "google_project_iam_member" "edns" {
project = var.project
role = "roles/dns.admin"
member = "serviceAccount:${google_service_account.edns.email}"
}
resource "google_service_account_iam_member" "edns" {
service_account_id = google_service_account.edns.name
role = "roles/iam.workloadIdentityUser"
# kube-system Namespaceに作成されたexternal-dnsサービスアカウントをGCPのサービスアカウントに紐づける
member = "serviceAccount:${var.project}.svc.id.goog[kube-system/external-dns]"
}
resource "google_service_account" "gke" {
account_id = "gkesa-${random_id.suffix.hex}"
}
locals {
gke_roles = [
"roles/logging.admin",
"roles/monitoring.admin",
]
}
resource "google_project_iam_member" "gke" {
project = var.project
count = length(local.gke_roles)
role = element(local.gke_roles, count.index)
member = "serviceAccount:${google_service_account.gke.email}"
}
resource "google_container_cluster" "primary" {
name = "test"
location = var.region
remove_default_node_pool = true
initial_node_count = 1
workload_identity_config {
workload_pool = "${var.project}.svc.id.goog"
}
}
resource "google_container_node_pool" "primary" {
name = "test-node-pool"
location = var.region
cluster = google_container_cluster.primary.name
node_count = 1
management {
auto_repair = true
auto_upgrade = true
}
node_config {
preemptible = true
machine_type = "e2-medium"
service_account = google_service_account.gke.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
workload_metadata_config {
mode = "GKE_METADATA"
}
}
}
ExternalDNSがCloud DNSを操作するためにWorkload Identityという機能を使用しています。詳細は以下をご覧ください。
以下のテキストをterraform.tfvarsというファイルに保存してください。
REPLACE MEとなっているところに、今回操作するGCPのプロジェクトIDをいれてください。
regionは変更しても構いませんが、この記事ではasia-northeast1という前提で進めていきます。
project = "REPLACE ME" region = "asia-northeast1"
main.tfとterraform.tfvarsを保存したディレクトリで以下のコマンドを実行してください。
terraform init
現状のインフラとコードの差分をチェックします。
terraform plan
GKEクラスターを作成します。
terraform apply
kubectlが使えるように、今回起動したGKEクラスターをkubeconfigに追加します。
gcloud container clusters get-credentials test --region asia-northeast1
以下のコマンドを実行し、Server Versionが取得できれば成功です。
kubectl version --short
Argo CD
Argo CDをHelmからインストールするので、HelmにArgo CDのリポジトリを追加します。
helm repo add argo https://argoproj.github.io/argo-helm
Argo CDをargocdというネームスペースにインストールします。
helm upgrade --install argocd argo/argo-cd --namespace argocd --create-namespace
ポートフォワードで接続できるようにします。後ほどALB経由で接続できるようにするので、これは一時的なものです。
kubectl port-forward service/argocd-server -n argocd 8080:443
Argo CDのadminパスワードを取得します。
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
argocdコマンドでログインします。Usernameにはadmin、Passwordには先ほど取得したadminパスワードを入力してください。
argocd login localhost:8080 --insecure
http://localhost:8080 にアクセスするとWEB UIからログインすることもできます。
ExternalDNS
ExternalDNSは、Kubernetesリソースを介して動的にCloud DNSにDNSレコードを追加、削除します。
Argo CDにアプリケーションとして追加します。
REPLACE MEはCloud DNSで管理している実在のドメインにしてください。
domain=REPLACE ME txtownerid=test gsa=$(gcloud iam service-accounts list --filter='email:(edns-*)' --format='value(email)') argocd app create external-dns \ --repo https://kubernetes-sigs.github.io/external-dns/ \ --helm-chart external-dns \ --revision 1.11.0 \ --dest-namespace kube-system \ --dest-server https://kubernetes.default.svc \ --helm-set "domainFilters[0]=$domain" \ --helm-set "txtOwnerId=$txtownerid" \ --helm-set policy=sync \ --helm-set serviceAccount.create=true \ --helm-set serviceAccount.name=external-dns \ --helm-set "serviceAccount.annotations.iam\.gke\.io/gcp-service-account=$gsa" \ --helm-set provider=google
デプロイします。
argocd app sync external-dns
Argo CDをCloud Load Balancing経由でアクセスできるようにする
Argo CDで使うSSL証明書を発行します。REPLACE MEの部分は、Argo CDに設定するドメインに置き換えて、managed-certificate.yamlというファイルに保存してください。
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: argocd-cert
spec:
domains:
- REPLACE ME
デプロイします。
kubectl apply -f managed-certificate.yaml -n argocd
Argo CDで使うLBの設定を行います。以下のテキストをfrontend-config.yamlというファイルに保存してください。
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
name: argocd-frontend-config
spec:
redirectToHttps:
enabled: true
デプロイします。
kubectl apply -f frontend-config.yaml -n argocd
Argo CDのIngressを有効にします。
domain={{SUBDOMAIN}}
helm upgrade -i argocd argo/argo-cd \
-n argocd --create-namespace \
--set 'server.service.type=NodePort' \
--set 'server.service.annotations.cloud\.google\.com/neg={"ingress": true}' \
--set 'server.ingress.enabled=true' \
--set "server.ingress.hosts[0]=$domain" \
--set "server.ingress.annotations.external-dns\.alpha\.kubernetes\.io/hostname=$domain" \
--set "server.ingress.annotations.kubernetes\.io/ingress\.class=gce" \
--set "server.ingress.annotations.networking\.gke\.io/managed-certificates=argocd-cert" \
--set "server.ingress.annotations.networking\.gke\.io/v1beta1\.FrontendConfig=argocd-frontend-config" \
--set 'server.extraArgs[0]=--insecure'
IngressからGCPのLBを起動するにはIngressのAnnotationsに設定を追加します。詳細は以下です。
https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress?hl=ja
SSLのプロビジョニングに1時間程度かかりますので気長にお待ちください。
片付け
片付けをするには少し順序があります。これはArgo CDで管理しているExternalDNSがArgo CDのドメインを管理しており、かつ、Argo CDのログイン先がLBの方に向いているからです。Argo CDを先にアンインストールするとExternalDNSが残ってしまいますし、アプリの方を先にアンインストールするとargocdコマンドが使えなくなってしまいます。
以下の手順に沿って、片付けを進めてください。
IngressをOFFにしてLBとサブドメインを解放します。
helm upgrade --install argocd argo/argo-cd --namespace argocd --create-namespace --set 'server.service.type=NodePort' --set 'server.ingress.enabled=false'
LBとドメインが削除されたのを確認してください。どちらもなくなっていればargocdコマンドが使えなくなっているので、ポートフォワードに切り替えます。
kubectl port-forward service/argocd-server -n argocd 8080:443
argocdコマンドのログイン先も変更します。
argocd login --insecure localhost:8080
アプリを削除します。
argocd app delete external-dns
SSLやFrontendConfigを削除します。
kubectl delete -f managed-certificate.yaml -n argocd kubectl delete -f frontend-config.yaml -n argocd
Argo CDをアンインストールします。
helm uninstall --namespace argocd argocd
GKEを削除します。
terraform destroy
以上で片付けは完了です。
