Argo CD で GitOps 環境を構築する on GKE

GitOps というアプリデプロイ戦略が Cloud Native な CD *1 で普及し始めています。

www.weave.works

ソースコードのリポジトリとは別にアプリの設定用リポジトリを用意し、リポジトリの状態とデプロイの状態を一致させるようにツールを利用して管理します。これにより設定の変更を GitHub(GitLab) flow に載せることができ、オペミスやスクリプトのバグによる事故を防ぐことが可能になるとのことです。

GitOps の CD ツールの一つである Argo CD を GKE で使ってみました。

argoproj.github.io

GKE のクラスタを作って credentials を設定し kubectl で操作できるようにします。

$ gcloud container clusters get-credentials xxx-cluster --zone asia-northeast-a --project xxxxx

接続を確認。ノード2つのクラスタを作りました。

$ kubectl get node

NAME                                                STATUS   ROLES    AGE   VERSION
gke-standard-cluster-1-default-pool-xxxxxxxxxxxxxxx   Ready    <none>   11m   v1.13.11-gke.14
gke-standard-cluster-1-default-pool-xxxxxxxxxxxxxxx   Ready    <none>   11m   v1.13.11-gke.14

Argo CD が動作するための namespace argocd を作ります。

$ kubectl create namespace argocd
namespace/argocd created

Argo CD の現時点の最新リリース 1.3.6 のマニフェストを使ってインストールします*2

Release v1.3.6 · argoproj/argo-cd · GitHub

$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.3.6/manifests/install.yaml

customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io created
serviceaccount/argocd-application-controller created
serviceaccount/argocd-dex-server created
serviceaccount/argocd-server created
role.rbac.authorization.k8s.io/argocd-application-controller created
role.rbac.authorization.k8s.io/argocd-dex-server created
role.rbac.authorization.k8s.io/argocd-server created
clusterrole.rbac.authorization.k8s.io/argocd-application-controller created
clusterrole.rbac.authorization.k8s.io/argocd-server created
rolebinding.rbac.authorization.k8s.io/argocd-application-controller created
rolebinding.rbac.authorization.k8s.io/argocd-dex-server created
rolebinding.rbac.authorization.k8s.io/argocd-server created
clusterrolebinding.rbac.authorization.k8s.io/argocd-application-controller created
clusterrolebinding.rbac.authorization.k8s.io/argocd-server created
configmap/argocd-cm created
configmap/argocd-rbac-cm created
configmap/argocd-ssh-known-hosts-cm created
configmap/argocd-tls-certs-cm created
secret/argocd-secret created
service/argocd-dex-server created
service/argocd-metrics created
service/argocd-redis created
service/argocd-repo-server created
service/argocd-server-metrics created
service/argocd-server created
deployment.apps/argocd-application-controller created
deployment.apps/argocd-dex-server created
deployment.apps/argocd-redis created
deployment.apps/argocd-repo-server created
deployment.apps/argocd-server created

デプロイが完了したので、argocd の namespace を覗いてみます。

$ kubectl get deploy,pod,svc -n argocd

NAME                                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/argocd-application-controller   1/1     1            1           3m29s
deployment.extensions/argocd-dex-server               1/1     1            1           3m29s
deployment.extensions/argocd-redis                    1/1     1            1           3m29s
deployment.extensions/argocd-repo-server              1/1     1            1           3m29s
deployment.extensions/argocd-server                   1/1     1            1           3m28s

NAME                                                 READY   STATUS    RESTARTS   AGE
pod/argocd-application-controller-59b7c6958d-676kv   1/1     Running   0          3m29s
pod/argocd-dex-server-658745cd65-kks5t               1/1     Running   0          3m29s
pod/argocd-redis-fc585c648-nr7z2                     1/1     Running   0          3m29s
pod/argocd-repo-server-6746fdc4dd-64c2x              1/1     Running   0          3m29s
pod/argocd-server-85b5959ffb-st7xt                   1/1     Running   0          3m28s

NAME                            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)             AGE
service/argocd-dex-server       ClusterIP   10.4.1.108    <none>        5556/TCP,5557/TCP   3m30s
service/argocd-metrics          ClusterIP   10.4.5.166    <none>        8082/TCP            3m30s
service/argocd-redis            ClusterIP   10.4.3.179    <none>        6379/TCP            3m30s
service/argocd-repo-server      ClusterIP   10.4.8.63     <none>        8081/TCP,8084/TCP   3m30s
service/argocd-server           ClusterIP   10.4.7.233    <none>        80/TCP,443/TCP      3m29s
service/argocd-server-metrics   ClusterIP   10.4.15.178   <none>        8083/TCP            3m30s

外部から Argo CD に接続できるよう、LoadBalancer を設定します。

$ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

しばらく待つと GCP のネットワークサービスに検知されてロードバランサーが作成され、argocd-server に EXTERNAL-IP が割り当てられます。

$ kubectl get svc argocd-server -n argocd
NAME            TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)                      AGE
argocd-server   LoadBalancer   10.4.7.233   xx.xx.xx.xx   80:30669/TCP,443:31636/TCP   16m

割り当てられた IP にブラウザでアクセスすると、Argo CD のログイン画面がでます*3

f:id:kondoumh:20191214104659p:plain

admin のパスワードは argocd-server の pod 名になっていますので、kubectl で取得してログインします。

f:id:kondoumh:20191214105054p:plain

今回はアプリを作る手間を省くため Argo CD の example リポジトリをフォークして GitOps の設定をします。

github.com

Argo CD の Setting -> Repositories を開きます。

f:id:kondoumh:20191214111337p:plain

public なリポジトリとしてフォークしたので認証情報なしで CONNECT REPO USING HTTPS に URL を設定するだけです。

f:id:kondoumh:20191214111539p:plain

接続に成功しました。

f:id:kondoumh:20191214111628p:plain

デプロイするアプリ用の namespace を作っておきます。

$ kubectl create ns prod
namespace/prod created

CREATE NEW APP を クリックして、デプロイ対象のアプリ情報を登録します。example の helm-guestbook をデプロイするので、先に登録したリポジトリを選択して Path で helm-guestbook を選択。

f:id:kondoumh:20191214112223p:plain

アプリの namespace は先ほど作成した prod を指定。

f:id:kondoumh:20191214112424p:plain

CREATE をクリックすると GitHub との Sync が開始されデプロイが始まります。

f:id:kondoumh:20191214112557p:plain

kubectl で確認。すでに ロードバランサーも作られてアプリがデプロイされています。

$ kubectl get deployment,svc,pod -n prod
NAME                                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/guestbook-helm-guestbook   2/2     2            2           4m2s

NAME                               TYPE           CLUSTER-IP   EXTERNAL-IP    PORT(S)        AGE
service/guestbook-helm-guestbook   LoadBalancer   10.4.11.37   xx.xx.xx.xxx   80:32362/TCP   4m3s

NAME                                            READY   STATUS    RESTARTS   AGE
pod/guestbook-helm-guestbook-764f9f8885-bqzpz   1/1     Running   0          4m2s
pod/guestbook-helm-guestbook-764f9f8885-hqvpd   1/1     Running   0          4m2s

アプリの IP にアクセスすると確かに起動しています。

f:id:kondoumh:20191214113433p:plain

Argo CD でアプリの詳細を見ると、kubectl で取得できる情報がグラフィカルに閲覧可能です。

f:id:kondoumh:20191214113535p:plain

グラフの各ノードをクリックすると、詳細情報が出て、状態、マニフェスト、イベント、ログなどを確認できます。

f:id:kondoumh:20191214114410p:plain

GitOps なので、設定のリポジトリを更新するとそれに応じてデプロイされたアプリの状態も変化します。

ということで、フォークしたリポジトリの設定ファイルで replicaCount を増やしてみます。

f:id:kondoumh:20191214114639p:plain

3分ほど待っていると、Pod が1個増えました。

f:id:kondoumh:20191214115010p:plain

kubectl でも確認できます。

$ kubectl get pod -n prod
NAME                                        READY   STATUS    RESTARTS   AGE
guestbook-helm-guestbook-764f9f8885-bqzpz   1/1     Running   0          29m
guestbook-helm-guestbook-764f9f8885-hqvpd   1/1     Running   0          29m
guestbook-helm-guestbook-764f9f8885-rfb6c   1/1     Running   0          4m25s

以上のように Argo CD は Git リポジトリとアプリのデプロイ状態を同期させることができます。

リアクティブな Web UI が使いやすいですが、もちろん argocd という CLI も提供されています。Helm chart 以外にも Kustomize / ksonnet などのパッケージにも対応しており、個別のツールをインストールしなくてもデプロイできます。

ビルド・テストやコンテナイメージの作成を CI で実施し GitOpt ツールを CD に適用すれば、開発からデプロイまでの自動化を実現できそうです。

*1:継続的デリバリ

*2:Helm chart によるインストールも可能ですが、今回は素のマニフェストを使いました。

*3:TLS 設定がないので警告が出ますが