LoginSignup
1

More than 1 year has passed since last update.

Carvel tools/kapp の特徴について説明してみました

Last updated at Posted at 2021-12-15

kappについて

VMware Tanzu Application Platform のベータリリースが発表されました。
Kubernetesの運用を簡素化する製品の1つとして注目していきたいです。今回はインストール時に利用されている kapp について、説明いたします。

kappとは

Carvel tools の1つです。その中でkappは、Kubernetesアプリケーション をコンセプトに作られたCLIです。同じラベルのリソースのセットをアプリケーションのように一括で管理できます。リソースの差分、ラベル付け、展開、および削除といった機能を備えています。

インストール方法

OSごとの インストール手順 を参考に実施してください。
また、この記事では minikube を利用して動作確認を行っています。

特徴

kappの特徴として、ドキュメント には、Diff stage と、 Apply stage という内容でまとめられています。

Diff stage

kapp deployを実行する際に、ファイルで指定されたリソースをKubernetesAPIに存在するリソースと比較します。その際、アノテーション(Annotations) であるkapp.k14s.io/versionedを利用することで、リソースをバージョン管理できます。
また、バージョン管理されたリソースが更新されると既存のリソースが新しく作成されます。
バージョン管理したいリソースに、アノテーションとして、kapp.k14s.io/versionedと値として空文字列を設定するだけで、リソースのバージョン管理ができます。

実際に試してみます。下記のようなConfigMapを備えたnginx.yamlを作成します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  annotations:
    kapp.k14s.io/versioned: ""
data:
  config-value: init-config
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:stable
          ports:
            - containerPort: 8080
          env:
            - name: TEST_CONFIG
              valueFrom:
                configMapKeyRef:
                  name: test-config
                  key: config-value

kappコマンドを使ってdeploymentを作成して、pod内の環境変数TEST_CONFIGを確認してみます。

$ kapp deploy -a nginx-sample -f ./nginx.yaml
Target cluster 'https://127.0.0.1:49154' (nodes: minikube)

Changes

Namespace  Name               Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    nginx-deployment   Deployment  -       -    create  -       reconcile  -   -
^          test-config-ver-1  ConfigMap   -       -    create  -       reconcile  -   -

Op:      2 create, 0 delete, 0 update, 0 noop
Wait to: 2 reconcile, 0 delete, 0 noop

Continue? [yN]: y

10:17:55AM: ---- applying 1 changes [0/2 done] ----
10:17:55AM: create configmap/test-config-ver-1 (v1) namespace: default
10:17:55AM: ---- waiting on 1 changes [0/2 done] ----
10:17:55AM: ok: reconcile configmap/test-config-ver-1 (v1) namespace: default
10:17:55AM: ---- applying 1 changes [1/2 done] ----
10:17:55AM: create deployment/nginx-deployment (apps/v1) namespace: default
10:17:55AM: ---- waiting on 1 changes [1/2 done] ----
10:17:55AM: ongoing: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:17:55AM:  ^ Waiting for generation 2 to be observed
10:17:55AM:  L ok: waiting on replicaset/nginx-deployment-85496bcc7b (apps/v1) namespace: default
10:17:55AM:  L ongoing: waiting on pod/nginx-deployment-85496bcc7b-2g5lm (v1) namespace: default
10:17:55AM:     ^ Pending: ContainerCreating
10:17:56AM: ongoing: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:17:56AM:  ^ Waiting for 1 unavailable replicas
10:17:56AM:  L ok: waiting on replicaset/nginx-deployment-85496bcc7b (apps/v1) namespace: default
10:17:56AM:  L ongoing: waiting on pod/nginx-deployment-85496bcc7b-2g5lm (v1) namespace: default
10:17:56AM:     ^ Pending: ContainerCreating
10:18:15AM: ok: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:18:15AM: ---- applying complete [2/2 done] ----
10:18:15AM: ---- waiting complete [2/2 done] ----

Succeeded

成功したので、kubectl execにて環境変数がどうなっているか確認します。

$ kubectl exec -it $(kubectl get pods -l app=nginx -o json | jq -r .items[0].metadata.name) -- env | grep TEST_CONFIG
TEST_CONFIG=init-config

ConfigMapで作成した値が環境変数TEST_CONFIGの値として設定されています。
次は、先ほど作成したnginx.yamlのConfigMapの値の部分だけ修正します。

data:
  config-value: update-config

再度、kapp deployを実行します。

$ kapp deploy -a nginx-sample -f ./nginx.yaml
Target cluster 'https://127.0.0.1:49154' (nodes: minikube)

Changes

Namespace  Name               Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    nginx-deployment   Deployment  2/2 t   30m  update  -       reconcile  ok  -
^          test-config-ver-2  ConfigMap   -       -    create  -       reconcile  -   -

Op:      1 create, 0 delete, 1 update, 0 noop
Wait to: 2 reconcile, 0 delete, 0 noop

Continue? [yN]: y

10:47:59AM: ---- applying 1 changes [0/2 done] ----
10:47:59AM: create configmap/test-config-ver-2 (v1) namespace: default
10:47:59AM: ---- waiting on 1 changes [0/2 done] ----
10:47:59AM: ok: reconcile configmap/test-config-ver-2 (v1) namespace: default
10:47:59AM: ---- applying 1 changes [1/2 done] ----
10:47:59AM: update deployment/nginx-deployment (apps/v1) namespace: default
10:47:59AM: ---- waiting on 1 changes [1/2 done] ----
10:47:59AM: ongoing: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:47:59AM:  ^ Waiting for generation 4 to be observed
10:47:59AM:  L ok: waiting on replicaset/nginx-deployment-85496bcc7b (apps/v1) namespace: default
10:47:59AM:  L ok: waiting on replicaset/nginx-deployment-5974d9b797 (apps/v1) namespace: default
10:47:59AM:  L ok: waiting on pod/nginx-deployment-85496bcc7b-2g5lm (v1) namespace: default
10:47:59AM:  L ongoing: waiting on pod/nginx-deployment-5974d9b797-cjs7v (v1) namespace: default
10:47:59AM:     ^ Pending
10:48:01AM: ongoing: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:48:01AM:  ^ Waiting for 1 unavailable replicas
10:48:01AM:  L ok: waiting on replicaset/nginx-deployment-85496bcc7b (apps/v1) namespace: default
10:48:01AM:  L ok: waiting on replicaset/nginx-deployment-5974d9b797 (apps/v1) namespace: default
10:48:01AM:  L ok: waiting on pod/nginx-deployment-85496bcc7b-2g5lm (v1) namespace: default
10:48:01AM:  L ongoing: waiting on pod/nginx-deployment-5974d9b797-cjs7v (v1) namespace: default
10:48:01AM:     ^ Pending: ContainerCreating
10:48:02AM: ok: reconcile deployment/nginx-deployment (apps/v1) namespace: default
10:48:02AM: ---- applying complete [2/2 done] ----
10:48:02AM: ---- waiting complete [2/2 done] ----

Succeeded

ConfigMapは新しいバージョンとして作成され、deploymentも更新されていることが確認できます。
kubectl execにて環境変数TEST_CONFIGがどうなっているか確認します。

$ kubectl exec -it $(kubectl get pods -l app=nginx -o json | jq -r .items[0].metadata.name) -- env | grep TEST_CONFIG
TEST_CONFIG=update-config

pod内の環境変数 TEST_CONFIG が変更されていることが確認できました。

kapp deployの実行時に、OpWait toが表示されます。
Op は差分の概要がわかる列で、create, update, delete, noopが表示されます。
Wait toはどのような条件で待機するのかをしますものですreconcileだとリソースが目的の状態になるまで待機します。
deleteは、削除されるまで待機します。 noopは、待機の条件なしとなります。

Apply stage

Apply stageでは、以下に示すような特徴が2つあります。これらについて説明していきます。

  • Apply順序の制御
  • Applyの待機

Apply順序の制御

kappには、特定の順序で変更が行われるためのアノテーションである kapp.k14s.io/change-groupkapp.k14s.io/change-rule が組み込まれています。
kapp.k14s.io/change-groupは、リソース変更を任意の名前のグループとしてまとめることができます。
kapp.k14s.io/change-ruleは、リソースの変更ルールを設定できます。change-groupと併用することで、グループごとに変更の順番を決めることができます。

Apply順序を試すRedisの サンプル がありますので、こちらを使って試してみます。サンプルは、下記の順序で構築していきます。

  1. プライマリのRedisの構築
  2. レプリカのRedisの構築
  3. プライマリとレプリカの同期チェック

それでは、実際に試してみます。サンプルソースを取得して、manifestがある対象のディレクトリに対して、kapp deployを実施します。

$ kapp deploy -a redis-ordering -f ./resource-ordering
Target cluster 'https://127.0.0.1:49154' (nodes: minikube)

Changes

Namespace  Name           Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    redis-primary  Deployment  -       -    create  -       reconcile  -   -
^          redis-primary  Service     -       -    create  -       reconcile  -   -
^          redis-replica  Deployment  -       -    create  -       reconcile  -   -
^          redis-replica  Service     -       -    create  -       reconcile  -   -
^          sync-check     Job         -       -    create  -       reconcile  -   -

Op:      5 create, 0 delete, 0 update, 0 noop
Wait to: 5 reconcile, 0 delete, 0 noop

Continue? [yN]: y

11:00:23AM: ---- applying 3 changes [0/5 done] ----
11:00:23AM: create deployment/redis-primary (apps/v1) namespace: default
11:00:23AM: create service/redis-replica (v1) namespace: default
11:00:23AM: create service/redis-primary (v1) namespace: default
11:00:23AM: ---- waiting on 3 changes [0/5 done] ----
11:00:23AM: ok: reconcile service/redis-replica (v1) namespace: default
11:00:23AM: ok: reconcile service/redis-primary (v1) namespace: default
11:00:23AM: ongoing: reconcile deployment/redis-primary (apps/v1) namespace: default
11:00:23AM:  ^ Waiting for generation 2 to be observed
11:00:23AM:  L ok: waiting on replicaset/redis-primary-64df9bf4dc (apps/v1) namespace: default
11:00:23AM:  L ongoing: waiting on pod/redis-primary-64df9bf4dc-djg8l (v1) namespace: default
11:00:23AM:     ^ Pending
11:00:23AM: ---- waiting on 1 changes [2/5 done] ----
11:00:23AM: ongoing: reconcile deployment/redis-primary (apps/v1) namespace: default
11:00:23AM:  ^ Waiting for 1 unavailable replicas
11:00:23AM:  L ok: waiting on replicaset/redis-primary-64df9bf4dc (apps/v1) namespace: default
11:00:23AM:  L ongoing: waiting on pod/redis-primary-64df9bf4dc-djg8l (v1) namespace: default
11:00:23AM:     ^ Pending: ContainerCreating
11:00:33AM: ok: reconcile deployment/redis-primary (apps/v1) namespace: default
11:00:33AM: ---- applying 1 changes [3/5 done] ----
11:00:34AM: create deployment/redis-replica (apps/v1) namespace: default
11:00:34AM: ---- waiting on 1 changes [3/5 done] ----
11:00:34AM: ongoing: reconcile deployment/redis-replica (apps/v1) namespace: default
11:00:34AM:  ^ Waiting for generation 2 to be observed
11:00:34AM:  L ok: waiting on replicaset/redis-replica-55c45464b8 (apps/v1) namespace: default
11:00:34AM:  L ongoing: waiting on pod/redis-replica-55c45464b8-srb4b (v1) namespace: default
11:00:34AM:     ^ Pending: ContainerCreating
11:00:34AM:  L ongoing: waiting on pod/redis-replica-55c45464b8-rj8pj (v1) namespace: default
11:00:34AM:     ^ Pending: ContainerCreating
....<省略>
11:00:41AM: ongoing: reconcile deployment/redis-replica (apps/v1) namespace: default
11:00:41AM:  ^ Waiting for 1 unavailable replicas
11:00:41AM:  L ok: waiting on replicaset/redis-replica-55c45464b8 (apps/v1) namespace: default
11:00:41AM:  L ok: waiting on pod/redis-replica-55c45464b8-srb4b (v1) namespace: default
11:00:41AM:  L ongoing: waiting on pod/redis-replica-55c45464b8-rj8pj (v1) namespace: default
11:00:41AM:     ^ Condition Ready is not True (False)
11:00:42AM: ok: reconcile deployment/redis-replica (apps/v1) namespace: default
11:00:42AM: ---- applying 1 changes [4/5 done] ----
11:00:42AM: create job/sync-check (batch/v1) namespace: default
11:00:42AM: ---- waiting on 1 changes [4/5 done] ----
logs | # waiting for 'sync-check--1-5wn94 > sync-check' logs to become available...
11:00:42AM: ongoing: reconcile job/sync-check (batch/v1) namespace: default
11:00:42AM:  ^ Waiting to complete (0 active, 0 failed, 0 succeeded)
11:00:42AM:  L ongoing: waiting on pod/sync-check--1-5wn94 (v1) namespace: default
11:00:42AM:     ^ Pending
11:00:43AM: ongoing: reconcile job/sync-check (batch/v1) namespace: default
11:00:43AM:  ^ Waiting to complete (1 active, 0 failed, 0 succeeded)
11:00:43AM:  L ongoing: waiting on pod/sync-check--1-5wn94 (v1) namespace: default
11:00:43AM:     ^ Pending: ContainerCreating
....<省略>
11:00:49AM: ok: reconcile job/sync-check (batch/v1) namespace: default
11:00:49AM:  ^ Completed
11:00:49AM: ---- applying complete [5/5 done] ----
11:00:49AM: ---- waiting complete [5/5 done] ----

Succeeded

kapp deployで出力された結果を見る限り、change-groupchange-ruleの指定した順番通りに実行されています。

Applyの待機

リソースタイプごとに待機動作に関するルールが組み込まれています。
サンプルがありますので、Deploymentリソースタイプの動作を確認します。
実際に試してみます。こちらも先ほど同様にサンプルソースを取得して、manifestがある対象のディレクトリに対して、kapp deployを実施します。

$ kapp deploy -a custom-wait -f ./deployment-with-custom-wait
Target cluster 'https://127.0.0.1:49154' (nodes: minikube)

Changes

Namespace  Name                         Kind        Conds.  Age  Op      Op st.  Wait to    Rs  Ri
default    deployment-with-custom-wait  Deployment  -       -    create  -       reconcile  -   -

Op:      1 create, 0 delete, 0 update, 0 noop
Wait to: 1 reconcile, 0 delete, 0 noop

Continue? [yN]: y

11:14:55AM: ---- applying 1 changes [0/1 done] ----
11:14:56AM: create deployment/deployment-with-custom-wait (apps/v1) namespace: default
11:14:56AM: ---- waiting on 1 changes [0/1 done] ----
11:14:56AM: ongoing: reconcile deployment/deployment-with-custom-wait (apps/v1) namespace: default
11:14:56AM:  ^ Waiting for generation 2 to be observed
11:14:56AM:  L ok: waiting on replicaset/deployment-with-custom-wait-86dcf88f5b (apps/v1) namespace: default
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-wf5jk (v1) namespace: default
11:14:56AM:     ^ Pending
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-tkvr4 (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-rlzlm (v1) namespace: default
11:14:56AM:     ^ Pending
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-jsxfw (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-hqhpg (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-h9vwm (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-h5n7z (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-fccnb (v1) namespace: default
11:14:56AM:     ^ Pending
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-7wg4q (v1) namespace: default
11:14:56AM:     ^ Pending: ContainerCreating
11:14:56AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-5mgxg (v1) namespace: default
11:14:56AM:     ^ Pending
11:14:57AM: ongoing: reconcile deployment/deployment-with-custom-wait (apps/v1) namespace: default
11:14:57AM:  ^ Waiting for at least 5 available replicas (currently 0 available)
11:14:57AM:  L ok: waiting on replicaset/deployment-with-custom-wait-86dcf88f5b (apps/v1) namespace: default
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-wf5jk (v1) namespace: default
11:14:57AM:     ^ Pending
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-tkvr4 (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-rlzlm (v1) namespace: default
11:14:57AM:     ^ Pending
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-jsxfw (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-hqhpg (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-h9vwm (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-h5n7z (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-fccnb (v1) namespace: default
11:14:57AM:     ^ Pending
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-7wg4q (v1) namespace: default
11:14:57AM:     ^ Pending: ContainerCreating
11:14:57AM:  L ongoing: waiting on pod/deployment-with-custom-wait-86dcf88f5b-5mgxg (v1) namespace: default
11:14:57AM:     ^ Pending
....<省略>
11:15:36AM: ok: reconcile deployment/deployment-with-custom-wait (apps/v1) namespace: default
11:15:36AM: ---- applying complete [1/1 done] ----
11:15:36AM: ---- waiting complete [1/1 done] ----

Succeeded

サンプルでは、apps-v1-deployment-wait-minimum-replicas-availableを50%と指定しています。
そのため、ちょっと分かりづらいですが、指定したレプリカ数の半数である5個作成時点で成功となりました。

まとめ

kappは、kubectlなどよく使われているKubernetes運用ツールをさらに便利に利用しやすくしたものと考えています。
ただ、それだけで今まで使い慣れてきたツールを変える必要があるかと言われると、ちょっと微妙なところがあります。kapp自体、Carvel toolsの1つにすぎす、単独では価値が分かりづらいです。
ここ に記載されていますように、Carvel toolsである kapp-cotroller, ytt, kbld などを組み合わせて利用することで Continuous Reconciliation と言われているアプリケーションのデプロイ自動化がより実現しやすくなるものと考えています。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1