LoginSignup
1
1

More than 1 year has passed since last update.

k8s で ECR の認証情報 Secret を定期的に取得する

Last updated at Posted at 2022-09-13

ECR から Docker のイメージをプルするための認証情報は aws ecr get-login-password で作成できます。k8s ではこの認証情報を Secret として保存することで、イメージをECR からプルしてくれます。しかし、この方法で取得した認証情報は12時間しか有効ではないため、定期的に認証を取得する必要があります。
k8s が動いているホストの cron で実行してもいいのですが、色々な事情によって k8s の cronjob を使ってやることにしました。
今回はその方法を記事にしようと思います。

前提

  • k8s がすでに用意されている
  • docker イメージをパブリックに公開できる環境がある。または、パブリックにある docker イメージを自己判断で使用できる環境である。
  • ECR にプライベートなイメージがすでに用意されている

流れ

  1. aws のログイン情報を Secret として登録
  2. aws-cli と kubectl を使用できる Docker イメージを作成する
  3. ServiceAccount と ClusterRoleBinding を作成する
  4. cronjob で定期的に ECR への認証情報を取得して Secret として保存

1. aws のログイン情報を Secret として登録

Secret を作成するために、AWS のログイン情報をファイルにまとめて起きます。
今回は .aws.credentials という名前で作成します。

.aws.credentials
AWS_ACCOUNT_ID=123456789012
AWS_ACCESS_KEY_ID=XXXXXXXXX
AWS_SECRET_ACCESS_KEY=YYYYYYYYY
AWS_DEFAULT_REGION=ap-northeaset-1

このファイルから Secret を作成しておきます。これはこの後の3の手順で Pod 内から使用します。
今回はSecret名を aws-credentials にしています。 Secret は名前空間を超えることはできないので注意してください。

kubectl create generic aws-credentials --from-env-file=.aws.credentials

2. aws-cli と kubectl を使用できる Docker イメージを作成する

k8s の cronjob で aws-cli と kubectl を実行するための Docker イメージを作成します。
すでに公開されている Docker イメージを使用するのであれば、このステップは飛ばすことができます。自己判断で決めてください。

イメージを自作する場合

alpine ベースの Docker イメージを作成します。

Dockerfile
FROM alpine:3.12
RUN apk --no-cache add aws-cli wget \
    && wget https://storage.googleapis.com/kubernetes-release/release/v1.24.0/bin/linux/amd64/kubectl \
    && mv kubectl /usr/local/bin/kubectl \
    && chmod +x /usr/local/bin/kubectl \
    && apk del wget

v1.24.0 部分が kubectl のバージョンです。
バージョン部分はハードコーディングしていますが、公式には最新版をインストールする方法の記載があります。
次のステップで説明しますが、Pod 内では kubectl で使用する config ファイルが Pod 起動時(?)に用意されます。そのため、このイメージに kubectl のための config ファイルを入れる必要はありません。パブリックとして公開するため、間違えてもいれないようにしてください。
Docekrfile を作成したら、パブリックなイメージとして docker hub や ECR などにプッシュします。

docker login
docker push my-image:latest

3. ServiceAccount と ClusterRoleBinding を作成する 

続いて、Pod から Secret を作成できるように権限を設定していきます。
k8s には Role Based Access Control(RBAC) という機能があります。リソースへのアクセス権限を設定した Role を付与することで、 リソースへのアクセスを許可することができます。
今回はクラスターで共通の ClusterRole を使用していきます。(クラスター全体ではなく、Namespace ごとに分離して権限を作成したい場合は Role を使用できます)

ServiceAccount の作成

まずは ServiceAccount を作成します。

# kubectl -n default create sa <ServiceAccount 名>
kubectl -n default create sa secrets-manager

ServiceAccount は 1:N の関係で ClusterRole と紐づけることができます。
ServiceAccount は Pod のマニュアルで指定します。

ClusterRole の作成

つづいて、ClusterRole を作成します。

secrets-cr.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secrets-cr  # ClusterRole の名前
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create", "updated", "delete"]

rules.resourcesecrets と記載しています。これで secret-cr が紐づいたリソースは secret に対して作成・更新・削除ができるようになります。 verbs には他にも get list watch などがあります。

ClusterRoleBinding で紐づける

最後に、作成した SecretAccount と CluterRole を紐づけます。紐付けには ClusterRoleBinding を使用します。(もし Role を作成していた場合は、RoleBinding)

secrets-crb.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: secrets-crb  # ClusterRoleBinding の名前
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: secrets-cr  # 紐づける ClusterRole
subjects:
- kind: ServiceAccount
  name: secrets-manager  # 紐づける ServiceAccount
  namespace: default

ClusterRoleBinding は最後に作成しないとエラーになるのでご注意ください。

4. Secret を更新する Cronjob を作成

最後に cronjob を作成して完成です。

aws-secret.yml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: create-aws-secret
  namespace: default
spec:
  schedule: "* */10 * * *"  # 有効期間は12時間
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          serviceAccount: secrets-manager  # 3. で作成した ServiceAccount を設定
          containers:
            - name: create-aws-secret
              image: < 2. で作成したパブリックな Docker イメージ>
              imagePullPolicy: IfNotPresent
              env:
                - name: SECRET_NAME
                  value: aws  # 作成・更新する secret の名前
              envFrom:
                - secretRef:
                    name: aws-credentials  # 1. で作成した aws 認証情報
              command:
                - /bin/sh
                - -c
                - |-
                  kubectl delete secret --ignore-not-found ${SECRET_NAME}
                  kubectl create secret docker-registry ${SECRET_NAME} \
                  --docker-server=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com \
                  --docker-username=AWS --docker-password=$(aws ecr get-login-password)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1