k8sの設定管理ツール「kpt」を試してみる
はじめに
先日行われた Kubernetes Meetup Tokyo #31 の中で kpt というk8sの設定管理ツールの存在を知りました
googlecontainertools.github.io
まだ出来て日が浅いとのことで開発も進んでいるらしく、どのようなものか実際に使って試してみました
kptとは
公式ドキュメントのFAQ に他のツールとの違いなどが書かれています
- 他のツールとどう違うか?
- 設定パッケージをコードとしてではなく、Kubernetesリソースモデルに準拠したYAML/JSONオブジェクトとして表す
- なぜテンプレートやDSLでないか?
- kubectl、kustomizeなどのk8sプロジェクトで開発されたツールと同じ書き方ができる
インストール
実際に動かしてみます
こちら からバイナリをダウンロードします
MacだとHomebrewでも入れられますが、6/9時点ではHomebrewがv0.27.0に対して、上記のバイナリがv0.29.0だったため、今回は最新版が使える方で導入しました
$ kpt version v0.29.0
pkgの作成
サンプルパッケージを作ってみます
kpt pkg init
でパッケージを作ります
$ mkdir kpt-sample-pkg
$ kpt pkg init kpt-sample-pkg
writing kpt-sample-pkg/Kptfile
writing kpt-sample-pkg/README.md
kpt-sample-pkg
ディレクトリを見るとKptfile
というものが出来ました
apiVersion: kpt.dev/v1alpha1 kind: Kptfile metadata: name: kpt-sample-pkg packageMetadata: shortDescription: sample description
kptで管理するリソース作成
今回のサンプルではnginxイメージのdeploymentとClusterIPのserviceをパッケージに含めます
(以下kpt-sample-pkg
ディレクトリで作業)
↓のdeployment.yaml
とservice.yaml
を作成します
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:1.18.0 name: nginx
service.yaml
apiVersion: v1 kind: Service metadata: labels: app: nginx name: nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: nginx
setter/substitutionの作成
kptで値を書き換えるよう、setter
/substitution
というものを作ります
setterの作成にはkpt cfg create-setter
を利用します
$ kpt cfg create-setter . replicas 2 --field "spec.replicas" --set-by "package-default" --description "replicas" --type integer
spec.replicas
の値についてsetterを作成しました
set-by/descriptionに加えて、値がintegerであることもオプションで指定しています
setterはOpenAPIに基づいて定義されるようです
Kptfileが書き換わったので差分を確認しておきます
--- Kptfile +++ Kptfile @@ -4,3 +4,13 @@ metadata: name: kpt-sample-pkg packageMetadata: shortDescription: sample description +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: replicas + type: integer + x-k8s-cli: + setter: + name: replicas + value: "2" + setBy: package-default --- deployment.yaml +++ deployment.yaml @@ -5,7 +5,7 @@ metadata: app: nginx name: nginx spec: - replicas: 2 + replicas: 2 # {"$kpt-set":"replicas"} selector: matchLabels: app: nginx
Kptfile
にsetterの情報が、deployment.yaml
のsetter対象であるspec.replicas
の部分に何やらコメントが追記されています
続いてimageを指定する部分もsetter化します
imageはnginx:1.18.0
のようにイメージ名:イメージタグ
の形式になっているため、まずはそれぞれをsetterとして定義します
$ kpt cfg create-setter . image-setter nginx --field "none" --set-by "package-default" --description "image name" $ kpt cfg create-setter . tag-setter 1.18.0 --field "none" --set-by "package-default" --description "image tag version"
作成したsetter(image-setter
とtag-setter
)を利用してspec.containers.image
を管理するために、substitutionを作成します
substitutionの作成にはkpt cfg create-subst
を利用します
$ kpt cfg create-subst . image-tag --field-value nginx:1.18.0 --pattern \${image-setter}:\${tag-setter}
ちなみに、最初のkpt cfg create-setter
はやらなくても自動(推測して)で作ってくれますが、set-byやdescriptionは埋められないので明示的に作りました
再度差分を確認すると、
--- Kptfile +++ Kptfile @@ -14,3 +14,27 @@ openAPI: name: replicas value: "2" setBy: package-default + io.k8s.cli.setters.image-setter: + description: image name + x-k8s-cli: + setter: + name: image-setter + value: nginx + setBy: package-default + io.k8s.cli.setters.tag-setter: + description: image tag version + x-k8s-cli: + setter: + name: tag-setter + value: 1.18.0 + setBy: package-default + io.k8s.cli.substitutions.image-tag: + x-k8s-cli: + substitution: + name: image-tag + pattern: ${image-setter}:${tag-setter} + values: + - marker: ${image-setter} + ref: '#/definitions/io.k8s.cli.setters.image-setter' + - marker: ${tag-setter} + ref: '#/definitions/io.k8s.cli.setters.tag-setter' --- deployment.yaml +++ deployment.yaml @@ -15,5 +15,5 @@ spec: app: nginx spec: containers: - - image: nginx:1.18.0 + - image: nginx:1.18.0 # {"$kpt-set":"image-tag"} name: nginx
replicasのときと同様にKptfile
とdeployment.yaml
が更新されました
作成したpkgをgit push
kptのpkgはgitで管理を行うため、gitへ上げておきます
kptではブランチ名でも管理可能ですが、バージョン管理できるようv0.1.0
のタグも打っておきます
この時点でのサンプルパッケージ
GitHub - sminamot/kpt-sample-pkg at v0.1.0
作成したpkgの利用
さきほど作ったkpt-sample-pkg
パッケージを実際に使ってみます
pkgの取得
v0.1.0
のバージョンを指定して取得します
$ kpt pkg get https://github.com/sminamot/kpt-sample-pkg.git@v0.1.0 ./ fetching package / from https://github.com/sminamot/kpt-sample-pkg to kpt-sample-pkg
取得したpkg情報を参照
$ kpt pkg desc /Users/sminamot/Documents/kpt-sample-pkg/Kptfile PACKAGE NAME DIR REMOTE REMOTE PATH REMOTE REF REMOTE COMMIT kpt-sample-pkg /Users/sminamot/Documents/kpt-sample-pkg https://github.com/sminamot/kpt-sample-pkg / v0.1.0 e94562c
setterの指定
setterの値を書き換えてみます
setterの一覧を確認
$ kpt cfg list-setters . NAME VALUE SET BY DESCRIPTION COUNT image-setter nginx package-default image name 1 replicas 2 package-default replicas 1 tag-setter 1.18.0 package-default image tag version 1 SUBSTITUTION PATTERN SETTERS image-tag ${image-setter}:${tag-setter} [image-setter,tag-setter]
replicas
とtag-setter
を書き換える
$ kpt cfg set . replicas 3 $ kpt cfg set . tag-setter 1.19.0
$ kpt pkg diff diff /var/folders/hf/s2x0n1yd7fgdptq9xp4dsf3c0000gn/T/kpt-089821092/deployment.yaml /var/folders/hf/s2x0n1yd7fgdptq9xp4dsf3c0000gn/T/kpt-029525683/deployment.yaml 8c8 < replicas: 3 # {"$kpt-set":"replicas"} --- > replicas: 2 # {"$kpt-set":"replicas"} 18c18 < - image: nginx:1.19.0 # {"$kpt-set":"image-tag"} --- > - image: nginx:1.18.0 # {"$kpt-set":"image-tag"}
書き換えたyamlはkubectlでそのままデプロイ可能です
$ kubectl apply -f . deployment.apps/nginx created service/nginx created
ちなみにreplicasのsetter定義時にintegerであることを指定したので、文字列などを設定しようとすると怒られます
$ kpt cfg set . replicas hoge set 0 fields Error: The input value doesn't validate against provided OpenAPI schema: validation failure list: replicas in body must be of type integer: "string"
今回の例ではv0.1.0
しか作成しませんでしたが、v0.2.0
をリリースした場合に利用する側で更新するには、
$ kpt pkg update kpt-sample-pkg@v0.2.0
と実行すればOKです
その他の機能
live
kptのパッケージをデプロイするためのサブコマンド
パッケージが管理するリソースを追跡するために最初に kpt live init
を実施してテンプレートリソースを作ります
$ kpt live init . $ tree . . ├── Kptfile ├── README.md ├── deployment.yaml ├── inventory-template.yaml └── service.yaml 0 directories, 5 files # inventory-template.yamlというのができてる
これによってstatusの制御やapply時の自動pruneが行われるようになります
kpt live preview
で実際にデプロイされるリソースを確認
$ kpt live preview . configmap/inventory-e00bb1dd created (preview) service/nginx created (preview) deployment.apps/nginx created (preview) 3 resource(s) applied. 3 created, 0 unchanged, 0 configured (preview) 0 resource(s) pruned, 0 skipped (preview)
kpt live apply
でデプロイ
reconcile-timeoutオプションを指定することで作成されたpodが利用可能になるまで待機してくれます
(公式Docでは--wait-for-reconcile
オプションを指定するようになってますが、--wait-timeout
と合わせて--reconcile-timeout
オプションに統合されたようです→関連Issue)
$ kpt live apply --reconcile-timeout=15m . configmap/inventory-e00bb1dd created service/nginx created deployment.apps/nginx created 3 resource(s) applied. 3 created, 0 unchanged, 0 configured configmap/inventory-e00bb1dd is NotFound: Resource not found service/nginx is NotFound: Resource not found deployment.apps/nginx is NotFound: Resource not found configmap/inventory-e00bb1dd is Current: Resource is always ready service/nginx is Current: Service is ready deployment.apps/nginx is InProgress: Available: 0/3 deployment.apps/nginx is InProgress: Available: 1/3 deployment.apps/nginx is InProgress: Available: 2/3 deployment.apps/nginx is Current: Deployment is available. Replicas: 3 all resources has reached the Current status 0 resource(s) pruned, 0 skipped
また、--output
オプションにtable
を指定するとより見やすい形式(色も付く)で表示されます
$ kpt live apply --reconcile-timeout=15m --output table . NAMESPACE RESOURCE ACTION STATUS CONDITIONS AGE MESSAGE default ConfigMap/inventory-e00bb1dd Created Current <None> 4s Resource is always ready default Service/nginx Created Current <None> 4s Service is ready default Deployment/nginx Created Current Available,Progressing 4s Deployment is available. Replicas: 3 default └─ ReplicaSet/nginx-6fd78f555b Current <None> 4s ReplicaSet is available. Replicas: 3 default ├─ Pod/nginx-6fd78f555b-6rgfd Current Initialized,Ready,ContainersReady,PodSch 4s Pod is Ready default ├─ Pod/nginx-6fd78f555b-8lf46 Current Initialized,Ready,ContainersReady,PodSch 4s Pod is Ready default └─ Pod/nginx-6fd78f555b-mlqr8 Current Initialized,Ready,ContainersReady,PodSch 4s Pod is Ready
ただ、このreconcile機能ですが、v0.29.0時点ではタイムアウトで落ちてもexit statusが0のため、改善されないとCIなどでは使えなさそう
cfg fmt
kpt cfgのサブコマンドにfmt
という、k8sのyamlファイルのフォーマット機能があります
これはkptで管理するリソースには限らず、既存のyamlに適用することができます
例えば以下のようなpod.yamlがあった場合(apiVersion/kindが下にあったり、インデントが統一されていない)に、
metadata: labels: run: nginx name: nginx spec: containers: - image: nginx:1.19.0 name: nginx dnsPolicy: ClusterFirst restartPolicy: Never kind: Pod apiVersion: v1
kpt cfg fmt
をかけると、
apiVersion: v1 kind: Pod metadata: name: nginx labels: run: nginx spec: restartPolicy: Never dnsPolicy: ClusterFirst containers: - name: nginx image: nginx:1.19.0
このように整形してくれます
kptへの移行はすぐに出来ないかもしれませんが、フォーマッタだけ導入するものアリかもしれません
まとめ
ドキュメントが最新バージョンのものに追いついていなかったり、機能的に物足りない点が多いですが、今後の改善に期待しましょう
今週末6/13(土)に開催される KubeFest Tokyo 2020 にも kptに関するLT があるようです
今回紹介出来なかった機能についても説明がありそうなので楽しみです😃