はじめに
前回の記事 でGKEのデプロイパイプラインを構築した。
GKEは費用の関係で頻繁に消したり作ったりしたかったため上記のパイプラインで実現したが、GKEの構築が自動化されていてもGKEへのアプリのデプロイが自動化されていなければ意味がないのでそこも自動化したい。
今回はGKE構築後にJOBを1つ実行するだけで、CD環境構築も行いつつGKEへのアプリのデプロイを自動で行われるパイプラインを構築する。
GKEへのCD環境として、タイトルにある通りArgoCDを利用する。また、パイプラインの実行はGithub Actionsで行い、マニフェストYAMLの管理としてkutomizeを利用する。
それぞれの技術要素の解説はしないため、参考に示す記事や公式サイトを参照してください。
環境
パイプライン上で利用する環境についてはソースコード内に記述されているため、ローカルの操作に必要なもののみ記述
- macOS Catalina Version 10.15.4
- fish (利用シェル)
- Google Cloud SDK 272.0.0
前準備
GKEの管理者としてのサービスアカウントを作成
GKEへのArgoのインストールのために、クラスタの管理者権限を持ったサービスアカウントを作成する。
サービスアカウント名はcontainer-admin-service-accountとして作成する。
# GCPにプロジェクト名を取得して環境変数に設定
$ set GCP_PROJECT (gcloud info --format='value(config.project)')
# サービスアカウント名を環境変数に設定
$ set CONTAINER_ADMIN_SA container-admin
# プロジェクトと名前を引数にサービスアカウント を作成
$ gcloud iam service-accounts create $CONTAINER_ADMIN_SA --project=$GCP_PROJECT --display-name $CONTAINER_ADMIN_SA
# 作成したサービスアカウントのID情報を環境変数に設定
$ set CONTAINER_ADMIN_SA_EMAIL (gcloud iam service-accounts list --project=$GCP_PROJECT --filter="displayName:$CONTAINER_ADMIN_SA" --format='value(email)')
# クラスタ管理に関わるAPIを使用する権限を付与する
$ gcloud projects add-iam-policy-binding $GCP_PROJECT \
--role roles/container.admin \
--member serviceAccount:$CONTAINER_ADMIN_SA_EMAIL
# 結果確認
$ gcloud projects get-iam-policy $GCP_PROJECT \
--flatten="bindings[].members" \
--filter="bindings.members:serviceAccount:$CONTAINER_ADMIN_SA_EMAIL" \
--format='table(bindings.members,bindings.role)'
# サービスアカウントのkeyファイル(json)の作成
$ set CONTAINER_ADMIN_SA_DEST ~/.gcp/container-admin.json
$ mkdir -p (dirname $CONTAINER_ADMIN_SA_DEST)
$ gcloud iam service-accounts keys create $CONTAINER_ADMIN_SA_DEST --iam-account $CONTAINER_ADMIN_SA_EMAIL
ArgoCD
ArgoCDインストールのためのパイプライン構築について記述していく。
ArgoCD自体の詳細は、ArgoCD公式ドキュメントやArgo CDによってGKEでGitOpsをするの記事を参照してください。
また、この章で紹介するコードは以下のGitリポジトリ上で公開しています。
https://github.com/sabure500/argocd-install
Github ActionsでArgoCDのインストールを行う
まずは、GKEへのArgoCDのインストールに関するパイプラインを作成する。
本章では、初期設定でのArgoCDのインストールまでのワークフローを記述する。
後ほどArgoCDの管理もArgoCDで行うための記述を追加するためargocd-install.yaml(仮)としている。
まず全体を示し、その後各stepを解説する。
name: 'argocd-install'
on:
push:
branches:
- master
repository_dispatch:
types: [argocd-install]
env:
PROJECT_ID: ${{secrets.PROJECT_ID}}
GKE_CLUSTER: my-gke-cluster
GKE_ZONE: us-west1-a
jobs:
argo-install:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: Setup Google Cloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: '289.0.0'
project_id: ${{secrets.PROJECT_ID}}
service_account_email: ${{ secrets.SA_EMAIL }}
service_account_key: ${{ secrets.SA_KEY }}
- name: Setup GKE
run: |-
gcloud container clusters get-credentials "$GKE_CLUSTER" --zone "$GKE_ZONE"
- name: Install ArgoCD Application
run: |-
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.5.2/manifests/install.yaml
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl get deploy,pod,svc -n argocd
- name: Download Argocd CLI
run: |-
curl -sSL -o ./argocd https://github.com/argoproj/argo-cd/releases/download/v1.5.2/argocd-linux-amd64
chmod +x ./argocd
- name: ArgoCD change password
run: |-
sleep 3m
ARGOCD_SERVER=$(kubectl get service argocd-server -n argocd |awk 'NR==2' | awk '{print $4}')
echo $ARGOCD_SERVER
ARGOCD_TEMP_PASSWORD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2)
./argocd login --insecure --username admin --password $ARGOCD_TEMP_PASSWORD $ARGOCD_SERVER
./argocd account update-password --current-password $ARGOCD_TEMP_PASSWORD --new-password ${{secrets.ARGOCD_PASSWORD}}
また、このワークフローの実行のために、事前にGithubにSecretsとして設定が必要な値は以下の通り
- PROJECT_ID : GCPのプロジェクト
- SA_EMAIL : パイプライン実行で利用するServiceAccountのID
- SA_KEY : 上記サービスアカウントのKey
- ARGOCD_PASSWORD : ArgoCDの管理者ユーザーのパスワードに設定する値
GCPへのログインと対象のクラスタ選択に関する記述
GCP公式で提供しているActionを利用してGCPへのログインを行っている。
事前にenvにて使用するクラスタの名前やゾーンを設定しておきそれを利用している。
また、GithubのSecretsで先ほど作成したServiceAccountのIDとKEYを入力して利用している。
withで設定できる引数等の詳細な記述方法については、使用しているActionの公式リポジトリを参照する
env:
PROJECT_ID: ${{secrets.PROJECT_ID}}
GKE_CLUSTER: my-gke-cluster
GKE_ZONE: us-west1-a
- name: Setup Google Cloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: '289.0.0'
project_id: ${{secrets.PROJECT_ID}}
service_account_email: ${{ secrets.SA_EMAIL }}
service_account_key: ${{ secrets.SA_KEY }}
- name: Setup GKE
run: |-
gcloud container clusters get-credentials "$GKE_CLUSTER" --zone "$GKE_ZONE"
GKEへのArgoCDのインストールに関する記述
基本的にArgoCD公式のGetting Startedを参考にしている。
- name: Install ArgoCD Application
run: |-
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.5.2/manifests/install.yaml
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl get deploy,pod,svc -n argocd
この記述で以下の手順を実現している
- argocdのNamespaceの作成
- argocdの公式マニフェストファイルをGKEにデプロイする
- argocdの公開用のIPを作成
ArgoCDの管理者パスワードの変更
ArgoCDインストール後の初期パスワードはPOD名になる。
この初期パスワードについても、地震が指定する値にパイプラインで変更する。
こちらも、基本的にArgoCD公式のGetting Started を参考にしている。
- name: Download Argocd CLI
run: |-
curl -sSL -o ./argocd https://github.com/argoproj/argo-cd/releases/download/v1.5.2/argocd-linux-amd64
chmod +x ./argocd
- name: ArgoCD change password
run: |-
sleep 3m
ARGOCD_SERVER=$(kubectl get service argocd-server -n argocd |awk 'NR==2' | awk '{print $4}')
echo $ARGOCD_SERVER
ARGOCD_TEMP_PASSWORD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2)
./argocd login --insecure --username admin --password $ARGOCD_TEMP_PASSWORD $ARGOCD_SERVER
./argocd account update-password --current-password $ARGOCD_TEMP_PASSWORD --new-password ${{secrets.ARGOCD_PASSWORD}}
上記の記述にて以下の手順を実現している
- ArgoCDにログインするために、ArgoCDのCLIを取得する
- PODが立ち上がり公開用のIPが作成されるまで待機※1
- 管理者ユーザーの初期パスワード(POD名)を取得
- 作成された公開用IPを利用してArgoCDへのログイン
- ArgoCDの管理者パスワードを変更する
ArgoCD自体の管理をArgoCDで行う
上記の章でパイプラインでArgoCDの構築ができるようになったが、このままだと構築後にArgoCDのプロジェクトやアプリケーションは手動で作成する必要がある。
設定は全てGitOpsで行いたいため、ArgoCDの初期設定に関してもパイプライで構築時に読み込む方法について記述していく。
ArgoCD独自設定のマニフェストファイルの作成
Argo構築時に作成したいArgoProjectやArgoApplicationの設定をyamlにして、パイプラインを実行するリポジトリと別リポジトリで管理する。
※このリポジトリに関しては、Credential情報がリポジトリの外に出せなかったため、privateにしている。
リピジトリの公開ができないため、ディレクトリ構成を以下に示す。
argocd-admin/
├ AppProject/
│ ├ admin.yaml
│ └ guestbook.yaml
├ AppApplication/
│ ├ argocd-admin.yaml
│ ├ guestbook.yaml
│ └ kubernetes-admin.yaml
├ argocd-server.yaml
└ kustomization.yaml
それぞれのyamlファイルの中身を解説していく
また、AppProjectとAppApplicationのyamlファイルについてはGUIから作成後に以下のコマンドで出力することもできる
- argocd proj get $APP_PROJECT_NAEM -o yaml
- argocd app get $APP_APPLICATION_NAEM -o yaml
AppProject/admin.yaml
KubernetesやArgoの管理用のリソースをまとめて管理するためのArgoプロジェクトに関する設定
詳細な書き方は、ArgoCD公式の宣言的なセットアップのページ に記載されているが、以下に簡単な解説を示す。
- spec.sourceReposでこのプロジェクト内のArgoアプリケーションがアクセス可能なGitリポジトリを指定する
- この【Personal access tokens】の部分がGitの外に出せずにベタ書きしている
- ここの値は各リポジトリの内容に合わせて修正する
- Perspnal Access Tokenの作り方についてはGithub公式のこのページを参照する
- spec.destinationsでこのプロジェクト内のArgoアプリケーションで利用できるNameSpeceとクラスタを指定する
- spec.clusterResourceWhitelistでこのプロジェクト内のArgoアプリケーションで管理できるNameSpaceやPV等のクラスタリソースを指定する
- spec.roleでこのプロジェクト内のArgoアプリケーションに関して、個々に実行可能なAction(CRUD)を指定する
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: admin
namespace: argocd
spec:
sourceRepos:
- https://【Personal access tokens】@github.com/sabure500/argocd-admin.git
- https://【Personal access tokens】@github.com/sabure500/kubernetes-admin.git
destinations:
- namespace: default
server: https://kubernetes.default.svc
- namespace: argocd
server: https://kubernetes.default.svc
- namespace: kube-system
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
- group: ""
kind: PersistentVolume
- group: rbac.authorization.k8s.io
kind: ClusterRole
- group: rbac.authorization.k8s.io
kind: ClusterRoleBinding
- group: storage.k8s.io
kind: StorageClass
- group: apiextensions.k8s.io
kind: CustomResourceDefinition
roles:
- name: argocd-admin
policies:
- p, proj:admin:argocd-admin, applications, *, admin/argocd-admin, allow
- p, proj:admin:kubernetes-admin, applications, *, admin/kubernetes-admin, allow
AppApplication/argocd-admin.yaml
ArgoCD自身のリソースを管理するマニフェストが入ったリピジトリ(自分自身)の内容を同期するためのArgoアプリケーションに関する設定
詳細な書き方については、ArgoCD公式の宣言的なセットアップのページ に記載されているが、以下に簡単な解説を示す。
- spec.projetでこのアプリケーションが所属するプロジェクトを指定する
- spec.source.repoURL,spec.source.targetRevisionで読み込むリポジトリとブランチを指定する
- spec.source.pathでリピジトリ内におけるkustomization.yamlがある場所を指定する
- spec.syncPolicy.automatedによって指定リポジトリの状況を読み込んでGKEクラスタに反映し続けるAutoSyncの設定を有効にしている
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd-admin
namespace: argocd
spec:
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: admin
source:
path: .
repoURL: https://【Personal access tokens】@github.com/sabure500/argocd-admin.git
targetRevision: master
syncPolicy:
automated: {}
AppApplication/kubernetes-admin.yaml
クラスタリソースのマニフェスト管理は別リポジトリにて行うこととし、その内容を同期するためのArgoアプリケーションに関する記述
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kubernetes-admin
namespace: argocd
spec:
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: admin
source:
path: .
repoURL: https://【Personal access tokens】@github.com/sabure500/kubernetes-admin.git
targetRevision: master
syncPolicy:
automated: {}
- 別リポジトリである、kubernetes-admin.gitでは以下のような構成でNamespaceを作成するためのマニフェストが入っている(今回はサンプルアプリ用のNamespaceを作成している)
kubernetes-admin/
├ Namespace/
│ └ guestbook.yaml
└ kustomization.yaml
apiVersion: v1
kind: Namespace
metadata:
name: guestbook
labels:
name: guestbook
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- Namespace/guestbook.yaml
ArgoProject/guestbook.yaml
構築後に自動でアプリケーションがデプロイされていることを確かめるために、サンプルアプリ用のArgoプロジェクトを作成する
- spec.sourceReposにてArgoCDのサンプルアプリ用リポジトリを直接参照する
- spec.destinations.namespaceにてこのプロジェクトが操作するNamespaceをguestbookに設定する
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: guestbook
namespace: argocd
spec:
sourceRepos:
- https://github.com/sabure500/argocd-example-apps.git
destinations:
- namespace: guestbook
server: https://kubernetes.default.svc
roles:
- name: guestbook
policies:
- p, proj:guestbook:guestbook, applications, *, guestbook/guestbook, allow
ArgoApplication/guestbook.yaml
サンプルアプリ用にArgoアプリケーションも作成する
- spec.sourceReposにてArgoCDのサンプルアプリ用リポジトリを直接参照する
- spec.destinations.namespaceにてこのプロジェクトが操作するNamespaceをguestbookに設定する
- spec.source.pathにて対象リポジトリ内のkustomization.yamlがあるフォルダを指定する
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
spec:
destination:
namespace: guestbook
server: https://kubernetes.default.svc
project: guestbook
source:
path: ./kustomize-guestbook
repoURL: https://github.com/sabure500/argocd-example-apps.git
targetRevision: master
公開用IPを作りたい場合
アプリデプロイ時に公開用IPも作成したい場合は、サンプルリポジトリをForkしてServiceの内容を以下の様に更新する(プロジェクトとアプリケーションの対象のリポジトリもFork先に変更する)
この記事の例でもFoekした自身のリポジトリを見ている
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
ports:
- port: 80
targetPort: 80
selector:
app: guestbook-ui
type: LoadBalancer
kustomization.yaml $ argocd-server.yaml
ここまでで作成したリソースをまとめて管理するための設定を記述する
- basesにてArgoCDインストール用のマニフェストファイルを指定する
- resourcesにて上記で作成した自身独自のリソースを指定する
- baseから取得したリソースの中で、argocd-serviceのみパブリックIPの追加といった設定変更を行いたいため、patchesStrategicMergeにて指定する
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- github.com/argoproj/argo-cd//manifests/cluster-install?ref=v1.5.2
resources:
- AppProject/admin.yaml
- AppProject/guestbook.yaml
- Application/argocd-admin.yaml
- Application/kubernetes-admin.yaml
- Application/filebeat.yaml
- Application/guestbook.yaml
patchesStrategicMerge:
- argocd-server.yaml
apiVersion: v1
kind: Service
metadata:
name: argocd-server
spec:
type: LoadBalancer
argocd-adminリポジトリの内容を読み込んでArgoCDを構築するパイプラインの作成
独自設定を読み込んでArgoCDのインストールを行うワークフローを記述する。
こちらもまず全体を示し、その後(仮)からの変更点を解説する。
name: 'argocd-install'
on:
push:
branches:
- master
repository_dispatch:
types: [argocd-install]
env:
PROJECT_ID: ${{secrets.PROJECT_ID}}
GKE_CLUSTER: my-gke-cluster
GKE_ZONE: us-west1-a
jobs:
argocd-install:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: Setup Google Cloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: '289.0.0'
project_id: ${{secrets.PROJECT_ID}}
service_account_email: ${{ secrets.SA_EMAIL }}
service_account_key: ${{ secrets.SA_KEY }}
- name: Setup GKE
run: |-
gcloud container clusters get-credentials "$GKE_CLUSTER" --zone "$GKE_ZONE"
- name: Checkout argocd-admin repository
uses: actions/checkout@v2
with:
repository: sabure500/argocd-admin
ref: master
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- name: Setup Kustomize
run: |-
curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
chmod u+x ./kustomize
- name: Install ArgoCD Application
run: |-
kubectl create namespace argocd
./kustomize build . | kubectl apply -n argocd -f -
kubectl get deploy,pod,svc -n argocd
- name: Download ArgoCD CLI
run: |-
curl -sSL -o ./argocd https://github.com/argoproj/argo-cd/releases/download/v1.5.2/argocd-linux-amd64
chmod +x ./argocd
- name: ArgoCD change password
run: |-
sleep 3m
ARGOCD_SERVER=$(kubectl get service argocd-server -n argocd |awk 'NR==2' | awk '{print $4}')
echo $ARGOCD_SERVER
ARGOCD_TEMP_PASSWORD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2)
./argocd login --insecure --username admin --password $ARGOCD_TEMP_PASSWORD $ARGOCD_SERVER
./argocd account update-password --current-password $ARGOCD_TEMP_PASSWORD --new-password ${{secrets.ARGOCD_PASSWORD}}
変更点1:jobを実行しているリポジトリとは別のリポジトリへのCheckout
以下のstepを追加することで,別リポジトリの内容をこのアクションで利用することができる。
actions/checkoutの詳細な使用方法は公式リポジトリ参照
また、この処理を実施するために事前に作成済みの、PERSONAL_ACCESS_TOKENをこのリピジトリのSecretに新しく登録する必要がある
- name: Checkout argocd-admin repository
uses: actions/checkout@v2
with:
repository: sabure500/argocd-admin
ref: master
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
変更点2:kustomizeコマンドの取得
今回は、別リポジトリから取得した内容をkustomizeによってbuildするため以下のstepを追加することでkustomizeを取得している
kustomizeインストールの詳細情報は公式リポジトリ参照
- name: Setup Kustomize
run: |-
curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
chmod u+x ./kustomize
変更点3:自身で用意した独自設定を読み込んでArgoCDのインストールを行う
ここまでの処理で別リポジトリの内容の所得とkustomizeコマンドの準備ができているため、以下の様なstepを追加することで独自設定を読み込んだArgoCDのインストールを行うことができる
ArgoCDがKubernetesにインストールされていない状態で、apiVersion: argoproj.io/v1alpha1
が使用できないため、事前に初期設定でインストール後に独自設定を反映する形にしている。
argocd-adminのkustomization.yamlにてbaseで元々のArgoCD公式のマニフェストを指定しているため、変更点の独自設定だけが更新される形になる
また、パブリックIPの付与をyamlファイルで定義する形に変更したため、CLIによって行っていた行は削除している
- name: Install ArgoCD Application
run: |-
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.5.2/manifests/install.yaml
./kustomize build . | kubectl apply -n argocd -f -
kubectl get deploy,pod,svc -n argocd
実行結果
作成したパイプラインを実行するだけで、以下の画像の様にすでにArgoCDの設定が反映され、Argoアプリケーションやプロジェクト、またサンプルアプリそのものがデプロイされた状態で構築される
参考
-
Argo CDによってGKEでGitOpsをする
- KubernetesにおけるGitOpsとArgoCDの使い方についてとてもわかりやすく解説されていたのでおすすめです
- ArgoCD公式ドキュメント
- kustomize公式リポジトリ
- actions/checkoutの使い方