๋ชฉ์ฐจ
ย Secrets
ConfigMap์ ์ผ๋ฐ ํ
์คํธ ํ์์ผ๋ก Configuration ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค. ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์ฑ ๊ฐ์ ๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ๋ค๋ฃฐ ๋ ํธ์คํธ ๋ค์๊ณผ ์ ์ ๋ค์์ ConfigMap์ ๊ตฌ์ฑํ๋ ๊ฒ์ ๊ด์ฐฎ์ง๋ง ํจ์ค์๋๋ฅผ ์ ์ฅํ๊ธฐ์ ์ ์ ํ์ง ์๋ค. Secret์ ํจ์ค์๋๋ ํค ๊ฐ์ ๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ๋ฐ์ดํฐ๋ฅผ ์ธ์ฝ๋ฉ๋ ํ์์ผ๋ก ์ ์ฅํ๋ค.
ConfigMap๊ณผ ๋น์ทํ๋ฉฐ, โCreate Secretโ, โInject into Podโ ๋ ๋จ๊ณ๋ฅผ ๊ฐ์ง๋ค.
ย Create Secrets
Imperative
kubectl create secret generic <secret-name> --from-literal=<key>=<value>
# kubectl create secret generic \
# app-secret --from-literal=DB_Host=mysql \
# --from-literal-DB_User=root \
# --from-literal-DB_Password=passwrd
Bash
๋ณต์ฌ
โข
--from-literal: ๋ช
๋ น ์์ฒด์์ ํค ๊ฐ ์์ ์ง์ ํ๋๋ฐ ์ฌ์ฉ๋๋ ์ต์
kubectl create secret generic <secret-name> --from-file=<path-to-file>
Bash
๋ณต์ฌ
Declarative
Secret์์ ๋ฏผ๊ฐ ๋ฐ์ดํฐ๋ ์ธ์ฝ๋ฉ๋ ํฌ๋งท์ผ๋ก ์ ์ฅํ๋ค. ๋ฐ์ดํฐ๋ฅผ ์ผ๋ฐ ํ
์คํธ๋ก ๋ช
์ํ๋ฉด ์์ ํ์ง ์๊ฒ ๋๋ฌธ์ ๋ช
๋ น์ ์ ๊ทผ์ผ๋ก Secret์ ๋ง๋ค ๋ ์ธ์ฝ๋ฉ๋ ํ์์ ๊ฐ์ ์ง์ ํด์ผ ํ๋ค.
Linux์์ echo -n ์ ์คํํ๋ฉด ๋ณํ์ํค๊ณ ์ ํ๋ ํ
์คํธ๊ฐ ์ถ๋ ฅ๋๋ค
$ echo -n 'mysql' | base64
bXlzcWw=
$ echo -n 'root' | base64
cm9vdA==
$ echo -n 'passwrd' | base64
cGFzd3Jk
Bash
๋ณต์ฌ
# secret-data.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
DB_Host: bXlzcWw=
DB_User: cm9vdA==
DB_Password: cGFzd3Jk
YAML
๋ณต์ฌ
ย View Secrets
์์ฑ๋ secrets๋ฅผ ํ์ธํ๊ธฐ ์ํด kubectl get secrets ๋ช
๋ น์ ์ฌ์ฉํ ์ ์๋ค. kubectl describe secrets ๋ช
๋ น์ ์ฌ์ฉํ๋ฉด ์์ฑ๊ฐ์ ํ์ธํ ์ ์์ง๋ง, key์ ๋์๋๋ value๋ค์ ํ์ธ ํ ์๋ ์๋ค.
๋ฐ๋ผ์ ๊ฐ์ ํ์ธํ๊ธฐ ์ํด์๋ yaml ํฌ๋งท์ผ๋ก secret์ ํ๋ณดํด์ผ ํ๋ค.
kubectl get secret app-secret -o yaml
Decode Secrets
๊ฐ์ ๋์ฝ๋ฉํ๊ธฐ ์ํด์๋ ์ธ์ฝ๋ฉ์ ์ฌ์ฉํ๋ base64 ์ปค๋งจ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค
$ echo -n 'bXlzcWw=' | base64 --decode
mysql
Bash
๋ณต์ฌ
ย Inject into Pod
Pod์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ฝ์
ํ๊ธฐ ์ํด ์ปจํ
์ด๋์ envFrom์ด๋ผ๋ ์์ฑ์ ์ถ๊ฐํ๋ค. envFrom์ list๋ก ํ์ํ๋งํผ ๋ง์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ ์ ์๋ค. envFrom.secretRef.name์ ๊ฐ์ผ๋ก ์์ฑํ Secret์ ์ด๋ฆ์ ์
๋ ฅํ๋ค.
# pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secret
YAML
๋ณต์ฌ
Secrets in Pods
Secret์ Pod์ ํ๊ฒฝ ๋ณ์๋ก ์ฃผ์
ํ ์ ์๊ณ , ๋จ์ผ ํ๊ฒฝ ๋ณ์ ์ฃผ์
๋ ๊ฐ๋ฅํ๋ฉฐ ํ์ผ๋ก์ ์ ์ฒด Secret์ ๋ณผ๋ฅจ์ ๋ฃ์ ์๋ ์๋ค.
ENV
envFrom:
- secretRef:
name: app-secret
YAML
๋ณต์ฌ
SINGLE ENV
env:
- name: DB_Password
valueFrom:
secretKeyRef:
name: app-secret
key: DB_Password
YAML
๋ณต์ฌ
VOLUME
volumes:
- name: app-secret-volume
secret:
secretName: app-secret
YAML
๋ณต์ฌ
โข
Pod์ Volume์ผ๋ก Secret์ด ์ฃผ์
๋๋ฉด Secret์ ๊ฐ๊ฐ์ ์์ฑ์ value๋ฅผ ์ฝํ
์ธ ๋ก ํ๋ ํ์ผ๋ก ์์ฑ๋๋ค.
$ ls /opt/app-secrets-volumes
DB_Host DB_Password DB_User
$ cat /opt/app-secrets-volumes/DB_Password
passwrd
Bash
๋ณต์ฌ
ย How to handle
โข
Secret์ Secret์ด ํ์ํ Pod๊ฐ ์์ ๋ ํด๋น Pod์ Node๋ก ์ ์ก๋๋ค.
โข
Kubelet์ Secret์ tmpfs์ ์ ์ฅํ์ฌ ๋์คํฌ ์ ์ฅ์์ ๊ธฐ๋ก๋์ง ์๋๋ก ํ๋ค.
โข
Secret์ ์์กดํ๋ Pod๊ฐ ์ญ์ ๋๋ฉด kubelet์ ํด๋น secret ๋ฐ์ดํฐ๋ฅผ ๋ก์ปฌ์์ ์ญ์ ํ๋ค.
ย Note on Secrets
ย Secrets are not Encrypted. Only encoded.
Secret์ ์ํธํ๋ ๊ฒ์ด ์๋๋ผ ์ธ์ฝ๋ฉ๋ ๊ฒ์ผ ๋ฟ์ด๊ธฐ ๋๋ฌธ์ ๋๊ตฌ๋ ํ์ผ์ ํ์ธํ ์ ์๊ณ ๋์ฝ๋ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํ์ธํ ์ ์๋ค.
๋ฐ๋ผ์ Github ๊ฐ์ SCM์ ํธ์ํ ๋ Secret ํ์ผ์ ํจ๊ป ํธ์ํ๋ฉด ์๋๋ค.
ย Secrets are not encrypted in ETCD
Secret์ ETCD์ ์ ์ฅ๋๋๋ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ETCD๋ ๋ฐ์ดํฐ๋ฅผ ์ํธํํ์ง ์๋๋ค. ๋ฐ๋ผ์ ๋ณด์์ฑ์ ์ํด ์ํธํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํด์ผ ํ๋ค.
ย Anyone able to create pods/deployments in the same namespace can access the secrets
๊ฐ์ ๋ค์์คํ์ด์ค์์ Pod๋ฅผ ๋ง๋ค ์ ์๋ ์ฌ๋์ ๋๊ตฌ๋ Secret์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ RBAC(์ญํ ๊ธฐ๋ฐ ์ก์ธ์ค ์ ์ด)์ ๊ตฌ์ฑํ์ฌ ์ก์ธ์ค ์ ํ์ ๋์ด์ผ ํ๋ค.
ย Consider third-party secrets store providers
AWS, Azure, GCP, Valut ๋ฑ์ Provider๋ฅผ ์ฌ์ฉํ๋ฉด Secret์ด ETCD๊ฐ ์๋ ์ธ๋ถ์ ์ ์ฅ๋๊ณ ๋ณด์ ์ฒ๋ฆฌ๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ข๋ค.