はじめてのArgoCD

2021.04.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ArgoCDことはじめとして、Getting Startedをやってみたレポートです。ArgoCDをインストールし、インストールしたクラスター内にアプリケーションを作成します。

環境

  • macOS Catalina 10.15.7 (19H524)

前提条件

EKSクラスター作成

以下を使ってEKSクラスターを作成します。

コンテキストの作成を忘れずに。

% aws eks update-kubeconfig --name blue-with-module

ArgoCD インストール

% kubectl create namespace argocd
namespace/argocd created
% kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/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-redis 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-redis 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-redis 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-gpg-keys-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 created
service/argocd-server-metrics created
deployment.apps/argocd-dex-server created
deployment.apps/argocd-redis created
deployment.apps/argocd-repo-server created
deployment.apps/argocd-server created
statefulset.apps/argocd-application-controller created

CRD2つなどいろいろなリソースが作成されていますね。

Argo CD CLI のダウンロード

HomeBrewでインストール出来るとのことでしたが、私の環境だとエラーになってしまいました。

% brew install argocd
(略)
curl: (22) The requested URL returned error: 404 
Error: Failed to download resource "argocd"
Download failed: https://ghcr.io/v2/homebrew/core/argocd-2.0.0.catalina.bottle.tar.gz

代わりにcurlで最新版 v2.0.1をダウンロードしました。

% VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
% curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-darwin-amd64
% chmod +x /usr/local/bin/argocd
% argocd version
argocd: v2.0.1+33eaf11
  BuildDate: 2021-04-15T22:34:01Z
  GitCommit: 33eaf11e3abd8c761c726e815cbb4b6af7dcb030
  GitTreeState: clean
  GoVersion: go1.16
  Compiler: gc
  Platform: darwin/amd64
FATA[0000] Argo CD server address unspecified

ArgoCD API Serverにアクセス

ServiceのタイプをLoadBalancerに変える方法でアクセス出来るようにしました。

% kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
service/argocd-server patched

kubectl get svc argocd-server -n argocdの出力結果のEXTERNAL-IP列の値を控えます。

% kubectl get svc argocd-server -n argocd
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)                      AGE
argocd-server   LoadBalancer   172.20.114.241   afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com   80:30907/TCP,443:31857/TCP   6h12m

CLIでログイン

まずはパスワードの値を取得します。

% kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
vcITNaHpilGRbAFh

argocd loginの後に先程控えたargocd-serverEXTERNAL-IPの値を入れます。

% argocd login afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com
WARNING: server certificate had error: x509: certificate is valid for localhost, argocd-server, argocd-server.argocd, argocd-server.argocd.svc, argocd-server.argocd.svc.cluster.local, not afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com. Proceed insecurely (y/n)? y
Username: admin
Password: vcITNaHpilGRbAFh
'admin:login' logged in successfully
Context 'afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com' updated

アプリケーション作成(CLI)

https://github.com/argoproj/argocd-example-apps.git こちらのサンプルアプリを使います。

% argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default

Sync

Sync前なので、Sync StatusがOutOfSyncになっています。

% argocd app get guestbook
Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from  (53e28ff)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  OutOfSync  Missing        
apps   Deployment  default    guestbook-ui  OutOfSync  Missing

Syncします。

% argocd app sync guestbook
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS    HEALTH        HOOK  MESSAGE
2021-04-19T19:23:05+09:00            Service     default          guestbook-ui  OutOfSync  Missing              
2021-04-19T19:23:05+09:00   apps  Deployment     default          guestbook-ui  OutOfSync  Missing              
2021-04-19T19:23:05+09:00            Service     default          guestbook-ui    Synced  Healthy              
2021-04-19T19:23:05+09:00   apps  Deployment     default          guestbook-ui  OutOfSync  Missing              deployment.apps/guestbook-ui created
2021-04-19T19:23:05+09:00            Service     default          guestbook-ui    Synced   Healthy              service/guestbook-ui created
2021-04-19T19:23:05+09:00   apps  Deployment     default          guestbook-ui    Synced  Progressing              deployment.apps/guestbook-ui created

Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        Synced to  (53e28ff)
Health Status:      Progressing

Operation:          Sync
Sync Revision:      53e28ff20cc530b9ada2173fbbd64d48338583ba
Phase:              Succeeded
Start:              2021-04-19 19:23:04 +0900 JST
Finished:           2021-04-19 19:23:05 +0900 JST
Duration:           1s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME          STATUS  HEALTH       HOOK  MESSAGE
       Service     default    guestbook-ui  Synced  Healthy            service/guestbook-ui created
apps   Deployment  default    guestbook-ui  Synced  Progressing        deployment.apps/guestbook-ui created

ArgoCIのUIでも確認してみましょう。先程控えたargocd-serverEXTERNAL-IPにブラウザアクセスします。

ログイン画面にリダイレクトします。入力内容は先程CLIで入力したのと同じ、usernameはadmin、passwordはkubectl get secretで取得したものです。 argocdlogin

UIでも状況が確認できます。 argocdapp guestbookのパネルをクリックすると詳細画面に遷移し、リソース構成を図で確認できます。 argocdappguestbook

アプリ確認

せっかくなので、デプロイしたアプリにブラウザアクセスしてみたいと思います。デプロイされたサービスはClusterIPだったので、外部からアクセス出来るように変更を加えます。

% kubectl patch svc guestbook-ui -p '{"spec": {"type": "LoadBalancer"}}'

kubectl get svc guestbook-uiの出力結果のargocd-serverEXTERNAL-IPに表示されるCLBのDNS値にブラウザアクセスします。

確認できました! guestbook

おまけ:差分検知検証1

この後再度argocd app sync guestbookを実行すれば、上記のServiceのタイプがGitリポジトリに上がっているものと異なっているので、差分を検知して修正してくれるのかなと思ったのですが、差分検知されませんでした。

% argocd app sync guestbook
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS   HEALTH        HOOK  MESSAGE
2021-04-19T21:15:35+09:00            Service     default          guestbook-ui    Synced  Healthy              
2021-04-19T21:15:35+09:00   apps  Deployment     default          guestbook-ui    Synced  Healthy              
2021-04-19T21:15:36+09:00            Service     default          guestbook-ui    Synced  Healthy              service/guestbook-ui unchanged
2021-04-19T21:15:36+09:00   apps  Deployment     default          guestbook-ui    Synced  Healthy              deployment.apps/guestbook-ui unchanged

Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        Synced to  (53e28ff)
Health Status:      Healthy

Operation:          Sync
Sync Revision:      53e28ff20cc530b9ada2173fbbd64d48338583ba
Phase:              Succeeded
Start:              2021-04-19 21:15:35 +0900 JST
Finished:           2021-04-19 21:15:36 +0900 JST
Duration:           1s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME          STATUS  HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  Synced  Healthy        service/guestbook-ui unchanged
apps   Deployment  default    guestbook-ui  Synced  Healthy        deployment.apps/guestbook-ui unchanged
kazue.masaki@HL00367 terraform % k get svc                
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP                                                                    PORT(S)        AGE
guestbook-ui   LoadBalancer   172.20.26.176   a8089e731853f41c4b735df54a41deb3-1678029976.ap-northeast-1.elb.amazonaws.com   80:31390/TCP   112m
kubernetes     ClusterIP      172.20.0.1      <none>

おまけ:差分検知検証2

先程はkubectl patchコマンドで設定変更(ServiceタイプをLoadBalancerに変える)しました。 argocdサブコマンドにはkubectl patchコマンドと同等のものがもあり、それで設定変更した場合なら差分検知してくれるのかなと思ってやってみました。

まずは一度ServiceタイプをClusterIPに戻します。
LoadBalancerに変えたときと同様patchコマンドを使ってみましたが、エラーになります。

% kubectl patch svc guestbook-ui -p '{"spec": {"type": "ClusterIP"}}'                                  
The Service "guestbook-ui" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'

対処方法がわからなかったので、kubectl editで対応しました。

editの一部

 spec:
   clusterIP: 172.20.26.176
   externalTrafficPolicy: Cluster
   ports:
-  - nodePort: 31373
-    port: 80
+  - port: 80
     protocol: TCP
     targetPort: 80
   selector:
     app: guestbook-ui
   sessionAffinity: None
-  type: LoadBalancer
+  type: ClusterIP

その後、argocdのコマンドで再度LoadBalancerに戻します。

% argocd app patch-resource guestbook --kind Service --resource-name guestbook-ui --patch '{"spec": {"type": "LoadBalancer"}}'

再度syncを試してみましたが、差分検知されませんでした。すみません今の私にはこの差分を検知させる方法がわからなかったです。分かり次第追記しようと思います。ご存じの方教えて下さい??‍

 % argocd app sync guestbook
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME    STATUS   HEALTH        HOOK  MESSAGE
2021-04-19T22:20:10+09:00            Service     default          guestbook-ui    Synced  Healthy              
2021-04-19T22:20:10+09:00   apps  Deployment     default          guestbook-ui    Synced  Healthy              
2021-04-19T22:20:11+09:00            Service     default          guestbook-ui    Synced  Healthy              service/guestbook-ui unchanged
2021-04-19T22:20:11+09:00   apps  Deployment     default          guestbook-ui    Synced  Healthy              deployment.apps/guestbook-ui unchanged

Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://afdb98ff0cc604d89bf72be854acf1b0-758120766.ap-northeast-1.elb.amazonaws.com/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        Synced to  (53e28ff)
Health Status:      Healthy

Operation:          Sync
Sync Revision:      53e28ff20cc530b9ada2173fbbd64d48338583ba
Phase:              Succeeded
Start:              2021-04-19 22:20:10 +0900 JST
Finished:           2021-04-19 22:20:11 +0900 JST
Duration:           1s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME          STATUS  HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  Synced  Healthy        service/guestbook-ui unchanged
apps   Deployment  default    guestbook-ui  Synced  Healthy        deployment.apps/guestbook-ui unchanged

追記おまけ:差分検知検証3

デフォルトの設定だと、今回の様なクラスターの設定変更を自動で検知して修正することはできないようです。Self-Healingという機能を有効化する必要がありました。というかデフォルトだとGitリポジトリに差分が発生(新規コミットがプッシュされる)しても自動同期してくれるわけではありませんでした。

というわけで設定変更です。Self-Healingを有効化するself-healオプションを加えます。この機能を使うには自動同期を有効化する必要もあるので、そのオプション--sync-policy automatedも加えます。

% argocd app set guestbook --self-heal --sync-policy automated

さあこれで差分が検知されて自動修正されるぞ…としばらく待ってみたのですがなにも起きません。

追記おまけ:差分検知検証4

Gitリポジトリに上がっている、今回修正をしたサービスのマニフェストファイルは以下です。

apiVersion: v1
kind: Service
metadata:
  name: guestbook-ui
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: guestbook-ui

タイプについての記述がありませんね。この場合デフォルトのタイプであるClusterIPが使われます。

明示的にタイプが定義されていないから、差分検知がされないのでは?と仮説を立てました。これを検証したいと思います。

"type": "ClusterIP"と明記したマニフェストファイルをGitリポジトリにプッシュする必要があります。現在sourceとして使っているリポジトリはargoprojのものなのでプッシュできません。自分のアカウントにForkしたリポジトリにsourceを変更します。

% argocd app patch guestbook --patch '{"spec": { "source": { "repoURL": "https://github.com/kazuemasaki/argocd-example-apps.git" } }}' --type merge
(長いので出力結果は省略 おそらく `argocd app get guestbook -o yaml`と同じ結果が表示されている)

そしてtypeを明記したマニフェストファイルをコミットしてプッシュします。

   ports:
   - port: 80
     targetPort: 80
+  type: ClusterIP  
   selector:
     app: guestbook-ui

しばらくするとSyncStatusがOutOfSyncになり、syncが開始されました!

なのですが、最終的にはSyncは失敗しました。。状況を確認します。下から2行目にご注目ください。

% argocd app get guestbook
Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://aeb20e694f65c4159be30376f75e0047-1861540336.ap-northeast-1.elb.amazonaws.com/applications/guestbook
Repo:               https://github.com/kazuemasaki/argocd-example-apps.git
Target:
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        Automated
Sync Status:        OutOfSync from  (783a4d4)
Health Status:      Healthy

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  OutOfSync  Healthy        Service "guestbook-ui" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'
apps   Deployment  default    guestbook-ui  Synced     Healthy        deployment.apps/guestbook-ui unchanged

Service "guestbook-ui" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when type is 'ClusterIP'

と出てますね。これは「おまけ:差分検知検証2」で kubectl patchコマンドでタイプをClusterIPに戻そうとした際に出たのと同じエラーですね。この差分を自動で修正するのはArgoCDでもできないみたいです。残念。ということで最終的には差分の自動検知はできましたが、自動修正には失敗したという結果になりました。