Carvelでパッケージを作って公開する

本記事は[TUNA-JP Advent Calendar 2021](https://qiita.com/advent-calendar/2021/tuna-jp)の12月19日分の投稿です。

## Tanzuのパッケージシステム

[Tanzu Kubernetes Grid](https://tanzu.vmware.com/jp/kubernetes-grid)や[Tanzu Community Edition](https://tanzucommunityedition.io/)ではKubernetes上のソフトウェアがパッケージとして提供されます。実際にTCEで作成したクラスターを確認すると、以下の通りCNIやCSIはパッケージとしてインストールされており、AKOやPinnipedもパッケージとして利用できることが確認できます。

```
$ tanzu package repository list -n tkg-system
/ Retrieving repositories...
  NAME        REPOSITORY                                                                  STATUS               DETAILS
  tanzu-core  projects.registry.vmware.com/tkg/packages/core/repo:v1.21.2_vmware.1-tkg.1  Reconcile succeeded

$ tanzu package installed list -n tkg-system
/ Retrieving installed packages...
  NAME            PACKAGE-NAME                     PACKAGE-VERSION  STATUS
  antrea          antrea.tanzu.vmware.com                           Reconcile succeeded
  metrics-server  metrics-server.tanzu.vmware.com                   Reconcile succeeded
  vsphere-cpi     vsphere-cpi.tanzu.vmware.com                      Reconcile succeeded
  vsphere-csi     vsphere-csi.tanzu.vmware.com                      Reconcile succeeded

$ tanzu package available list -n tkg-system
/ Retrieving available packages...
  NAME                                                DISPLAY-NAME                       SHORT-DESCRIPTION                                                                                                     
  addons-manager.tanzu.vmware.com                     tanzu-addons-manager               This package provides TKG addons lifecycle management capabilities.                                                   
  ako-operator.tanzu.vmware.com                       ako-operator                       NSX Advanced Load Balancer using ako-operator                                                                         
  antrea.tanzu.vmware.com                             antrea                             networking and network security solution for containers                                                               
  calico.tanzu.vmware.com                             calico                             Networking and network security solution for containers.                                                              
  kapp-controller.tanzu.vmware.com                    kapp-controller                    Kubernetes package manager                                                                                            
  load-balancer-and-ingress-service.tanzu.vmware.com  load-balancer-and-ingress-service  Provides L4+L7 load balancing for TKG clusters running on vSphere                                                     
  metrics-server.tanzu.vmware.com                     metrics-server                     Metrics Server is a scalable, efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines.
  pinniped.tanzu.vmware.com                           pinniped                           Pinniped provides identity services to Kubernetes.                                                                    
  vsphere-cpi.tanzu.vmware.com                        vsphere-cpi                        The Cluster API brings declarative, Kubernetes-style APIs to cluster creation, configuration and management. Cluster API Provider for vSphere is a concrete implementation of Cluster API for vSphere.
  vsphere-csi.tanzu.vmware.com                        vsphere-csi                        vSphere CSI provider
```

パッケージリポジトリはOCIイメージとしてバンドル化されており、kapp-controllerはこのOCIファイルを参照してパッケージのインストールを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27668/9f93001f-a96c-62d3-b175-f412f2b2d7d8.png)

リポジトリを追加することにより追加パッケージを利用することが可能になります。

```
$ tanzu package repository add tce-repo ¥
  --url projects.registry.vmware.com/tce/main:0.9.1 ¥
  --namespace tanzu-package-repo-global

$ tanzu package repository list -n tanzu-package-repo-global
- Retrieving repositories...
  NAME      REPOSITORY                                   STATUS       DETAILS
  tce-repo  projects.registry.vmware.com/tce/main:0.9.1  Reconciling

$ tanzu package repository list -n tanzu-package-repo-global
- Retrieving repositories...
  NAME      REPOSITORY                                   STATUS               DETAILS
  tce-repo  projects.registry.vmware.com/tce/main:0.9.1  Reconcile succeeded

$ tanzu package available list -n tanzu-package-repo-global
- Retrieving available packages...
  NAME                                           DISPLAY-NAME        SHORT-DESCRIPTION
  cert-manager.community.tanzu.vmware.com        cert-manager        Certificate management
  contour.community.tanzu.vmware.com             Contour             An ingress controller
  external-dns.community.tanzu.vmware.com        external-dns        This package provides DNS synchronization functionality.
  fluent-bit.community.tanzu.vmware.com          fluent-bit          Fluent Bit is a fast Log Processor and Forwarder
  gatekeeper.community.tanzu.vmware.com          gatekeeper          policy management
  grafana.community.tanzu.vmware.com             grafana             Visualization and analytics software
  harbor.community.tanzu.vmware.com              Harbor              OCI Registry
  knative-serving.community.tanzu.vmware.com     knative-serving     Knative Serving builds on Kubernetes to support deploying and serving of applications and functions as serverless containers
  local-path-storage.community.tanzu.vmware.com  local-path-storage  This package provides local path node storage and primarily supports RWO AccessMode.
  multus-cni.community.tanzu.vmware.com          multus-cni          This package provides the ability for enabling attaching multiple network interfaces to pods in Kubernetes
  prometheus.community.tanzu.vmware.com          prometheus          A time series database for your metrics
  velero.community.tanzu.vmware.com              velero              Disaster recovery capabilities
```

## Carvelとは

パッケージ管理ステムとして[Carvel](https://carvel.dev/)が利用されています。Carvelはアプリケーション開発者とプラットフォーム運用者が、Kubernetes環境でコンテナ化されたアプリケーションをビルド、配布、インストール、管理するためのツール群で、以下のツールで構成されています。以前はk14s(Kubernetes Tools)という名前で公開されていました。

- ytt : YAMLのテンプレートとオーバーレイによるパッチの実現
- kbld : コンテナイメージのビルドと参照
- imgpkg : コンテナレジストリを介してアプリケーションの構成をバンドル、共有する
- kapp : 複数のリソースを単一のアプリケーションのようにインストール・アップグレード・削除・Reconcileする
- kapp-controller : App　CRDによりアプリケーションをデプロイ可能
- vendir : ディレクトリの内容を宣言的に記述する

## パッケージの作成

パッケージがコンテナイメージで提供されていることがわかったので、[Tutorial: Create and Install a Package](https://carvel.dev/kapp-controller/docs/latest/packaging-tutorial/)を参考にしてカスタムパッケージを作成してみます。以下で作成したサンプルは[こちら](https://github.com/masanara/carvel-test-repo)においてあります。

### パッケージ化の対象

今回は[podinfo](https://github.com/stefanprodan/podinfo)をDeploymentとして作成し、Serviceとしてアクセス可能にする以下のようなシンプルなマニフェストをパッケージ化してみます。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: podinfo
  name: podinfo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      containers:
      - image: stefanprodan/podinfo:6.0.3
        name: podinfo
        env:
        - name: PODINFO_UI_COLOR
          value: blue
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: podinfo
  name: podinfo
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 9898
  selector:
    app: podinfo
  type: LoadBalancer
```

### マニフェストのテンプレート化

yttのTemplating機能を利用して変数化したいパラメータを外部ファイルから参照する構成にしてパッケージ化することで、パッケージインストール時に変数の値をカスタマイズすることが可能になります。今回はpodinfoのreplica数、環境変数`PODINFO_UI_COLOR`、Serviceタイプ等が指定できるよう、マニフェストをテンプレート(`config.yml`)とData Value(`values.yml`)に分離します。

- config.yml

```yaml
#@ load("@ytt:data", "data")
#@ def labels():
app: podinfo
#@ end
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  replicas: #@ data.values.replicas
  selector:
    matchLabels: #@ labels()
  template:
    metadata:
      labels: #@ labels()
    spec:
      containers:
      - image: stefanprodan/podinfo:6.0.3
        name: podinfo
        env:
        - name: PODINFO_UI_COLOR
          value: #@ data.values.ui_color
---
apiVersion: v1
kind: Service
metadata:
  labels: #@ labels()
  name: podinfo
spec:
  ports:
  - protocol: TCP
    port: #@ data.values.svc_port
    targetPort: #@ data.values.app_port
  selector: #@ labels()
  type: #@ data.values.svc_type
```

- values.yml

```yaml
#@data/values-schema
---
replicas: 3
ui_color: blue
svc_port: 80
app_port: 9898
svc_type: LoadBalancer
```

`package-contents/config`ディレクトリを作成し、ファイルをconfigディレクトリ配下にコピーします。

```bash
$ mkdir -p package-contents/config
$ cp config.yml package-contents/config/config.yml
$ cp values.yml package-contents/config/values.yml
```

この状態でyttコマンドでconfigディレクトリを指定すると、config.ymlとvalues.ymlからpodinfoのマニフェストが生成されます。

```bash
$ ytt -f package-contents/config
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  replicas: 5
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      containers:
      - image: stefanprodan/podinfo:6.0.3
        name: podinfo
        env:
        - name: PODINFO_UI_COLOR
          value: blue
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: podinfo
  name: podinfo
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9898
  selector:
    app: podinfo
  type: LoadBalancer
```

### パッケージOCIイメージの公開

kbldを利用して`stefanprodan/podinfo`のタグ(`6.0.3`) をダイジェストに変換し、lockファイル(`package-contents/.imgpkg/images.yml`)を生成します。

```bash
$ kbld -f package-contents/config/ --imgpkg-lock-output package-contents/.imgpkg/images.yml
resolve | final: stefanprodan/podinfo:6.0.3 -> index.docker.io/stefanprodan/podinfo@sha256:4e41e8b95094a657236d3f4a923af7101ca35c43d89bcf7874f907c68e784644
```

lockファイルにはタグとダイジェストのマッピングが記録されています。lockファイルによりpodinfoコンテナイメージの一貫性を保証することが可能になります。

```yaml
---
apiVersion: imgpkg.carvel.dev/v1alpha1
images:
- annotations:
    kbld.carvel.dev/id: stefanprodan/podinfo:6.0.3
    kbld.carvel.dev/origins: |
      - resolved:
          tag: 6.0.3
          url: stefanprodan/podinfo:6.0.3
  image: index.docker.io/stefanprodan/podinfo@sha256:4e41e8b95094a657236d3f4a923af7101ca35c43d89bcf7874f907c68e784644
kind: ImagesLock
```

マニフェストのパッケージ化準備ができたので、imgpkgコマンドを利用して`package-contents`配下のファイル群をOCIイメージに変換し、`masanara/podinfo:1.0.0`としてdocker hubにpushします。

```bash
$ imgpkg push -b masanara/podinfo:1.0.0 -f package-contents
dir: .
dir: .imgpkg
file: .imgpkg/images.yml
dir: config
file: config/config.yml
file: config/values.yml
Pushed 'index.docker.io/masanara/podinfo@sha256:5a188481d1cc69168215bbf4778d7687988def9b31173f1fbb657e1321c16866'
Succeeded
```

## リポジトリバンドルの作成

### PackageMetadataカスタムリソースの作成

リポジトリバンドルに登録するpodinfoパッケージのPackageMetadataカスタムリソースを作成します。(`metadata.yml`)

```yaml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: PackageMetadata
metadata:
  # This will be the name of our package
  name: podinfo.corp.com
spec:
  displayName: "Podinfo App"
  longDescription: "Podinfo is a tiny web application made with Go that showcases best practices of running microservices in Kubernetes"
  shortDescription: "Podinfo app for demoing"
  categories:
  - demo
```

podinfoパッケージを定義するための

Data Value(`values.yml`)ファイルで指定している要素をOpenAPIスキーマとして記述します。

>  OpenAPI Schemaの出力にはytt v0.38.0以降が必要です。2021/12/18現在の最新バージョンはv0.38.0です。

```bash
$ ytt -f package-contents/config/values.yml --data-values-schema-inspect -o openapi-v3 > schema-openapi.yml
```

生成される`schema-openapi.yml`は以下のような内容になります。

```yaml
openapi: 3.0.0
info:
  version: 0.1.0
  title: Schema for data values, generated by ytt
paths: {}
components:
  schemas:
    dataValues:
      type: object
      additionalProperties: false
      properties:
        replicas:
          type: integer
          default: 5
        ui_color:
          type: string
          default: blue
        svc_port:
          type: integer
          default: 80
        app_port:
          type: integer
          default: 9898
        svc_type:
          type: string
          default: LoadBalancer
```

### Packageカスタムリソースの作成

リポジトリバンドルに含めるパッケージ情報をPackageカスタムリソースとして作成します。Pakcageカスタムリソースもyttのテンプレート機能を利用して作成します。Packageリソースのテンプレートを`package-template.yml`として作成します。`imgpkgBundle`としてパッケージのOCIを参照します。

```yaml
#@ load("@ytt:data", "data")  # for reading data values (generated via ytt's data-values-schema-inspect mode).
#@ load("@ytt:yaml", "yaml")  # for dynamically decoding the output of ytt's data-values-schema-inspect
---
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
  name: #@ "podinfo.corp.com." + data.values.version
spec:
  refName: simple-app.corp.com
  version: #@ data.values.version
  releaseNotes: |
        Initial release of the Podinfo App package
  valuesSchema:
    openAPIv3: #@ yaml.decode(data.values.openapi)["components"]["schemas"]["dataValues"]
  template:
    spec:
      fetch:
      - imgpkgBundle:
          image: #@ "masanara/podinfo:" + data.values.version
      template:
      - ytt:
          paths:
          - "config/"
      - kbld:
          paths:
          - "-"
          - ".imgpkg/images.yml"
      deploy:
      - kapp: {}
```

リポジトリバンドルOCIイメージに必要なディレクトリを作成します。

```bash
$ mkdir -p test-repo/.imgpkg test-repo/packages/podinfo.corp.com
```

yttによりPackageリソーステンプレートに対して、Data ValueとしてOpenAPIスキーマファイルと`version="1.0.0"`を指定してPackageカスタムリソースのマニフェストを作成します。

```bash
$ ytt -f package-template.yaml --data-value-file openapi=schema-openapi.yml --data-value version="1.0.0" > test-repo/packages/podinfo.corp.com/1.0.0.yml
```

作成されるマニフェスト`1.0.0.yml`は以下のような内容になります。

```yaml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
  name: podinfo.corp.com.1.0.0
spec:
  refName: podinfo.corp.com
  version: 1.0.0
  releaseNotes: |
    Initial release of the Podinfo App package
  valuesSchema:
    openAPIv3:
      type: object
      additionalProperties: false
      properties:
        replicas:
          type: integer
          default: 5
        ui_color:
          type: string
          default: blue
        svc_port:
          type: integer
          default: 80
        app_port:
          type: integer
          default: 9898
        svc_type:
          type: string
          default: LoadBalancer
  template:
    spec:
      fetch:
      - imgpkgBundle:
          image: masanara/podinfo:1.0.0
      template:
      - ytt:
          paths:
          - config/
      - kbld:
          paths:
          - '-'
          - .imgpkg/images.yml
      deploy:
      - kapp: {}
```

### リポジトリバンドルOCIのイメージの作成

作成したPackageMetadataマニフェストをリポジトリバンドルのパッケージ名のディレクトリにコピーします。

```bash
$ cp metadata.yml test-repo/packages/podinfo.corp.com
```

kbldを利用してパッケージOCIイメージ(`masanara/podinf`)のタグ(1.0.0) をダイジェストに変換し、lockファイル(`test-repo/.imgpkg/images.yml`)を生成します。

```bash
$ kbld -f test-repo/packages/ --imgpkg-lock-output test-repo/.imgpkg/images.yml
resolve | final: masanara/podinfo:1.0.0 -> index.docker.io/masanara/podinfo@sha256:5a188481d1cc69168215bbf4778d7687988def9b31173f1fbb657e1321c16866
```

リポジトリバンドルに含めるマニフェストを準備できたので、imgpkgコマンドを利用して`package-contents`配下のファイル群をOCIイメージに変換し、`masanara/test-repo:1.0.0`としてdocker hubにpushします。


```bash
$ imgpkg push -b masanara/test-repo:1.0.0 -f test-repo
dir: .
dir: .imgpkg
file: .imgpkg/images.yml
dir: packages
dir: packages/podinfo.corp.com
file: packages/podinfo.corp.com/1.0.0.yml
file: packages/podinfo.corp.com/metadata.yml
Pushed 'index.docker.io/masanara/test-repo@sha256:b05ead6d4f080573ea0cc746c116a4ab615d9a304516f1fe8c9fa2ee743ba80a'
Succeeded
```

## パッケージリポジトリの利用

### kapp-controllerの準備

作成したパッケージリポジトリをkubernetesクラスター上で利用するには、クラスター上でkapp-controllerが構成されている必要があります。TCEで作成するワークロードクラスターはkapp-controllerが構成済みになっています。(バージョンはv0.23.0)

```bash
$ kubectl get pod -n tkg-system
NAME                                                     READY   STATUS    RESTARTS   AGE
kapp-controller-9bd988bf5-g8qk7                          1/1     Running   0          15h
tanzu-capabilities-controller-manager-6ff97656b8-s5ffb   1/1     Running   0          15h

$ kubectl get deploy kapp-controller -n tkg-system -oyaml | grep kapp-controller.carvel.dev/version
    kapp-controller.carvel.dev/version: v0.23.0
    kapp.k14s.io/original: '{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kapp-controller.carvel.dev/version":"v0.23.0","kapp.k14s.io/change-rule":"upsert
          f:kapp-controller.carvel.dev/version: {}
```

### PackateRepositoryの登録

パッケージとリポジトリバンドルをOCIとしてdocker hubにpushできたので、TCEのワークロードクラスターにPackageRepositoryとして登録してみます。

```bash
$ tanzu package repository add test-repo --url masanara/test-repo:1.0.0 --namespace tanzu-package-repo-global
/ Adding package repository 'test-repo'...
 Added package repository 'test-repo'
```

しばらくするとリポジトリが`Reconcile succeeded`となり、リポジトリとして利用可能になります。


```bash
$ tanzu package repository list -n tanzu-package-repo-global
/ Retrieving repositories...
  NAME       REPOSITORY                                   STATUS               DETAILS
  tce-repo   projects.registry.vmware.com/tce/main:0.9.1  Reconcile succeeded
  test-repo  masanara/test-repo:1.0.0                     Reconciling

$ tanzu package repository list -n tanzu-package-repo-global
/ Retrieving repositories...
  NAME       REPOSITORY                                   STATUS               DETAILS
  tce-repo   projects.registry.vmware.com/tce/main:0.9.1  Reconcile succeeded
  test-repo  masanara/test-repo:1.0.0                     Reconcile succeeded
```

### パッケージの確認

利用可能なpackageを確認すると、追加した`podinfo.corp.com`が利用可能になっています。


```bash
$ tanzu package available list
- Retrieving available packages...
  NAME                                           DISPLAY-NAME        SHORT-DESCRIPTION
  cert-manager.community.tanzu.vmware.com        cert-manager        Certificate management
  contour.community.tanzu.vmware.com             Contour             An ingress controller
  external-dns.community.tanzu.vmware.com        external-dns        This package provides DNS synchronization functionality.
  fluent-bit.community.tanzu.vmware.com          fluent-bit          Fluent Bit is a fast Log Processor and Forwarder
  gatekeeper.community.tanzu.vmware.com          gatekeeper          policy management
  grafana.community.tanzu.vmware.com             grafana             Visualization and analytics software
  harbor.community.tanzu.vmware.com              Harbor              OCI Registry
  knative-serving.community.tanzu.vmware.com     knative-serving     Knative Serving builds on Kubernetes to support deploying and serving of applications and functions as serverless containers
  local-path-storage.community.tanzu.vmware.com  local-path-storage  This package provides local path node storage and primarily supports RWO AccessMode.
  multus-cni.community.tanzu.vmware.com          multus-cni          This package provides the ability for enabling attaching multiple network interfaces to pods in Kubernetes
  podinfo.corp.com                               Podinfo App         Podinfo app for demoing
  prometheus.community.tanzu.vmware.com          prometheus          A time series database for your metrics
  velero.community.tanzu.vmware.com              velero              Disaster recovery capabilities
```

パッケージの詳細情報を確認してみます。リポジトリバンドル作成時に指定したメタデータを確認することが可能です。


```bash
$ tanzu package available get podinfo.corp.com
/ Retrieving package details for podinfo.corp.com...
NAME:                 podinfo.corp.com
DISPLAY-NAME:         Podinfo App
SHORT-DESCRIPTION:    Podinfo app for demoing
PACKAGE-PROVIDER:
LONG-DESCRIPTION:     Podinfo is a tiny web application made with Go that showcases best practices of running microservices in Kubernetes
MAINTAINERS:          []
SUPPORT:
CATEGORY:             [demo]

$ tanzu package available list podinfo.corp.com
/ Retrieving package versions for podinfo.corp.com...
  NAME              VERSION  RELEASED-AT
  podinfo.corp.com  1.0.0
```

### パッケージのインストール

バージョンを指定して、パッケージをインストールします。

```bash
$ tanzu package install podinfo -p podinfo.corp.com -v 1.0.0
/ Installing package 'podinfo.corp.com'
| Getting namespace 'default'
| Getting package metadata for 'podinfo.corp.com'
| Creating service account 'podinfo-default-sa'
| Creating cluster admin role 'podinfo-default-cluster-role'
| Creating cluster role binding 'podinfo-default-cluster-rolebinding'
- Creating package resource
/ Package install status: Reconciling

 Added installed package 'podinfo' in namespace 'default'
```

しばらく待つと、パッケージのSTATUSが`Reconcile succeeded`となります。

```bash
$ tanzu package installed list -A
/ Retrieving installed packages...
  NAME            PACKAGE-NAME                     PACKAGE-VERSION  STATUS               NAMESPACE
  podinfo         podinfo.corp.com                 1.0.0            Reconcile succeeded  default
  antrea          antrea.tanzu.vmware.com                           Reconcile succeeded  tkg-system
  metrics-server  metrics-server.tanzu.vmware.com                   Reconcile succeeded  tkg-system
  vsphere-cpi     vsphere-cpi.tanzu.vmware.com                      Reconcile succeeded  tkg-system
  vsphere-csi     vsphere-csi.tanzu.vmware.com                      Reconcile succeeded  tkg-system
```

### リソースの確認

パッケージのインストールにより作成されたリソースを確認します。

```bash
$ tanzu package installed list
/ Retrieving installed packages...
  NAME     PACKAGE-NAME      PACKAGE-VERSION  STATUS
  podinfo  podinfo.corp.com  1.0.0            Reconcile succeeded

$ kubectl get deploy,pod,svc
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/podinfo   5/5     5            5           81s

NAME                          READY   STATUS    RESTARTS   AGE
pod/podinfo-dc445f8f9-jkr9q   1/1     Running   0          81s
pod/podinfo-dc445f8f9-plzsd   1/1     Running   0          81s
pod/podinfo-dc445f8f9-w4jc7   1/1     Running   0          81s
pod/podinfo-dc445f8f9-xxx8q   1/1     Running   0          81s
pod/podinfo-dc445f8f9-zlbg9   1/1     Running   0          81s

NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
service/kubernetes   ClusterIP      100.64.0.1      <none>            443/TCP        30h
service/podinfo      LoadBalancer   100.64.96.207   192.168.201.120   80:32274/TCP   81s
```

デフォルトでパッケージをインストールしたため、podinfoは5つのPodで構成され、作成されたサービスにアクセスすると`"color": "blue"`となっています。

```
$ curl 192.168.201.120
{
  "hostname": "podinfo-dc445f8f9-jkr9q",
  "version": "6.0.3",
  "revision": "",
  "color": "blue",
  "logo": "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif",
  "message": "greetings from podinfo v6.0.3",
  "goos": "linux",
  "goarch": "amd64",
  "runtime": "go1.16.9",
  "num_goroutine": "6",
  "num_cpu": "2"
}
```

### パラメータの更新

インストールしたパッケージはパラメータの指定が可能になっています。利用可能なvaluesを確認してみます。

```bash
$ tanzu package available get podinfo.corp.com/1.0.0 --values-schema

  KEY       DEFAULT       TYPE     DESCRIPTION
  svc_type  LoadBalancer  string   <nil>
  ui_color  blue          string   <nil>
  app_port  9898          integer  <nil>
  replicas  5             integer  <nil>
  svc_port  80            integer  <nil>
```

`ui_color`と`replicas`を以下のようにyamlファイルで指定します。

```yaml
ui_color: green
replicas: 3
```

作成したyamlファイルを指定してインストーされているパッケージをアップデートします。(`tanzu package install podinfo -p podinfo.corp.com -v 1.0.0 -f podinfo-values.yaml`としてインストール時に指定することも可能です。)

```bash
$ tanzu package installed update podinfo -v 1.0.0 -f podinfo-values.yaml
| Updating package 'podinfo'
/ Getting package install for 'podinfo'
| Creating secret 'podinfo-default-values'
| Updating package install for 'podinfo'

 Updated package install 'podinfo' in namespace 'default'
```

しばらく待って状態を確認すると、pod数は3に減少しており、podinfoにアクセスすると`"color": "green"`に更新されていることが確認できます。


```bash
$ tanzu package installed get podinfo
/ Retrieving installation details for podinfo...
NAME:                    podinfo
PACKAGE-NAME:            podinfo.corp.com
PACKAGE-VERSION:         1.0.0
STATUS:                  Reconcile succeeded
CONDITIONS:              [{ReconcileSucceeded True  }]
USEFUL-ERROR-MESSAGE:
$ kubectl get deploy,pod,svc
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/podinfo   3/3     3            3           5m1s

NAME                           READY   STATUS    RESTARTS   AGE
pod/podinfo-649d465d9c-8x52n   1/1     Running   0          55s
pod/podinfo-649d465d9c-hfdvz   1/1     Running   0          53s
pod/podinfo-649d465d9c-q6ggk   1/1     Running   0          52s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)        AGE
service/kubernetes   ClusterIP      100.64.0.1       <none>            443/TCP        31h
service/podinfo      LoadBalancer   100.71.166.216   192.168.201.120   80:31754/TCP   5m1s
$ curl 192.168.201.120
{
  "hostname": "podinfo-649d465d9c-hfdvz",
  "version": "6.0.3",
  "revision": "",
  "color": "green",
  "logo": "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif",
  "message": "greetings from podinfo v6.0.3",
  "goos": "linux",
  "goarch": "amd64",
  "runtime": "go1.16.9",
  "num_goroutine": "6",
  "num_cpu": "2"
}
```

## 後片付け

追加したpodinfoパッケージを削除します。


```bash
$ tanzu package installed delete podinfo
Deleting installed package 'podinfo' in namespace 'default'. Are you sure? [y/N]: y
| Uninstalling package 'podinfo' from namespace 'default'
/ Getting package install for 'podinfo'
/ Deleting package install 'podinfo' from namespace 'default'
\ Package uninstall status: Deleting
| Deleting admin role 'podinfo-default-cluster-role'
| Deleting role binding 'podinfo-default-cluster-rolebinding'
| Deleting secret 'podinfo-default-values'
| Deleting service account 'podinfo-default-sa'

 Uninstalled package 'podinfo' from namespace 'default'
```

追加したtest-repoを削除します。


```
$ tanzu package repository delete test-repo -n tanzu-package-repo-global
/ Deleting package repository 'test-repo'...
 Deleted package repository 'test-repo' from namespace 'tanzu-package-repo-global'
```

## まとめ

Carvelを使ってマニフェストをパッケージ化し、パッケージリポジトリを作成してkubernetesクラスター上でパッケージを利用することができました。Carvelのyttやimgpkg等は単体で利用しても便利なツールですが、kapp-controllerと組み合わせることでkubernetesクラスター上のパッケージ管理を実現することが可能です。