Kubernetes Secret
목차
비밀번호, OAuth 토큰, API 키, TLS 인증서, ssl키 와 같은 민감한 Credential이 요구 되는 데이터를 base64로 인코딩 하여 저장, 관리
- 데이터 저장은 1MiB 이하로만 가능
- Pod에 Secret 적용시 자동 Decoding되어 애플리케이션에서 바로 사용 가능
- 기본 사용방법은 configMap와 동일 → Kubernetes configMap 확인
- kubectl create cm → kubectl create secret
- envFrom.configMapRef → envFrom.secretRef
- name → secretName 로 바꿔 사용
Secret Pod
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: sc-container
image: busybox
volumeMounts:
- name: web-secret
mountPath: /secrets
envFrom:
- secretRef:
name: secret-sc
volumes:
- name: web-secret
secret:
secretName: secret-sc
key: sc-sourceConfigMap Pod (비교)
apiVersion: v1
kind: Pod
metadata:
name: cm-pod
spec:
containers:
- name: cm-container
image: busybox
volumeMounts:
- name: cm-secret
mountPath: /configmap
envFrom:
- configMapRef:
name: secret-sc
volumes:
- name: web-cm
configMap:
name: configMap-cm
key: cm-source참고 base64
- 쉽게 디코딩 되는 아쉬움 있음
$ echo 'kubernetes secret' | base64
a3ViZXJuZXRlcyBzZWNyZXQK
$ echo a3ViZXJuZXRlcyBzZWNyZXQK | base64 -d
kubernetes secret활용
#secret 생성
$ kubectl create secret generic secret-sc \
--from-literal=rootpw=k8sroot \
--from-literal=database=k8sdb \
--from-literal=user=k8suser \
--from-literal=password=k8suserconfigMap secret 동시 사용 예제
apiVersion: v1
kind: Pod
metadata:
name: sc-pod
spec:
containers:
- name: my-container
image: busybox
env:
- name: ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: secret-sc
key: rootpw
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: configmap-cm
key: databaseconfigMap secret 동시 사용 예제2
apiVersion: v1
kind: Pod
metadata:
name: sc-pod
spec:
containers:
- name: my-container
image: busybox
envFrom:
- configMapRef:
name: configmap-cm
- secretRef:
name: secret-sc추가: seald-secrets(링크)
- Secret에 저장되는 값은 단순 base64인코딩 값이므로 쉽게 디코딩이 가능하다. 민감한 데이터는 쉽게 디코딩되어 노출될 위험이 높다.
- SealedSecret 사용 시 클러스터에서 실행되는 Controller에 의해서만 암/복호화가 가능
- SealedSecret Controller는 Kubernetes Secret으로 복호화를 수행
- 복호화는 SealedSecret Controller내 저장된 인증서를 통해 처리
실행되는 Controller가 문제가 생길경우 복호화가 불가능
예기치 않은 상황에 대비해 내장된 인증서를 로컬에 저장하여 사용 가능함
#링크에서 릴리즈 버전 확인하여 설치 현재 0.26.2
$ KUBESEAL_VERSION='0.26.2'
$ wget "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION:?}/kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz"
$ tar -xvzf kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz kubeseal
#전역 사용 설정
$ sudo install -m 755 kubeseal /usr/local/bin/kubeseal
$ kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.26.2/controller.yaml
#또는 wget으로 다운받고 그 파일(controller.yaml) apply
#Pod 확인
$ kubectl get pods -n kube-system | grep sealed-secrets-controller
sealed-secrets-controller-7f4d55d696-56c9t 1/1 Running 0 22s
#base64기반 yaml 파일 생성
$ kubectl create secret generic secret-from-sealedsecret \
--dry-run=client --from-literal=superpwd=k8ssecret -o yaml > mysecret.yaml
#파일에서 vi mysecret.yaml에서 data 에 암호화된 부분 확인 ->azhzc2VjcmV0
$ echo azhzc2VjcmV0 | base64 -d
k8ssecret
#쉽게 디코딩
#SealedSecret controller가 보유한 인증서 암호화
$ cat mysecret.yaml | kubeseal -o yaml > mysecret-sealed.yamlmysecret.yaml
apiVersion: v1
data:
superpwd: azhzc2VjcmV0
kind: Secret
metadata:
creationTimestamp: null
name: secret-from-sealedsecretmysecret-sealed.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: secret-from-sealedsecret
namespace: default
spec:
encryptedData:
superpwd: AgB2DoUuu1job77bFv73W8ReEzpkYhaB9d15gGPpgGo16rGay5MyS/9WTa5CLyhfhHoowSKqSSRXFniGg692PgyeUCEVsOBh8k5J0B7jmb8OBa+OYHOebZguY4Gr4rNjV2QSqNlEIqzuBslBZSnyDsAgmDYq3qqvsnkuCQPFZzsTQcw8oPHdS5kI3MgvZp/Sh20LvjIfjki2BN7bjYrF74D3HKNukiw6X5M7F9dFneszeSO9Nv1LJ1sFMUqXwFouyvFsn6JTLbIjiKf/Gv9vdTaGRaPfT48RWLmOipnwI+qD2QaZdrO/Sjo96CSKLpHc76QmZR7QSLJu1LU0+92LxknTnBmi1o7dnhE3dScS4MooUG7LkB+jXlQpd1flJfXxRfEJmy6EJ0/HYUfo73rCBQvdzdllgJ33z569OAvoAwnLbDP/I0AhPTk8PRlPIeOz5frzbSCMfnCtddfhxMuF309FbJG36HPNn8siB9rKTkqVNSGlXvJwZvHv93bgrxgsJkp9ao5Xt4ITokC9rXl6GR0kzNy9mkuku64C6BZioxrnPtjnYhpEr6sQgo/3rDkkrTm5d/2A6yiRgzoXfJuIFeKuItj1RlkuMuwJH7ACRzlqf6hy0onhW6a+bucZ4Rjz9NE7BNPbBB97GFY/x4NCLaZQ38FiZIc9dQV4eBOCTOd1QE4ovqUO7+ihiT7OeMzprspCLR7svZruRAE=
template:
metadata:
creationTimestamp: null
name: secret-from-sealedsecret
namespace: default$ kubectl apply -f mysecret-sealed.yaml
sealedsecret.bitnami.com/secret-from-sealedsecret created
#확인
$ kubectl get sealedsecret
NAME AGE
secret-from-sealedsecret 13s
#secret를 통해서도 확인 가능
$ kubectl get secret
NAME TYPE DATA AGE
...
secret-from-sealedsecret Opaque 1 29s
#데이터 확인 mysecret.yaml의 base64 인코딩 값과 같음
$ kubectl get secret secret-from-sealedsecret -o jsonpath='{.data.superpwd}'
azhzc2VjcmV0Controller가 보유한 인증서 저장
#mycert.pem으로 저장 'kubeseal --fetch-cert > mycert.pem'로도 가능
$ kubeseal --controller-name=sealed-secrets-controller \
--controller-namespace=kube-system --fetch-cert > mycert.pem
$ cat mycert.pem
-----BEGIN CERTIFICATE-----
MIIEzTCCArWgAwIBAgIRAPogo3H13Lz+gpZ0O3jpZoYwDQYJKoZIhvcNAQELBQAw
ADAeFw0yNDA0MTYwNDM0MTVaFw0zNDA0MTQwNDM0MTVaMAAwggIiMA0GCSqGSIb3
...저장된 인증서로 SealedSecret 생성
$ kubectl create secret generic secret-from-localsealed \
--dry-run=client --from-literal=superpwd=k8ssecret -o yaml > lsecret.yaml
$ cat lsecret.yaml | kubeseal --controller-name=sealed-secrets-controller \
--controller-namespace=kube-system --format yaml \
--cert mycert.pem > lsecret-sealed-local.yaml
$ kubectl get secret secret-from-localsealed -o jsonpath='{.data.superpwd}'
azhzc2VjcmV0암호화키 교체 (–re-encrypt)
#encryptedData 의 키값이 변경됨 결과값(azhzc2VjcmV0->k8ssecret)은 같음
$ kubeseal --re-encrypt < lsecret-sealed-local.yaml > tmp.yaml \
&& mv tmp.yaml lsecret-sealed-local.yamlPrivate-key 백업/복원
- 클러스터가 문제가 생길경우 private-key가 소실되어 암복호화가 불가능해지는 것을 방지 하기 위하여 별도로 백업. 새로운 클러스터 재구성시 private-key를 복원하여 seald-secret를 복호화 하여 secret를 얻을 수 있다.
#백업
$ kubectl get secret -n kube-system -l \
sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > main.key
#복원
$ kubectl apply -f main.key
# pod 재생성하여 pod 가 새로 업데이트된 key 값을 반영하도록 한다.
$ kubectl delete pod -n kube-system -l \
app.kubernetes.io/name=sealed-secrets