Tanzu Application Platform

開発チームが使う Namespace の払い出し作業を楽にしよう – Tanzu Application Platform 1.4 から提供する Namespace Provisioner 機能とは

この記事では、VMware Tanzu Application Platform (以降TAP)1.4 から提供している Namespace Provisioner 機能について紹介します。

TAP が目指しているのは、開発者の皆様にとっての面倒な作業を減らし、プラットフォームチームにとっての運用周りの手間を減らすことにあります。
手間を減らす機能としてはこれまでに Service Bindings などの機能を紹介していますが、今回は TAP 1.4 から提供している Namespace Provisioner 機能について紹介します。
(ちなみに、そもそも TAP をインストールできず TAP の Namespace Provisioner 機能も含め試せない場合は、こちらのブログを参考に TAP をインストールしてみてください。)

Namespace Provisioner は、プラットフォームチームがアプリの Workload が意図通りに機能するために必要なリソースと適切な権限を備えた Namespace を安全かつ自動化された方法でプロビジョニングするための機能です。TAP 1.4 からデフォルトで利用できるようになっており、この機能を使うことで Kubernetes (K8s) に詳しくないプラットフォームエンジニアでも共有 K8s クラスター内の複数の開発者用 Namespace の払い出しを簡単に実現できます。

まず、TAP 1.4 前のバージョンではどのような手順で開発者用 Namespace を払い出しているかをみてみましょう。
今回は demo という名前の Namespace に Java アプリの Workload をデプロイするとします。

参考ドキュメントは下記となります。
https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.3/tap/GUID-set-up-namespaces.html

下記の Step1 ~ Step3 の作業はプラットフォームチーム側の作業になります。

Step1. demo という名前の Namespace を作成します。

$kubectl create ns demo

Step2. この namespace 上で Workload を作成時にコンテナイメージを <Container Repository> から pullしたり、pushできるように Secret を作成します。
(今回は Azure ACR サーバーにアクセスすることを例にしています)

tanzu secret registry add registry-credentials --server ${ACR_SERVER} --username ${ACR_USERNAME} --password ${ACR_PASSWORD} --namespace demo

Step3. demo Namespace 上に RBAC の設定を行います。

下記のように rbac.yaml を作成し、kubectl apply コマンドで実行します。

$ cat <<EOF > ${HOME}/workspace/tap-install/rbac.yaml
apiVersion: v1
kind: Secret
metadata:
  name: tap-registry
  annotations:
    secretgen.carvel.dev/image-pull-secret: ""
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: e30K
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
secrets:
- name: registry-credentials
imagePullSecrets:
- name: registry-credentials
- name: tap-registry
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: default-permit-deliverable
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: deliverable
subjects:
- kind: ServiceAccount
  name: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: default-permit-workload
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: workload
subjects:
- kind: ServiceAccount
  name: default
EOF

kubectl apply -f ${HOME}/workspace/tap-install/rbac.yaml -n demo
Step4. 開発者は上記の Step3 まで経て出来上がった Namespace をもらって、自分で開発したアプリコードを demo Namespace 上にデプロイします。 以下は Java アプリをデプロイする例となります。
(ここは開発者の作業範囲になります)
tanzu apps workload apply tanzu-java-web-app \
--app tanzu-java-web-app \
--git-repo https://github.com/gordon-jin/tanzu-java-web-app \
--git-branch main \
--type web \
--annotation autoscaling.knative.dev/minScale=1 \
-n demo \
-y
また、デプロイ済みのアプリの状態は下記のコマンドで確認できます。
(Knative Services が Ready になれば、問題なくアプリにアクセスできます。)
$ tanzu apps wld get tanzu-java-web-app -n demo
? Overview
name: tanzu-java-web-app
type: web

? Source
type: git
url: https://github.com/gordon-jin/tanzu-java-web-app
branch: main

? Supply Chain
name: source-to-url

RESOURCE READY HEALTHY TIME OUTPUT
source-provider True True 7d1h GitRepository/tanzu-java-web-app
image-provider True True 7d1h Image/tanzu-java-web-app
config-provider True True 7d1h PodIntent/tanzu-java-web-app
app-config True True 7d1h ConfigMap/tanzu-java-web-app
service-bindings True True 7d1h ConfigMap/tanzu-java-web-app-with-claims
api-descriptors True True 7d1h ConfigMap/tanzu-java-web-app-with-api-descriptors
config-writer True True 7d1h Runnable/tanzu-java-web-app-config-writer

? Delivery
name: delivery-basic

RESOURCE READY HEALTHY TIME OUTPUT
source-provider True True 7d1h ImageRepository/tanzu-java-web-app-delivery
deployer True True 7d1h App/tanzu-java-web-app

? Messages
No messages found.

? Pods
NAME READY STATUS RESTARTS AGE
tanzu-java-web-app-00001-deployment-db6bd4497-hjtmn 2/2 Running 0 7d1h
tanzu-java-web-app-build-1-build-pod 0/1 Completed 0 7d1h
tanzu-java-web-app-config-writer-pgkzb-pod 0/1 Completed 0 7d1h

? Knative Services
NAME READY URL
tanzu-java-web-app Ready https://tanzu-java-web-app.demo.172.17.203.60.sslip.io

To see logs: "tanzu apps workload tail tanzu-java-web-app --namespace demo"
いかがでしょうか?
開発者が利用する 1 個の Namespace を払い出すたびにプラットフォームチームは Step1 ~ Step3 の面倒なことを繰り返しながら実行する必要があります。
特に Step3 のような長い Yaml ファイルを Namespace を払い出すたびに使う必要があります。

 

では、TAP 1.4 でこの作業がどのように楽になるかをみてみましょう。

Step1. demo namespace を作成します。

$kubectl create ns demo

Step2. Secret を作成
(こちらの Step は最初の一回のみ実行する必要があります )

tanzu secret registry add registry-credentials --server ${ACR_SERVER} --username ${ACR_USERNAME} --password ${ACR_PASSWORD} --namespace tap-install --export-to-all-namespaces -y

Step3. 払い出す Namespace にラベルを設定します。

kubectl label namespaces demo apps.tanzu.vmware.com/tap-ns=""
これで作成済みの demo Namespace を開発者に渡すことができます。
二回目以降は Step2 も省くことができるので、
「Step1. namespace を作成」、「Step2. 払い出す Namespace にラベルを設定する」だけで新しい Namespace を簡単に払い出すことができます。

具体例でみる Namespace Provisioner 機能

さて、上の説明だけではイメージがつかないと思うので、実際の TAP 1.4 を使い Namespace の払い出しと払い出された Namespace 上にアプリの Workload をデプロイしてみたいと思います。

(下記の Step1 と Step2 はプラットフォームチーム側の作業になります)

Step1. dev01 という名前の Namespace を作成します。

$ kubectl create ns dev01
namespace/dev01 created

Step2. dev01 Namespace にラベルを設定します。
(今回は、二回目以降の Namespace 払い出しの作業になるため 「Secret 作成」の作業は省きます)

$ kubectl label namespaces dev01 apps.tanzu.vmware.com/tap-ns=""
namespace/dev01 labeled

ここからは開発者の作業になります。

tanzu apps workload apply tanzu-java-web-app \
--app tanzu-java-web-app \
--git-repo https://github.com/gordon-jin/tanzu-java-web-app \
--git-branch main \
--type web \
--annotation autoscaling.knative.dev/minScale=1 \
-n dev01 \
-y

しばらく経つと TAP GUI から tanzu-java-web-app という workload が dev01 Namespace 上にデプロイされているのを確認できます。

該当 workload の URL を確認し、アプリにアクセスしてみます。

$ kubectl get ksvc -n dev01
NAME URL LATESTCREATED LATESTREADY READY REASON
tanzu-java-web-app https://tanzu-java-web-app.dev01.172.17.203.60.sslip.io tanzu-java-web-app-00001 tanzu-java-web-app-00001 True
$ curl -sk https://tanzu-java-web-app.dev01.172.17.203.60.sslip.io
welcome tanzu and TAP

いかがでしょうか?
Namespace の払い出し作業がかなりシンプルになってるのを確認できると思います。

Namespace Provisioner 機能の仕組み

では、Namespace Provisioner 機能の仕組みについて少し説明します。
実際、apps.tanzu.vmware.com/tap-ns=”” というラベルを新しく作成した Namespace に設定すると裏でなにが起きているかをみてみましょう。

$ kubectl get secrets,serviceaccount,rolebinding,configmap -n dev01
NAME TYPE DATA AGE
secret/default-token-xm7pt kubernetes.io/service-account-token 3 38s
secret/registries-credentials kubernetes.io/dockerconfigjson 1 14s

NAME SECRETS AGE
serviceaccount/default 2 38s

NAME ROLE AGE
rolebinding.rbac.authorization.k8s.io/default-permit-deliverable ClusterRole/deliverable 14s
rolebinding.rbac.authorization.k8s.io/default-permit-workload ClusterRole/workload 14s

NAME DATA AGE
configmap/kube-root-ca.crt 1 38s

上記のように一覧のリソースが自動的に作成されているのを確認できます。

Namespace Provisioner のアーキテクチャについてもみてみましょう。

Namespace Provisioner のアーキテクチャ図:
Namespace Provisioner は、tap-namespace-provisioning という Namespace にインストールされる Carvelアプリケーションで構成されています。

$ kubectl get pods -n tap-namespace-provisioning
NAME READY STATUS RESTARTS AGE
controller-manager-6dc566c644-mbnlf 1/1 Running 0 2d5h

Provisioner アプリケーションは ytt を使用してリソースのセットを複数の Namespace にインストールするようにテンプレート化しています。

tap-namespace-provisioning の Namespace にある desired-namespaces という ConfigMap は
どの Namespace にリソースを配置するかを示す宣言的な方法を提供します。

$ kubectl get configmap -n tap-namespace-provisioning
NAME DATA AGE
controller-config 1 2d5h
desired-namespaces 1 2d5h
expansion-template 1 2d5h
kube-root-ca.crt 1 2d5h
ns-selector-config 1 2d5h
provisioner-ctrl 1 2d5h
provisioner-ctrl-change-5jdlp 1 3m58s
provisioner-ctrl-change-7gcv2 1 24m
provisioner-ctrl-change-f7vnv 1 14m
provisioner-ctrl-change-nr6ph 1 90s
provisioner-ctrl-change-tchjz 1 34m
$ kubectl describe configmap desired-namespaces -n tap-namespace-provisioning
Name: desired-namespaces
Namespace: tap-namespace-provisioning
Labels: kapp.k14s.io/app=1678235192605669950
kapp.k14s.io/association=v1.5c8b25dcf919f5c82c8b6da7f53b1c32
Annotations: doc:
This resources has been created for you as part of the necessary resources for running your cluster supply chain. You are free to make cha...
kapp.k14s.io/change-group: namespace-provisioner.apps.tanzu.vmware.com/delete-after-app
kapp.k14s.io/create-strategy: fallback-on-update
kapp.k14s.io/identity: v1;tap-namespace-provisioning//ConfigMap/desired-namespaces;v1
kapp.k14s.io/original:
{"apiVersion":"v1","data":{"namespaces.yaml":"#@data/values\n---\nnamespaces:\n"},"kind":"ConfigMap","metadata":{"annotations":{"doc":"Thi...
kapp.k14s.io/original-diff-md5: 58e0494c51d30eb3494f7c9198986bb9
namespace-provisioner.apps.tanzu.vmware.com/no-overwrite:

Data
====
namespaces.yaml:
----
#@data/values
---
namespaces:
- name: demo
- name: dev01


BinaryData
====

Events: <none>

先程、ラベルを設定した dev01 の Namespace も確認できます。

最後に kapp CLI を使って Namespace Provisioner によって作成されたリソースを確認します。

$ kapp inspect -n tap-namespace-provisioning -a provisioner-ctrl 
Target cluster 'https://172.17.203.54:6443' (nodes: tkg-gj1-full2-control-plane-vrxmx, 3+)

Resources in app 'provisioner-ctrl'

Namespace Name Kind Owner Rs Ri Age 
demo default ServiceAccount kapp ok - 2d 
^ default-permit-deliverable RoleBinding kapp ok - 2d 
^ default-permit-workload RoleBinding kapp ok - 2d 
^ registries-credentials Secret kapp ok - 2d 
dev01 default ServiceAccount kapp ok - 57m 
^ default-permit-deliverable RoleBinding kapp ok - 57m 
^ default-permit-workload RoleBinding kapp ok - 57m 
^ registries-credentials Secret kapp ok - 57m

Rs: Reconcile state
Ri: Reconcile information

8 resources

Succeeded

まとめ

ここまで TAP 1.4 で提供している Namespace Provisioner 機能について紹介しました。
この機能を利用することで、プラットフォームチームは必要なリソースと適切な権限を備えた Namespace をかなりシンプルに払い出すことができ、開発者はその Namespace を使ってアプリの Workload を K8s へデプロイできます。

VMware ブログでは、引き続き TAP の新機能を続々と紹介させていただきます。