[K3s-03] K3s에서 Docker credentials를 주입하는 방법
목차
AWS의 관리형 쿠버네티스 클러스터인 EKS는 기본적으로 AWS ECR 권한을 가지고 있지만, 온프레미스 환경의 경우 Docker 권한을 직접 주입해야 합니다(프라이빗 Docker 레지스트리에서 이미지를 가져오기 위해). 기본 아이디어는 AWS에서 ECR 인증 토큰을 가져와 ‘regcred’라는 이름의 Secret(dockerconfigjson)을 생성하는 cronjob을 만드는 것입니다(이름은 ‘regcred’로 설정할 수 있습니다). 예제 네임스페이스로는 ‘practice’를 사용하겠습니다.
apiVersion: v1
kind: Secret
metadata:
name: ecr-registry-helper-secrets
namespace: practice
stringData:
AWS_SECRET_ACCESS_KEY: "XXX" # Replace with your AWS secret access key
AWS_ACCESS_KEY_ID: "XXX" # Replace with your AWS access key ID
AWS_ACCOUNT: "XXX" # Replace with your AWS account ID
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ecr-registry-helper-cm
namespace: practice
data:
AWS_REGION: "ap-northeast-2" # Replace with your ECR region
DOCKER_SECRET_NAME: regcred # Replace with your desired ECR token secret name
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-default
namespace: default
이제 ‘CronJob’에게 시크릿을 삭제하고 생성할 수 있는 권한을 부여하는 Role
과 RoleBinding
을 생성합니다.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: practice
name: role-full-access-to-secrets
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["regcred"] # 원하는 ECR 토큰 시크릿 이름으로 교체
verbs: ["delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: default-role-binding
namespace: practice
subjects:
- kind: ServiceAccount
name: sa-default # serviceaccount 이름이 다르면 해당 이름으로 교체
namespace: practice
apiGroup: ""
roleRef:
kind: Role
name: role-full-access-to-secrets # role 이름이 다르면 교체
apiGroup: ""
마지막으로 CronJob
을 생성합니다. 이미지 omarxs/awskctl
은 컨테이너 내에서 AWS 커맨드라인을 사용하도록 구성되어 있습니다. 네임스페이스 또한 꼭 설정해주세요.
apiVersion: batch/v1
kind: CronJob
metadata:
name: ecr-registry-helper
namespace: default
spec:
schedule: "0 */10 * * *" # 원하는 스케줄로 교체
successfulJobsHistoryLimit: 2
suspend: false
jobTemplate:
spec:
template:
spec:
serviceAccountName: sa-default # serviceaccount 이름이 다르면 교체
containers:
- name: ecr-registry-helper
image: omarxs/awskctl:v1.0
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: ecr-registry-helper-secrets # secret 이름이 다르면 교체
- configMapRef:
name: ecr-registry-helper-cm # configmap 이름이 다르면 교체
command:
- /bin/bash
- -c
- |-
ECR_TOKEN="$(aws ecr get-login-password --region ${AWS_REGION})"
NAMESPACE_NAME=practice # 원하는 namespace로 교체
kubectl delete secret --ignore-not-found $DOCKER_SECRET_NAME -n $NAMESPACE_NAME
kubectl create secret docker-registry $DOCKER_SECRET_NAME --docker-server=https://${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com --docker-username=AWS --docker-password=${ECR_TOKEN} --namespace=$NAMESPACE_NAME
echo "Secret was successfully updated at $(date)"
restartPolicy: Never
이 cronjob은 10시간마다 실행됩니다. AWS ECR 토큰은 12시간 동안 유효하므로, 만료되기 전에 새로고침됩니다. 추가로, cronjob을 수동으로 실행하는 방법은 다음과 같습니다.
kubectl create job --from=cronjob/ecr-registry-helper ecr-registry-helper-manual -n practice
# CronJob 이름이 다르면 교체
Check whether it shows this kind of message when looking at the logs: Secret was successfully updated at Sat Jan 1 00:00:00 UTC 2023
# Manual Job 삭제
kubectl delete job ecr-registry-helper-manual -n practice # Job 이름과 Namespace가 다르면 교체
Now, all you need to do is put imagePullSecrets
on the Pod spec.
# 예제 Pod
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: practice
spec:
containers:
- name: test-container
image: <your-account>.dkr.ecr.<your-region>.amazonaws.com/<your-image>:<your-tag> # ECR 이미지로 교체
imagePullPolicy: Always
imagePullSecrets:
- name: regcred # secret 이름이 다르면 교체
TL;DR #
apiVersion: v1
kind: Secret
metadata:
name: ecr-registry-helper-secrets
namespace: default
stringData:
AWS_SECRET_ACCESS_KEY: "" # AWS 비밀 액세스 키로 교체
AWS_ACCESS_KEY_ID: "" # AWS 액세스 키 ID로 교체
AWS_ACCOUNT: "" # AWS 계정 ID로 교체
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ecr-registry-helper-cm
namespace: default
data:
AWS_REGION: "eu-central-1" # ECR 리전으로 교체
DOCKER_SECRET_NAME: regcred # 원하는 ECR 토큰 시크릿 이름으로 교체
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-default
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: role-full-access-to-secrets
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["regcred"] # 원하는 ECR 토큰 시크릿 이름으로 교체
verbs: ["delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: default-role-binding
namespace: default
subjects:
- kind: ServiceAccount
name: sa-default # serviceaccount 이름이 다르면 교체
namespace: default
apiGroup: ""
roleRef:
kind: Role
name: role-full-access-to-secrets # Role 이름이 다르면 교체
apiGroup: ""
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ecr-registry-helper
namespace: default
spec:
schedule: "0 */10 * * *" # 원하는 스케줄로 교체
successfulJobsHistoryLimit: 2
suspend: false
jobTemplate:
spec:
template:
spec:
serviceAccountName: sa-default # serviceaccount 이름이 다르면 교체
containers:
- name: ecr-registry-helper
image: omarxs/awskctl:v1.0
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: ecr-registry-helper-secrets # secret 이름이 다르면 교체
- configMapRef:
name: ecr-registry-helper-cm # configmap 이름이 다르면 교체
command:
- /bin/bash
- -c
- |-
ECR_TOKEN="$(aws ecr get-login-password --region ${AWS_REGION})"
NAMESPACE_NAME=default # 원하는 namespace로 교체
kubectl delete secret --ignore-not-found $DOCKER_SECRET_NAME -n $NAMESPACE_NAME
kubectl create secret docker-registry $DOCKER_SECRET_NAME --docker-server=https://${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com --docker-username=AWS --docker-password=${ECR_TOKEN} --namespace=$NAMESPACE_NAME
echo "Secret was successfully updated at $(date)"
restartPolicy: Never
registries.yaml #
K3s의 경우 추가적인 프라이빗 레지스트리 구성을 지원합니다. 시작할 때, K3s는 /etc/rancher/k3s/registries.yaml
이 존재하는지 확인합니다. 해당 파일에 포함된 레지스트리 구성이 컨테이너 구성을 생성할 때 사용됩니다.
따라서 yaml 파일에 자격 증명이 올바르게 구성되어 있으면 Kubernetes의 배포에서 imagePullSecrets
를 추가할 필요가 없습니다.
mirrors:
<REGISTRY>:
endpoint:
- https://<REGISTRY>/v2
configs:
<REGISTRY>:
auth:
username: <BASIC AUTH USERNAME>
password: <BASIC AUTH PASSWORD>
token: <BEARER TOKEN>
tls:
ca_file: <PATH TO SERVER CA>
cert_file: <PATH TO CLIENT CERT>
key_file: <PATH TO CLIENT KEY>
insecure_skip_verify: <SKIP TLS CERT VERIFICATION BOOLEAN>