[Retry, k8s] 22. 컨피그 & 스토리지 API - 시크릿

Date:     Updated:

카테고리:

태그:


🔔 시크릿


쿠버네티스의 시크릿은 암호, 토큰 또는 키와 같은 소량의 중요한 데이터를 포함하는 오브젝트

  • 시크릿 리소에서는 하나의 시크릿 안에 여러 키-벨류 값이 저장된다.

  • 하나의 시크릿당 저장 가능한 데이터 사이즈는 총 1MB로 제한된다.

종류 개요
Qpaque 범용 용도
kubernetes.io/tls TLS 인증서용
kubernetes.io/basic 기본 인증용
kubernetes.io/dockerconfigjson 도커 레지스트리 인증 정보용
kubernetes.io/ssh-auth SSH 인증 정보용
kubernetes.io/service-account-token 서비스 어카운트 토큰용
bootstrap.kubernetes.io/token Bootstrap 토큰용


(1) 시크릿 타입 - 범용 용도의 시크릿 (Qpaque)

일반 사용자명과 패스워드 같은 인증 정보 등의 임의의 사용자 정의 데이터를 저장하는데 사용되는 시크릿 타입


📜 kubectl로 파일에서 값을 참조하여 생성(–from-file)

  • 파일명이 그대로 키가 되기 때문에 확장자는 붙이지 않는 것이 좋다.

  • 확장자를 붙일 경우 “–from-file=username=username.txt” 등과 같이 지정한다.

# 파일 생성할 때 개행 코드가 들어가지 않도록 "echo -n" 출력 결과를 리다이렉트하여 파일에 쓰는 방법을 사용
$ echo -n "root" > ./username
$ echo -n "rootpasswd" > ./password


# 파일에서 값을 참조하여 시클릿 생성
$ kubectl create secret generic --save-config sample-db-auth \
--from-file=./username --from-file=./password
secret/sample-db-auth created


# 시크릿 확인
$ kubectl get secrets sample-db-auth -o json | jq .data
{
  "password": "cm9vdHBhc3N3ZA==",
  "username": "cm9vdA=="
}


# 보통은 base64로 인코드되어 있다.
$ kubectl get secret sample-db-auth -o json | jq -r .data.username
cm9vdA==


# 일반 텍스트로 변경하려면 base64로 디코드가 필요
$ kubectl get secret sample-db-auth -o json | jq -r .data.username | base64 --decode
root


📜 kubectl로 envfile에서 값을 참조하여 생성(–from-env-file)

$ cat env-secret.txt
username=root
password=rootpassword


$ kubectl create secret generic --save-config sample-db-auth \
--from-env-file ./env-secret.txt
secret/sample-db-auth created


📜 kubectl로 직접 값을 전달하여 생성(–from-literal)

$ kubectl create secret generic --save-config sample-db-auth \
--from-literal=username=root --from-literal=password=rootpassword
secret/sample-db-auth created


📜 매니페스트에서 생성(-f)

  • “data”는 base64로 인코딩된 문자열 값으로 받는다.

  • “stringData”는 필드는 임의의 문자열을 값으로 받는다.

$ cat <<EOF > sample-db-auth.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
data: 
  username: cm9vdA==
  password: cm9vdHBhc3N3ZA=
EOF
$ cat <<EOF > sample-db-auth-nobase64.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
stringData: 
  username: root
  password: rootpassword
EOF




(2) 시크릿 타입 - TLS 타입 시크릿 (kubernetes.io/tls)

TLS 연결을 위한 인증서와 개인 키를 저장하는 데 사용되는 시크릿 타입

  • TLS 타입의 시크릿은 인그레스 리소스 등에서 사용하는 것이 일반적이다.

  • TLS 타입의 시크릿은 매니페스트로 생성할 수 있지만, 기본적으로 비밀키와 인증서 파일로 생성하는 것을 추천한다.

# 자체 서명된 인증서 생성
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ~/tls.key -out ~/tls.crt -subj "/CN=sample1.example.com"


# 비밀키와 인증서 파일로 생성 (--key, --cert) - TLS 시크릿 생성
$ kubectl create secret tls --save-config tls-sample --key ~/tls.key --cert ~/tls.crt


(3) 시크릿 타입 - 도커 레지스트리 타입의 시크릿 (kubernetes.io/dockerconfigjson)

도커 레지스트리에 인증하기 위한 도커 구성 파일을 저장하는 데 사용되는 시크릿 타입

  • 사용하고 있는 컨테이너 레지스트리가 프라이빗 저장소인 경우, 도커 이미지를 가져오려면 인증이 필요하다.

  • 쿠버네티스에서는 이 인증 정보를 시클릿으로 정의하여 사용할 수 있다.

  • 도커 레지스트리 인증용 시크릿도 매니페스트로 생성할 수 있지만, 형식이 특수하므로 kubectl로 직접 생성하는 것이 편하다.

  • 이 타입의 시크릿은 ~/.docker/config.json 파일 대체용으로 사용한다.


📜 kubectl로 직접 생성

# 도커 레지스트리 인증 정보의 시크릿 생성
$ kubectl create secret docker-registry --save-config sample-registry-auth \
--docker-server=REGISTRY_SERVER \
--docker-username=REGISTRY_USER \
--docker-password=REGISTRY_USER_PASSWORD \
--docker-email=REGISTRY_USER_EMAIL


# base64로 인코드된 dockercfg 형식의 JSON 데이터
$ kubectl get secrets -o json sample-registry-auth | jq .data
{
  ".dockerconfigjson": "eyJhdXRocyI6eyJSRUdJU1RSWV9TRVJWRVIiOnsidXNlcm5hbWUiOiJSRUdJU1RSWV9VU0VSIiwicGFzc3dvcmQiOiJSRUdJU1RSWV9VU0VSX1BBU1NXT1JEIiwiZW1haWwiOiJSRUdJU1RSWV9VU0VSX0VNQUlMIiwiYXV0aCI6IlVrVkhTVk5VVWxsZlZWTkZVanBTUlVkSlUxUlNXVjlWVTBWU1gxQkJVMU5YVDFKRSJ9fX0="
}


# base64로 디코드한 dockercfg 형식의 JSON 데이터
$ kubectl get secrets sample-registry-auth -o yaml | grep "\.dockerconfigjson" | awk -F' ' '{print $2}' | base64 --decode
{"auths":{"REGISTRY_SERVER":{"username":"REGISTRY_USER","password":"REGISTRY_USER_PASSWORD","email":"REGISTRY_USER_EMAIL","auth":"UkVHSVNUUllfVVNFUjpSRUdJU1RSWV9VU0VSX1BBU1NXT1JE"}}}


📜 이미지 다운로드 시 시크릿 사용

  • 인증이 필요한 도커 레지스트리의 프라이빗 저장소에서 이미지를 다운로드 하는 경우, 시크릿을 사전에 생성한 후, 파드의 정의 “spec.imagePullSecrets”에 docker-registry 타입의 시크릿을 지정해야 한다.
apiVersion: v1
kind: Pod
metadata:
  name: sample-pull-secret
spec:
  containers:
  - name: secret-image-container
    image: REGISTRY_NAME/secret-image:latest
  imagePullSecrets:
  - name: sample-registry-auth




(4) 시크릿 타입 - 기본 인증 타입의 시크릿 (kubernetes.io/basic-auth)

기본 인증을 위한 사용자 이름과 비밀번호를 저장하는데 사용되는 시크릿 타입


📜 kubectl로 직접 전달하여 생성 (–from-literal)

$ kubectl create secret generic --save-config sample-basic-auth \
--type kubernetes.io/basic-auth \
--from-literal=username=root --from-literal=password=rootpassword


📜 매니페스트에서 생성()

apiVersion: v1
kind: Secret
metadata:
  name: sample-basic-auth
type: kubernetes.io/basic-auth
data:
  username: cm9vdA==
  password: cm9vdHBhc3N3ZA=




(5) 시크릿 타입 - SSH 인증 타입의 시크릿 (kubernetes.io/ssh-auth)

SSH를 위한 개인 키를 저장하는 데 사용되는 시크릿 타입


📜 kubectl로 파일에서 값을 참조하여 생성 (–from-file)

$ ssh-keygen -t rsa -b 2048 -f sample-key -C "sample"

$ kubectl create secret generic --save-config sample-ssh-auth \
--type kubernetes.io/ssh-auth
--from-file=ssh-privatekey=./sample-key


📜 매니페스트 생성

apiVersion: v1
kind: Secret
metadata:
  name: sample-ssh-auth
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: LS0tLS1CRUdJTIBPUEVOU1NIIFB...




(6) 시크릿 사용

시크릿을 컨테이너에서 사용할 경우 크게 두 가지 패턴으로 나룰 수 있다.

  1. 환경 변수로 전달

    • 시크릿의 특정 키만

    • 시크릿의 전체 키

  2. 볼륨으로 마운트

    • 시크릿의 특정 키만

    • 시크릿의 전체 키


📜 환경 변수로 전달

$ cat <<EOF > sample-db-auth-nobase64.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
stringData: 
  username: root
  password: rootpassword
EOF
  • env로 하나씩 정의하기 때문에 환경 변수명을 지정할 수 있는 것이 특징
# 특정 키만
$ cat <<EOF > sample-secret-single-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-single-env
spec:
  containers:
  - name: secret-container
    image: nginx:1.16
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: sample-db-auth
          key: username
EOF


# sample-secret-single-env 파드의 DB_USERNAME 환경 변수 확인
$ kubectl exec -it sample-secret-single-env -- env | grep DB_USERNAME
DB_USERNAME=root
  • envFrom으로 시크릿 전체를 변수로 전달할 수 있어, 키마다 각각 설정할 필요 없으므로 매니페스트가 길어지지는 않지만 시크릿에 어떤 값이 저장되어 있는지 매니페스트 정의에서는 판단하기 힘들다.
# 전체 키
$ cat <<EOF > sample-secret-multi-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-multi-env
spec:
  containers:
  - name: secret-container
    image: nginx:1.16
    envFrom:
    - secretRef:
        name: sample-db-auth
EOF


# sample-secret-multi-env 파드의 환경 변수 확인
$ kubectl exec -it sample-secret-multi-env -- env
..(생략)..
password=rootpassword
username=root
..(생략)..
  • envFrom에서 여러 시크릿을 가져오면 충돌할 가능성이 있다. 이런 경우에는 접두사를 붙여 충돌을 방지할 수 있다.
# 전체 키
$ cat <<EOF > sample-secret-prefix-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-prefix-env
spec:
  containers:
  - name: secret-container
    image: nginx:1.16
    envFrom:
    - secretRef:
        name: sample-db-auth
      prefix: DB1_
    - secretRef:
        name: sample-db-auth
      prefix: DB2_
EOF


# sample-secret-multi-env 파드의 환경 변수 확인
$ kubectl exec -it sample-secret-prefix-env -- env | grep ^DB
DB1_password=rootpassword
DB1_username=root
DB2_password=rootpassword
DB2_username=root


📜 볼륨으로 마운트

$ cat <<EOF > sample-db-auth-nobase64.yaml
apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
stringData:
  username: root
  password: rootpassword
EOF
# 볼륨으로 마운트하는 경우에도 특정 키를 마운트 하는 경우
$ cat <<EOF > sample-secret-single-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-single-volume
spec:
  containers:
  - name: secret-container
    image: nginx:1.16
    volumeMounts:
    - name: config-volume
      mountPath: /config
  volumes:
  - name: config-volume
    secret:
      secretName: sample-db-auth
      items:
      - key: username
        path: username.txt
EOF


# sample-secret-single-volume 파드의 /config/username.txt 파일 확인
$ kubectl exec -it sample-secret-single-volume -- cat /config/username.txt
root
# 시크릿 전체를 마운트
$ cat <<EOF > sample-secret-multi-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-multi-volume
spec:
  containers:
  - name: secret-container
    image: nginx:1.16
    volumeMounts:
    - name: config-volume
      mountPath: /config
  volumes:
  - name: config-volume
    secret:
      secretName: sample-db-auth
EOF


# 파드 내부의 /config 디렉터리 내용 확인
$ kubectl exec -it sample-secret-single-volume -- ls /config/
password  username


📜 동적 시크릿 업데이트

  • 볼륨 마운트를 사용한 시크릿에서는 일정 기간(기본 업데이트 주기 60초)마다 kube-apiserver로 변경을 확인하고 변경이 있을 경우 파일을 교체한다.

  • 이 주기를 조정하려면 “kubelet의 –sync-frequency 옵션”을 지정해야 한다.

  • 환경 변수를 사용한 시크릿의 경우 파드를 기동할 때 환경 변수가 정해지기 때문에 동적으로 변경할 수는 없다.

231312

# 시크릿에 마운트된 디렉터리 확인
$ kubectl exec -it sample-secret-multi-volume -- ls -la /config
total 4
drwxrwxrwt 3 root root  120 Apr  8 09:06 .
drwxr-xr-x 1 root root 4096 Apr  8 09:06 ..
drwxr-xr-x 2 root root   80 Apr  8 09:06 ..2023_04_08_09_06_41.2801225511
lrwxrwxrwx 1 root root   32 Apr  8 09:06 ..data -> ..2023_04_08_09_06_41.2801225511
lrwxrwxrwx 1 root root   15 Apr  8 09:06 password -> ..data/password
lrwxrwxrwx 1 root root   15 Apr  8 09:06 username -> ..data/username


# 파드의 /config/username 파일 내용 확인
$ kubectl exec -it sample-secret-multi-volume -- cat /config/username
root


# 시크릿 변경 전 경과 시간(AGE) 확인
$ kubectl get pod sample-secret-multi-volume
NAME                         READY   STATUS    RESTARTS   AGE
sample-secret-multi-volume   1/1     Running   0          11m
  • 일정 기간(최대 60초)이 경과하면 볼륨에 마운트된 파일 값이 변경된 것을 확인할 수 있다.

  • 파드가 다시 생성되지 않기 때문에 순단(순간 단절)도 발생하지 않는다.

# 시크릿 내용 업데이트
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
data:
  username: YWRtaW4=
EOF
secret/sample-db-auth configured


# 시크릿에 마운트된 디렉터리 확인
$ kubectl exec -it sample-secret-multi-volume -- ls -la /config
total 4
drwxrwxrwt 3 root root  120 Apr  8 09:20 .
drwxr-xr-x 1 root root 4096 Apr  8 09:06 ..
drwxr-xr-x 2 root root   80 Apr  8 09:20 ..2023_04_08_09_20_21.2388709565
lrwxrwxrwx 1 root root   32 Apr  8 09:20 ..data -> ..2023_04_08_09_20_21.2388709565
lrwxrwxrwx 1 root root   15 Apr  8 09:06 password -> ..data/password
lrwxrwxrwx 1 root root   15 Apr  8 09:06 username -> ..data/username


# root에서 amdin으로 변경
$ kubectl exec -it sample-secret-multi-volume -- cat /config/username
admin


# 동적으로 파일 변경된 후의 경과 시간을 확인
$ kubectl get pods sample-secret-multi-volume
NAME                         READY   STATUS    RESTARTS   AGE
sample-secret-multi-volume   1/1     Running   0          15m


KUBERNETES 카테고리 내 다른 글 보러가기

댓글 남기기