---
title: Tanzu Application Platform 1.2 on Azure ハンズオン
tags: ["Kubernetes", "Cartographer", "AKS", "Tanzu", "TAP", "Knative", "Azure", "Tekton", "Service Binding", "Code Server", "Contour", "cert-manager"]
categories: ["Dev", "CaaS", "Kubernetes", "TAP"]
date: 2022-09-01T17:38:20Z
updated: 2022-09-02T00:28:00Z
---

Tanzu Application Platform (TAP)をインストールし、様々な機能を試すハンズオンです。

TAPの大まかな構成要素を次の図で表すと、

![alt_text](https://lh4.googleusercontent.com/5Ic7iU8TWPAdPpzLmzfDY4KMnDYnb8Apuuo7iQ6KynOrM_Hv1Z2-W-g_iOf3bgZ2ztYls2djLG1vMYwZvXr0vdP4q_7Kdfeatnz1wVIjMwycPnWrIwpmc4Ieerc0_Zi8FXNQwLUSgYtqEqnib1YvQv4)

本ハンズオンでカバーするのは次の黄色の部分のみです。

![alt_text](https://lh6.googleusercontent.com/6pTMmvySDY0ePk76m3joYRMuOPfQPbLKtc-O8LKSjsUOPdcr7Lsl4is46ad6CLCAWfjITBjjUxX_1W7xh9UCpZen2c7Bc6MSk7v6zxscHoMQQNmn74eAg3ITeiYED3-5mNKIndC8RtkYifl7KMVIzh4)

本ハンズオンではAzure Kubernetes Service (AKS)にTAP 1.2をインストールします。

以降、[O] がつく節はPlatform Operatorが担当する作業です。[D] がつく節はApp Developerが担当する作業です。

ハンズオン参加者は事前に与えられたハンズオン作業環境 (VS Code Server) にアクセスしてください。

> ℹ️ ハンズオン環境をAKS上に作成する方法は[こちら](https://docs.google.com/document/d/1_cDGvYR4F39oe9C-azkh_GRcuGRsXPIKbU2v39AqvRg)を参照してください。
>
> ハンズオン環境をローカルで実行したい場合は、以下で実行できます(未検証)。
>
> ```
> docker run \
>   --name code-server \
>   --rm \
>   -p 3000:3000 \
>   -e PASSWORD=password  \
>   -e PORT=3000 \
>   -e NAMESPACE=handson-00 \
>   ghcr.io/making/code-server@sha256:3b671ae5a4e991e72eda10253b6edc945d52ec49b4a246f3034d4ab93457cee2
> ```

次のようなダイアログが表示されたら"Yes, I trust the authors"をクリックしてください。

![alt_text](https://lh6.googleusercontent.com/WZGRfdRO8HfjHfgND7jb2FN202z3VnzkuGtob2V-7g6NenexDQTcq0FF-KOXL0OQkaApBKAzEZcoSK1dgjeEqa9JDG42RAEDTLfboQP_54KjwG54I1bEkxJMkCDnhe45aTjHpJMbLdC7M-zkX1bWF_M)

<br>

**目次**
<!-- toc -->

### Tanzu Application Platformのインストール (Iterate Profile)

まずはイテレーション開発用のiterate profileをインストールします。Iterate ProfileはTAPの全構成要素のうち、次の図の部分のみをインストールします。


![alt_text](https://lh4.googleusercontent.com/9dMOrYWnowau_v8ejjav1zr176cNFBa84ZIfyyf4_hZl-98fqAqNQYEi3S98tJ53Set6Qg0FoKToL6Do3kRXoUhy6Il2SuG-vIrwLseZUzZuTp3_TgNUKjtiHudA-zlH95r_S9EtffPwN4PODKcgZXk "image_tooltip")

#### [O] リソースグループの作成

TAPをインストールするためのAzureリソースグループを作成します。

![alt_text](https://lh4.googleusercontent.com/sRIbzT919c8AE8c0TbV-i9qDAVEaoicnLjOWhpyylaB3xqlvv4i06vSOkCGIDe5_B6L-apERwtiqDjPi9CY6BzGHjkwaFwXZB6rSXn6HOxBpIpeDDshY7RaTiJdJX-4tpmwd8a9_9uU4MERnOyQ4w54)

VS Codeのメニューから”Terminal” -> “New Terminal”を選択し、作業用のターミナルを開いてください。

まずはAzureにログインします。次のコマンドを実行してください。

```
az login --allow-no-subscriptions
```

ログインのURLとコードが出力されるので、ブラウザで開いてコードを入力し、


![alt_text](https://lh5.googleusercontent.com/Mh4M-GmLwOyNBrD6eXdvIv9kEjmqkY8eJSdWJQSyi7mdAmpWIoF_2_T8CG5IoAspcRtBrwwcx4t0NHVEeoYgwepaIaz0V0viMutr-lqAKqfx288vc4upci8kWybIZowTMYUrUWnJZXUq0S_4BaLKaYE)


リソースグループ名は”tap-${NAMESPACE}”とします。次のコマンドを実行し、リソースグループを作成してください。

環境変数`NAMESPACE`に値が入っていない場合は任意の値を設定してください。

```
az group create --name tap-${NAMESPACE} --location japaneast
```


#### [O] Azure Container Registryインスタンスの作成

次にAzure Container Registry (ACR)のインスタンスを作成します。このRegistryにはTAPにデプロイするアプリの

* コンテナイメージ
* マニフェスト
* ソースコード

が格納されます。

次のコマンドを実行してください。

```
ACR_NAME=tap${RANDOM}
az acr create --resource-group tap-${NAMESPACE} \
  --location japaneast \
  --name ${ACR_NAME} --sku standard \
  --admin-enabled true
```

ACRへの接続情報を変数に設定します。次のコマンドを実行してください。これらの変数はTAPインストール時に使用します。

```
ACR_SERVER=${ACR_NAME}.azurecr.io
ACR_USERNAME=${ACR_NAME}
ACR_PASSWORD=$(az acr credential show --name ${ACR_NAME} --resource-group tap-${NAMESPACE} --query 'passwords[0].value' --output tsv)
```


次のコマンドで、接続情報が正しいことを試します。試した後は生成されたconfigファイルを削除します。

```
docker login ${ACR_SERVER} -u ${ACR_USERNAME} -p ${ACR_PASSWORD}
rm -rf ${HOME}/.docker/config.json
```

> **TODO**
> 今回はadminユーザーを使用しているが、本来は使用すべきでない。要検討。

#### [O] Azure Kubernetes Serviceクラスタの作成

次にAzure Kubernetes Service (AKS)のK8sクラスタを作成します。このK8sクラスタにTAPをインストールします。

次のコマンドを実行してください。

```
az aks create \
  --resource-group tap-${NAMESPACE} \
  --location japaneast \
  --name tap-sandbox \
  --node-count 2 \
  --enable-cluster-autoscaler \
  --min-count 1 \
  --max-count 10 \
  --node-vm-size standard_f4s_v2 \
  --load-balancer-sku standard \
  --network-plugin kubenet \
  --network-policy calico \
  --zones 1 2 3 \
  --generate-ssh-keys \
  --enable-aad
```


次のコマンドでK8sクラスタへの接続情報を取得してください。

```
az aks get-credentials --resource-group tap-${NAMESPACE} --name tap-sandbox --admin --overwrite-existing
```

次のコマンドでK8sクラスタへ接続できることを確認してください。

```
kubectl cluster-info
```

![alt_text](https://lh6.googleusercontent.com/Qe1XSiEemevVllnAeJ80-S5sSG3Ze3Kk-_f6td8ozDS16EplT0T4d4tkmYT7OW_JP-2HZL4wU5ToXflQNcdPEoAtTGmBelrzOiOfTPCN9u8xi3u4pQXem30vTLl1OaQ70S3vAcRdCqzyZNdeQEqgV1g)

#### [O + D] EULAのAgree

[Tanzu Network](https://network.tanzu.vmware.com/) のアカウントがない場合は作成してください。 

Tanzu Networkにログインして、次のプロダクトのELUAをAgreeしてください。

* [Tanzu Application Platform](https://network.tanzu.vmware.com/products/tanzu-application-platform/)
* [Cluster Essentials for VMware Tanzu](https://network.tanzu.vmware.com/products/tanzu-cluster-essentials/)

Agreeしていない場合は、 "Click here to sign the EULA" をクリックしてください。

#### [O + D] Tanzu CLIのインストール


TAPをインストールしたり、TAPにアプリをデプロイするために使用するTanzu CLIをインストールします。Tanzu CLIは[Tanzu Network](https://network.tanzu.vmware.com/products/tanzu-application-platform/)からダウンロードできます。

CLIからTanzu CLIなどをダウンロードするために、API TOKENを取得します。

[https://network.tanzu.vmware.com/users/dashboard/edit-profile](https://network.tanzu.vmware.com/users/dashboard/edit-profile) (要ログイン)

下の図の"REQUEST NEW REFRESH TOKEN"をクリックし、API TOKENを取得してください。

![alt_text](https://lh4.googleusercontent.com/vsABG53iZz8b9f35pSDEor6NqcY4lncNeUaxu_6gxzmsWYep4g2CxOCAVXmCFjTIv7Kt3xmV0nrbh0KoWKNzn6F84MwAa2l6RGpvmYBivv-iOMdBecpKt5j03OUeb4fbqm7uzMAw1HD7eqCFzfxwfeI)

取得したAPI TOKENを使用して、次のコマンドを実行してください。

```
API_TOKEN=......
pivnet login --api-token=${API_TOKEN}
```


次のコマンドを実行して、Tanzu CLIをダウンロードし、インストールしてください。

```
pivnet download-product-files --product-slug='tanzu-application-platform' --release-version='1.2.1' --glob='tanzu-framework-linux-amd64.tar'
tar xvf tanzu-framework-*-amd64.tar
mkdir -p ${HOME}/.local/bin
install cli/core/*/tanzu-core-*_amd64 ${HOME}/.local/bin/tanzu
```


次のコマンドを実行して、CLIのversionを確認してください。

```
tanzu version
```

![alt_text](https://lh3.googleusercontent.com/ewJQYDzfD7pUi76uLNetMq3pAs6vXrtgBQsTmTso0LaRF8UCpKeMZO2XlrWPeIKlwx8PgXy3lv7Jpqcqq4TAs64Pauihr8G10ECsT4kBv5dmpa4t_IGRk5DqiZJcVYhLR0YpIYSYy2Kfb3dliWs23YY)


次のコマンドを実行してTAPで使用するプラグインをインストールしてください。

```
tanzu plugin install --local cli all
```

![alt_text](https://lh3.googleusercontent.com/TJb4sKxUCvO8CIeqgBtbfUjMS8GS1w7przaYqKSnyOH_yid1dHVOCVDFlUaPikUVBXBMEIe81v2BuW7OQhsOQvsi7fTKIEbcMOooHtJy-VbNErImVVCODaY7D4g4nLhW_ZqH6FA5H5lY1PupbrzdqrU)


不要なファイルは削除してください。

```
rm -f tanzu-framework-linux-amd64.tar
rm -rf cli
```

#### [O] Cluster Essentials for VMware Tanzuのインストール


TAPを管理するための主要なOSSコンポーネントとして、[kapp controller](https://github.com/vmware-tanzu/carvel-kapp-controller)と[secretgen controller](https://github.com/vmware-tanzu/carvel-secretgen-controller)があります。

これらはGithub上のmanifestを使用してもインストールできますが、Cluster Essentials for VMware Tanzuとして[Tanzu Network](https://network.tanzu.vmware.com/products/tanzu-cluster-essentials)からも配布されているため、今回はCluster Essentials for VMware Tanzuをインストールします。

次のコマンドでCluster Essentials for VMware TanzuのInstallerをダウンロードします。

```
mkdir -p ${HOME}/workspace/tap-install
cd ${HOME}/workspace/tap-install
pivnet download-product-files --product-slug='tanzu-cluster-essentials' --release-version='1.2.0' --glob='tanzu-cluster-essentials-linux-amd64-*'
```


次のコマンドでCluster Essentials for VMware Tanzuをインストールします。TANZUNET_USERNAMEにはTanzu Networkのユーザー名(メールアドレス)を、TANZUNET_PASSWORDにはパスワードを設定してください。

```
TANZUNET_USERNAME=...
TANZUNET_PASSWORD=...

mkdir tanzu-cluster-essentials
tar xzvf tanzu-cluster-essentials-*-amd64-*.tgz -C tanzu-cluster-essentials

export INSTALL_BUNDLE=registry.tanzu.vmware.com/tanzu-cluster-essentials/cluster-essentials-bundle:1.2.0
export INSTALL_REGISTRY_HOSTNAME=registry.tanzu.vmware.com
export INSTALL_REGISTRY_USERNAME=${TANZUNET_USERNAME}
export INSTALL_REGISTRY_PASSWORD=${TANZUNET_PASSWORD}
cd tanzu-cluster-essentials
./install.sh --yes
cd ..
```

次のコマンドを実行して、Cluster Essentials for VMware Tanzuインストール後の全Pod一覧を確認してください。

```
kubectl get pod -A
```

![alt_text](https://lh6.googleusercontent.com/a4UohMzcM9jznwtfUtptyaMmOKywhVqUtRknWNhNVsQjT2UFPu0VHKcCE6bzCUPozr9dApgq2RwGiCg_11inpcPnGBZChkGAjlewPUoD-9LWpIwzPSR82vUu4cn7U0mMjG3TI2vn7xC8vjWG2KTn4GM)

#### [O] Package Repositoryの登録


TAPはkapp controllerの[Package Repository](https://carvel.dev/kapp-controller/docs/v0.40.0/packaging/#package-repository)という仕組みを使用して配布されています。

次のコマンドで、TAPのPackage Repositoryを"tap-install" namespaceに登録します。

```
TANZUNET_USERNAME=...
TANZUNET_PASSWORD=...

kubectl create ns tap-install

tanzu secret registry add tap-registry \
  --username "${TANZUNET_USERNAME}" \
  --password "${TANZUNET_PASSWORD}" \
  --server registry.tanzu.vmware.com \
  --kubeconfig ${HOME}/.kube/config \
  --export-to-all-namespaces \
  --yes \
  --namespace tap-install

tanzu package repository add tanzu-tap-repository \
  --url registry.tanzu.vmware.com/tanzu-application-platform/tap-packages:1.2.1 \
  --namespace tap-install \
  --kubeconfig ${HOME}/.kube/config
```

登録したPackage Repositoryから利用可能なPackage一覧を次のコマンドで確認できます。

```
tanzu package available list --namespace tap-install --kubeconfig ${HOME}/.kube/config
```

![alt_text](https://lh6.googleusercontent.com/O7MZpGPBHAtqR9r3BGEEhhHwBJj761Am1qWHPvfXx60OWqv8_f9kfZmnmtnLjJZfqoqGivgY_Gd9oOoVWV8CCxuh91EW-U4zW7n1YQ7ZVLoZJxbqIkSqrgPTrOOwNzgRkrPB4WQBRI220EoQbZ9L47o)

#### [O] Iterate Profileのインストール


いよいよTAP (Iterate Profile)をインストールします。

次のコマンドでTAPをインストールするための設定ファイルを作成します。cnrs.domain_nameに設定したドメイン名は後に変更します。

```yaml
cd ${HOME}/workspace/tap-install
cat <<EOF > tap-values.yml
profile: iterate

ceip_policy_disclosed: true

cnrs:
  domain_name: tap.example.com
  domain_template: "{{.Name}}-{{.Namespace}}.{{.Domain}}"

buildservice:
  kp_default_repository: ${ACR_SERVER}/build-service
  kp_default_repository_username: ${ACR_USERNAME}
  kp_default_repository_password: ${ACR_PASSWORD}

supply_chain: basic

ootb_supply_chain_basic:
  registry:
    server: ${ACR_SERVER}
    repository: supply-chain
  gitops:
    ssh_secret: ""

contour:
  infrastructure_provider: azure
  envoy:
    service:
      type: LoadBalancer
      annotations: {}
EOF
```


次のコマンドでTAPをインストールします。

```
tanzu package install tap \
  -p tap.tanzu.vmware.com \
  -v 1.2.1 \
  --values-file ${HOME}/workspace/tap-install/tap-values.yml \
  -n tap-install \
  --kubeconfig ${HOME}/.kube/config \
  --wait=false
```


インストールの進捗状況を次のコマンドで確認できます。12分くらいでインストールが完了します。

```
while [ "$(kubectl -n tap-install get app tap -o=jsonpath='{.status.friendlyDescription}')" != "Reconcile succeeded" ];do
  date
  kubectl get app -n tap-install
  echo "---------------------------------------------------------------------"
  sleep 30
done
echo "✅ Install succeeded"
```

![alt_text](https://lh5.googleusercontent.com/VUNYooyq7tqG0mQtIAkdO4uno1lmFY5XAPSh8Mht8Xxk_Sy4KwiAfKYJiOz_UvGv6zDIFBkOYpXQbSjFlbpgi6N6lq8f81u6SqEyF789PIMcmU8DQYNO1nlQBpb6mtPG5dzUP0-CYBcoYNsGHqQ747s)


TAP上のアプリケーションへのリクエストは全て"tanzu-system-ingress" namespaceのenvoyを経由します。envoyにはLoad Balancerがアタッチされ、External IPが設定されます。このIPを使用して、ドメイン名を用意します。今回は[sslip.io](https://sslip.io/)を使用します。例えばdemo.8-8-8-8.sslip.ioは8.8.8.8に解決されます。

次のコマンドを実行して、tap-values.yml中のexample.comをa-b-c-d.sslip.ioに置換します。(a.b.c.dはEnvoyのExternal IP)

```
DOMAIN_NAME=$(kubectl get -n tanzu-system-ingress svc envoy -ojsonpath='{.status.loadBalancer.ingress[0].ip}' | sed 's/\./-/g').sslip.io
sed -i.bak "s|example.com|${DOMAIN_NAME}|g" tap-values.yml
```

次のコマンドを実行して、TAPに変更を適用します。

```
tanzu package installed update tap -f tap-values.yml -n tap-install --kubeconfig ${HOME}/.kube/config
```

設定されたことを次のコマンドで確認できます。

```
kubectl get cm -n knative-serving config-domain -ojsonpath='{.data}'
```

![alt_text](https://lh3.googleusercontent.com/3lbUE2XkO-rN-aUFSwsXqMIdvbvSdTfqQHUEC35qU3-mFB0-P-0aqBuee5GmmEExhkZwuql7-4uXoA6GqZ9lxqZyQs1NjXk9MpzkUVtdNEjD4w1Q_JJ2SUsXx6NjW1lkI9uf9NSgkbWEHb_00FsNGIE)

以降、アプリへのリクエストのルーティングは次の図のようになります。


![alt_text](https://lh6.googleusercontent.com/a7OA6MBhWGqe7C0gldZInI4Ny5e3qyesYGvvNOU-o1y-qVwJ-cGACJGDsy8-_A8CBH8ofFpF8TeFQy0b1kkvqnzMLkbM8tqKsVb4_7aOel7pyKngUiTWRy6fM0VUD06zP76S1LxSnBEqyLIoueYgL-8)

### Tanzu Application PlatformにWorkloadをデプロイ


インストールしたTAPにWorkloadをデプロイします。


#### [O] Workloadデプロイのための準備


"demo" namespaceにWorkloadをデプロイします。本節の作業は**デプロイしたいnamespace毎に必要**です。

```
kubectl create ns demo
```


このnamespace上でTAPで作成されるコンテナイメージをACRからpullしたり、ACRにpushできるようにSecretを作成します。次のコマンドを実行してください。

```
tanzu secret registry add registry-credentials --server ${ACR_SERVER} --username ${ACR_USERNAME} --password ${ACR_PASSWORD} --namespace demo --kubeconfig ${HOME}/.kube/config
```


> **TODO**
> 今回はadminユーザーを使用しているが、本来は使用すべきでない。要検討。


このnamespace上にTAPがWorkloadをデプロイできるためのRBACの設定を行います。次のコマンドを実行してください。

```yaml
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
```

次のコマンドを叩いて、Secetを確認してください。

```
kubectl get secret -n demo
```

![alt_text](https://lh3.googleusercontent.com/XAzJxH8BmQNaPx11_I3IgFRLehkVjvVZ2YrEGWmW_XMw3ZtQV4GfXQ_icB4uHApRKAHiPp_xP8yGHxoB_V0S6l5QXQQbCGqu8B1pWyaSBNf_7rRNV-o50rxJhgkdAOPP3sOAFcZwSjrQINAZjKn5kOI)

#### [D] Node.jsアプリをGit上のソースコードからデプロイ

"demo" namespaceに簡単なNode.jsのアプリをデプロイします。ソースコードは[Git](https://github.com/making/hello-nodejs)から取得します。

```
tanzu apps workload apply hello-nodejs \
  --app hello-nodejs \
  --git-repo https://github.com/making/hello-nodejs \
  --git-branch master \
  --type web \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=hello-nodejs
```


次のコマンドを実行し、"Knative Services"に **Ready** が表示されればアプリのデプロイが完了です。

```
tanzu apps workload get -n demo hello-nodejs
```

![alt_text](https://lh3.googleusercontent.com/EQ7ByhEaIxxV1ZMsfVq8OYJddPkfgn-kLsVqxmtYWjELsWmnXFzKcAMOdn8cCY3v7ohz5Q-FAPKHa4z1EpWbJXGlGjKQ0KgkZheIM_DuSyiGcKtbkRCdnz0ylkmF6Vc3BnMHHJLoMGoFby7pgryXgm4)

このWorkloadから作成される主要なリソースは次のコマンドで確認できます。

```
kubectl get workload,pod,gitrepo,imgs,build,podintent,taskrun,deliverable,imagerepository,app,ksvc -n demo -owide -l app.kubernetes.io/part-of=hello-nodejs
```

![alt_text](https://lh4.googleusercontent.com/uMzp0Nk5kVSfQliWzQ3je4a5CEZ68wI_kKn9-1BWDghiZif2wjdqf7kW6okm-Lpvgd2HZTIMZlAniSPra4RytV0ET4mbi3FM1fdUYXt_6RVl0BlO1vU-cLEU6mP8f5gfevlfe6_l-6iyFp71JrO2-TU)


kubectl treeプラグインを使うと作成されたリソースが階層的にわかります。

```
kubectl tree -n demo workload hello-nodejs
```

![alt_text](https://lh5.googleusercontent.com/albPmYYnC5477zRl9GWFJe_U1ucaXfCcHOf-LAHtFmojalWajPoBEV6pDdBuSAkdBPrXGx5f1ioMCL9Uw7s5qzKJ5NKRjfbtCq700ttKhCtX8dtr4xC90J2Mg7-3j_lDuX37VGog2VIIVJcrgyXo0HE)


アプリにアクセスしましょう。

```
curl -sv $(kubectl get ksvc -n demo hello-nodejs  -ojsonpath='{.status.url}')
```

![alt_text](https://lh3.googleusercontent.com/JOOg5-2RxWsCMSzcyyPUXzpPsU_hdsnwlZ-DluCMVkIQJkTUHbpZdfrS9z2nOOLHiLsFZPMYTbFprqsF14Kj0_jsC9xobe9wdMqwdspSW6CF1AybbZUkFDvvsuRssskAyMY9fOMLcexpjV6LzSFbTGY)


ソースコードを変更し、Gitにpushするとアプリはローリングアップデートで再デプロイされます。

[https://github.com/making/hello-nodejs](https://github.com/making/hello-nodejs) を自分のレポジトリにフォークして、Workloadを更新し、ソースコードを更新してみてください。

```
FORKED_REPO=https://…
tanzu apps workload apply hello-nodejs \
  --app hello-nodejs \
  --git-repo ${FORKED_REPO} \
  --git-branch master \
  --type web \
  -n demo \
  -y
```


TAPではRuntimeに使用している[Knative Serving](https://knative.dev/docs/serving/)の仕様によりデフォルトで、1分間リクエストがないとインスタンス数が自動で0になります (Scale to Zero)。再度リクエストを受け付けた際にインスタンスが自動で再作成 されます。
最小インスタンス数を1以上に設定することで、"Scale to Zero"を無効にできます。

次のコマンドで最小インスタンス数を指定できます。

```
tanzu apps workload apply hello-nodejs \
  --app hello-nodejs \
  --git-repo https://github.com/making/hello-nodejs \
  --git-branch master \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  -n demo \
  -y
```


デプロイしたWorkloadを次のコマンドで削除します。

```
tanzu apps workload delete -n demo hello-nodejs -y
```

#### [D] JavaアプリをGit上のソースコードからデプロイ


"demo" namespaceに簡単なJavaのアプリをデプロイします。ソースコードは[Git](https://github.com/sample-accelerators/tanzu-java-web-app)から取得します。

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


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=tanzu-java-web-app
```


次のコマンドを実行し、"Knative Services"に **Ready** が表示されればアプリのデプロイが完了です。

```
tanzu apps workload get -n demo tanzu-java-web-app
```

![alt_text](https://lh4.googleusercontent.com/1vk0Vu_TdiJVjPWWtDmnRYYCXP8eg8ybXgycj2_JujrnpiNs8hzEqcGD1z4fPmdkCUScwoqbVoq-rn8bndvElZabpxHuzay_NBV-kmYL6sT2wVfl3oKWu2fcH4xVf8sAizybG3OZtWocNg-t0h8-VgU)


このWorkloadから作成される主要なリソースは次のコマンドで確認できます。

```
kubectl get workload,pod,gitrepo,imgs,build,podintent,taskrun,deliverable,imagerepository,app,ksvc -n demo -owide -l app.kubernetes.io/part-of=tanzu-java-web-app
```

![alt_text](https://lh6.googleusercontent.com/C7HfsQqxaoIfQlGgTmtcz7nfYNPEXzBlyKOxxqL15ygiR96_H9elVquzRAxcYPbf_OpuTINxwyZpbnCFqLh64rQRYRVU0I5aYHva6EB3060V0Ly9HeJTftTtTH1yFtVss3QRsZhzGRl22XXye0YA0zE)


kubectl treeプラグインを使うと作成されたリソースが階層的にわかります。

```
kubectl tree -n demo workload tanzu-java-web-app
```

![alt_text](https://lh6.googleusercontent.com/hG_EdK-u61301gPGBBAWjhcAJwPXZgY-I9Rgf0A3YBf9eYV4D-BtCwVSRXF3_b1S6_rMVXVfeKHu-6krfGmJCvwGa7lGAWAfTsqEefK0GuxMwGtnmwkU8q2UrpdUEOdYNST3IcwVqkQLXb_-ryeHmxU)


アプリにアクセスしましょう。

```
curl -sv $(kubectl get ksvc -n demo tanzu-java-web-app  -ojsonpath='{.status.url}')
```

![alt_text](https://lh6.googleusercontent.com/4s9npTXAL3nS01xLh7ziYEyt3-_RMrkgwz3o5dcqIKaRTSdbitoPYBO_JGkPIT1_4W8C2qPM1ATqQK_joVLz-wUlydu3dHMH9D-_W-412ttdPbFxY6Trt-UcEJNHRd2CsApBf10IJE1Z7jY-QhD5FmA)


デプロイしたWorkloadを次のコマンドで削除します。

```
tanzu apps workload delete -n demo tanzu-java-web-app -y
```

#### [D] Dockerfileでイメージビルド


TAPではデフォルトで[Kpack](https://github.com/pivotal/kpack)により[Tanzu Buildpacks](https://docs.vmware.com/en/VMware-Tanzu-Buildpacks/index.html)を使用してソースコードからコンテナイメージが自動で作成されます。Buildpackではなく、Dockerfileでコンテナイメージを作成することも可能です。内部的には[Kaniko](https://github.com/GoogleContainerTools/kaniko)が使用されます。

先ほどデプロイしたNode.jsのアプリを今度はDockerfileを使用してデプロイしましょう。次のコマンドを実行してください。

```
tanzu apps workload apply hello-nodejs \
  --app hello-nodejs \
  --git-repo https://github.com/making/hello-nodejs \
  --git-branch master \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --param dockerfile=./Dockerfile \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=hello-nodejs
```


次のコマンドを実行し、"Knative Services"に **Ready** が表示されればアプリのデプロイが完了です。

```
tanzu apps workload get -n demo hello-nodejs
```

![alt_text](https://lh5.googleusercontent.com/iM1t4Z39jUse8uGYIDRSwUqWAwz0VYQIL2fcD_WdlkgkKqrVNdh_ypfh0_QulZS64B_p0T7uyeFVw-Fu3hr7SxMuM9kS8iKI9XfsDxXv9oFS1Mq-ul84W2_0Iv3r_Sv4p-R-a4zcvWnAAEuWC-m_FPc)

このWorkloadから作成される主要なリソースは次のコマンドで確認できます。

```
kubectl get workload,pod,gitrepo,imgs,build,podintent,taskrun,deliverable,imagerepository,app,ksvc -n demo -owide -l app.kubernetes.io/part-of=hello-nodejs
```

![alt_text](https://lh6.googleusercontent.com/HmIpgmdb8oKmiulm1rugDQd_FSNRwPo0xYfkJgwgaBQ2sowLG96KJE4xtZD6XzGCY-AHUtaUY42yZGFGI11S8AaqPjr9oLrfDPXp6QLGY7VpqpSV063d2L0BNFgSqo-WSdJnS1_5_ppNQymGe8JSo20)

kubectl treeプラグインを使うと作成されたリソースが階層的にわかります。**Buildpackを使った場合と作成されるリソースに違いがあることを確認してください**。

```
kubectl tree -n demo workload hello-nodejs
```

![alt_text](https://lh3.googleusercontent.com/6frV81dJjYy94vIj9ST1Tv2-KcWRJ2qHtjiGOIrwox8nyo7E220oxd6nL2FT6y8PtSFyzuMirAJz86zDB0w8KuTiFLtCyZy4eQWtqkfmFfNSNoPf9fz51ADkUUL3y-LZG2H4JLo3WICESZDvK0lPeiE)


アプリにアクセスしましょう。

```
curl -sv $(kubectl get ksvc -n demo hello-nodejs  -ojsonpath='{.status.url}')
```

![alt_text](https://lh6.googleusercontent.com/BJNOxIaqxb7I6jsiJ3z8jfgT5ghY6iMU7kgF_9KAYxmoPKKVczoyYOaRepwqf2jRaRbreyKi6Us5oKH_gRE7BY8S2-eKUI2gwfkhR6YwG0ZpkiPt8dAddUcITe_YG0ryypXZeBd6QU3X0h4l6XLPaCQ)


デプロイしたWorkloadを次のコマンドで削除します。

```
tanzu apps workload delete -n demo hello-nodejs -y
```

#### [D] Docker Imageを直接デプロイ

ここまでTAPにソースコードからアプリをデプロイしてきましたが、ビルド済みのDocker Imageからアプリをデプロイすることもできます。この場合、これまでとは異なるSupply Chainを使用します。

利用可能なSupply Chain一覧を次のコマンドで確認できます。

```
tanzu apps cluster-supply-chain list
```

![alt_text](https://lh4.googleusercontent.com/o0k-aYzW1SZZg7ruFo2fWnE2TW4Sf6S1JrATzFdB_44R4pQ0XoVpVLvLechTX_nhG6CEyPw7m-DU3lvaOt8voruNfnRSMvxqxH0ntyRzXPZZ-MQdB_wpNAy5oYdzWZlr9Pn21ESwEyk3E3ltoJmfJjQ)


これまでは"source-to-url" Supply Chainを使用してきました。今回は"basic-image-to-url" Supply Chainを使用します。

それぞれのSupply Chainを使用するためのWorkloadの条件は次のコマンドで確認できます。

```
tanzu apps cluster-supply-chain get source-to-url
tanzu apps cluster-supply-chain get basic-image-to-url
```

![alt_text](https://lh6.googleusercontent.com/V1hoY33VdPxZjQlGb2wHbqpplUAqsDGtOFQSLtOOSyZvhcVadi6zFEpbG0BfrH3n4IXRffLqsgITilK_pDevDzKBXrCWnT_LzL0Gana748kO-0h9_8eQU_rcSyCxTdxTREeylp9Gc9KzykEONuV5dlw)


Workloadのspec.imageに値が設定されている場合は"basic-image-to-url" Supply Chainが選択されます。

--imageオプションでデプロイしたいDocker Imageを指定します。ここではTAP 1.2のBuildpackではサポートされていないRubyのアプリケーションをデプロイします。次のコマンドを実行してください。

```
tanzu apps workload apply hello-ruby \
  --app hello-ruby \
  --image gcr.io/knative-samples/helloworld-ruby \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --env TARGET="TAP" \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=hello-ruby
```


次のコマンドを実行し、"Knative Services"に **Ready** が表示されればアプリのデプロイが完了です。

```
tanzu apps workload get -n demo hello-ruby
```

![alt_text](https://lh3.googleusercontent.com/0ePAXWk-qMNzFXXmZWl_eZAoDU-fSuNBN0GzsJ1ZQmhTow33Vpx0k3e2sP2GEpuZ1PPHcBLyxoV0axkalLIJX3ofnEmFdUrTZ4lAP8YbFsQ4MSMeW_ea8kddqQbZlx2KepnZ1W2QGCs_Vb3awvNmu48)

このWorkloadから作成される主要なリソースは次のコマンドで確認できます。

```
kubectl get workload,pod,gitrepo,imgs,build,podintent,taskrun,deliverable,imagerepository,app,ksvc -n demo -owide -l app.kubernetes.io/part-of=hello-ruby
```

![alt_text](https://lh6.googleusercontent.com/dTExH9MyKk9r8Sjiu33LyoOcKqT7WGjEir1XjX350OoORQc8KzGAthNak7xxIbHLg-6NGgfQUbroiY8NwyjDlRC9DBORWXF-PZUd9H61dRkzXHjuvGDjOp7qKo2HVptCEHGuOi9ave_oYvF9XSOs7dQ)


kubectl treeプラグインを使うと作成されたリソースが階層的にわかります。**Buildpackソースコードからコンテナイメージをビルドする場合と作成されるリソースに違いがあることを確認してください**。


```
kubectl tree -n demo workload hello-ruby
```

![alt_text](https://lh4.googleusercontent.com/JhfF5rfuSEJS5MIxQgt9VmsNOKKqlcji3XOvFJXbjx8Bi7DUYupKcLWfLeEDXrkZvs3d9a8JVhAv-DethYZncZqfDtmdjdH7INZE_9v2EgXotqmFNphLZ5PPsPJBMl2sk0RZnGUKBRzYyK28Qnrw1as)


アプリにアクセスしましょう。

```
curl -sv $(kubectl get ksvc -n demo hello-ruby  -ojsonpath='{.status.url}')
```

![alt_text](https://lh3.googleusercontent.com/9C1vhdOY1KmjJypcavfHnc0TrKfXZdGnsVdCv31G1Mtz9tx3Bs1TwnddRvhda1RFA_o1cu4Of7MVPrsLQEDgW_SkeQ94xMMIAKpg9SFt-8dnnQeu5o0urhEUtl6DQtF8_7Gio9esHLG5q7CX_HW3AR0)


デプロイしたWorkloadを次のコマンドで削除します。

```
tanzu apps workload delete -n demo hello-ruby -y
```

#### [D] Javaアプリをローカルパスのソースコードからデプロイ


これまではGit上のソースコードからアプリをデプロイしていましたが、今回はローカルパスにあるソースコードからアプリをデプロイします。先にデプロイしたJavaアプリのソースコードをgit cloneします。

```
cd ${HOME}/workspace
git clone https://github.com/sample-accelerators/tanzu-java-web-app
cd tanzu-java-web-app
```


ローカルパスのソースコードをTAP上にデプロイするために、Tanzu CLIはいったんソースコードをコンテナレジストリにアップロードします。ACRにアップロードできるようにACRへログインします。ログインするためのスクリプトを次のコマンドで作成します。az acr loginコマンドでログインするにはDocker Deamonが必要です。Docker Daemonが起動していない環境ではスクリプトのようにログインできます。

```
cat << EOF > ${HOME}/acr-login.sh
###/bin/bash
set -e
ACR_NAME=$(az acr list --resource-group tap-${NAMESPACE} --query '[0].name' --output tsv)
az acr login -n ${ACR_NAME} --expose-token > ${HOME}/acr-token.json
ACR_SERVER=\$(cat ${HOME}/acr-token.json | jq -r .loginServer)
ACR_TOKEN=\$(cat ${HOME}/acr-token.json | jq -r .accessToken)
set -x
docker login${ACR_SERVER} -u 00000000-0000-0000-0000-000000000000 -p${ACR_TOKEN}
EOF
chmod +x ${HOME}/acr-login.sh
```

次のコマンドでACRへログインしてください。

```
${HOME}/acr-login.sh 
```


Tokenは約3時間で失効します。失効したら再度このスクリプトを実行してください。

次のコマンドでローカルパスのソースコードをTAPにデプロイします。

```
cd ${HOME}/workspace/tanzu-java-web-app

tanzu apps workload apply tanzu-java-web-app \
  --app tanzu-java-web-app \
  --local-path . \
  --source-image ${ACR_SERVER}/sources/demo/tanzu-java-web-app \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=tanzu-java-web-app
```


次のコマンドを実行し、"Knative Services"に **Ready** が表示されればアプリのデプロイが完了です。

```
tanzu apps workload get -n demo tanzu-java-web-app
```

![alt_text](https://lh6.googleusercontent.com/ZVOWlUFICdlahit8gVpkhqtdYEGDOEOuK_2_dVvUu0Q5uSPI4d2u2Fjbnxr2MMvOw9bim-VvjB55gHamvlmv0sJpi-uqLob0t8I5jciG0fmzJQZa-AyamWI7XGF67JShgFPvIsJhIcTORyiNBfGb4tk)


このWorkloadから作成される主要なリソースは次のコマンドで確認できます。

```
kubectl get workload,pod,gitrepo,imgs,build,podintent,taskrun,deliverable,imagerepository,app,ksvc -n demo -owide -l app.kubernetes.io/part-of=tanzu-java-web-app
```

![alt_text](https://lh3.googleusercontent.com/Bvp45D_OgGl5fy6-dcHtJcFFw4fISE3uBEUzBV0sLdcGs7jTA7uh3w0RHr-KMGm4UF53eo5Wt5RV6XTMRCx8qYmr0e84f8zOtWoJH8e_wDnscLeFetjW5XyQvSGhsWAtsmhCyXwUKXjJDpSyizFpABs)


kubectl treeプラグインを使うと作成されたリソースが階層的にわかります。**Git上のソースコードからデプロイする場合と作成されるリソースに違いがあることを確認してください**。

```
kubectl tree -n demo workload tanzu-java-web-app
```


![alt_text](https://lh3.googleusercontent.com/0ZnIYsOcJpFTuyfqqjobsWeFVRAx6KM2sYyBPnGqF9w2mWbXazbp430z95CrX8b-UvqG00t6UvRwta0TSnZ4VtK2tVUKhRoHts3AKiic5Bqk5tfwMeGYebiv9aP617lns4JciDaIHgFFWHrsGhLXL4U)


アプリにアクセスしましょう。

```
curl -sv $(kubectl get ksvc -n demo tanzu-java-web-app  -ojsonpath='{.status.url}')
```

![alt_text](https://lh6.googleusercontent.com/XmbGrPhvcMjNGFZm7cPc81PoPYqrOYGAzTFdHKDxTAQ67vFH0lPUKIat0R344U-4LQPA0m6BQT0KJuFzsck334770K4pqjSC_qcgzjX36un2WkBx53gop-QkHpgXO23_9smsZrk495yBRhO_MAYVa5E)


ブラウザからもアクセスしましょう。

![alt_text](https://lh3.googleusercontent.com/uqrvg3_WSkT2Kz5rDF5Wwm2MKruxyp7zfua7OTzXZHhokZ0X_Fw9_9idLEObITfysqyQaAxGJ-hnwQGLBKbLZxCjBYJ5LWPZUE9fPPlVbzhgwIbHe5AQu98NVGLtwybqPT7qigZXyBpPzgA9AVCBkAE)


#### [D] Tanzu VS Code Extensionsのインストール


開発中、ローカルパスのソースコードを変更する際に効率よくTAPにデプロイするためにVS CodeのExtensionが用意されています。

次のコードでExtensionをダウンロードしてください。

```
pivnet download-product-files --product-slug='tanzu-application-platform' --release-version=1.2.1 --glob='*.vsix'
```


次のコマンドでExtensnionをVS Code Serverにインストールします。

```
for vsix in $(ls *.vsix);do
    /usr/lib/code-server/bin/code-server --install-extension ${vsix}
done
rm -f *.vsix
```

![alt_text](https://lh4.googleusercontent.com/vAYUM2sg8Xv62RszzDyhmSJEKscr_ef2N92VBuL-8cNKng8nFcWpgFCuyVHBJCp1-Hoi7fqCOrSvPnlUUElVouElQv_WiEKGjAtzaNrSA3Jv5JPnu8Gr9Ny5VVT6I47rm_0pyTxxT3cEfN86PI96QxY)


VS Code ServerのExtension一覧に次の図のような"Tanzu …" Extensnionが表示されていることを確認してください。

![alt_text](https://lh4.googleusercontent.com/rvUnArHegzyrXhogh-olTfbWES4jkKf7Xx4lvM2vSuhMEp-vp7Rk8Xldyv8YAALUZrRJJ4BEDD_mVm_XaDv9rm_xsFFBniQTBprfg73klGn0IUK1o02C0zlArdHb08ixd1lshj8_3uWIp37LIOhtVqA)

右下のポップアップの"Update Workspace Settings"ボタンをクリックし、 "Restart Now" ボタンをクリックしてリスタートしてください。

#### [D] Live Update


変更したソースコードが即時TAP上に反映される”Live Update”を試します。Live Updateは[Tilt](https://tilt.dev/)によって実現されます。

まずは、git cloneしたソースコードをVS Code Serverで開きます。メニューから”File” -> "Open Folder"を選択してください。

![alt_text](https://lh3.googleusercontent.com/wserHUItfTkDXEiCWitrrdyRHktwwyUfA_QFXdtjFVHofDFHtub2a7LKHb_sIwZ22yxL_kl5FLIYWFq3vXLMjzfHQOHxMtQ0kQvbZLKNn15TOLBc5ZIp8n_6tF4X2bmjAc-oNJb6Jdbmjh4Oe-lKmaw)


"/home/coder/workspace/tanzu-java-web-app"を選択してください。


![alt_text](https://lh3.googleusercontent.com/IEgIFN43REWTj4K-j7C1oHINpurdKLgKUlCdRBwhMhpSfHcxqs5sitnb18f1GPR8_CIZnFsgvriUjIXQl54Qo_U569hXtSGNh2deLITwhoNsy-zkpcWuJOkr9cUiM01VXT1nZ600rS1K5fmsBX2vVls)


次の図のように、Extensions一覧から”Tanzu Developer Tools”を右クリックして、”Extension Settings”を選択してください。


![alt_text](https://lh4.googleusercontent.com/jljWPUot7E0FXzxvKaBN9gF4ztXs6JpefPlgAe2Hh61EfqPznj1IllYJvD2UL2M2NxlKMSLBHycCdqrIHtAgAW0bXdbMCtNs_VC74vONSFWgePDQADJ-W7Iis0wdFLLnhonw82_6cPByV3E98qST9wM)


次の図のように、Workspaceタブで"Namespace"に"demo"を"Source Image"に

```
echo $(cat ${HOME}/acr-token.json | jq -r .loginServer)/sources/demo/tanzu-java-web-app
```

の出力結果を設定してください。


![alt_text](https://lh5.googleusercontent.com/btZ55Fblq4FtcgntnRcl7HovZJHIlCBEbnqHeJYOal8VzMHCmWih0nrloLW9aJtTRlpYt1vKKauehLnmq6r9bjYyq1MCJF7m3ogP0rhLiecqOtDGeutGQ7dd_vtgontyoQCOKWRJiPGHyN3finCeYo8)


tanzu-java-web-appフォルダの"Tiltfile"を右クリックし、"Tanzu: Live Update Start" をクリックします。

![alt_text](https://lh5.googleusercontent.com/-4jr9oyOroWq35rv4dGKXGi1c56kdJ802Zmk8VEMNQZvds7d0fVZdldxUDIZrVa5-Pnwv8B_DIfl6PgbU_hW3UtuWbkbGhj4BL1LNBL_0UdE5iMFOfvuthNG7RRrjCMCg38mjY5qVXYa_L03GPI5jAk)

次の図のようなエラーが出るでしょう。デプロイ先のK8sクラスタを誤らないために予防されています。


![alt_text](https://lh6.googleusercontent.com/rRSfXDR4vOUc80h05E0a2Ce1C8PYn3uAnzeRHpTYMvqSuFCNFmc6xO1ToJjlmUTXHfDRkd2rDrC-JI5dVaMAs_vtqxqVpFclVai8--NPSjfbvGj82RMP0VmY3b8cHHCVVsoUX6ZGF57BTctiGBTgXeI)


出力された `allow_k8s_contexts('tap-sandbox-admin')` を、次の図のようにTiltfileに追記してください。Tilefileを保存するとデプロイが始まります。

![alt_text](https://lh3.googleusercontent.com/o5xzVthlgLHU6hEfH7OBSRpKxEAKOydeumwQF-sqrT8G-xJqCr1qvnq3n8Ibt0Yev99kmG4618Ja1IZVKSRxKgfq0gcFj_VGPsyrEUFevEvEweFclOtx4ZD7CUnSzrQnp-h0Vrg0jR09G_sxLtK3wu4)

初回のデプロイが完了したら、ブラウザからアクセスしましょう。

![alt_text](https://lh3.googleusercontent.com/uqrvg3_WSkT2Kz5rDF5Wwm2MKruxyp7zfua7OTzXZHhokZ0X_Fw9_9idLEObITfysqyQaAxGJ-hnwQGLBKbLZxCjBYJ5LWPZUE9fPPlVbzhgwIbHe5AQu98NVGLtwybqPT7qigZXyBpPzgA9AVCBkAE)

次にソースコードを変更しましょう。 src/main/java/com/example/springboot/HelloController.java を開き、index()メソッドの返り値の文字列を変更してください。変更のあったファイルだけがコンテナに転送され、コンテナ内のアプリだけが再起動します。


![alt_text](https://lh4.googleusercontent.com/fvarY_ysxLx368JRSz6nmq0odaGOWGPb0ZjzS9-xRkE4x7Y2CFQZMUtTzt80eEB365diZrfSi_i8EsLmMj9e_pfl-2mywC-BQg0-vGsSCHTzCZk5bifW03TMLPO_zDOUJ4iXdFOz07X-cUieG2zVS9g)


ブラウザをリロードし、変更が即時に反映されていることを確認してください。

![alt_text](https://lh5.googleusercontent.com/mWb1GGfl6XZjSAgsyoIuGRhxd_NsZ6kO8cRgsLKapptZQZJTYIDR1nV0ginnn1wyRlLZQWiioLUHShu8YIxNOwOVJg9EDdp8MuBD0nL23_Sd1iq9j_tUwFzA6AfQBxAntFmZz1QFxQYQRzRr1nFfIUk)


もう一度、コードを変更してください。

![alt_text](https://lh3.googleusercontent.com/h18Loefv3Arxug6HeIdNnZ4cA80eA1vKR5Fd5hmQtp3NcyUJj7W9LItoyQ7FNYhgEYiaVPowCqsxX0ZGjv_rFepCGr5Hn4hTg_1CVgekB6im6CI3kgtjVWPnnW5dVOzmhkD-eyj4VTcHVwvIQseBD3M)


ブラウザをリロードし、変更が即時に反映されていることを確認してください。

![alt_text](https://lh4.googleusercontent.com/CgthcAhee6UErT9zHABzlxV4EX9pLfBOZ6sdIfKwN7YBwH540rcTYlRVHJZdnS71ZxSPHQcKxOf4vYtAD_nxCyL4aBbysUZBaG42KoR1u1eVz7_OAdxUcimC_wKMUeuypRPhErbg1QkRfy1_gZ5FjrE)

Live Updateを止める場合は、Tiltfileを右クリックし、"Tanzu: Live Update Stop" をクリックします。

![alt_text](https://lh6.googleusercontent.com/DEhLDkyLD2WhItp_kN3qqq7MRxN8NaYOw7WDpKQ-P4R19YsJ70u8BuU9pVPvg2rESIdzTVVgn0t6arjUQ9GNyx4FTi5u2JMf9emZy8S73LILpAA60X7Cxq-6lZL6-Cyf0ulwkOqwuS5ogBb8ntLpCLY)

次の図のようなログが出力されます。エンターキーを押すと、ターミナルが閉じます。この手順でLive Updateを止めないと、Tiltが起動し続け、次のStart時にポートが衝突するので、注意してください。

![alt_text](https://lh5.googleusercontent.com/jSzoScvBkUtRI5DPanntnsxAE37AupyBk_8KyOOgSFbNsfxd6mBWlJFMMPGkT9xxMwplAgwsk3kfHvwDNtIfs4C8DEqJTLkBcu4ChVH-7RKVWB0JLdodKWNK_UQ71Uf31__KxTvyYwqjq85-DiO0M8I)

#### [D] Live Debug


次にTAP上にデプロイされたアプリを直接Debugできる、"Live Debug"を試します。

次の図のように、tanzu-java-web-app/configフォルダの"workload.yaml"を右クリックし、"Tanzu: Java Debug Start" をクリックします。

![alt_text](https://lh3.googleusercontent.com/T4c6xqKM_cUFL2C0ve9Eq8BNv_1YUiDRmZJatuxUyawl_pdvpySWXBRIVO_DtN9w7cAVFM4yNUnNfCO6xDMgj1iHxKWPNk9s83BBOgWOlLD-_iWiu1k1XNB_u8d5cfW3MhVZ4jU1TesPQjQDWXCkdKo)

しばらくすると、次の図のように、"Port forwarding to tanzu-java-web-app-******" というメッセージが出力され、フッターのバーの色が代わります。

![alt_text](https://lh5.googleusercontent.com/XKSBbuYROg_pH2RVLL1izX-lKrUi2cQsRqUqwQoic7O2wOMNwcxu4I1IHOGaHkG4c0M6eeld5wAm1mYOKlEvEz2KaAC2C6OaVi9fDLUJ7fkQobn1idrZho4O9ueTZ19qvMXR4bFdyscBCYn1ZGNpQ2k)

ソースコードを開いて、止めたい行の左をクリックして、Break Pointを設定します。

![alt_text](https://lh6.googleusercontent.com/XMiWxwELG-ZwdNa9hl4e67cMU4t0pEuulXy0PYMIXd-hcbNGd7eMOhWnRgciJAv1BTfUVWFlO9yxMfIYvLr_InS0bIyg0aiULj2h7dHOeiu2N4piaO41l-oyxFbPiWSEKT7zAjTs43asb7heM-HhIHM)

この状態で、アプリにアクセスすると、次の図のようにBreak Pointを通った場所で停止します。この状態の変数などを確認することができます。バーの ▶️ ボタンをクリックすると、処理が再開します。

![alt_text](https://lh3.googleusercontent.com/lZHgK7Qjs8k7wpjzzsOE8VZm9o3AV_z_-9PuzdT58ZK6jHuXfZQ908WrzriiAr8NZr-daH_lnLyhRG8q_I3JoBT5mR8tG83_qb3tNdFeer7cJDDQGhcniwLwYPCDsAoPe5IeWlAcEDf8_EhH1UduZFY)


Live Debugを終了する場合は、バーからStopを選択してください。この方法で止めないとDebugモードやPort Forwardが残ったままになるので気をつけてください。

![alt_text](https://lh5.googleusercontent.com/OaF8-_h1TnBuejI0-yvdOXFVkSvlpV9dCgCiXn0f-eEHjBPNEUi9XnUvLl-wiBd_iWEh--tMkA7siSI7b3Od2Lt4t592B4HRck72-TPsKTWOEvw0lameYFnKAinoSMlr99VnKC-4clduZe2Xf3fqUsw)

#### [O] HTTPS対応


TAPをデフォルトでインストールした場合はHTTPのみ有効になっています。TLS証明書を作成し、tap-values.ymlに設定することでHTTPSに対応できます。

TLS証明書は[cert-manager](https://cert-manager.io/)を用いて作成します。次のコマンドを実行してください。

```yaml
DOMAIN_NAME=$(kubectl get -n tanzu-system-ingress svc envoy -ojsonpath='{.status.loadBalancer.ingress[0].ip}' | sed 's/\./-/g').sslip.io

cat <<EOF > ${HOME}/workspace/tap-install/default-tls.yaml
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: cnrs-selfsigned-issuer
  namespace: tanzu-system-ingress
spec:
  selfSigned: { }
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cnrs-ca
  namespace: tanzu-system-ingress
spec:
  commonName: cnrs-ca
  isCA: true
  issuerRef:
    kind: Issuer
    name: cnrs-selfsigned-issuer
  secretName: cnrs-ca
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: cnrs-ca-issuer
  namespace: tanzu-system-ingress
spec:
  ca:
    secretName: cnrs-ca
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cnrs-default-tls
  namespace: tanzu-system-ingress
spec:
  dnsNames:
  - "*.tap.${DOMAIN_NAME}"
  issuerRef:
    kind: Issuer
    name: cnrs-ca-issuer
  secretName: cnrs-default-tls
---
apiVersion: projectcontour.io/v1
kind: TLSCertificateDelegation
metadata:
  name: contour-delegation
  namespace: tanzu-system-ingress
spec:
  delegations:
  - secretName: cnrs-default-tls
    targetNamespaces:
    - "*"
EOF

kubectl apply -f ${HOME}/workspace/tap-install/default-tls.yaml
```


次のコマンドで、作成されたSecretを確認します。

```
kubectl get secret -n tanzu-system-ingress
```

![alt_text](https://lh4.googleusercontent.com/3WzFMT5U8-rX50cRa0k6sXWDLOngb1aIOBoCvl1J6GQ1orI8EPLbB1xNE1mKDHW-6rN8MhyM_A78Am1SWY6JTp9vacaW0fEOrFWgCC9Lru-8_WE77Z03gNVPvIy5RlHUvs60LmF-Coqw263LNq6Xnt8)


ワイルドカード証明書である、 "cnrs-default-tls" をデフォルトのTLS証明書として使用します。
TLSCertificateDelegationが作成されていることで、この"cnrs-default-tls"が他のnamespaceでも利用可能になります。


次のように、tap-values.ymlのcnrs.default_tls_secretを設定してください。

```yaml
### …

cnrs:
  # ...
  default_tls_secret: tanzu-system-ingress/cnrs-default-tls

### …
```


次のコマンドを実行して、TAPに変更を適用します。

```
tanzu package installed update tap -f ${HOME}/workspace/tap-install/tap-values.yml -n tap-install --kubeconfig ${HOME}/.kube/config
```

![alt_text](https://lh6.googleusercontent.com/49DCc5UNhu3v7WvW74zqa179ZdWjVjqzPFU8haUh_ACouFob2tSeLjX6fDFk_Z9eSo0_fu5KdGZS0kWEakPu9n_SsRrrSuxa7qaiaOUZ-UooH1zYnc-EtdocYyzLDG23uJfkYZQMdP3-R-_izMxWzjE)


TAPのRuntimeであるKnative ServiceがHTTPSをデフォルトで使用するように、次のコマンドで設定を変更します。

```
kubectl patch configmap config-network -n knative-serving --type merge --patch '{"data":{"default-external-scheme": "https"}}'
```


次のコマンドを実行してください。Knative ServicesのURLが"https"に変更されているのがわかります。

```
tanzu apps workload get -n demo tanzu-java-web-app
```

![alt_text](https://lh4.googleusercontent.com/pZCcxp6yABld5At3TnBoGa5RRVsadKOu5CpVDYU3AD1sqeP7nlGcfVlEp7JhBB2SmlJUZoeXFVUi48rTxZleae9LfYgMWngzMqshKVNJs5_cxlRXShHiPbh60gbrxkqHXls1XDLQhk1ix1RJ9BQ3kkI)


アプリにアクセスしましょう。今回は自己署名証明書を使用しているため、curlのオプションに-kをつけてください。

```
curl -skv $(kubectl get ksvc -n demo tanzu-java-web-app  -ojsonpath='{.status.url}')
```

![alt_text](https://lh5.googleusercontent.com/Y_OgaXnl4ce-_fmjqJiCYVqrhnp65MJtCFpbphnJ3p_UHjXyl_NwUPoAQA8DIpx8Y0aLXPxMMl93fC2duxmPzo82_AtO1BGgdtWrDXSWsCjbd51siMB15p0UDA52OvcaTaMo-CUp-gvuY62F4hJS-Mg)


ブラウザでもアクセスしましょう。Chromeの場合は、自己署名証明書を使用している場合、次の図のようなワーニングが表示されます。

![alt_text](https://lh6.googleusercontent.com/leqKVppkCAsEnn9uyMzy-oBpsbppQyt6qaF5neGLE7JV8IMDMiqLFJSuvxiWAC93vpsFoqpC982t8buJMkPUYlXRRLuceQFGxCBOPDFEjPK9j5yKsLl1GxzEH8UwpDhEDZxoxMA5TW0QOJcFADbitfo)

ワーニング画面で"THISISUNSAFE"を入力すると、画面へアクセスできます。

![alt_text](https://lh5.googleusercontent.com/Di8RhgjRnF0Jgio37jdrHXU7iSJ9UG_1kY_J2P4sy3FDu20g7E80gsNqnFQnYRDKYbUhJdKt2i7K_upf79rKEtFws7Sp75Olf88P2EbOpHxb8Jl5KhzKZGzN_s4lHhnl9lt1jxM38hDm7YAazuy48Gs)

### Tanzu Application Platformのインストール (Full Profile)

次にfull profileをインストールします。full ProfileはTAPの全構成要素をインストールします。ただし、今回は使用しないLearning Centerはインストールから除外します。

![alt_text](https://lh4.googleusercontent.com/5Ic7iU8TWPAdPpzLmzfDY4KMnDYnb8Apuuo7iQ6KynOrM_Hv1Z2-W-g_iOf3bgZ2ztYls2djLG1vMYwZvXr0vdP4q_7Kdfeatnz1wVIjMwycPnWrIwpmc4Ieerc0_Zi8FXNQwLUSgYtqEqnib1YvQv4)

#### [O] Full Profileのインストール

まず、tap-values.ymlの"profile"を"iterate"から"full"に変更してください。

```yaml
profile: full

### …
```


そして、次のコマンドを実行し、tap-value.ymlにfull profileのインストールに必要な設定項目を追記してください。

```yaml
DOMAIN_NAME=$(kubectl get -n tanzu-system-ingress svc envoy -ojsonpath='{.status.loadBalancer.ingress[0].ip}' | sed 's/\./-/g').sslip.io

cat <<EOF >> ${HOME}/workspace/tap-install/tap-values.yml

tap_gui:
  ingressEnabled: true
  ingressDomain: tap.${DOMAIN_NAME} 
  service_type: ClusterIP
  tls:
    secretName: cnrs-default-tls
    namespace: tanzu-system-ingress
  app_config:
    app:
      baseUrl: https://tap-gui.tap.${DOMAIN_NAME}
    backend:
      baseUrl: https://tap-gui.tap.${DOMAIN_NAME}
      cors:
        origin: https://tap-gui.tap.${DOMAIN_NAME}

accelerator:
  domain: tap.${DOMAIN_NAME}  
  ingress:
    include: true
    enable_tls: true
  tls:
    secret_name: cnrs-default-tls
    namespace: tanzu-system-ingress
  server:
    service_type: ClusterIP

metadata_store:
  app_service_type: ClusterIP
  ingress_enabled: "true"
  ingress_domain: tap.${DOMAIN_NAME}
  ns_for_export_app_cert: "*"

scanning:
  metadataStore:
    url: ""

excluded_packages:
- grype.scanning.apps.tanzu.vmware.com
- learningcenter.tanzu.vmware.com
- workshops.learningcenter.tanzu.vmware.com
EOF
```


次のコマンドを実行して、TAPに変更を適用します。

```
tanzu package installed update tap -f ${HOME}/workspace/tap-install/tap-values.yml -n tap-install --kubeconfig ${HOME}/.kube/config
```


インストールの進捗状況を次のコマンドで確認できます。5分くらいでインストールが完了します。

```
while [ "$(kubectl -n tap-install get app tap -o=jsonpath='{.status.friendlyDescription}')" != "Reconcile succeeded" ];do
  date
  kubectl get app -n tap-install
  echo "---------------------------------------------------------------------"
  sleep 10
done
echo "✅ Update succeeded"
```

![alt_text](https://lh4.googleusercontent.com/4LXALzgVv03GHGl9CblBbUBRK1EJXFp0b14VTfCl9GhJlNKhmSoA-uphzS8tzWki9firNMd2XSdcWkr47Cub_sJOhLsMl2hhnLPco2favvYqxZSj8MMSflSCWAl_5Ih-fcQvnlKC8ocotunnh2XGJLA)

#### [D] TAP GUIにアクセス


full profileではDeveloper向けのPortal UIとして、TAP GUIが用意されています。TAP GUIのFQDNは次のコマンドで確認できます。

```
kubectl get httpproxy -n tap-gui tap-gui
```

![alt_text](https://lh4.googleusercontent.com/EbjPvDnyO_HbENuC0_WjcTUZv0RoakamGLNdQlDWVlJWTZbDjiSN0YvojHZI_9oN_iNVTwhIBr5wWGT0uS_-iwlv7vTsSnO5xXGiG1hSCVWOTJs261VksNDyEOz29WntnYy9d6ESi8wyBxP1LyE6nSo)


このFQDNにブラウザでアクセスしてください。次の図のようなワーニングが表示されるので、"THISISUNSAFE"を入力してください。

![alt_text](https://lh4.googleusercontent.com/4GfjwkP7foAiSr4BWG-_8fDQxk-iysIP7xaR0FPKtNvr6G5FznqSd0dkl8D0CCXcHhSgpE8QRJiVs2ZhlaI9ujielmymwVPt9jDzFhlbAzdFLVaevXMUDyZcijHQ116tdcNdI68ZjX_G3VNxfgovh2s)

トップページが表示されます。TAP GUIの認証はK8sの認証と独立しており、デフォルトでは誰でもTAP GUIにアクセスできます。"Enter"ボタンをクリックしてください。

![alt_text](https://lh5.googleusercontent.com/HNCc09XnR6xVh4sAUD3wGy9gOGDrXd7cebxkCXFhKG-Dy7lCTyw9E2uuct9eiSoYC6lQkXEb4JzLaq0w6da8-jhPoOzEAYzM9fRH1VXVQNw6oq8CNazucgzFZvKYpXo-DWjOiNDdObtF0FSIj3Ci0eo)

次の図のような、Catalog一覧画面が表示されます。

![alt_text](https://lh6.googleusercontent.com/gMpJ1gvUH21RzETS674UkqbjbvGgtmY72KFVvFGERfWjdhVZzHVhoiZehyTHeC4n58CqTEo-q_hLGBjjIXbaf48EKWTugnDyA80_m-fVBuQKmiiOgYnXj2HK12KJW6hhbE-5sQqEmexz6JlTKcG3aGM)

サイドバーの➕アイコンをクリックしてください。次の図のようにWorkload一覧が表示されます。

![alt_text](https://lh4.googleusercontent.com/Ls6pCPR1Xa-pIqGgFyV_2hVNACtQ_C-Q7fFewWiWpiVtRVcAOzpnUFLwIzcDZQ4gH7ACQ8ZoHLICXwPyM8g1CBzrs4UhNv3UrjGoTT0jQBtLBqOpEEZdOrxJMVj_imHWdRuF_HNYy7vghTZJAuB5DpQ)

Workload名をクリックしてください。このWorkloadに対するSupply Chainが視覚化されます。

![alt_text](https://lh3.googleusercontent.com/4RotvnQqqwpoX1Bp1hGig7H-O-T6Jt73eyxLTGTuCX2mon7IWoTkXd7f_k0cOP7bHrFYw7WQ4czbPwGnkOlN0MIcfrlpBwUb17KHsyK3O3zQmJ0tmNpFuIOl0xJqceK8zX2V4zxtmBMtQOCqUrZtgWQ)

#### [D] Catalogの登録

TAP GUIにtanzu-java-web-appのCatalogを登録します。サイドメニューから🏠のアイコンをクリックしてください。
右上の"REGISTER ENTITY"ボタンをクリックします。

![alt_text](https://lh6.googleusercontent.com/HtJD1ahGUd1ndiy1H3ZHDZqCD1ko7hQ2pCbN2svwl8_mpGHt6ecjerl1klnZqaJeMjD71mBR-gT5VIutvx8BZJ__iZqkieqy-8nHhQOSrTFe1ZAblN0NmkVh7Yh4pNBvfUz7AYgSZm2TIkzDXg-t0QU)


Repository URLに [https://github.com/sample-accelerators/tanzu-java-web-app/blob/main/catalog/catalog-info.yaml](https://github.com/sample-accelerators/tanzu-java-web-app/blob/main/catalog/catalog-info.yaml) を入力してください。

![alt_text](https://lh6.googleusercontent.com/ysVqyoqdpOb3CopazrwbaGK80iwZK8fF6jZAwrwUvaa0ZdqvbzN_jDvp7eZDmO-4bnihcoyASNPpXpKiLXhSow0DOzZ_2FB81NlG7opesxS72SSDtSymYjgvqehNHs9WxuJfEedAa6vF_0yniiYeJ-8)

"ANALYZE" ボタンをクリックしてください。

![alt_text](https://lh6.googleusercontent.com/AbjOZ5IaF7np47atUoZhqN28D2EnsFhnaaB-M1e9XX-Abvu1WnGMilkGmCd44Z8wdel6Ou3VBMcMqCi7ZskjSfdRuNgiQ0cQwEeOpGCvXSAuQ8UnqTgCXfQ2SLurdaXIAgoZp0FEeI3ETXgD_6_QIjw)


"IMPORT" ボタンをクリックしてください。

![alt_text](https://lh6.googleusercontent.com/AndFzrCDGKbcjXlXyPFqmwgMX2MGydfuq_dnsIbJeVozE78SDBQhPh2WAnWSdl7KTlJWflNb5TCyefz1Dn7b3Bi95sKJG_wNV56ovO3B40tNqRn3ZkOLbH8tfjqx7OhaPiCHdGV3rAJHgf3gXnmwWzs)


再度、サイドメニューの🏠アイコンをクリックしてください。 

![alt_text](https://lh6.googleusercontent.com/OuDmO9aML_-hOqexo5BPPlHgEjbFHKRyM-Pph5XStvQqSl-pDV-UOW74ZqKHfu9kHapUPbCqCC1PcJIpTZp62_mxHy5INkrau-VaWkQlOF0uRAA4OeeTkDYi8yebnLzEWPbRTH6ZBBaH1va6FB3m5W4)


左下の"YOUR ORGANIZATION”が"All 1"になっていることを確認してください。"All" をクリックしてください。

![alt_text](https://lh3.googleusercontent.com/AGjDjJRDY8wQvUihzRvhdih1Qdn75FoUZZHH0hvdywJET2yQXO5z45gACvQM1GYPQF8JPbdf614SofoA7INXmO_rPuFhtW1muxGeJ8fmqtxF-IqmWlfAru_AJwutc-jLE6zntcG30LxXJKs3fQjMyfI)


Component一覧に "tanzu-java-web-app" が表示されます。"tanzu-java-web-app" をクリックしてください。

![alt_text](https://lh5.googleusercontent.com/MrIt5QJQTB3NYnOXsJpT2lffMiMKsRgMa_8yb3CYUFwTzEYsRe7L3jsPJQak3A-aQIRJEBBNam6dR95Wnpg-FxTFhC5kmgyIjwGhbxIOkHGyDyKFUqs5GhVKUvbtoYnivk0ey52zlrt6eiFqM1fh3GI)

componentの詳細画面が表示されます。Runtime Resourcesタブをクリックしてください。

![alt_text](https://lh5.googleusercontent.com/llA_Inqz4JcnGBlQKgVg5pgRBZxMEfA9iW6wCeGKIieVmbL4bqv61nxra3qxjv8GGnIwG5RYIrb7y8MkNct-1hLLnHrBV30wS2vrOxCw2i9CGKzhbtfZpwUKleE1KPZ0IqYgHZyzdmvLtcR9_tp7DHs)


tanzu-java-web-appに関するResource一覧が表示されます。
Resource Nameが"tanzu-java-web-app-000NN-deployment-XXXXX"で、Statusが"Running"でKindが"Pod"なResourceを選択してください。

![alt_text](https://lh3.googleusercontent.com/jJ_PdKoy6mxf22a0qNt_kZmb-adabd7flMCR3nf8Ev_XCF0gyxm2KhNxfaGWSGGURl5puqxK4RNUpqen1pgdYUkdbrdtE3KcHxNVGOUMGZVsLVZKH0Y2zuMKWV0gWtKRH7fnaZavBVtPIMbOeGHdltA)


Podの詳細情報が表示されます。"VIEW POD LOGS"をクリックしてください。

![alt_text](https://lh3.googleusercontent.com/OPwamFCEDtH2mVQzlCXCBBfo2zpPgHlKW-SYYglDsvkCuNYBuL2X8lDwzF0CCUwMTEFcqN_h-oH5TgV7EnJSd1yhtFdXwlp6GgwzsQ7UwmmKJ2m10CgtqRuSjR88WWVAAzeAHnFvoUB91PzRNleaFcI)


Podのログが表示されます。

![alt_text](https://lh6.googleusercontent.com/0n3-C_ayZ2oMTFwPIe5WZS-fX4FEq0yz9tmpRka_d4vI1eoPXIl8Pcdne-np5XYBrbT6lItbxP3AziP62J1gCyiHI4Mnm0h0VN4TUKmH-urmpuuHyyNsodyJkfHVQ763ZjK4DjOLu3i50vbS06qPcH4)

#### [D] App Live Viewの確認


"Overview"タブに戻ってください。
Spring Bootで作られたアプリでSpring Boot Actuatorが含まれている場合は、"Live View" が見られます。

```
⚠️ AdBlockをインストールしている場合は、TAP GUIでは無効化してください。
```

![alt_text](https://lh4.googleusercontent.com/XrHyTJbcb0JzfeW4dlrhDyOUAc9YLBj7wjieorrTM8jZ6gidfavMlNYAzLYaVehJaZiQm1mVPR33hIgdzgnYQaA9gmbPMWs8dabRGNw33KaPmpwwDDraOhyvA54MI6o0KaBfBmlOvAIhaahbJZxIrK0)


Spring Boot Actuatorのエンドポイントを選択できます。

![alt_text](https://lh6.googleusercontent.com/i4PqORr_L0GUsPbbNWckDmWj0i9DkpmG6wBwBFW5DkKAmGsQf5xAWW5GGoci_4ZFBQ2ImwR56WkeqzLquJqx4UXKC6hPjJqCInCTa0Vt4RBSVEK17faXoHmaWTvYiLHG9lXgLEP_y9kS1BYL_uSW59U)


"Memory"を選んだ場合

![alt_text](https://lh4.googleusercontent.com/Q_7b5Jdw2jmZiMABdCWfMGv7Um7vBW8U7Yvxpmqy19ogIaqTNGD4z1fXxIZ_hKPTHf5cQ7ed1zAwfu_f-qLJcQq9AOa08RhxYRL6xC1MDs_lUBsQzoFWX0-0GfHm2dqt4r2BuNwVA43L_LekslS1wb4)


"Threads"を選んだ場合

![alt_text](https://lh5.googleusercontent.com/5EfD4segtjvOKFAhTY15A1JKvsxKX5Pg67i8T_KsfqPeHh8qkKJC-T8Nn-IIUX6uTdYMeYwbqhz4Fz4IPAuHZEDiw1NzhSBgTiUH5xIBYoR5m0GOwarNKO_1X4WlRsujrOH3G2mLvJLVq4F87gIFVOs)


"Log Levels" を選んだ場合

![alt_text](https://lh5.googleusercontent.com/ppM8riWO7_yYugFYFYIBs6kPIA1UH6Ze4dc0c3FFIt1_jnmWI5YGdY0vIi9U4p_I3AuTcwJl9TmGbqLF_Ur5GcHQGki5w_etV0BIX-EGpu9hBoGAJjO6TpylJUlt8cIXs0Qo2fb7aq97wQJ4DEVuZM8)

#### [D] App Acceleratorから雛形プロジェクトを作成

サイドメニューから⨁アイコンをクリックしてください。
Accelerators一覧が表示されます。ここからプロジェクトを生成することができます。

"Tanzu Java Web App" の "Choose" を選択してください。

![alt_text](https://lh4.googleusercontent.com/4UYl2hexgtTWeN4Q_1LuCPPcAfKy9__ybvwXFvRQSQcLK3D9Jy6ydhB2IPI6AhBJwaPcqb4u21yRM-Mk2MpM9AzaXfTXzL7d-IsifnogGMxGXX_8UByWT26SDwwMEZfsmfS4ITU1StMv9S_WCTZvAmA)

雛形のプレースホルダーに埋める値を入力します。“Name”に”hello-tanzu”を、“Prefix for the container image repository” に

```
echo $(cat ${HOME}/acr-token.json | jq -r .loginServer)/sources/demo
```

の出力結果を設定してください。 "EXPLORE FILE" ボタンをクリックするとプレースホルダーを埋めた状態で生成されるプロジェクトを確認することができます。

![alt_text](https://lh5.googleusercontent.com/oLSfI3eV_HtlDUVE2rev1xOOBwmv4H7Lf1naBgVlchRZRuLFWQGgcM_es1xl1zR-CQLbTZZz6XjfGvYSUmKX35G_5SDCRiUzIQgKKFJjXAqbbrwF72MyCCDki_Psk-wLUc_w_F5mYXiuMwtQXDpiiz4)

config/workload.yamlに "Name" で指定した値が設定されていることを確認してください。

![alt_text](https://lh5.googleusercontent.com/iVOqeo_SJdwaOSgsphaX81JSJRAg4QAuul_k6-lAB4nQhib09JThi-M_ux-mvNxNOOMkXMQctHy9XS78BJjVqHb4nxjDI7Rctjda0HsEz56DqkB5A2TeRWK_eNxK6pik_sbs_RWkSRMQXL9MMz7BAUo)

Tiltfileに "Prefix for the container image repository" で指定した値が設定されていることを確認してください。

確認できたらダイアログを閉じて、 "NEXT" ボタンをクリックしてください。

![alt_text](https://lh3.googleusercontent.com/R_Z_NdeBG5be_DO1RglDh4dyErzXX8wTthVGWwb9MqQNoi1S9ICzWRIergYpxqq8QgLxHx-kNCz_5hyVPGJGQj-URsi5r4YLpwMoTPAl8HNUXb4-7ehI8dkIrABvugczdM-nmqCuolZgSQSyK7mMan4)

"GENERATE ACCELERATOR" ボタンをクリックしてください。

![alt_text](https://lh5.googleusercontent.com/E6Lcb0E9YrAwRXuEK_6loUi_5afAdTsp9JXCndvONebBg5oSY2rgPoKEjR2q0YQcrIdWtxPv8sgujcFkLBmVLKg2MtJoi6VvS5j5XBZzn14cBiu9mGFAkviL_jlU6AeQlWmdLyw1ztxuU7j6V_hdQSE)

ZIPファイルが生成されるのでDownloadしてください。

![alt_text](https://lh3.googleusercontent.com/9_TG_bY8P01nlGvPcx_fkk7JLQqDNKqKaSDePEPGFS3l8tX5_qCY_tQcn9M0OZuHKONHCvu_CB3MvJPa6TRgnA8_eKE4fkJK9r2qRqvCmUcLfY7_bc63Ec2OUs80fknSmsBhdCh7QMUc3FKM5u9CIZA)

Downloadしたhello-tanzu.zipをworkspaceフォルダにDrag&Dropしてください。

![alt_text](https://lh6.googleusercontent.com/r2Ymbudkq1Z33V8yTrjrag1n-zJHrmx7dbFh0PxSmgWYbDV9txVhxP4XgsdEU5OhzkfZUenKOHNaL4TX9MpfckPmzLRDY-Hl1sA1Am-nGl5pH_Z5NsY-kLM2xBORdxPApm4DxKmL-on6m1PY1vndHFo)

TerminalでZipを展開します。次のコマンドを実行してください。

```
cd ${HOME}/workspace
unzip hello-tanzu.zip
cd hello-tanzu
```


メニューから”File” -> "Open Folder"を選択してください。"/home/coder/workspace/hello-tanzu" を選択し、"OK" ボタンをクリックしてください。

![alt_text](https://lh4.googleusercontent.com/-cNxNV0cMP4SMHwgru7yceQq0iwXGfb6MFSkJHsBrbZY-GyFq6vCPcmvfQjwJXnYzh6MjlVicVVWk7XxwZsR2kMpSM9RGscClCnz3itnKx4cNVklYIkpKwXvRlJEQVOH2r_AwsWWEONRbjTt0tQ9scw)


Extensions一覧から”Tanzu Developer Tools”を右クリックして、”Extension Settings”を選択し、”Source Image”に次のコマンドの出力結果を設定してください。

```
echo $(cat ${HOME}/acr-token.json | jq -r .loginServer)/sources/demo/hello-tanzu
```

![alt_text](https://lh6.googleusercontent.com/vC81Xr_UDjCbLruVr_vFLiuwKNLTnZOcVt3lw4KthmKS1R40DM-xfmtFXXrfhXTrz6hmuxwIQagu8VYfqeRrD4hcM7oFdS6564C0BoG81ruYANAbSqzGNRsEihF2Uq3Do9mu-4DK3U55DtLu0Yt24Rg)

ACRに再ログインしてください。

```
${HOME}/acr-login.sh 
```

Tiltfileの末尾に次の内容を追記してください。

```
allow_k8s_contexts('tap-sandbox-admin')
```


Tiltfileを右クリックして "Tanzu: Live Update Start" を選択してください。

![alt_text](https://lh4.googleusercontent.com/WEQy733W_kbFx8bXCzIeImLSAyy-G0yqM0gqxhL7Z51LE4tdjZBg6H9LZz8W4oS4ajpvJl2uTYLlWNRTEwn8WdErZITvvDHfTc9DsUVzCriezXu68gOWpy2xNhO5nXYRM5c-eV8VbumW8Ch8OdirlG8)

ローカルパスのソースコードからWorkloadが作成されるのでしばらく待ってください。

![alt_text](https://lh5.googleusercontent.com/39jP6itThlqbfNvgNAoQw4dtTL2k_qQDpMYm1St_NbR84dXJvgMZuAWLBBZCUiUpX5uSGE53eYscJLR2o6NVg3YNLiCVwiPSfew3SntQMRzR6JQDbtFpWVxhTYwg8WOS9bYSV4LgtFw5wCiJ6r7ZGBE)

ログが出力され始めたらTAP GUIのサイドメニューの➕アイコンをクリックし、hello-tanzuのWorkloadを選択してください。Supply Chainでどこまで進んでいるかがわかります。

![alt_text](https://lh4.googleusercontent.com/Y8T0pzvczCIgf5EcekvRv_qse5STowD4WPN9nyRrIcj7xIWkvs4P6gK-aNYtuhT-ZVX4mdbDE3u0QsTo9WsWnKsMiZliGl4awb_UAZ9c46LuD3VSdx9MImDKHU1LXRjo0bGy4qau3pMr-uohDcGFmC8)

次のようなアプリログが出力されたら、デプロイが完了です。

![alt_text](https://lh4.googleusercontent.com/bqIFQgc6UabzjdQ0MQDxJ051NvjQpX09D_aMCSzuvZg8YilG6LMpeBoPmaERzZAeyG7KABcq6vg4yaoMC3hS8JqWoDreDm4gTW_KugvSN_dovFingg5kN3oPX-1lmTV8DwgP1jELnnqmeH_mI-cV4Fw)

TAP GUIでWorkloadを確認するとDeliveryに✅が入っていることが確認できます。

![alt_text](https://lh3.googleusercontent.com/GFP-R0wCmrnxy7xL3E2Qurc-O_IHBlUZVna6f6ybvhK81qBj6Qb9waGA4evMKA5tz3MKiumUrZ5PT8LazF4ubum9zd-aLrLvwOgczp7TTmyLuSR1eh0Ups-f_qKmPWpFkpuSAwi-Ibusr8BgTHToDK0)

次のコマンドを実行してアプリにアクセスしてください。

```
curl -skv $(kubectl get ksvc -n demo hello-tanzu  -ojsonpath='{.status.url}')
```

![alt_text](https://lh5.googleusercontent.com/ZBdXRnvjptxRhOZgFGCxoLmhdOJ4Lo9VL9ZCaUtJCJxesqdszV0uxZyU_5_kMoyRxUajVWiL0PSPgrmDrJu8WfhLyVt3uiHKmn5Ke7V1v1W3bG1P6IndoEMJr57FkGlrr3cwWnvlN7TIdS7knesIz70)


HelloControllerのソースコードを変更してください。

![alt_text](https://lh3.googleusercontent.com/UEVSsaPfKnjiMjNr98pw8x7tRfWtDLDcSNQVlq5ZiCvyWpYuOp3gYYXyk3G66YBbNT6s1xs5DLvzZ2HXNyMRBy_K334d0TfoP5fpxkCcB82GxbbtAKhIYTkGvp9uFTGSYb8nj-ScJqHma84Ukla3tfQ)


Live Updateでソースコードの変更が反映されたら、再度アプリにアクセスして、レスポンスが変わることを確認してください。

```
curl -skv $(kubectl get ksvc -n demo hello-tanzu  -ojsonpath='{.status.url}')
```

![alt_text](https://lh3.googleusercontent.com/jAGQIxfV2bIXGc-rAll3muQrDs62v--tP4aJZ3X4UOoB_HOwy0tMcfrjX_yED2C2q6VEthAej4ZOdmK_ustPxvvhBfx0ENS_TI5BU0osxw8zX2Qt7EDEHx1uz-000DYxCUeiHNpJJbajRup5UCMNgHc)

確認できたらTiltfileを右クリックして、"Tanzu: Live Update Stop"をクリックし、Live Updateを終了してください。

![alt_text](https://lh3.googleusercontent.com/ZpVXJGDvrw2TGdDgNi9MPJY7sJDiSxMWop2v9QFp2baAI_ez650v1-sKGOekcCygtL0d00Odu57Y9le9kcbxnqs03HP5cUJdIfiU_ZSlDcR7Vysk9LD6r8zT6iuv343FIZBWj0832GTJ_zCcwrHsM0k)


次のコマンドを実行してWorkloadを削除してください。

```
tanzu apps workload delete -n demo hello-tanzu --kubeconfig ${HOME}/.kube/config -y
```

#### [O] Acceleratorの追加


[https://github.com/spring-socks/template](https://github.com/spring-socks/template) を追加します。

```
tanzu accelerator create spring-socks --git-repository https://github.com/spring-socks/template --git-branch main
```

Accelerator一覧に "Spring Socks Template" が表示されることを確認してください。

![alt_text](https://lh4.googleusercontent.com/pDLvEs5ZePbV6wF2__Za0pmSwCea6712XJ6DnOhsKSzGzjG6WPNz-mRQPcaZWuT8jB57HaSlb5RbVSmQFYFWLUd8zzEeMmQSH9uPX8ESttNtXyRp8H9I3I_ouqANULRjZiiq76tFLmg95nmm0iH7ghk)


#### [O] TAP GUIのロゴのカスタマイズ


TAP GUIのロゴとタイトルを変更します。tap-values.ymlの次の箇所を変更します。

```yaml
### ….
tap_gui:
  # ….
  app_config:
    customize:
      custom_name: "<Your Product Name> Developer Portal"
      custom_logo: "<base64 encoded logo data>"
    app:
      title: "<Your Product Name> Developer Portal"
      # ….
### ….
```


次のコマンドを実行して、TAPに変更を適用します。

```
tanzu package installed update tap -f ${HOME}/workspace/tap-install/tap-values.yml -n tap-install --kubeconfig ${HOME}/.kube/config
```


次のコマンドを実行し、TAP GUI のPod (server-xxxxx) が新規作成され、READYが "1/1" になるまで待ってください。

```
kubectl get pod -n tap-gui
```

![alt_text](https://lh3.googleusercontent.com/vIq9-Y1E4KddrkuD7_ncqN0xQHPjMJtlj86GWERswNYbAAMMofKVzS2yeREY3slPezGGtfFgEeCiGO6q6V5fr-LVFMA69TeYyTTuPWvprqK1P_W-FZ7j5CvSr5uK3SbUPzCKOH9P_hEWBnBeut6u8Yc)

READYになったら、TAP GUIに再アクセスしてください。


ロゴやタイトルが変更されていることを確認してください。


### Tanzu Application Platformのその他の機能

#### [O] "source-test-to-url" Supply Chainへの変更


ここまで "source-to-url" Supply Chainを使用してきましたが、今度はコンテナイメージを作る前にユニットテストを挟んだ"source-test-to-url" Supply Chainを使用します。

"source-test-to-url" Supply Chainはiterate profileでも利用可能です。

いったんここまで作ったWorkloadを次のコマンドで削除してください。

```
kubectl delete workload -A --all
```


現在のSupply Chainを次のコマンドで確認します。

```
tanzu apps cluster-supply-chain list
```

![alt_text](https://lh3.googleusercontent.com/5YGZkr0Th_MMAKrNQ28jtSJ_JunX-Z_ErJ7HaCLW__UgTFsgZuEJgpWGUduHcdcXq3Mqv_MqoHAAcB48TIbFmqrwoEFaj3SwP_AYgZ6-IOl4xnY91YBIxUpInwW-U4NGaJHa1HGnNhgrOTl7jYL98zY)


次のように、tap-values.yml中の"basic"と設定されている箇所を"testing"に変更してください。

```yaml
### …

supply_chain: testing

ootb_supply_chain_testing:
  # …

### …
```


次のコマンドを実行して、TAPに変更を適用します。

```
tanzu package installed update tap -f ${HOME}/workspace/tap-install/tap-values.yml -n tap-install --kubeconfig ${HOME}/.kube/config
```


更新後のSupply Chainを次のコマンドで確認します。"source-test-to-url"が表示されることを確認してください。

```
tanzu apps cluster-supply-chain list
```

![alt_text](https://lh4.googleusercontent.com/GTxrHCrr57VP_OYqRBbT6u0KHpHI2K4jycaFJdY8RG5RZD2uX2BqaRPtHv1BxDE0GI40gVMwyF5JxdRhGdhUNSTfVk80rEQX43prXCJqgd3jH-j2uHkBttaEzyKvclwWOTMIBC_Af7y7IuixG4LEl1M)

Supply Chainを使うためのSelectorを確認してください。

```
tanzu apps cluster-supply-chain get source-test-to-url
tanzu apps cluster-supply-chain get testing-image-to-url
```

![alt_text](https://lh3.googleusercontent.com/uMEv-zvxe_qjZ7oYiZiVjb0pGsQ4vnLigPc6je1S6Co4dSfNMMeGhZo36X4H-7tI0bUeagKdewQfj4ZOHZc_iXWJtcEkbK2P9Jcdi_yI0Enk9f2so6APnZM3V_HW0u1jFMKx23sd-P_3lNvTLgdBKyY)


"source-test-to-url" を使うにはWorkloadに "apps.tanzu.vmware.com/hast-tests: true" というlabelがついている必要があります。

#### [O or D] Pipelineの作成

Supply Chainの中で使用されるテストスクリプトをTektonのPipelineとして定義します。次のコマンドでPipelineを作成してください。

```yaml
cat <<'EOF' > ${HOME}/workspace/tap-install/pipeline-maven.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: maven-test-pipeline
  labels:
    apps.tanzu.vmware.com/pipeline: test
spec:
  params:
  - name: source-url
  - name: source-revision
  tasks:
  - name: test
    params:
    - name: source-url
      value: $(params.source-url)
    - name: source-revision
      value: $(params.source-revision)
    taskSpec:
      params:
      - name: source-url
      - name: source-revision
      steps:
      - name: test
        image: eclipse-temurin:17
        script: |-
          set -ex
          cd `mktemp -d`
          curl -s $(params.source-url) | tar -m -xzvf -
          ./mvnw clean test -V --no-transfer-progress
EOF

kubectl apply -f ${HOME}/workspace/tap-install/pipeline-maven.yaml -n demo
```


次のコマンドでWorkloadを作成してください。

```
tanzu apps workload apply tanzu-java-web-app \
  --app tanzu-java-web-app \
  --git-repo https://github.com/sample-accelerators/tanzu-java-web-app \
  --git-branch main \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --label apps.tanzu.vmware.com/has-tests=true \
  -n demo \
  -y
```


次のコマンドでWorkloadの状態を確認してください。

```
tanzu apps workload get -n demo tanzu-java-web-app
```


Supply Chainに "source-tester" が追加されていることがわかります。

![alt_text](https://lh5.googleusercontent.com/O94_yYbju5UBvdbxKYG2wfr7OyBFKtlZ792N-Baw9iAmxfaO0fq5eq35jYFViTxBYXPjWn5DA0o840FCMjJ3RuE-vwWv2F2GMJouy6M_RmRDe31La4vkth8j3a9W3DFTI4k8y9qU5J93UPUUa63ZXEY)

次のコマンドを実行してログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=tanzu-java-web-app
```

テストの実行ログを確認できます。

![alt_text](https://lh4.googleusercontent.com/-gCxGHTCmC-kyIJMV9MTp0pM234ftPGSm_HOVneoSTFFWSRxlfbhggskGWSptln7CS6LtwwdhVs1uybrF_jdkasiIx4HRvsrSByvH2iQY6gYXM3C2NnqqLmgFLK2m0r6ByydPJ60qtJdtUMTchEbOCU)


TAP GUIでSupply Chainを確認してください。"Source Tester"が追加されていることを確認できます。

![alt_text](https://user-images.githubusercontent.com/106908/187975069-2c1ec694-41d8-4b25-ab96-2b04ff083f3e.png)

Source Testerをクリックするとテストの実行ログを確認することができます。

![alt_text](https://user-images.githubusercontent.com/106908/187975277-9ad6f4f7-aaba-43c3-9823-17d03aac51fd.png)

テストがパスし、アプリがデプロイされてDeliveryに✅がつくまで待ってください。

![alt_text](https://user-images.githubusercontent.com/106908/187975437-af1935f7-a369-43b1-bfcc-23bed79cbcab.png)

次のコマンドでアプリにアクセスしてください。

```
curl -skv $(kubectl get ksvc -n demo tanzu-java-web-app  -ojsonpath='{.status.url}')
```

![alt_text](https://lh6.googleusercontent.com/HEuTWk_gLQvuktWq8kUMNAihVF9IdKJh4W2NiCyFnM0YPeqe15r1b0bIvaRbuYaKnCEMcyxHWwwrXZsRDU_Y6lTAbYE2W1Ugla0C8rj_rfS1eYZ8oFRyHg9sSSOV7SO-RQCFDsr9itN3JGfztPBDxs8)

* 同じnamespaceで複数のPipelineを扱いたい場合は [https://ik.am/entries/701](https://ik.am/entries/701) を参照。

* Pipelineでキャッシュを使いたい場合は [https://ik.am/entries/700](https://ik.am/entries/700) を参照。

#### [D + O] Service Binding


次はデータベースアクセスのあるアプリ vehicle-api をデプロイします。TAPでは"[Service Binding](https://github.com/servicebinding/spec)"の仕組みを使って、アプリにデータベースを"アタッチ"することができます。これによりアプリはデータベースの接続情報を意識することなく、データベースにアクセスできるようになります。

Service Bindingはiterate profileでも利用可能です

データベースとしてAzure PostgreSQLを使用します。

次のコマンドでAzure PostgreSQLのインスタンスを作成してください。

```
POSTGRESQL_USERNAME=vehicle
POSTGRESQL_PASSWORD=$(openssl rand -base64 32)

az postgres server create \
    --resource-group tap-${NAMESPACE} \
    --name vehicle-db-${NAMESPACE} \
    --location japaneast \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --admin-user ${POSTGRESQL_USERNAME} \
    --admin-password ${POSTGRESQL_PASSWORD} \
    --version 11 \
    --output tsv
```

次のコマンドでAKSから作成したインスタンスにアクセスを許可するためのFirewallの設定を行います。

```
ALLOWED_IP=...

az postgres server firewall-rule create \
    --resource-group tap-${NAMESPACE} \
    --name vehicle-db-${NAMESPACE}-allowed-ip \
    --server vehicle-db-${NAMESPACE} \
    --start-ip-address ${ALLOWED_IP} \
    --end-ip-address ${ALLOWED_IP} \
    --output tsv
```

ALLOWED_IPの値はAKSのoutbound用のIPを設定します。次のコマンドで確認できます。
何も出力されなかったら、もう一度同じコマンドを実行してください。

```
kubectl run -n default curl --timeout=5m --restart=Never --image=curlimages/curl --rm -it -- curl -s https://httpbin.org/ip
```

![alt_text](https://lh5.googleusercontent.com/D-qn62tTR10AuP1PwkppyFH6wSEc8T8Z5RIdzV5sEU7aC5044xEfbT8EWTKMxh0ho4gKH-MMNIoS06lsPr-dBLmPjUQdq_Mh-XERqYVYNtr_rziDPLPSuAUI2rPwD3CyERbk0gMFcaL6Zu0gFzAUtwY)

作成したインスタンスにデータベースを作成します。

```
az postgres db create \
    --resource-group tap-${NAMESPACE} \
    --name vehicle \
    --server-name vehicle-db-${NAMESPACE} \
    --output tsv
```

PostgreSQLへの接続情報を次のコマンドで出力します。

```
az postgres server show --resource-group tap-${NAMESPACE} --name vehicle-db-${NAMESPACE}  > ${HOME}/vehicle-db.json
```

[Service Bindingの仕様](https://github.com/servicebinding/spec#example-secret)に合わせて、次のような形式のSecretを作成します。

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: <Service Instance Name>
type: servicebinding.io/<Type>
stringData:
  type: <Type>
  host: …
  port: …
  username: …
  password: …
  # …
```

実際にどのようなフィールドを設定すべきかは、このService Bindingに対応したクライアントライブラリに依存します。

TAPではSpring Bootのアプリのコンテナイメージには[spring-cloud-bindings](https://github.com/spring-cloud/spring-cloud-bindings)というライブラリをbuildpackで自動で埋め込みます。

このライブラリを使う場合は[PostgreSQL](https://github.com/spring-cloud/spring-cloud-bindings#postgresql-rdbms)にアクセスする際に、Secretのフィールドがアプリのプロパティへと次の表のようにマッピングされます。

![alt_text](https://lh3.googleusercontent.com/ykZpl1QaT0P8QsfD6K78SHOqLd1FkjzNnKMX7gvvjMyGFwd4eUPVcRBHSPuGHh76wGBGwmA4KYdnmABxRoU1GrlJtkonNWEgmw67Qq8rEzwKpZWSKsCQ40diBFBX_rLMH0P8I2gvkSVwvXGcp0j20eI)


このマッピングに合うように、Azure PostgreSQLにアクセスするためのSecretを次のように作成します。

```yaml
cat <<EOF > ${HOME}/vehicle-db.yaml
apiVersion: v1
kind: Secret
metadata:
  name: vehicle-db
type: servicebinding.io/postgresql
stringData:
  type: postgresql
  host: $(cat ${HOME}/vehicle-db.json  | jq -r .fullyQualifiedDomainName)
  port: "5432"
  username: ${POSTGRESQL_USERNAME}@vehicle-db-${NAMESPACE}
  password: "${POSTGRESQL_PASSWORD}"
  database: vehicle
  sslmode: require
EOF

kubectl apply -f ${HOME}/vehicle-db.yaml -n demo
```

このデータベースを使用したアプリをデプロイします。Service Bindingの設定は--service-refオプションで行います。

次のコマンドを実行してください。

```
tanzu apps workload apply vehicle-api \
  --app vehicle-api \
  --git-repo https://github.com/making/vehicle-api \
  --git-branch main \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --label apps.tanzu.vmware.com/has-tests=true \
  --service-ref vehicle-db=v1:Secret:vehicle-db \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=vehicle-api
```

Known Issueですが、Service Bindingを使用してWorkloadをデプロイした場合、最初のrevision (00001) は接続情報のSecretが設定されていない状態でアプリがデプロイされてしまいます。その結果、デフォルトのlocalhostに接続しに行こうと試み、エラーが発生します。

![alt_text](https://lh6.googleusercontent.com/SsNc8xiuesyFJahrHg8eiQo98vUO-kaw8Fel75mN1retjSHoPNmmRPcmyHQ9xtOcHsBuEfDTIz8wJG7H1T1xv9qaqZoFu6YSn-aQ6M-ZWv1qOgD0pAEB8i85d483dO7udpqnSNTpl0jkvzoCBdhw6xA)

revision 00001ができたすぐ後にrevision 00002がデプロイされ、このrevisionではは接続情報のSecretが正しく設定されるため、Service Binidingから接続情報をプロパティが設定され、PostgreSQLに接続できます。

![alt_text](https://lh3.googleusercontent.com/Z7w8ty-XmXAssyxuvS6ug1Q64e9e2Hnhp_JDjPoRhEL8AzHviMxtdDXr6cX5bamUq59kvhpuuj5ePefcckCe_LUIRQcRcUooPt3QAQu3aIBNdyxM3Odrra-2M3qZ0oPZzVoGUq1OKwkqbjcGLN0zxR8)


次のコマンドでアプリにアクセスしてください。

```
curl -sk $(kubectl get ksvc -n demo vehicle-api -ojsonpath='{.status.url}')/vehicles | jq .
```

![alt_text](https://lh4.googleusercontent.com/gW-gzw46g5xRx3ZKNZhumBd73r5-L6LRpybNmGumd2XgFH0YnPTp7a-IxX5iruRreti4F35q3YStU56DBsiQL4J9S8H0Rv2RIGcRaFmWmsUxoXUKEz-sX_rTvXAZyWSU8Pp5lWr4wsFNcQ6hWr25bqw)


次のコマンドでデータを追加してください。

```
curl -sk $(kubectl get ksvc -n demo vehicle-api -ojsonpath='{.status.url}')/vehicles -d "{\"name\":"Sienta\"}" -H "Content-Type: application/json" | jq .
```

![alt_text](https://lh6.googleusercontent.com/FgyYxjKrh5iWBfxm-osMpGECeHUO4ZOJgNGMN1nKLv6s3AJZLxM0V3UxZUu8WyIDruxCx7bTvQjqRQLNY7-eENf4Q57E1YPdz2mYPKlEFdL975MkEmbis99ioiaOvzSzLAwIKb0BxV7XCsJ6V48Frbs)


次のコマンドを再度実行し、追加したデータが表示されることを確認してください。

```
curl -sk $(kubectl get ksvc -n demo vehicle-api -ojsonpath='{.status.url}')/vehicles | jq .
```

![alt_text](https://lh6.googleusercontent.com/fkqEOXp2U0juMSyX-AAqTplrwZ2EB7WIbyD41nCdkgfZ6gSijroV2eLbkFLHQv4vLnW3sK-JldJ_E_BVSIuqftPnbOUrHOx3HWfqnDqbt0h5uUSCgRn-NvBIONSVrJ-SYOBMV6ev0WpbUg4I4V-R3V0)

アプリのPodを次のコマンドで削除してください。しばらくすると自動で復旧します。

```
kubectl delete pod -n demo -l app.kubernetes.io/component=run,app.kubernetes.io/part-of=vehicle-api --force
```


復旧後に再度アプリにアクセスし、データが失われていないことを確認してください。

```
curl -sk $(kubectl get ksvc -n demo vehicle-api -ojsonpath='{.status.url}')/vehicles | jq .
```

TAP GUIにvehicle-apiのCatalogを登録します。次のURLを登録してください。

[https://github.com/making/vehicle-api/blob/main/catalog/catalog-info.yaml](https://github.com/making/vehicle-api/blob/main/catalog/catalog-info.yaml)

![alt_text](https://lh5.googleusercontent.com/Yy2UPK1CtDjKJ1VhBUCYGyIOOD9LoFKcrx_nXo4_bm2LZ9fQj9gDlfaGAXaafXXHBfx3ayXIToUcdVZUW8M8sGYgKBxxQ33zCqOdn3jSVGr4zF-EVZD57jfY9q3Y3OzuBda4GyH6jklKtatQF6xevWw)


vehicle-apiのApp Live Viewを確認してください。

![alt_text](https://lh6.googleusercontent.com/I9KqNwIcsGGipHjI9QRJ5Yc4v5m3nqkVD27VB-BBfXm4K3-YVg-fppCIzKkMQIlsE9jo__NWv-0YNzW05pr2IqEW9y6rNVGnSDoJ1p1tI9GXbFJZrK2LT2yv80V_rIkQxeCzCYsoMxBj4PPjySu2r5g)

Healthを選択するとPostgreSQLとの接続状態の確認ができます。

![alt_text](https://lh4.googleusercontent.com/kLt58Gq-E9t3cd65qbSAdnZayhGbM50_wQpPRPknYK1WoG8HBZRHJQ4YYgToqyM2FDEkOlNd1iN6xLwybWYw4d9uk90DdaR9OoiXnVkXuTQvKdGahEevtbpVnWjOneIDfGrsQLxdCeR0RQZD_Dfd-2o)

#### [D + O] Resource Claim


前節ではアプリに必要なデータベースの接続情報をSecretとして直接作成し、バインドしました。

今回はResource Claimという、プールされたリソースからサービスのインスタンスを確保する方法でService Bindingを行います。

Resource Claimはiterate profileでも利用可能です

demo namespaceに作成したSecretを次のコマンドで削除してください。

```
kubectl delete secret -n demo vehicle-db
```


次のコマンドでResource ClaimによってSecretを管理するためのRBACの設定を行います。

```yaml
cat <<EOF > ${HOME}/workspace/tap-install/resourceclaim-role.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: resource-claims
  labels:
    servicebinding.io/controller: "true"
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "watch"]
EOF
kubectl apply -f ${HOME}/workspace/tap-install/resourceclaim-role.yaml
```

PostgreSQLのInstance Classを定義します。ここでは "type" fieldが "servicebinding.io/postgresql" であるSecretをPostgreSQLインスタンスと定義します。

```yaml
cat <<EOF > ${HOME}/workspace/tap-install/clusterinstanceclass.yaml
---
apiVersion: services.apps.tanzu.vmware.com/v1alpha1
kind: ClusterInstanceClass
metadata:
  name: postgresql
spec:
  description:
    short: PostgreSQL
  pool:
    group: ""
    kind: Secret
    fieldSelector: type=servicebinding.io/postgresql
EOF

kubectl apply -f ${HOME}/workspace/tap-install/clusterinstanceclass.yaml
```


次のコマンドでこのクラスタ上で定義されているInstane Class一覧を表示します。

```
tanzu service classes list
```

![alt_text](https://lh3.googleusercontent.com/jjwM9IfIFj9f8z0lFXUC4NV77AcRQvY8oIOF1JZDIjg8fVNEDWbsOYg3q6A4NfoNvOphGPG4DFJckOyr4Y9mnoJjXx4KajZ-HeUq1mnDyl4d2vmW4Ei48qqEAY63vYr7aBwHDzEzOXmXaJuAgqf4pws)


次のコマンドでdemo namespaceで利用可能なPostgreSQLインスタンス一覧を表示します。

```
tanzu service claimable list --class postgresql -n demo
```


まだ利用可能なインスタンスは用意されていません。

![alt_text](https://lh4.googleusercontent.com/R2daH3I6tD-DioyPQW0DRjJs5f20bFDsr4Lh5Ti4-cGH93hu23l4vLG0-pN5QtuzarjRCVRfyS50xh1Fh18pzKyh_0CrlIMgaSzBgwM75ocjtx3MhYOlQ1rA4Ab1BHWCo4Q35qMbKrRS-Z5Rya38Mf0)


サービスインスタンスを管理するnamespaceとしてservice-instancesを作成します。

```
kubectl create namespace service-instances
```


前説で作ったAzure PostgreSQLへの接続情報を持つSecretをservice-instances namespaceに作成します。

```
kubectl apply -f ${HOME}/vehicle-db.yaml -n service-instances
```


次のコマンドで再度demo namespaceで利用可能なPostgreSQLインスタンス一覧を表示します。

```
tanzu service claimable list --class postgresql -n demo
```


まだ利用可能なインスタンスはありません。vehicle-dbはdemo namespaceではなく、service-instances namespaceに作成されているからです。

![alt_text](https://lh4.googleusercontent.com/R2daH3I6tD-DioyPQW0DRjJs5f20bFDsr4Lh5Ti4-cGH93hu23l4vLG0-pN5QtuzarjRCVRfyS50xh1Fh18pzKyh_0CrlIMgaSzBgwM75ocjtx3MhYOlQ1rA4Ab1BHWCo4Q35qMbKrRS-Z5Rya38Mf0)


次のコマンドでservice-instances namespaceに作成されているSecretを他のnamespaceで参照できるようなポリシーを作成します。

```yaml
cat <<EOF > ${HOME}/workspace/tap-install/resourceclaimpolicy.yaml
apiVersion: services.apps.tanzu.vmware.com/v1alpha1
kind: ResourceClaimPolicy
metadata:
  name: cross-namespace
  namespace: service-instances
spec:
  consumingNamespaces:
  - '*'
  subject:
    group: ""
    kind: Secret
EOF
kubectl apply -f ${HOME}/workspace/tap-install/resourceclaimpolicy.yaml
```


次のコマンドで再度demo namespaceで利用可能なPostgreSQLインスタンス一覧を表示します。

```
tanzu service claimable list --class postgresql -n demo
```


今度はservice-instances namespaceにvehicle-dbが利用可能になりました。

![alt_text](https://lh4.googleusercontent.com/Kc-A1rWIbpE_DesIcvyXaIqebDBbdwlMEUlg-1Nafsvqm_TAgdPJJHHg3FVgbkTNuizg-C_sFLVjuCSwhFAqcO5ikEgM854nEk1DzWsYh_rfwdg4FrDpjeHVKQ9Kkaf8sU5NHebXp9NsDcm7l12VzA8)


次のコマンドでservice-instances namespaceのvehicle-dbをdemo namespaceで使うための確保を行います。

```
tanzu service claim create vehicle-db \
  --resource-name vehicle-db \
  --resource-namespace service-instances \
  --resource-kind Secret \
  --resource-api-version v1 \
  -n demo
```

![alt_text](https://lh3.googleusercontent.com/ZJYRHSU1C2HMyQNS4BKMz1cYcERawuefiNsWEMGels42RbXqaZrGomvKvlrp1niS5ir9JmNmiGM47MgWfebHRpOHnuxjHYMogVlwbE_CaMT5CouKs1xt6Bby3cF6K3TSgqTRQkCno5wM5RLSIyC0S8o)


確保したサービスの情報を次のコマンドで確認できます。

```
tanzu services claims get vehicle-db -n demo
```

![alt_text](https://lh4.googleusercontent.com/CPk2WqPU3wzHLozbP03SF9iN2_h_tr2sx-O9mmYS3pquGhksqPIfe-ybvs7edeQG5nRqW4P_SokKTh_Ilfwoc2i_rew_SaBdzaFEbgkR2zTXLJuUfnWCCUU8zDuLsBsn0CL-51mXPDJOhLsh5DhJNik)

service-instances namespaceからこのインスタンスに関するSecretがコピーされます。

```
kubectl get secret -n demo vehicle-db
```

![alt_text](https://lh6.googleusercontent.com/51COvE6dv1ifAcuRwo2CSidhRNQrdj_RRXztunSyqWEXS_u_-MKp00kp2nr_TbAjZaepT2cJergf8l7wAOcgq0EjGFOu4BgeVeqEPK-bvxIWjhi-5_yC0izB7NUb40koHLxh2Xgssq_vG17Pqz_ewY4)

次のコマンドで再度demo namespaceで利用可能なPostgreSQLインスタンス一覧を表示します。

```
tanzu service claimable list --class postgresql -n demo
```


vehicle-dbは確保されたため、利用可能ではなくなりました。

![alt_text](https://lh4.googleusercontent.com/R2daH3I6tD-DioyPQW0DRjJs5f20bFDsr4Lh5Ti4-cGH93hu23l4vLG0-pN5QtuzarjRCVRfyS50xh1Fh18pzKyh_0CrlIMgaSzBgwM75ocjtx3MhYOlQ1rA4Ab1BHWCo4Q35qMbKrRS-Z5Rya38Mf0)


確保したリソースはResourceClaimリソースとして管理されます。次のコマンドでSecretの代わりにResourceClaimをバインドしてください。

```
tanzu apps workload apply vehicle-api \
  --app vehicle-api \
  --git-repo https://github.com/making/vehicle-api \
  --git-branch main \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --label apps.tanzu.vmware.com/has-tests=true \
  --service-ref vehicle-db=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:vehicle-db \
  -n demo \
  -y
```


次のコマンドでログを確認してください。

```
stern -n demo -l app.kubernetes.io/part-of=vehicle-api
```


生成されたmanifestがResourceClaimを使用していることが分かります。

![alt_text](https://lh3.googleusercontent.com/xFEYSEVtcfmj0w33ia6KK1gtOVW-U1vk7TL3Piz_PjW443rDaL48r4SqKEueolfw6fVhgyBMpF1MxsTT7DBvlKmMC7cus9sXCk6MNZEWsVgnSHBMcx-RedxNrzEyTjvtJpwQvndGJx7X0YcZ8ZyjolI)

今回はResourceClaimの名前とSecretの名前が同じだったので変更点が分かりづらいですが、ResourceClaimとSecretの名前は必ずしも一致するわけではありません。また、適切なRBAC設定されている場合、DeveloperはSecretを参照することはできませんが、ResourceClaimは参照できます。したがって、Developer観点ではSecretをバインドするよりもResourceClaimを参照する方がより良いです。Operator観点でもResouce Claimを使用すると、リソースをプールして公開することにより、self-serviceのようにDeveloperにデータベースを利用してもらえるという運用的メリットがあります。

#### [O] DeveloperのRBAC


Azure AD上でグループを作成してください。

```
GROUP_ID=$(az ad group create --display-name tap-demo-developer-${NAMESPACE} --mail-nickname tap-demo-developer-${NAMESPACE} --query id -o tsv)
```

グループ内のメンバー一覧を確認します。この段階ではメンバーは空です。

```
az ad group member list --group tap-demo-developer-${NAMESPACE} 
```

ログインユーザーをグループに追加します。

```
az ad group member add --group tap-demo-developer-${NAMESPACE} --member-id $(az ad signed-in-user show --query id --output tsv)
```


グループ内のメンバー一覧を確認し、追加したユーザーが含まれていることを確認してください。

```
az ad group member list --group tap-demo-developer-${NAMESPACE} 
```

グループに対し、demo namepsaceへの`app-editor` Roleと、`app-editor-cluster-access` CluserRoleをバインドします。

```
kubectl create rolebinding app-editor -n demo --clusterrole app-editor --group ${GROUP_ID}
kubectl create clusterrolebinding app-editor-${GROUP_ID} --clusterrole app-editor-cluster-access --group ${GROUP_ID}
```

demo namespaceのrolebiningを確認してください。

```
kubectl get rolebinding -n demo app-editor -owide
```

![alt_text](https://lh6.googleusercontent.com/91lukCwZmhWU42JRmT2Jra70kQpKdHtDUSU4G0uEK3hWOMJLNq8FQqkxqz6aH6037_zIv7ozOgW_s7UOJRYVzmGhgc4Ykxf3YElRIrcQ7aJ0WBb7UGAi8I-WloQc_ofZrjZSWu87YIAxXzdktvGmZkU)

clusterrolebiningを確認してください。

```
kubectl get clusterrolebinding app-editor-${GROUP_ID} -o wide
```

![alt_text](https://lh3.googleusercontent.com/1NC98Gyc6JZuzVITHW30i7ztSFE4EDuexzWkJbCZSnnlNozq99oTg1tLb_DDysz50kJaUK7Md98bc1sXJxpzaTe0OfRwy-y5BYTnAVoHgPRvVDbPf-KG5gnv49YeHrxbV-uM6r9_V3N6DP6CNIQOqMg)


adminではなく、一般ユーザーとしてAKSにアクセスするためのconfigを取得します。

```
az aks get-credentials --resource-group tap-${NAMESPACE} --name tap-sandbox --overwrite-existing
```

default namespaceのPod一覧の取得を試みてください。権限がなく、アクセスを拒否されます。

```
kubectl get pod -n default
```

![alt_text](https://lh6.googleusercontent.com/7v-4PYJ-ETia_LaTwcqjtPASPrg8KH8SGWcoOBYgBqwhpPafM0mAu1_MRGY6VXjVoHnRyO-bts1ZZojkLzcns8Oarku0RzM6-ni5RwDEp_Iqvl2dg5PZ5a5AAm3rXD7hM8KXXHC0DuvyxcTjvEvBbpQ)

demo namespaceのPod一覧の取得を試みてください。権限があるためPod一覧を取得できます。

```
kubectl get pod -n demo
```

![alt_text](https://lh6.googleusercontent.com/G5dRAurgl8Mb6DNjNyjeBIH5Nnq0-JDJTxpVPkKUCdgfqzOIYf5Ks4LFyE2sITaHDzKID6J0aEU6H0bvK0L-kN4GPPbnDSz8JBxPSpeuO7FoMjst-EG4G5c3re9rb-tUkXSxhd3-EZyKBc_shDCyufU)

demo namespaceのWorkload一覧を取得できることを確認してください。

```
tanzu apps workload list -n demo
```


![alt_text](https://lh6.googleusercontent.com/XVbt9BoSicXwo16h3NO3ueFsRGu6HrwAFqrMHke2LP0JnDy4aFV8pwvfP8wqZ3SzwZJOxj_GHF3KlZipurj3XWkfnR_mVDseXqcZAketKnzUnZVJQOUiBkeIsSP65YtZl34pDi6LpH2FtzzUrjhFsBQ)


demo namespaceでもSecretは取得できません。

```
kubectl get secret -n demo
```

![alt_text](https://lh6.googleusercontent.com/XVbt9BoSicXwo16h3NO3ueFsRGu6HrwAFqrMHke2LP0JnDy4aFV8pwvfP8wqZ3SzwZJOxj_GHF3KlZipurj3XWkfnR_mVDseXqcZAketKnzUnZVJQOUiBkeIsSP65YtZl34pDi6LpH2FtzzUrjhFsBQ)

一方、ResourceClaimであれば取得できます。

```
tanzu service claim list -n demo
```

![alt_text](https://lh3.googleusercontent.com/C-aEbd6zFHJD9_Hkqoqse7Sw0u1dQ-ik3XbcuPlIxT9DSPPLBLzDXpPeRCNrVvWdlWt3ee_MHPbjZvY_vTb0R_3718ffN_k9nOC5cvoSxZ_-wcXW_xS0pSyAnw6FcW5KnYBoPNJUtcz75QtWyfQVCK8)

Workloadを削除できることを確認してください。

```
tanzu apps workload delete -n demo vehicle-api -y 
```

Workloadを作成できることを確認してください。

```
tanzu apps workload apply vehicle-api \
  --app vehicle-api \
  --git-repo https://github.com/making/vehicle-api \
  --git-branch main \
  --type web \
  --annotation autoscaling.knative.dev/minScale=1 \
  --label apps.tanzu.vmware.com/has-tests=true \
  --service-ref vehicle-db=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:vehicle-db \
  -n demo \
  -y
```

#### [O] TAP GUIのAzure AD連携

TBD

[https://ik.am/entries/708](https://ik.am/entries/708) を参照

#### [D + O] WorkloadのGitOps

TBD
[https://ik.am/entries/706](https://ik.am/entries/706) を参照

### リソースの削除

ハンズオンが終わったら、次のコマンドを実行して作成したリソースを削除してください。

```
az group delete --name tap-${NAMESPACE} -y
```
