Published on

ECR Credential-Provider 사용해보기

Authors
  • avatar
    Name
    Jay
    Twitter

CronJob을 이용?

자체적으로 EC2(Ubuntu 20.04)에 Kubernetes Cluster를 Kubeadm로 만들어서 사용하는데, ECR를 연결하여 사용하려고 했다. AWS cli 명령어 aws ecr get-login-password를 사용하여 Docker secret에 추가하여 인증할 수도 있다. Kubernetes 공식문서에 친절하게 나와 있다. 하지만 이렇게 aws ecr get-login-password로 받은 token은 12시간동안 유효하게 된다. 따라서 Cronjob을 만들어서 주기적으로 업데이트해주는 작업으로 해결한 블로그들을 여럿 보았다.

Kubelet Crendential Provider를 사용

하지만 좀 더 깔끔한 방법이 있을 것 같아서 찾아보는 과정에서 1.26부터 stable된 kubelet image credential provider 설정을 발견하게 되었다.

이 기능을 사용하기 위해서는 아래처럼 두가지의 kubelet flag를 설정해줘야 한다. --image-credential-provider-config --image-credential-provider-bin-dir

Kubelet flag 설정

kubeadm을 사용했기 때문에 kubelet systemd service 설정값을 보면 아래처럼 환경변수 값을 가져오는 것을 확인할 수 있다.

systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

나는 여기에 추가해야 되는 flag 두 개를 넣어줘서 테스트를 하게 되었다.

cat /var/lib/kubelet# cat kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9

plugin binary 설정

--image-credential-provider-bin-dir에서 plugin binary file 경로를 가르켜야 하는데, go로 source code를 compile하였다. 그리고 binary file을 /usr/local/bin으로 이동하였다.

curl -OL https://go.dev/dl/go1.20.8.linux-amd64.tar.gz
sudo tar -C /usr/local -xvf go1.20.8.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
git clone https://github.com/kubernetes/cloud-provider-aws.git
cd cloud-provider-aws/cmd/ecr-credential-provider
go build
mv ecr-credential-provider /usr/local/bin

config file 설정

그리고 --image-credential-provider-config에 연결한 config 파일도 작성하였다.

ecr.yml

apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
providers:
  - name: ecr-credential-provider
    matchImages:
      - '*.dkr.ecr.*.amazonaws.com'
      - '*.dkr.ecr.*.amazonaws.com.cn'
      - '*.dkr.ecr-fips.*.amazonaws.com'
      - '*.dkr.ecr.us-iso-east-1.c2s.ic.gov'
      - '*.dkr.ecr.us-isob-east-1.sc2s.sgov.gov'
    apiVersion: credentialprovider.kubelet.k8s.io/v1
    defaultCacheDuration: '12h'

준비가 되어서 /var/lib/kubelet# cat kubeadm-flags.env를 아래와 같이 수정하였다.

KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9 --image-credential-provider-config=/home/ubuntu/ecr.yml --image-credential-provider-bin-dir=/usr/local/bin/"

ECR pull 권한

최소한의 권한만 주는게 Best practice지만 일단 Read쪽 권한 전부와 GetAuthorizationToken를 추가하여 테스트를 진행했다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ecr:GetRegistryPolicy",
        "ecr:DescribeImageScanFindings",
        "ecr:GetLifecyclePolicyPreview",
        "ecr:GetDownloadUrlForLayer",
        "ecr:DescribeRegistry",
        "ecr:DescribePullThroughCacheRules",
        "ecr:DescribeImageReplicationStatus",
        "ecr:GetAuthorizationToken",
        "ecr:ListTagsForResource",
        "ecr:ListImages",
        "ecr:BatchGetRepositoryScanningConfiguration",
        "ecr:GetRegistryScanningConfiguration",
        "ecr:BatchGetImage",
        "ecr:DescribeImages",
        "ecr:DescribeRepositories",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetRepositoryPolicy",
        "ecr:GetLifecyclePolicy"
      ],
      "Resource": "*"
    }
  ]
}

kubelet restart

이제 새로운 flag가 적용되도록 restart를 하면 정상적으로 ECR에서 image를 pull해온다. 😎

sudo systemctl daemon-reload && sudo systemctl restart kubelet