IK.AM

@making's tech note


Carvel imgpkgでコンテナイメージをair-gapped環境にrelocateする

🗃 {Dev/Carvel/imgpkg}
🏷 Kubernetes 🏷 Carvle 🏷 air-gapped 🏷 kbld 🏷 imgpkg 
🗓 Updated at 2021-12-14T00:00:00+09:00  🗓 Created at 2021-12-14T00:00:00+09:00 {✒️️ Edit  ⏰ History  🗑 Delete}

TUNA-JP Advent Calendar 2021 その2の14日目のエントリです。

前の記事 ではkbldを使ったイメージのrelocationを説明しましたが、deprecatedな手法であるため、 本記事では代替となるimppkgを使った手法を説明します。

Carvelimgpkg は imgpkgは任意のファイル(k8sマニフェストが主な用途)をimgpkg bundleというフォーマットでOCIイメージにパッケージングし、コンテナレジストリで配布可能にします。 imgpkg bundleなOCIイメージである唯一の用件は.imgpkg/images.ymlファイルが存在することです。

kbld同様に、imgpkgもair-gapped環境へのbundleのrelocationに対応しており、インターネットに繋がっていない環境でk8sを扱わないといけない方にかなり重宝するツールです。

基本的は こちらのドキュメント の通りです。

目次

imgpkgのインストール

Macの場合、brewでインストールできます。

brew tap vmware-tanzu/carvel
brew install imgpkg

他の環境では https://github.com/vmware-tanzu/carvel-imgpkg/releases からバイナリをダウンロードし、/usr/local/bin などにインストールしてください。

なお、以下の説明ではkbldも使用するので、前の記事 を参考にkbldもインストールしてください。

imgpkg, kbld含むCarvelのツールを一式インストールしたい場合は、次のコマンドでインストールできます。

wget -O- https://carvel.dev/install.sh | bash
# or with curl...
curl -L https://carvel.dev/install.sh | bash

次のバージョンで動作確認しています。

$ kbld version
kbld version 0.31.0

$ imgpkg version
imgpkg version 0.23.1

guestbookのrelocation

前の記事と同様に、サンプルアプリとして guestbook をrelocateしてみます。まずはmanifestをダウンロードします。

mkdir -p guestbook/config
cd guestbook/config
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/frontend-deployment.yaml
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/frontend-service.yaml
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/redis-follower-deployment.yaml
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/redis-follower-service.yaml
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/redis-leader-deployment.yaml
wget https://github.com/kubernetes/website/raw/main/content/en/examples/application/guestbook/redis-leader-service.yaml
cd ..

imgpkg bundleの.imgpkg/images.ymlファイルはkbldのlockファイルとしてkbldコマンドで自動生成できます。

--imgpkg-lock-outputオプションを使用して、lockファイルを生成します。次のコマンドを実行してください。

mkdir -p .imgpkg
kbld -f config --imgpkg-lock-output .imgpkg/images.yml

生成された.imgpkg/images.ymlは次の内容です。3つのイメージ(redis, gb-frontend, gb-redis-follower)のdigestが出力されていることがわかります。 前記事で作成したlockファイルとは若干フォーマットが異なります。

---
apiVersion: imgpkg.carvel.dev/v1alpha1
images:
- annotations:
    kbld.carvel.dev/id: docker.io/redis:6.0.5
    kbld.carvel.dev/origins: |
      - resolved:
          tag: 6.0.5
          url: docker.io/redis:6.0.5
  image: index.docker.io/library/redis@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
- annotations:
    kbld.carvel.dev/id: gcr.io/google_samples/gb-frontend:v5
    kbld.carvel.dev/origins: |
      - resolved:
          tag: v5
          url: gcr.io/google_samples/gb-frontend:v5
  image: gcr.io/google_samples/gb-frontend@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
- annotations:
    kbld.carvel.dev/id: gcr.io/google_samples/gb-redis-follower:v2
    kbld.carvel.dev/origins: |
      - resolved:
          tag: v2
          url: gcr.io/google_samples/gb-redis-follower:v2
  image: gcr.io/google_samples/gb-redis-follower@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
kind: ImagesLock

relocationとは関係ありませんが、このlockファイルを使って、次のコマンドを実行すると、イメージ名がdigest付きのものに変換されたmanifestが出力され、常に同じイメージを使用するimmutableなmanifestとして利用できます。

kbld -f config -f .imgpkg/images.yml

次のようなフォルダ構成になっています。

$ tree -a    
.
|-- .imgpkg
|   `-- images.yml
`-- config
    |-- frontend-deployment.yaml
    |-- frontend-service.yaml
    |-- redis-follower-deployment.yaml
    |-- redis-follower-service.yaml
    |-- redis-leader-deployment.yaml
    `-- redis-leader-service.yaml

2 directories, 7 files

このimgpkg pushコマンドでこのフォルダをOCIイメージとしてパッケージし、コンテナレジストリで配布できます。 このOCIイメージがimgpkg bundleです。ここではimgpkg bundleを公開するコンテナとしてghcr.ioを使用します。

次のコマンドでimgpkg bundleを作成及び公開します。

imgpkg push -b ghcr.io/making/guestbook-bundle:1.0 -f .

なお、このguestbookのimgpkg bundleはghcr.io/making/guestbook-bundle:1.0でpublicに公開されています。

relocationとは関係ありませんが、次のコマンドでこのbundleを展開し、manifestを取得することができます。

$ imgpkg pull -b ghcr.io/making/guestbook-bundle:1.0 -o /tmp/guestbook

Pulling bundle 'ghcr.io/making/guestbook-bundle@sha256:138f19f7c0ec1d19d2572c14b51853f3f5faa326f98f1d556a00c5d386503342'
  Extracting layer 'sha256:8b8a0dd7885b6ef32c8e93ea2a5ca3f78a7ac101822bb05baf61e453cac94d74' (1/1)

Locating image lock file images...
One or more images not found in bundle repo; skipping lock file update

Succeeded

$ tree -a /tmp/guestbook
/tmp/guestbook
|-- .imgpkg
|   `-- images.yml
`-- config
    |-- frontend-deployment.yaml
    |-- frontend-service.yaml
    |-- redis-follower-deployment.yaml
    |-- redis-follower-service.yaml
    |-- redis-leader-deployment.yaml
    `-- redis-leader-service.yaml

2 directories, 7 files

このimgpkg bundleはimageのrelocationに利用できます。

移行元のコンテナレジストリから移行先のコンテナレジストリへ直接relocationする方法と中間のtarファイルを経由する方法があります。

以下では移行先のコンテナレジストリとして こちらの記事 で利用したHarborを使用します。 air-gappedな環境からこのHarborへアクセスすることができる前提です。

移行元のコンテナレジストリから移行先のコンテナレジストリへ直接relocation

操作端末が移行元のコンテナレジストリと移行先のコンテナレジストリの両方にアクセスできる場合、直接relocationが可能です。

次のコマンドで元のコンテナレジストリ(ここではDockerHubとGoogle Container Registry)からHarborへrelocationできます。移行先のレジストリが自己署名証明書を使っている場合は --registry-ca-cert-path を指定してください。

imgpkg copy -b ghcr.io/making/guestbook-bundle:1.0 --to-repo $HARBOR_HOST/library/guestbook-bundle --registry-ca-cert-path $HOME/.config/tanzu/tkg/providers/ytt/03_customizations/harbor-ca.pem 

次のようなログが出力されます。

copy | exporting 4 images...
copy | will export gcr.io/google_samples/gb-frontend@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
copy | will export gcr.io/google_samples/gb-redis-follower@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
copy | will export ghcr.io/making/guestbook-bundle@sha256:138f19f7c0ec1d19d2572c14b51853f3f5faa326f98f1d556a00c5d386503342
copy | will export index.docker.io/library/redis@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
copy | exported 4 images
copy | importing 4 images...

 610.61 MiB / 610.61 MiB [=============================================================================================] 100.00% 49.24 MiB/s 12s

copy | done uploading images

Succeeded

Harborでlibrary/guestbook-bundleを確認すると、次の図のように5つのイメージが登録されています。guestbookに使われる3つのイメージとrelocateされたbundleのイメージともう一つはrelocation前の情報を保持するメタデータです。 移行先のイメージ名は同一($HARBOR_HOST/library/guestbook)で、異なるtagで分かれています。

image

次のコマンドでrelocateされたbundleを展開します。

imgpkg pull -b $HARBOR_HOST/library/guestbook-bundle:1.0 -o /tmp/guestbook --registry-ca-cert-path $HOME/.config/tanzu/tkg/providers/ytt/03_customizations/harbor-ca.pem

変換先のイメージ名へのマッピングは、relocateされた/tmp/guestbook/.imgpkg/images.ymlに次のように出力されています。

---
apiVersion: imgpkg.carvel.dev/v1alpha1
images:
- annotations:
    kbld.carvel.dev/id: docker.io/redis:6.0.5
    kbld.carvel.dev/origins: |
      - resolved:
          tag: 6.0.5
          url: docker.io/redis:6.0.5
  image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
- annotations:
    kbld.carvel.dev/id: gcr.io/google_samples/gb-frontend:v5
    kbld.carvel.dev/origins: |
      - resolved:
          tag: v5
          url: gcr.io/google_samples/gb-frontend:v5
  image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
- annotations:
    kbld.carvel.dev/id: gcr.io/google_samples/gb-redis-follower:v2
    kbld.carvel.dev/origins: |
      - resolved:
          tag: v2
          url: gcr.io/google_samples/gb-redis-follower:v2
  image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
kind: ImagesLock

このrelocate済みのlockファイルを使用して、次のコマンドを実行することで、relocateされたmanifestを生成することができます。

cd /tmp/guestbook
kbld -f config -f .imgpkg/images.yml

出力は次の通りです。imageが全てHarborに置き換わっていることを確認してください。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kbld.k14s.io/images: |
      - origins:
        - resolved:
            tag: v5
            url: gcr.io/google_samples/gb-frontend:v5
        - preresolved:
            url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
        url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: guestbook
      tier: frontend
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - env:
        - name: GET_HOSTS_FROM
          value: dns
        image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
        name: php-redis
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: guestbook
    tier: frontend
  name: frontend
spec:
  ports:
  - port: 80
  selector:
    app: guestbook
    tier: frontend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kbld.k14s.io/images: |
      - origins:
        - resolved:
            tag: v2
            url: gcr.io/google_samples/gb-redis-follower:v2
        - preresolved:
            url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
        url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
  labels:
    app: redis
    role: follower
    tier: backend
  name: redis-follower
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      containers:
      - image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
        name: follower
        ports:
        - containerPort: 6379
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: redis
    role: follower
    tier: backend
  name: redis-follower
spec:
  ports:
  - port: 6379
  selector:
    app: redis
    role: follower
    tier: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kbld.k14s.io/images: |
      - origins:
        - resolved:
            tag: 6.0.5
            url: docker.io/redis:6.0.5
        - preresolved:
            url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
        url: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
  labels:
    app: redis
    role: leader
    tier: backend
  name: redis-leader
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      containers:
      - image: harbor-10-213-232-22.sslip.io/library/guestbook-bundle@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
        name: leader
        ports:
        - containerPort: 6379
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: redis
    role: leader
    tier: backend
  name: redis-leader
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
    role: leader
    tier: backend

このmanifestをkubectl applyで適用すればair-gappedな環境にguestbookをインストールすることができます。

tarファイルを経由して移行元のコンテナレジストリから移行先のコンテナレジストリへrelocation

完全にインターネットアクセスが遮断されている環境の場合、上記の方法が利用できません。 その場合は、一時的にtarファイルを経由することでrelocationできます。

次のコマンドを実行することでlockファイルに書かれた全てのイメージをダウンロードし、tarファイルにまとめることができます。

imgpkg copy -b ghcr.io/making/guestbook-bundle:1.0 --to-tar guestbook-bundle.tar

次のようなログが出力されます。各Dockerイメージの全てのlayerをダウンロードしていることがわかります。

copy | exporting 4 images...
copy | will export gcr.io/google_samples/gb-frontend@sha256:dc8de8e0d569d2f828b187528c9317bd6b605c273ac5a282aebe471f630420fc
copy | will export gcr.io/google_samples/gb-redis-follower@sha256:42707dbdccb4c8177523e2687c7b3cdb3d13473b0df1d3ef2c558fda09772c6f
copy | will export ghcr.io/making/guestbook-bundle@sha256:138f19f7c0ec1d19d2572c14b51853f3f5faa326f98f1d556a00c5d386503342
copy | will export index.docker.io/library/redis@sha256:800f2587bf3376cb01e6307afe599ddce9439deafbd4fb8562829da96085c9c5
copy | exported 4 images
copy | writing layers...
copy | done: file 'manifest.json' (72.645µs)
copy | done: file 'sha256-25d34e6a8c07fe57114baaa650962827351af5046989cc2361d695a748ecac04.tar.gz' (51.381813ms)
copy | done: file 'sha256-2e8f81c7b07f28d78092ab450f032cb5f0db66cb2c87696bca00a1548af00c15.tar.gz' (32.262µs)
copy | done: file 'sha256-44264eaa8a750fb07340a6ab1cfb185534e02f60a775a803cd176b369de56f72.tar.gz' (1.083929772s)
copy | done: file 'sha256-904a0292174da3a627c8e999351f8879c6bfabde14163b2ae51607d0c1120cf4.tar.gz' (30.607µs)
copy | done: file 'sha256-8ca7577888307f392a71a9e051a2635001440b124e3b3ae5cb3e10e8dca0906a.tar.gz' (156.685278ms)
copy | done: file 'sha256-04fe4ce897d62a8f1adc5d381f61c4a6ce437a73cfdf7775f5fc96ebde1fc7c7.tar.gz' (362.426205ms)
copy | done: file 'sha256-33cc09c9b190539635d7c971301f623d94fda5b4b5647966c6c240902119009f.tar.gz' (2.835126183s)
copy | done: file 'sha256-91875635f69d9961c1b3203c1ca80ec03b0ccab3a7bbe16e763a0636ea3cc45c.tar.gz' (2.354601493s)
copy | done: file 'sha256-0afca0c798a59b50622df9aaad0dd407f7c7b9f77999cab832f70bffd3c8c63f.tar.gz' (2.558074586s)
copy | done: file 'sha256-3327f7a496f3f9a645339962c5ff7707e5d3d8527605c0b61e2437df8d05d57e.tar.gz' (54.698µs)
copy | done: file 'sha256-2dd003996c9ab82cac8112be0a4c04068e666e7a5d0cce3c65fb8f064de284e7.tar.gz' (3.556102472s)
copy | done: file 'sha256-03a4abad74f97d7acb3497f868e3eaff523184606b54ecdbf176bfe85a10e796.tar.gz' (79.497615ms)
copy | done: file 'sha256-a41be782ae7e5ade04fdcb9a1b7e47dfc657577d52ca2c56e69bc15d6ff0d9ab.tar.gz' (44.344µs)
copy | done: file 'sha256-1bacb18640994730a015fc7704e0cef48a50c2a829dc127acff37988f85a58cc.tar.gz' (61.838µs)
copy | done: file 'sha256-8b8a0dd7885b6ef32c8e93ea2a5ca3f78a7ac101822bb05baf61e453cac94d74.tar.gz' (42.586µs)
copy | done: file 'sha256-98037b32ce5f6bbc4cdfb87147f17d72d114cc4631d91a4f55385aa5abc97efa.tar.gz' (35.413µs)
copy | done: file 'sha256-50e0f355ff269fbd8a5e68547368f185309f10ad76ff5843b48089b90f8e9efe.tar.gz' (30.876µs)
copy | done: file 'sha256-cda0ea55460bc42da178ec0cbd19648bfbcb6afefa33e274869edb8ab135f43e.tar.gz' (54.076µs)
copy | done: file 'sha256-4878e74c8c6b5ff2fd3739f532749ac8b45aa996736e2a2f27dcc66594406245.tar.gz' (47.253µs)
copy | done: file 'sha256-d5ff438dbf35424bce6e08e9033a2e064d553c50b0c061a598565a0434420f24.tar.gz' (19.869013ms)
copy | done: file 'sha256-059f03d738ad08278e0a4c25ca340c43ee5ac09fd89ec4958a1577f24c61c495.tar.gz' (77.417µs)
copy | done: file 'sha256-6a864f6e4c8d1d717410a06ce2df7968ce243151f41c31b276de9c37b9c903a0.tar.gz' (103.617µs)
copy | done: file 'sha256-405e75bf6bb0104d67fcebf58e07cd21bf344589df9c1a41c00354a60ea3a604.tar.gz' (2.373124382s)
copy | done: file 'sha256-02bd07740270c2e091dd2d53ff514e569ab6317f8e13127325c02b8f373799e7.tar.gz' (38.17µs)
copy | done: file 'sha256-03733ea6a63584425902e780cf1a3270cc136085ca96c08c11f1c3723424865e.tar.gz' (47.399µs)
copy | done: file 'sha256-8cd20313beb311f9333c1f47bbe7694bb922e79f5403daa59e5e16ff79e9db43.tar.gz' (34.617µs)
copy | done: file 'sha256-85a6a5c53ff0d7433fa114f3d8b94992deda869addc164bd15ce40e2f72f0fd6.tar.gz' (89.354µs)
copy | done: file 'sha256-63dbb66c5119bb5086d9e6fb6b154211afc20b44ed136ab7df808f6044cfc6f1.tar.gz' (4.245842471s)
copy | done: file 'sha256-76f2a0c8ea98ebd699a77ced9c677e97cd54b038a8c5e89670af78f38b047b33.tar.gz' (4.82692417s)
copy | done: file 'sha256-6831bc8b21065044f27b834e6959951a56e7be04b70b1c3ff4935f4f082911ae.tar.gz' (35.121µs)
copy | done: file 'sha256-d13522578ad9c68f9a771d9dfc2a14315b97c7ee6690853b02cd9c261046d8b7.tar.gz' (50.528µs)
copy | done: file 'sha256-229000940745435809100da0b14f1673c6b4d553050c3adf492a915fd9932527.tar.gz' (34.316µs)
copy | done: file 'sha256-40087910590b3b16fd4006b5b33c8dcc8e8f7a90e6f5353d31125482e599fa9f.tar.gz' (49.624µs)
copy | done: file 'sha256-8949ef43a825d8300849dd9cb479ee0e797bbba65454cb45514f777790f7716d.tar.gz' (43.714µs)
copy | done: file 'sha256-80cabc759585527d8170ded333679a336272d34fe3d3639eb81fcd4afd554b4b.tar.gz' (2.573495726s)
copy | done: file 'sha256-5b11fc09c1a26b11a7df7d593adf43baff53c5cdba71cf8a87ae4a6dd17eb52c.tar.gz' (5.117038618s)
copy | done: file 'sha256-bd04f262ac91b3a38b06b8004da69851b15ca4cbc3a792e3764de72996c53372.tar.gz' (1.983376429s)
copy | done: file 'sha256-ffbb094f4f9e7c61d97c2b409f3e8154e2621a5074a0087d35f1849e665d0d34.tar.gz' (3.204704484s)
copy | done: file 'sha256-860f8957d8be856e2235a28e49fc4dca17254951e0eb67d760769755656f5cad.tar.gz' (3.940850006s)
copy | done: file 'sha256-1e491fca5994eec2c4eea799393cb2261fd53972e306192495fd33ec10789c7d.tar.gz' (1.606319291s)
copy | done: file 'sha256-a72d84b9df6aa0cd3bdee9e9ce6151139ef2f93fae7bd1726036a667b54f4798.tar.gz' (3.95064013s)
copy | done: file 'sha256-c4e50f4448ab04efcb3246f3bb1a7851c14230b4a19511065cb0d36dc3843166.tar.gz' (1.589249363s)
copy | done: file 'sha256-8559a31e96f442f2c7b6da49d6c84705f98a39d8be10b3f5f14821d0ee8417df.tar.gz' (3.668950858s)
copy | done: file 'sha256-5ce7b314b19cb499ab621f796ded0d51f065120efadc4db046fca0e209a4604d.tar.gz' (86.461µs)
copy | done: file 'sha256-35ea1373cc96d130eeb2b3d16463ca4112d4bd70253d826f4cc744154e4ab41d.tar.gz' (1.661959936s)
copy | done: file 'sha256-0bc5fc03390faf708237384e2d2bebf6d15fcb2ee6fd29590cc82b6a99a487d3.tar.gz' (30.026µs)
copy | done: file 'sha256-3347b8f8a6bb3d71e9dcd56712406b0cc244cb8d3f6d6f29b2d057cb12e16071.tar.gz' (44.944µs)
copy | done: file 'sha256-df294a3127fb3f435b8573ed3749eea2c8ba0f500b0dfc3e72449e21b8dd8b4d.tar.gz' (2.154603868s)
copy | done: file 'sha256-cad41b2f70e519a55e1792d31026fd65c8c42f76e38944a584ff2719ab46327c.tar.gz' (33.465µs)
copy | done: file 'sha256-38cf5d0545e9b0b3b3996fcd484cb25823b9bb2163b3675d809479a093a319bc.tar.gz' (40.908µs)
copy | done: file 'sha256-79e2bb3c8c7d7e6f4700b36afc4bafefa4eae8b8d235c54961f8462d346429af.tar.gz' (43.788µs)
copy | done: file 'sha256-18fcacdee8c50bfd26be61e6f1a4f8ec366be232029a81392b070175eb8086b0.tar.gz' (32.519µs)
copy | done: file 'sha256-d003069fe633e007e207bfc0b2084e0d3b19cabd7d7a308367946cd858fabcc6.tar.gz' (45.325µs)
copy | done: file 'sha256-3c641f1df61fc7d52d72d38d2f33f5eda5d07c734b49cb8a6c27ab19dd4a82b6.tar.gz' (162.54645ms)
copy | done: file 'sha256-f08f0aaf2b28c6273ae9d36fd5290631b23d20bd95ed8b199b0112100f1df940.tar.gz' (16.196249508s)
copy | done: file 'sha256-b69876b7abed8f17b52974bf0be00fcaf4d2d3d622bd2349c8e16407331e8b88.tar.gz' (234.79223ms)
copy | done: file 'sha256-04c4bfb0b023392acc73045aece284a6d14adfcb2cc74bce1e46bed266b8626a.tar.gz' (25.573µs)
copy | done: file 'sha256-95aa1587cc1d863f1578c056d9349b284081c1747f95afc930dff5d76257b343.tar.gz' (37.744µs)
copy | done: file 'sha256-f0f26ca0b5c28d69822884ac52a5c11834a3b4814107ea0b9062b995b53450e8.tar.gz' (26.498µs)
copy | done: file 'sha256-ae79957c435c134f7eac689451a33d4d4a6561e9a1156f63f865dde409d3c341.tar.gz' (949.813462ms)
copy | done: file 'sha256-b1ad81e0d5836d20a5deab240146c524b20f1c4eb3fcdab4fd05f9e7567e9a1e.tar.gz' (122.357198ms)
copy | done: file 'sha256-8df5dd91de8744e600658d9bc0fe8762472a743f7bc9ddc11290c62e99ef33c5.tar.gz' (23.414µs)
copy | done: file 'sha256-6740c67243e3995aa86510395d873ad2d4b362cd64c881a32dba20d965a88b98.tar.gz' (22.374µs)
copy | done: file 'sha256-5f87ad8ff31c56b999b8c50976cb4d780d3a65c4ac49929af53718877a53ac6b.tar.gz' (35.589µs)
copy | done: file 'sha256-862b2b6c212df122d0cc5b0bc23864c5874de338f17b0dfa7da836aeca0b9f98.tar.gz' (110.467027ms)
copy | done: file 'sha256-6482c539a928e9561b259316816a6933b2cd8ddd0d703ebc73aa310db2c8c7cd.tar.gz' (117.151702ms)
copy | done: file 'sha256-0027e794f2380b6fb5275c0b6c78e9cbcc29821b043c51ad81ca54eb46a801a7.tar.gz' (10.042576098s)

Succeeded

出来上がったtarファイルは全イメージを含むのでサイズが大きいです。

$ ls -lh guestbook-bundle.tar
-rw-r--r--  1 toshiaki  wheel   611M Dec 12 21:57 guestbook-bundle.tar

このtarファイルをUSBメモリなどを使用して、air-gapped環境に持ち込みます。

air-gapped環境で、次のコマンドを実行しHarborにrelocateします。

imgpkg copy --tar guestbook-bundle.tar --to-repo $HARBOR_HOST/library/guestbook-bundle --registry-ca-cert-path $HOME/.config/tanzu/tkg/providers/ytt/03_customizations/harbor-ca.pem 

前と同じく、次の図のようにHarborには同一のイメージ名($HARBOR_HOST/library/guestbook)でtagが異なる5つのイメージが登録されています。

image

前と同じく、次のコマンドでrelocateされたHarbor上のイメージを使ってguestbookをインストールするためのmanifestが生成されます。

imgpkg pull -b $HARBOR_HOST/library/guestbook-bundle:1.0 -o /tmp/guestbook --registry-ca-cert-path $HOME/.config/tanzu/tkg/providers/ytt/03_customizations/harbor-ca.pem
cd /tmp/guestbook
kbld -f config -f .imgpkg/images.yml

imgpkg(とkbld)を使うことでイメージのrelocationを行えることを確認しました。

kbld単体でrelocateした場合に比べ、imgpkg bundleをいったんコンテナレジストリにpushする必要があるため一手間多いと感じるかもしれません。 imgpkg bundleはimgpkg pullするだけではなくkapp controllerの App CRPackage CR で直接参照することもできますし、 nestしたbundleを一括でrelocateすることもできます。

imgpkg bundleはrelocateされることを前提としてイメージ+manifestの配布手段として、 Tanzu Kubernetes GridやTanzu Community EditionあるいはTanzu Application PlatformのPackageで利用されています。

また https://github.com/vmware-tanzu/carvel-imgpkg/issues/55imgpkg pushでコンテナレジストリに直接pushする代わりにtarに出力するオプションが検討されているので、 今後のバージョンでコンテナレジストリへのpushは不要になるかもしれません。

kbldのrelocationがdeprecatedであるため、現時点でコンテナレジストリへのpushをどうしても行いたくない場合を除いてimgpkgを使うと良いでしょう。