Argo CD の自動同期: automated・selfHeal・prune
- 公開日
- カテゴリ:ArgoCD
- タグ:Kubernetes,ArgoCD,学習メモ

Argo CD の Application は、そのままでは Git とクラスタの違いを表示するだけで、人が Argo CD の画面(ブラウザで開く管理画面)のボタンを押すまでクラスタを変えない。
この記事では、Application の YAML に設定を 3 つ追加して、Git に push するだけでクラスタの中身が Git の内容に合う状態にする。
contents
- 前提
- 自動同期を決める 3 つの設定
- automated: push すると Pod が増える
- selfHeal: kubectl scale で変えた Pod の数が Git の数に戻る
- prune: Git から消した Deployment がクラスタからも消える
- Git で前のコミットに戻す
- 自動同期の全体像
- 用語メモ
- 参考 URL
前提
GitHub の private リポジトリ argocd-study に web/deployment.yaml(nginx の Deployment web。replicas: 1)があり、Argo CD の Application web がそれを default namespace に入れている状態から始める。Argo CD は v3.5.5。
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web Synced Healthy
$ kubectl get deployment,pods -n default
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 1/1 1 1 23h
NAME READY STATUS RESTARTS AGE
pod/web-557577df75-5m5lr 1/1 Running 1 23h
この記事で使う Argo CD の用語。
| 言葉 | 意味 |
|---|---|
| Sync | Git の YAML をクラスタに apply すること。自分で kubectl apply を実行する代わりに、Argo CD が実行する |
Synced / OutOfSync | Git の YAML とクラスタの中身を比べた結果。同じなら Synced、違えば OutOfSync |
| Argo CD の画面の SYNC ボタン / REFRESH ボタン | Argo CD の画面は、kubectl port-forward svc/argocd-server -n argocd 8080:443 を実行して https://localhost:8080 をブラウザで開く。SYNC を押すと、Argo CD が Git の YAML を取得してクラスタに apply する。REFRESH を押すと、Git の YAML を取得してクラスタと比べ直すだけで、apply はしない |
自動同期を決める 3 つの設定
追加する設定は 3 つで、いずれも Application の YAML の spec.syncPolicy に書く。
| 設定 | 何をするか | 書かないとき |
|---|---|---|
automated | Git の内容が変わって OutOfSync になったら、人が画面の SYNC ボタンを押さなくても Sync する | 人が画面の SYNC ボタンを押すまで Sync しない |
selfHeal: true | クラスタの中身が変わって OutOfSync になったときも、Git の内容に合わせて戻す | OutOfSync と表示するだけで、戻さない |
prune: true | Git から消えたものを、クラスタからも消す | クラスタに残したままにする |
この 3 つを 1 つずつ追加して、追加する前と後で動きがどう変わるかを確認する。
automated: push すると Pod が増える
Application web の YAML に spec.syncPolicy.automated を追加して、apply し直す。automated: {} の {} は、automated の中に設定を何も書かないという意味。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example-user/argocd-study.git
targetRevision: HEAD
path: web
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated: {}
$ kubectl apply -f application.yaml
# => application.argoproj.io/web configured
apply しても、この時点では何も起きない。Git の内容とクラスタの中身が一致している(Synced)ので、Sync する対象がない。
Git を変えて push する
GitHub のリポジトリの web/deployment.yaml の replicas: 1 を replicas: 2 に変えて push する。
- replicas: 1
+ replicas: 2
Argo CD は GitHub からファイルを定期的に取得する。既定では 2〜3 分に 1 回で、設定で変えられる。(すぐに反映したいときは、Argo CD の画面の REFRESH ボタンを押す)
別のターミナルで default namespace の Pod を -w 付きで表示しておくと、新しい Pod が作られるのが見える。
$ kubectl get pods -n default -w
NAME READY STATUS RESTARTS AGE
web-557577df75-5m5lr 1/1 Running 1 25h
web-557577df75-lcjzc 0/1 Pending 0 0s
web-557577df75-lcjzc 0/1 ContainerCreating 0 0s
web-557577df75-lcjzc 1/1 Running 0 0s
$ kubectl get deployment web -n default
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 25h
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web Synced Healthy
ここで起きたことを順に書くと、次のようになる。
- Argo CD が GitHub からファイルを取得し、Git の
replicas: 2とクラスタのreplicas: 1が違うのでOutOfSyncになった automatedが書いてあるので、人が画面の SYNC ボタンを押さなくても Argo CD が Sync(apply)した- apply された
replicas: 2に合わせて、Kubernetes が Pod を 1 つ作った
selfHeal: kubectl scale で変えた Pod の数が Git の数に戻る
selfHeal がないときの動き
kubectl scale は、クラスタにある Deployment の replicas を直接書き換えるコマンド。Git の内容は変えずに、クラスタの中身だけを変える。
$ kubectl scale deployment web -n default --replicas=3
# => deployment.apps/web scaled
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web OutOfSync Healthy
$ kubectl get deployment web -n default
NAME READY UP-TO-DATE AVAILABLE AGE
web 3/3 3 3 25h
Git の内容は replicas: 2、クラスタの Deployment は replicas: 3。違いがあるので、数秒で OutOfSync になる。ところが、そのまま待っても Pod は 3 つのまま変わらない。
automated は、Git の内容が変わったときに Sync する設定。クラスタの中身が変わったときは、OutOfSync と表示するだけで Sync しない。これが selfHeal を書かないときの動き。
selfHeal を追加する
automated の下に selfHeal: true を書いて、Application を apply し直す。
syncPolicy:
automated:
selfHeal: true
$ kubectl apply -f application.yaml
# => application.argoproj.io/web configured
数秒後に Pod が 1 つ Terminating になり、Deployment の replicas は Git の内容と同じ 2 に戻る。
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web Synced Healthy
$ kubectl get deployment web -n default
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 25h
この状態でもう一度 kubectl scale deployment web -n default --replicas=3 を実行すると、新しい Pod は ContainerCreating から Terminating になり、Running になる前に消える。クラスタの Deployment を自分で変えても、Git に書いてある数に戻される。
prune: Git から消した Deployment がクラスタからも消える
prune がないときの動き
消す対象を先に用意する。GitHub の web/ ディレクトリに、Deployment hello の YAML(web と同じ nginx の Deployment で、名前だけ違う)を hello.yaml として追加して push する。Application の path: web が指しているのはディレクトリなので、同じディレクトリに追加したファイルは、Application を変えなくても一緒にクラスタに入る。
$ git add web/hello.yaml
$ git commit -m "Add hello"
$ git push
しばらく待つと、クラスタに Deployment hello が作られる。次に、hello.yaml を Git から削除して push する。
$ git rm web/hello.yaml
$ git commit -m "Remove hello"
$ git push
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web OutOfSync Healthy
$ kubectl get deployment -n default
NAME READY UP-TO-DATE AVAILABLE AGE
hello 1/1 1 1 53s
web 2/2 2 2 25h
Git に hello.yaml はもうないが、クラスタには Deployment hello がある。違いがあるので OutOfSync になる。ところが、Deployment hello は消えない。
自動同期がするのは「Git にあるものを apply する」ことだけで、「Git にないものを消す」ことはしない。これが prune を書かないときの動き。
prune を追加する
automated の下に prune: true を書いて、Application を apply し直す。
syncPolicy:
automated:
selfHeal: true
prune: true
$ kubectl apply -f application.yaml
# => application.argoproj.io/web configured
しばらく待つと、クラスタから Deployment hello が消える。
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web Synced Healthy
$ kubectl get deployment -n default
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 25h
prune が消すのは、Argo CD がクラスタに入れたもの(annotation argocd.argoproj.io/tracking-id が付いている)のうち、Git にないものだけ。同じ namespace にあっても、Argo CD が入れたものでなければ消さない。
Git で前のコミットに戻す
selfHeal: true があると、kubectl scale で戻しても Git の内容に戻される。画面の HISTORY AND ROLLBACK にある Rollback も、公式ドキュメントによると automated が有効な Application では使えない。変更を取り消すときも Git を使う。
git revert は、指定したコミットの逆の変更を新しいコミットとして作るコマンド。replicas を 2 にしたコミットを revert して push する。
$ git log --oneline
xxxxxxx Remove hello
xxxxxxx Add hello
xxxxxxx Scale web to 2
xxxxxxx Move deployment to web/
xxxxxxx Add web deployment
$ git revert --no-edit <Scale web to 2 のハッシュ>
# => [main xxxxxxx] Revert "Scale web to 2"
$ git push
しばらく待つと、Pod が 1 つ Terminating になり、Deployment の replicas は 1 に戻る。
$ kubectl get deployment,pods -n default
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 1/1 1 1 25h
NAME READY STATUS RESTARTS AGE
pod/web-557577df75-5m5lr 1/1 Running 1 25h
$ kubectl get applications -n argocd
NAME SYNC STATUS HEALTH STATUS
web Synced Healthy
自動同期の全体像
Deployment と Pod を変えたのは、すべて argocd-application-controller。(図の角が二重の箱は動くプログラム、それ以外の箱は etcd に保存されたデータ)
用語メモ
| 用語 | 読み方 | 意味 |
|---|---|---|
| Sync | シンク | Git の YAML をクラスタに apply すること。kubectl apply 相当 |
| Refresh | リフレッシュ | Git の YAML を取り直して、クラスタと比べ直すこと。apply はしない |
| automated | オートメイテッド | OutOfSync になったら、人が画面の SYNC ボタンを押さなくても Sync する設定。自動同期 |
| selfHeal | セルフヒール | クラスタの中身が変わったときも、Git の内容に合わせて戻す設定 |
| prune | プルーン | Git から消えたものを、クラスタからも消す設定。もとは「剪定」の意味 |
まとめ
automated: Git の内容が変わってOutOfSyncになったら、Argo CD が自動で Sync するselfHeal: true: クラスタの中身をkubectl scaleなどで直接変えても、Git の内容に戻すprune: true: Git から消えたものを、クラスタからも消す
参考 URL
- [official] Automated Sync Policy - Argo CD
- [official] FAQ - Argo CD
- [official] Resource Tracking - Argo CD

