민감한 정보를 저장하는 Secret

Created
Apr 10, 2022
Created by
Tags
Kubernetes
Property
 
 
  • 시크릿(Secret)은 SSH 키, 비밀번호와 같이 민감한 정보를 저장하기 위한 용도로 사용한다.
  • 네임스페이스에 종속된다.
  • 개별 시크릿의 크기는 1MiB로 제한된다.
  • 시크릿 볼륨 소스는 지정된 오브젝트 참조가 실제로 시크릿 유형의 오브젝트를 가리키는지 확인하기 위해 유효성을 검사한다. 따라서, 시크릿에 의존하는 모든 파드보다 먼저 시크릿을 만들어야 한다.
  • 시크릿을 생성하는 명령어는 3가지로 나뉘고 시크릿타입은 opaque, dockerconfigjson, tls 등이 있다.
 
 
$ ku create secret --help Create a secret using specified subcommand. Available Commands: docker-registry Create a secret for use with a Docker registry generic Create a secret from a local file, directory, or literal value tls Create a TLS secret
 
 

opaque 타입의 시크릿 생성하기

 
opaque 타입은 사용자가 정의하는 데이터를 저장할 수 있는 범용 시크릿이다.
 
my-password 라는 시크릿을 아래와 같이 생성한다.
시크릿도 컨피그맵처럼 —from-literal, —from-env-file 등의 옵션을 사용할 수 있다.
ubuntu@ip-10-220-12-225:~$ kubectl create secret generic my-password --from-literal password=1234 secret/my-password created
 
시크릿을 조회해보면 2개가 나온다. (default-token-nqqnl 시크릿은 ServiceAccount 라는 오브젝트에 의해 네임스페이스 별로 이미 만들어진 것이다.)
ubuntu@ip-10-220-12-225:~$ ku get secrets NAME TYPE DATA AGE default-token-nqqnl kubernetes.io/service-account-token 3 40d my-password Opaque
 
직접 만든 my-password 라는 시크릿을 YAML 형식으로 조회해보면 password 키에 대응하는 값이 1234가 아닌 MTIzNA==으로 되어있다.
쿠버네티스가 기본적으로 시크릿 값을 base64 방식으로 인코딩하기 때문이다.
notion image
ubuntu@ip-10-220-12-225:~$ echo MTIzNA== | base64 -d 1234
 
따라서 YAML 파일로 시크릿을 생성할 때도 base64으로 인코딩된 문자열을 작성해야 한다.
 
 
 

 
 

파드에서 생성한 시크릿 불러오기

 
시크릿을 파드에서 환경변수로 사용하려면 아래와 같이 YAML을 작성하고 클러스터에 적용한다.
apiVersion: v1 kind: Pod metadata: name: env-from-secret spec: containers: - name: my-container image: busybox args: ['tail', '-f', '/dev/null'] envFrom: - secretRef: # my-password 라는 시크릿에서 키/값을 불러옴 name: my-password
 
apply 하면 디코딩된 값이 컨테이너의 환경변수에 들어간다. password=1234
notion image
 
valueFrom 으로 원하는 키/값만 선택해서 다른 이름으로 불러올 수도 있다. MY_PW=1234
apiVersion: v1 kind: Pod metadata: name: value-from-secret spec: containers: - name: my-container image: busybox args: ['tail', '-f', '/dev/null'] env: - name: MY_PW valueFrom: # my-password 라는 시크릿의 password 키/값을 가져와 MY_PW 라는 이름으로 바꿈. secretKeyRef: name: my-password key: password
notion image
 
시크릿을 파일로 마운트해서 불러올 수도 있다. (시크릿 키 이름으로 된 파일 내용이 시크릿 값으로 되어있음.)
apiVersion: v1 kind: Pod metadata: name: volume-mount-secret spec: volumes: # my-password 라는 시크릿을 컨테이너에 마운트하는 데 필요한 볼륨 정의 - name: secret-volume secret: # 가져올 시크릿 secretName: my-password containers: - name: my-container image: busybox args: ['tail', '-f', '/dev/null'] volumeMounts: # secret-volume 이 불러올 시크릿 값을 /etc/secret 에 마운트시킨다 - name: secret-volume mountPath: /etc/secret
notion image
 
apiVersion: v1 kind: Pod metadata: name: selective-volume-mount-secret spec: volumes: # my-password 라는 시크릿을 컨테이너에 마운트하는 데 필요한 볼륨 정의 - name: secret-volume secret: # 가져올 시크릿 secretName: my-password # my-password 시크릿에 있는 password 키/값만 선택하고 값은 /etc/secret/mypw 에 저장함 items: - key: password path: mypw containers: - name: my-container image: busybox args: ['tail', '-f', '/dev/null'] volumeMounts: # secret-volume 이 불러올 시크릿 키/값을 /etc/secret 에 마운트시킨다 - name: secret-volume mountPath: /etc/secret
notion image
 
 
 

 
 

이미지 레지스트리 접근을 위한 dockerconfigjson 타입의 시크릿 생성하기

 
 
AWS ECR 같은 프라이빗 레지스트리에서 도커이미지를 받아오려면 레지스트리에 로그인을 해야 한다.
쿠버네티스에서는 docker login 명령어 대신에 레지스트리 접근에 필요한 인증 정보를 저장하는 시크릿을 생성한다.
 
레지스트리 인증을 위해 시크릿을 생성하는 방법은 2가지가 있다.
 
  1. docker login 명령어로 레지스트리에 로그인 할 때 도커가 만들어주는 ~/.docker/config.json 사용
  1. 시크릿 만들 때 직접 —-docker-username, —-docker-password 으로 인증 정보 명시
 
 
  1. ~/.docker/config.json 사용
 
~/.docker/config.json 을 아래와 같이 작성한다. (프라이빗 레지스트리로 AWS ECR 을 사용한다고 가정.)
{ "auths" : { "credHelpers": { "public.ecr.aws": "ecr-login", "<ECR 레지스트리 주소>": "ecr-login", } } }
 
레지스트리에 로그인한다.
$ aws ecr get-login-password --profile ecr-user --region ap-northeast-2 \ | docker login --username AWS --password-stdin <레지스트리 주소> Login Succeeded
 
~/.docker/config.json 내용이 아래와 같이 바뀐다. (auths.<ECR 레지스트리 주소>.auth 에 레지스트리 로그인에 필요한 토큰이 들어감.)
$ cat ~/.docker/config.json { "auths": { "<ECR 레지스트리 주소>": { "auth": "QVdTOmV5SndZW..." }, "credHelpers": {} } }
 
바뀐 ~/.docker/config.json 을 가지고 $ kubectl create secret generic 명령어로 시크릿을 생성한다.
이 때 시크릿 키 이름을 .dockerconfigjson 으로 명시하지 않으면 error: failed to create secret Secret "registry-auth-from-dockerconfigjson" is invalid: data[.dockerconfigjson]: Required value 에러가 발생한다.
$ kubectl create secret generic \ registry-auth-from-dockerconfigjson \ --from-file=.dockerconfigjson=/home/ubuntu/config.json \ --type=kubernetes.io/dockerconfigjson
 
생성된 시크릿을 조회해본다. .dockerconfigjson 을 키 이름으로 하고 토큰을 값으로 하는 kubernetes.io/dockerconfigjson 타입의 시크릿이 만들어졌다.
ubuntu@ip-10-220-12-225:~$ ku get secrets registry-auth-from-dockerconfigjson -o yaml apiVersion: v1 data: .dockerconfigjson: ewogICAgICAgICJhdXRocyI6IHsKI... kind: Secret metadata: creationTimestamp: "2022-04-10T08:15:19Z" name: registry-auth-from-dockerconfigjson namespace: default resourceVersion: "4734200" uid: d7f7dc11-a609-48e6-ad5b-83a476469aba type: kubernetes.io/dockerconfigjson
 
 
  1. —-docker-username, —-docker-password 으로 인증 정보 명시
 
$ kubectl create secret docker-registry 명령어에 —docker-username, —docker-password 옵션을 줘서 레지스트리 로그인 인증 정보를 명시하여 시크릿을 생성할 수 있다.
$ kubectl create secret docker-registry \ ecr-registry-auth-by-cmd \ --docker-username=AWS --docker-password=$(aws ecr get-login-password --profile ecr-user --region ap-northeast-2)
 
~/.docker/config.json 으로 시크릿을 만들었을 때와 마찬가지로 .dockerconfigjson 을 키 이름으로 하고 로그인에 필요한 토큰을 값으로 하는 시크릿이 생성되었다.
$ ku get secrets ecr-registry-auth-by-cmd -o yaml apiVersion: v1 data: .dockerconfigjson: eyJhdXRocyI6eyJodHRw... kind: Secret metadata: creationTimestamp: "2022-04-10T07:56:42Z" name: ecr-registry-auth-by-cmd namespace: default resourceVersion: "4732710" uid: 7b00a93b-1cc1-4fcb-8f27-784cd9aefe1b type: kubernetes.io/dockerconfigjson
 
 

프라이빗 레지스트리에서 이미지를 받아서 파드 생성하기

 
디플로이먼트를 아래와 같이 만들었다.
apiVersion: apps/v1 kind: Deployment metadata: name: deployment-using-image-registry-secrets spec: replicas: 3 selector: matchLabels: # matchLabels 에 있는 라벨이 붙은 파드들을 리플리카셋으로 묶음. app: app template: metadata: labels: app: app spec: containers: - name: app image: <프라이빗 레지스트리 주소>:<이미지태그> ports: - containerPort: 8000 imagePullSecrets: - name: ecr-registry-auth-by-cmd # 레지스트리 인증에 사용할 시크릿 이름
 
$ kubectl apply -f 명령어로 디플로이먼트를 생성한다.
notion image
 
프라이빗 레지스트리에 있는 이미지로 파드가 생성된 것을 확인할 수 있다.
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku describe pod deployment-using-image-registry-secrets-78f955769c-64k88 Name: deployment-using-image-registry-secrets-78f955769c-64k88 Namespace: default Priority: 0 Node: ip-10-220-6-77/10.220.6.77 Start Time: Sun, 10 Apr 2022 09:47:45 +0000 Labels: app=app pod-template-hash=78f955769c Annotations: <none> Status: Running IP: 11.244.1.90 IPs: IP: 11.244.1.90 Controlled By: ReplicaSet/deployment-using-image-registry-secrets-78f955769c Containers: app: Container ID: docker://12e7d7aba0ad6aa7f1890b36958b633e3b1c5288b3d8e1bf762b6c101d4bce8f Image: <프라이빗 레지스트리 주소>:latest Image ID: docker-pullable://<프라이빗 레지스트리 주소>@sha256:fcd06e50decc221bb316bdc2e44886391c2b5618ab6e0c38a2d7a36d16e78248
 
 
 

 
 

TLS 키를 저장할 수 있는 시크릿 생성하기

 
파드 내부의 애플리케이션이 SSL 인증서나 비밀키를 써야할 때 tls 시크릿을 생성한다.
 
 
  1. SSL 인증서 및 키 생성
$ openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 --subj "/CN=example.com" -keyout cert.key -out cert.crt .........+..........+.....+......+.+..+...+....+........+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+..................+..+.+..+....+...........+....+...+......+.....+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+..............................+...+....+..+....+......+...+.....+................+...........+....+...........+....+.....+.+......+..............+......+...+....+...+.....+.............+......+..............+.......+...+.....+...............+.+..............+...................+...+............+..+...+...+....+...+...+...+..+...+......+...+.........................+........+.............+...........+...+............+.............+...+..+......+.......+...+..............+...+...............+....+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ..+...+...+.+...+...+............+..+...+..........+........+...+.+...+...+.....+.........+..........+.....+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+.....+.........+...+.........+....+..+.......+.....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+..+.+......+...+......+..+..........+...............+..+......+.+.........+......+...+........+...+......+.+........+.........+.+...........+....+.....+..........+.....+.+......+.........+.....+...+......+.+...+.....+......+.+.....+................+.....+..................+.......+.....+...+....+......+......+.....+......+.......+..+...+.......+...+..+.....................+....+.....+...+...............+..........+...+........+.......+..+..................+....+...+..+.+............+..+....+..+....+..............+....+......+.........+.....+.+......+...........+..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -----
$ ls -al | grep cert -rw-rw-r-- 1 ubuntu ubuntu 1814 Apr 10 10:27 cert.crt -rw------- 1 ubuntu ubuntu 3272 Apr 10 10:27 cert.key
 
  1. TLS 생성 (타입이 kubernetes.io/tls 으로 되어있다.)
$ ku create secret tls my-tls-secret --cert cert.crt --key cert.key
notion image
 
tls.cert 라는 키 이름에는 인증서가 인코딩 된 값으로 들어있고 tls.key 라는 키 이름에는 비밀키가 인코딩 되어 들어가있다.
$ ku get secret my-tls-secret -o yaml apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0...= tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0t...= kind: Secret metadata: creationTimestamp: "2022-04-10T10:28:37Z" name: my-tls-secret namespace: default resourceVersion: "4746494" uid: e65f5dc2-715e-489c-a3ea-0bfa8418202b type: kubernetes.io/tls
 
 
 
 
참고자료