Amazon ECRがOCI ArtifactをサポートしてHelm chartsも管理できるようになったよ


はじめに

2020/8/28 に Amazon ECR が OCI Artifact をサポートしました。
これにより Helm charts や OPA Bundles など、コンテナイメージ以外の
コンテンツタイプ (アーティファクト) を ECR で保存、配布できるようになります。

OCI Artifact Support In Amazon ECR
https://aws.amazon.com/jp/blogs/containers/oci-artifact-support-in-amazon-ecr/

例えば組織内で安全に Helm charts を共有しようとした場合に
これまでは ChartMuseum 等を使用して、プライベートな
Helm chart registry を構築する必要がありましたが、ECR だけで管理できるようになります。

8/17の AWS Container Day at KubeCon で Developer Preview として発表されたばかりだった
認識ですが、2週間もたたずに正式リリース?となったようです。
今回のローンチの対象は SDK と CLI のサポートで、マネジメントコンソール側の変更は
今年後半にリリース予定とのこと。

ほぼドキュメント通りの手順になってしまいますが、やってみます。

作業環境

  • Helm: v3.3.0
  • AWS CLI: 2.0.43
  • Kubernetes: 1.16.5 (Docker Desktop)

Helm のインストール

クライアント端末に Helm 3 がインストールされていない場合はインストールしておきます。
Github のリリースページからバイナリを取得、インストールスクリプトの使用、
パッケージマネージャー経由など複数のインストール方法が準備されています。

Installing Helm
https://helm.sh/docs/intro/install/

$ helm version
version.BuildInfo{Version:"v3.3.0", GitCommit:"8a4aeec08d67a7b84472007529e8097ec3742105", GitTreeState:"dirty", GoVersion:"go1.14.7"}

Helm 3 における OCI のサポートは 現在 experimental な機能とみなされているため
HELM_EXPERIMENTAL_OCI を環境変数に設定する必要があります。

export HELM_EXPERIMENTAL_OCI=1

ECR レポジトリの作成と認証

AWS CLI で作成します。
特に追加のオプション等は不要で、いつもどおり作成できます。

$ aws ecr create-repository --repository-name helm-test
{
    "repository": {
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:123456789012:repository/helm-test",
        "registryId": "123456789012",
        "repositoryName": "helm-test",
        "repositoryUri": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test",
        "createdAt": "2020-08-29T12:22:02+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
}

以下のコマンドで Helm クライアントを ECR に認証します。

$ aws ecr get-login-password | helm registry login \
> --username AWS --password-stdin 123456789012.dkr.ecr.region.amazonaws.com
Login succeeded

aws ecr get-login コマンドは非推奨になっており、AWS CLI v2 では削除されているため
aws ecr get-login-password を使用します。

参考:AWS CLIでECRにログインする時はget-loginではなくget-login-passwordを使おう
https://qiita.com/hayao_k/items/3e4c822425b7b72e7fd0

Chart の作成

helm create コマンドで Chart の雛形を作成することができます。

$ mkdir helm-test 
$ cd helm-test

$ helm create mychart
Creating mychart

今回はこの雛形をそのまま利用します。

ECR へ Push

helm chart save コマンドで Chart ディレクトリをローカルキャッシュに保存します。
この際、リモートの ECR の URI を使用して、エイリアスを作成します。
このあたりは、コンテナイメージを push するときと同じ感覚です。

$ helm chart save mychart mychart
ref:     mychart:0.1.0
digest:  c455f9c99430ee099ea66999a40a0978947ccfd76e6922cdb8a911491326b0ed
size:    3.5 KiB
name:    mychart
version: 0.1.0
0.1.0: saved

$ helm chart save mychart 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
ref:     123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
digest:  4865989e73df2c14b15ee2a1befa11673e455cc5a728239a05f5bc12b13cadb3
size:    3.5 KiB
name:    mychart
version: 0.1.0
mychart: saved

$ helm chart list
REF                                                             NAME    VERSION DIGEST  SIZE    CREATED
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-te...    mychart 0.1.0   4865989 3.5 KiB 28 seconds
mychart:0.1.0                                                   mychart 0.1.0   4865989 3.5 KiB About a minute

helm chart push コマンドで ECR に push できます。

$ helm chart push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
The push refers to repository [123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test]
ref:     123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
digest:  4865989e73df2c14b15ee2a1befa11673e455cc5a728239a05f5bc12b13cadb3
size:    3.5 KiB
name:    mychart
version: 0.1.0
mychart: pushed to remote (1 layer, 3.5 KiB total)

今回のリリースではマネジメントコンソールに変更が入っていないため、
現在は普通に Docker イメージが格納されているだけのように見えます。

push した Chart を確認すると、適切な artifactMediaType で保存されていることがわかります。

$ aws ecr batch-get-image --repository-name helm-test --image-ids imageTag=mychart --query 'images[].imageManifest'
[
    "{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:65a07b841ece031e6d0ec5eb948eacb17aa6d7294cdeb01d5348e86242951487\",\"size\":141},\"layers\":[{\"mediaType\":\"application/tar+gzip\",\"digest\":\"sha256:acd033c1b722f7dcbfb38a909c422540c584feef52ad4aedb8289eb074638f27\",\"size\":3562}]}"
]

ECR から Chart を pull する

pull を確認するため、helm chart remove コマンドで ローカルキャッシュ上の Chart を削除します。

$ helm chart remove 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
mychart: removed

$ helm chart remove mychart:0.1.0
0.1.0: removed

helm chart pull コマンドで pull します。

$ helm chart pull 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
mychart: Pulling from 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test
ref:     123456789012.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
digest:  4865989e73df2c14b15ee2a1befa11673e455cc5a728239a05f5bc12b13cadb3
size:    3.5 KiB
name:    mychart
version: 0.1.0
Status: Downloaded newer chart for 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart

$ helm chart list
REF                                                             NAME    VERSION DIGEST  SIZE    CREATED
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-te...    mychart 0.1.0   4865989 3.5 KiB 9 hours

Chart のデプロイ

pull した Chart を使用して Kubernetes にデプロイするには
helm chart export コマンドを使用して一度ローカルに export する必要があります。

helm chart export 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart --destination ./chart-install
ref:     123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/helm-test:mychart
digest:  4865989e73df2c14b15ee2a1befa11673e455cc5a728239a05f5bc12b13cadb3
size:    3.5 KiB
name:    mychart
version: 0.1.0
Exported chart to chart-install\mychart/

helm install コマンドで Namespce: helm-test に Chart をインストールします。

$ cd chart-install
$ kubectl create ns helm-test
namespace/helm-test created

$ helm install mychart ./mychart -n helm-test
NAME: mychart
LAST DEPLOYED: Sun Aug 30 11:28:24 2020
NAMESPACE: helm-test
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace helm-test -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=mychart" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace helm-test port-forward $POD_NAME 8080:80

問題なくデプロイできました。

$ kubectl get all -n helm-test
NAME                           READY   STATUS    RESTARTS   AGE
pod/mychart-5965fbff94-xxnd2   1/1     Running   0          32s

NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/mychart   ClusterIP   10.99.155.110   <none>        80/TCP    32s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/mychart   1/1     1            1           32s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/mychart-5965fbff94   1         1         1       32s

$ helm list -n helm-test
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
mychart helm-test       1               2020-08-30 11:28:24.6691172 +0900 JST   deployed        mychart-0.1.0   1.16.0

削除は helm uninstall コマンドを使用します。

$ helm uninstall mychart -n helm-test
release "mychart" uninstalled

$ kubectl delete ns helm-test
namespace "helm-test" deleted

Chart を ECR から削除する

ECR 上の Chart を削除する手順は、Docker イメージの時と変わりません。

$ aws ecr batch-delete-image --repository-name helm-test --image-ids imageTag=mychart
{
    "imageIds": [
        {
            "imageDigest": "sha256:4865989e73df2c14b15ee2a1befa11673e455cc5a728239a05f5bc12b13cadb3",
            "imageTag": "mychart"
        }
    ],
    "failures": []
}

コンソールから削除を行うことも可能です。

ECR Public に push する

2020/12/1 にリリースされた ECR Public に helm chart を push して公開することも可能です。
基本的には手順は変わらないのですが、AWS CLI で操作する場合は以下の点に注意します。

  • ecr-public という専用のサブコマンド使用する
  • リージョンは us-east-1 を指定する

リポジトリを作成、

$ aws ecr-public create-repository --repository-name helm-test --region us-east-1
{
    "repository": {
        "repositoryArn": "arn:aws:ecr-public::123456789012:repository/helm-test",
        "registryId": "123456789012",
        "repositoryName": "helm-test",
        "repositoryUri": "public.ecr.aws/xxxxxxxx/helm-test",
        "createdAt": 1607177292.959
    },
    "catalogData": {}
}

認証し、

$ aws ecr-public get-login-password --region us-east-1 | helm registry login \
> --username AWS --password-stdin public.ecr.aws/xxxxxxxx
Login succeeded

push すると

$ helm chart save mychart public.ecr.aws/xxxxxxxx/helm-test:mychart
$ helm chart push public.ecr.aws/xxxxxxxx/helm-test:mychart

ECR Public Gallery に公開されます。

参考

Pushing a Helm chart
https://docs.aws.amazon.com/AmazonECR/latest/userguide/push-oci-artifact.html

以上です。
参考になれば幸いです。