https://kubernetes.io/docs/concepts/configuration/secret/
민감한 정보를 보관해두고 Pod에 주입시켜서 사용 할수 있게 해준다.
기본 시크릿
생성
--from-file
# Create files needed for rest of example.
$ echo -n "admin" > ./username.txt
$ echo -n "1f2d1e2e67df" > ./password.txt
$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created
--from-literal
kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
kubectl create -f ./secret.yaml
조회
kubectl get secrets
사용
Pod에서 Secret을 파일로 사용 케이스
- 여러 Pods에서 동시에 접근이 가능하다.
spec.volumes[].secret.secretName
에 추가하 Secret이름을 추가함spec.containers[].volumeMounts[]
spec.containers[].volumeMounts[].readOnly = true
spec.containers[].volumeMounts[].mountPath
data
맵의 키는mountPath
의 파일이름이 됨
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod",
"namespace": "myns"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo",
"readOnly": true
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret"
}
}]
}
}
Secret의 특정 Path만 노출하기
spec.volumes[].secret.items
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod",
"namespace": "myns"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo",
"readOnly": true
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret",
"items": [{
"key": "username",
"path": "my-group/my-username"
}]
}
}]
}
}
Secret 파일 권한설정
- 아무런 설정이 없으면
0644
- JSON의 경우 8진수 표기법이 안되기 때문에 10진수로 입력을 함
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod",
"namespace": "myns"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo"
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret",
"defaultMode": 256
}
}]
}
}
마운트된 Secret의 볼륨
- base64 디코딩이 된 파일로 존재
$ ls /etc/foo/
username
password
$ cat /etc/foo/username
admin
$ cat /etc/foo/password
1f2d1e2e67df
마운트된 Secret은 자동 업데이트됨
업데이트 시간 : kubelet sync period + ttl(secret cache in kublet)
Secret 환경변수로 사용
- 여러 Pods에서 사용가능
env[x].valueFrom.secretKeyRef
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
Secret 환경변수사용
base64 디코딩이 된 상태로 환경변수로 세팅됨
$ echo $SECRET_USERNAME
admin
$ echo $SECRET_PASSWORD
1f2d1e2e67df
Private Registry Pulling
Private 레지스트리를 관리하면 아래를 참고한다.
https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
Secret의 자동 마운트 방법
https://kubernetes.io/docs/tasks/run-application/podpreset/
깊게 보기
제한사항
- Pod에서 사용하기 전에 생성 되어야 함
- Secret은 같은 namespace에서만 접근 가능
- Secret당 1MB 크기 제한
- apiserver와 kubelet memory issue로 제약함
- 작지만 너무 많은 secret가 있어도 동일한 이슈 발생 할수 있음
- secret은 kubectrl의
--manifest-url
--config
다음과 같은 cli 옵션을 제공하지 않은 - Pod 명세로만 주입 가능
- 무조건 REST API 방식으로 제공됨
- secret 사용값이 optional 해도 Pod에 정의된 secret은 무조건 존재해야함
- 지정한 secret이 없으면 Pod 기동이 안됨
envFrom
에서secretKeyRef
으로 접근 할 경우도 존재해야만 Pod가 시작됨- 단 환경 변수 이름 오류(
InvalidVariableNames
)의 경우는 무시하고 Pod가 시작됨
Secret과 Pod의 라이프타임 작용
- Pod 생성시 secret을 체크하지 않음
- Pod가 스케쥴링이 되면 kublet이 secret value를 패치 시도
- secret value가 없거나 API 딜레이가 걸리면 주기적으로 다시 패치 시도
- Pod시작이 되지 않으면 event에 기록됨
- fetch가 완료되면 마운트나 환경 변수로 입력이 되고 컨테이너 시작이 됨
보안특징
보호
- Secret은 Pod와 독립적으로 생성됨
- 시스템적으로도 Secret은 가능한 디스크에 기록되지 않게 되어 있음
- Secret은 Pod가 요청할때 전송되고 디스크에 기록되지 않음
- 전송된 Secret은
tmpfs
에 저장되고 Pod 삭제시 함께 삭제됨 - Secret은 API Server나 kublet간에 통신 채널인 SSL/TLS을 그대로 이용함
주의사항
- API server는 Secret Data를 etcd에 plaintext로 저장함
- admin 사용자만 접근하도록 제한 필요
- etcd를 더 이상 사용하지 않을때는 꼭 디스크를 완벽하게 지워야함
- manifest(JSON or YAML)파일로 secret data(base64 encoded)를 관리하면 base64 decoding을 하면 plaintext로 바로 나오기 때문에 더 주의있게 관리가 필요
- application에서 secret data가 사용될때 로깅이나 전송되지 않게 주의 필요
- 여러개의 replica와 etcd가 동작할때 비암호화 통신으로 동작함
- 추가로 설정이 필요
- 현재는 kubelet을 통해서 누구나 secret data 접근이 가능함
- 제한 접근 기능을 추가할 예정임
- 같은 Node에 여러 Pod의 Secret이 존재할 수 있지만 Pod가 요청했던 Secret만 컨테이너에서 접근 가능함, 다른 Pod는 Secret을 액세스 할수 없음
- 한 Pod에는 여러개의 컨테이너가 있는 경우 컨테이너 끼리는
volumeMounts
가 노출됨 - Pod를 보안 레벨에 따라서 나누는 전략을 사용하는게 안전