今回は ArgoCD ver 2.5でBeta版になったServer-side Apply機能について簡単に触れてみます。
Server-side Applyとは
Server-side Applyは、Kubernetesでv 1.14から利用可能になった、リソースの作成・管理方法の1つです。
Kubernetesはリソースを宣言的手法で管理するコマンドとして kubectl apply
を利用することができます。
リソースを宣言的に管理するための差分を検出・比較するのは、従来は kubectl
コマンドが行っていました (Client-sdie Apply) 。この手法ではいくつかの課題が知られており、これを解決するための方法として Server-side Apply (以降 SSAと記載) という機能が実装されました。
SSAはリソースの管理に metadata.managedField
というフィールドを使用します。このフィールドには、kubectl
やKubernetesコンポーネントなど、誰がこのリソースを管理・更新したのかを記録します。そして前回更新したのと別の誰かがフィールドを更新しようとすると、コンフリクトを発生させて上書きを防止します。
SSAの詳細な説明はこちらのドキュメント等をご確認ください。
- Kubernetes Document - Server-Side Apply
- Qiita - Kubernetes 1.14: Server-side Apply (alpha)
- ThinkIT - Kubernetes 1.18の新機能を学び、使ってみよう
ArgoCD Server-side Applyとは
さて、ArgoCDのドキュメントにもClient-side Applyでの課題は記載されており、大きく2つの課題が紹介されています。
管理するリソースのマニフェストファイルのサイズが巨大な場合: Kubernetesリソースのannotationsには、256kbのサイズ制限があります。Client-side Applyでは、差分管理のため、annotationの
last-applied-configuration
という値にリソースの状態を記録しています。そのためマニフェストのサイズが巨大になると256kbを超える場合があります(例: Fixing Argo CD “Too long must have at most 262144 bytes” error)。ArgoCDが完全には管理しないリソースにパッチを当てる場合: ArgoCDだけでなく、それ以外の方法でリソースを更新したい場合も、Server-Side Applyを適用したほうが管理しやすくなります。
ArgoCDのアップデートによりSSAが実装されたことで、これらの課題を解消することが期待できます。
ArgoCDでのSSA機能は、Application
からリソースを作成・更新する時、対象のリソースにSSAを適用します。SSAの設定はArgoCDの Application
リソースの定義で行い、 Application
適用後に kubectl apply
等で変更しようとすると、差分があればコンフリクトを返します。
なお、 ArgoCDから Application
経由でリソースを更新する際は、現在は差分があっても 強制的に更新されるようです( --force-conflicts
オプションを付けて更新するようなイメージ)。
※参考: GitHub - argoproj/argo-cd: Server-Side Apply support for ArgoCD
ArgoCD Server-side Applyを試す
ここからArgoCD SSAを試してみます。今回は EKS ver.1.21上に ArgoCD ver 2.5をデプロイしています。
$ kubectl version Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:03:20Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"21+", GitVersion:"v1.21.14-eks-fb459a0", GitCommit:"b07006b2e59857b13fe5057a956e86225f0e82b7", GitTreeState:"clean", BuildDate:"2022-10-24T20:32:54Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"} $ argocd version argocd: v2.4.2+c6d0c8b BuildDate: 2022-06-21T21:03:41Z GitCommit: c6d0c8baaa291cd68465acd7ad6bef58b2b6f942 GitTreeState: clean GoVersion: go1.18.3 Compiler: gc Platform: linux/amd64 argocd-server: v2.5.1+504da42 BuildDate: 2022-11-01T21:14:30Z GitCommit: 504da424c2c9bb91d7fb2ebf3ae72162e7a5a5be GitTreeState: clean GoVersion: go1.18.8 Compiler: gc Platform: linux/amd64 Kustomize Version: v4.5.7 2022-08-02T16:35:54Z Helm Version: v3.10.1+g9f88ccb Kubectl Version: v0.24.2 Jsonnet Version: v0.18.0
今回はServer-side Applyを有効にした Application
を作成し、SSAが適用されていることを確認します。ArgoCDでSSAを有効にするには、以下のように Application
の spec.syncPolicy.syncOptions
に設定を追加します。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: guestbook-ssa namespace: argocd spec: project: default source: repoURL: https://github.com/argoproj/argocd-example-apps.git targetRevision: HEAD path: guestbook destination: server: https://kubernetes.default.svc namespace: default syncPolicy: syncOptions: - ServerSideApply=true
上記 app-ssa.yaml
をデプロイします。
$ kubectl apply -f app-ssa.yaml
application.argoproj.io/guestbook-ssa created
デプロイ後Syncを行い、Statusを確認すると、作成されたDeploymentは annotations.last-applied-configuration
がなく、 metadata.managedFiled
が追加されていることが確認できます。
$ kubectl get deploy guestbook-ui -oyaml --show-managed-fields apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2022-11-05T03:22:23Z" generation: 1 labels: app.kubernetes.io/instance: guestbook-ssa managedFields: - apiVersion: apps/v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:labels: f:app.kubernetes.io/instance: {} f:spec: f:replicas: {} f:revisionHistoryLimit: {} f:selector: {} f:template: f:metadata: f:labels: f:app: {} f:spec: f:containers: k:{"name":"guestbook-ui"}: .: {} f:image: {} f:name: {} f:ports: k:{"containerPort":80,"protocol":"TCP"}: .: {} f:containerPort: {} manager: argocd-controller operation: Apply time: "2022-11-05T03:22:23Z" (以下割愛)
また、SSAの動きを確認するため、上記 Application
で作られたDeploymentのイメージタグを事前に変更してから、 Application
で指定するマニフェストファイルと同じ内容のファイルをapplyすると、想定通りコンフリクトが発生しました。
# edit前のイメージタグを確認 $ kubectl get deploy -oyaml | grep image: - image: gcr.io/heptio-images/ks-guestbook-demo:0.2 # kubectl editでイメージタグを変更 $ kubectl edit deploy guestbook-ui deployment.apps/guestbook-ui edited $ kubectl get deploy -oyaml | grep image: - image: gcr.io/heptio-images/ks-guestbook-demo:0.1 # kubectl applyで更新すると差分を検知してコンフリクトを発生 $ kubectl apply -f guestbook-ui-deploy.yaml --server-side error: Apply failed with 1 conflict: conflict with "kubectl-edit" using apps/v1: .spec.template.spec.containers[name="guestbook-ui"].image Please review the fields above--they currently have other managers. Here are the ways you can resolve this warning: * If you intend to manage all of these fields, please re-run the apply command with the `--force-conflicts` flag. * If you do not intend to manage all of the fields, please edit your manifest to remove references to the fields that should keep their current managers. * You may co-own fields by updating your manifest to match the existing value; in this case, you'll become the manager if the other manager(s) stop managing the field (remove it from their configuration). See https://kubernetes.io/docs/reference/using-api/server-side-apply/#conflicts
なお ArgoCDからSyncをした場合は、上記イメージタグも上書きされることも確認できました。
# Syncして更新 $ argocd app sync guestbook-ssa TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE 2022-11-05T12:32:43+09:00 Service default guestbook-ui Synced Healthy 2022-11-05T12:32:43+09:00 apps Deployment default guestbook-ui OutOfSync Healthy 2022-11-05T12:32:43+09:00 apps Deployment default guestbook-ui Synced Progressing 2022-11-05T12:32:43+09:00 Service default guestbook-ui Synced Healthy service/guestbook-ui serverside-applied 2022-11-05T12:32:43+09:00 apps Deployment default guestbook-ui Synced Progressing deployment.apps/guestbook-ui serverside-applied (以下割愛) # イメージタグは元に戻った $ kubectl get deploy -oyaml | grep image: - image: gcr.io/heptio-images/ks-guestbook-demo:0.2