[CKA] Secret 구성
Secret 구성의 핵심 개념과 구성 방법, 실습 풀이를 정리합니다.
비밀번호나 민감한 정보를 일반 설정과 분리해 저장할 때 Secret을 사용합니다.
Secret의 data 값은 Base64로 인코딩될 뿐 암호화되지는 않습니다. 저장 시 암호화와 접근 제어는 별도로 구성해야 합니다.
생성 방식
명령형
# 일반적인 생성 방식
kubectl create secret generic <secret-name> --from-literal=<key>=<value>
#여러 literal을 사용한 방식
kubectl create secret generic \
app-secret --from-literal=DB_Host=mysql \
--from-literal=DB_User=root \
--from-literal=DB_Password=paswrd
# 파일로 분리
# 파일의 이름이 secret 내의 키가 됩니다.
# 파일의 내용이 해당 키의 값이 됩니다.
kubectl create secret generic <secret-name> --from-file=<path-to-file>
# 특정 파일을 사용한 방식
kubectl create secret generic \
app-secret --from-file=app_secret.properties
따로 인코딩 과정을 거치지 않습니다.
kubectl create secret generic db-secret \
--from-literal=DB_Host=sql01 \
--from-literal=DB_User=root \
--from-literal=DB_Password=password123
secret/db-secret created
선언형
Secret의 data 필드에는 Base64로 인코딩한 값을 넣어야 합니다. Base64는 보안 수단이 아니며, YAML에 평문을 넣고 싶다면 stringData 필드를 사용할 수 있습니다.
echo -n 'mysql' | base64
echo -n 'root' | base64
echo -n 'paswrd' | base64
data에 평문을 넣으면 다음과 같은 오류가 발생합니다.
Error from server (BadRequest): error when creating "secret.yaml": Secret in version "v1" cannot be handled as a Secret: illegal base64 data at input byte 4
아래는 오류를 재현하는 잘못된 예시입니다.
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
DB_Host: mysql
DB_User: root
DB_Password: paswrd
올바른 선언형 예시는 평문을 받는 stringData를 사용할 수 있습니다.
apiVersion: v1
kind: Secret
metadata:
name: app-secret
stringData:
DB_Host: mysql
DB_User: root
DB_Password: paswrd
view secrets
따로 값은 확인되지 않으며 이전에 인코딩된 옵션에서 디코딩하여 사용합니다.
echo -n 'cm9vdA==' | base64 --decode
kubectl get secrets
kubectl describe secrets
in Pods
envFrom:
- secretRef:
name: app-secret
env:
- name: DB_Password
valueFrom:
secretKeyRef:
name: app-secret
key: DB_Password
volumes:
- name: app-secret-volume
secret:
secretName: app-secret
Secret을 볼륨으로 연결하면 키별 파일로 읽을 수 있습니다. 컨테이너에서는 해당 볼륨을 volumeMounts로 마운트합니다.
주의사항
- Secrets는 완전히 암호화되지 않습니다.
단순히 인코딩만 되어있으므로 외부에서 유출될 경우 디코딩되어 피해가 발생할 수 있습니다. - etcd에서 또한 마찬가지로 암호화되어있지 않습니다.
유휴 상태일 때 혹은 필요시 암호화 구성을 해야합니다. - 네임스페이스에서 Pod나 Deployment를 생성할 권한이 있으면 그 네임스페이스의 Secret을 Pod에 연결해 읽을 수 있습니다.
따라서 RBAC(역할 기반 접근 제어)를 구성하여 엑세스 제한이 필요합니다. - 상황에 따라 특정 리소스만 엑세스할 수 있도록 설정 가능합니다.
- AWS, Azure 등 필요에 따라 외부 secret Provider를 구성해야합니다.
모범 사례
- Secret 개체 정의 파일을 소스 코드 저장소에 체크인하지 않습니다.
- Secret의 저장 시 암호화를 활성화하여 ETCD에 암호화된 상태로 저장합니다.
쿠버네티스가 비밀을 처리하는 방식입니다.
- Secret은 해당 노드의 포드에 필요한 경우에만 노드로 전송됩니다.
- Linux 노드에서 kubelet은 Secret 볼륨 데이터를 tmpfs에 저장합니다.
- Secret에 의존하는 Pod가 삭제되면 kubelet은 Secret 데이터의 로컬 복사본도 삭제합니다.
- 기본적으로 Secret은 etcd에 평문으로 저장됩니다.