์•”ํ˜ธ, ํ† ํฐ ๊ฐ™์€ ์†Œ๋Ÿ‰์˜ ๊ธฐ๋ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ ์“ฐ๋Š” ์˜ค๋ธŒ์ ํŠธ. Secret์— ์ €์žฅ๋œ ๊ฐ’์€ Pod์ด ์‚ฌ์šฉํ•œ๋‹ค.

4 minute read

์•”ํ˜ธ, ํ† ํฐ ๊ฐ™์€ ์†Œ๋Ÿ‰์˜ ๊ธฐ๋ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ ์“ฐ๋Š” ์˜ค๋ธŒ์ ํŠธ. Secret์— ์ €์žฅ๋œ ๊ฐ’์€ Pod์ด ์‚ฌ์šฉํ•œ๋‹ค.

ConfigMap๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ๊ธฐ๋ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•˜๊ธฐ ์œ„ํ•œ ํŠน๋ณ„ํ•œ ์˜ค๋ธŒ์ ํŠธ์ด๋‹ค.

๋‹จ, ์ฃผ์˜ํ•  ๊ฒƒ์€ โ€œSecret ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์™„๋ฒฝํ•œ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹คโ€๋ผ๋Š” ์ ์ด๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๋‚ด์šฉ ์ฐธ์กฐ.

Secret ์ƒ์„ฑ

yaml ํŒŒ์ผ๋กœ ์ƒ์„ฑ

ConfigMap๊ณผ ๋‹ฌ๋ฆฌ data ํ•ญ๋ชฉ์˜ ๊ฐ’์ด base64 ํ˜•์‹์œผ๋กœ ์ธ์ฝ”๋”ฉ ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค. base64 ์ธ์ฝ”๋”ฉ์€ ์•„๋ž˜์˜ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

# encoding
$ echo "root" | base64
cm9vdAo=

# decoding
$ echo "cm9vdAo=" | base64 -d
root


apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque # ์ž„์˜์˜ ์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ์ดํ„ฐ
data:
  username: cm9vdAo= # (base64) root
  password: cGFzc3dvcmQxMjMK # (base64) password123

type: Opaque๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š”๋ฐ, Secret ์˜ค๋ธŒ์ ํŠธ์˜ ๋””ํดํŠธ ํƒ€์ž…์ด๋‹ค. ์ง์ ‘ ์ •์˜ํ•ด์„œ ์“ฐ๋Š” Secret์„ Opaque(๋ถˆ๋ถ„๋ช…ํ•œ) ํƒ€์ž…์œผ๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค.

kubectl๋กœ ์ƒ์„ฑ

$ kubectl create secret generic [secret-name] \
  --from-literal=username=root \
  --from-literal=password=password123

kubectl๋กœ ์ƒ์„ฑํ•˜๋ฉด, ํ‰๋ฌธ๊ฐ’์„ ๋„ฃ์–ด๋„ ์•Œ์•„์„œ base64๋กœ ์ธ์ฝ”๋”ฉ ํ•ด์ค€๋‹ค. Secret ์˜ค๋ธŒ์ ํŠธ๋Š” kubectl๋กœ ์ƒ์„ฑํ•˜๋Š”๊ฒŒ ๋” ํŽธํ• ์ง€๋„!


Pod์˜ Secret ์‚ฌ์šฉ

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ธฐ

...
spec:
  containers:
    - name: ...
      image: ...
      envFrom:
        - secretRef:
            name: my-secret

๋ณผ๋ฅจ ๋งˆ์šดํŠธ๋ฅผ ํ†ตํ•ด ๋ฐ›๊ธฐ

ConfigMap์˜ ๋ฐฉ์‹๊ณผ ๊ฑฐ์˜ ๋น„์Šทํ•˜๋ฏ€๋กœ ํŒจ-์Šค!



Secret์˜ ์ทจ์•ฝ์ 

Secret์€ ConfigMap ๋•Œ์™€ ๋‹ฌ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ base64 ์ธ์ฝ”๋”ฉํ•ด์„œ ๋ณด๊ด€ํ•œ๋‹ค๋Š” ๊ฒƒ ๋ง๊ณ ๋Š” ์•„๋ฌด๋Ÿฐ ์ฐจ์ด๊ฐ€ ์—†๋‹ค. ์‹ค์ œ๋กœ ๋งˆ์Œ๋งŒ ๋จน์œผ๋ฉด ์›๋ž˜์˜ ํ‰๋ฌธ๊ฐ’์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

$ k get secrets db-secret -o json
{
    "apiVersion": "v1",
    "data": {
        "DB_Host": "c3FsMDE=",
        "DB_Password": "cGFzc3dvcmQxMjM=",
        "DB_User": "cm9vdA=="
    },
    "kind": "Secret",
    "metadata": {
        ...
    },
    "type": "Opaque"
}

$ echo "c3FsMDE=" | base64 -d
root

k get secrets -o json์œผ๋กœ ํ™•์ธํ•œ base64 ๊ฐ’์„ ๋‹ค์‹œ ๋””์ฝ”๋”ฉ ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


ConfigMap ์˜ค๋ธŒ์ ํŠธ์™€ Secret ์˜ค๋ธŒ์ ํŠธ๋Š” etcd์— ์ €์žฅ๋œ๋‹ค. ํ‰์†Œ์—” api-server๋ฅผ ํ†ตํ•ด etcd์— ์ ‘์†ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์œผ๋กœ key-value ๊ฐ’์„ ์ฝ์–ด์˜ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ Secret์€ etcd์— ์•”ํ˜ธํ™” ๋˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ์ €์žฅ๋œ๋‹ค. ์ฆ‰, ๋ˆ„๊ตฐ๊ฐ€ etcd์— ์ ‘๊ทผํ•˜๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, Secret์˜ ํ‰๋ฌธ๊ฐ’์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.


์–ด๋Ÿฌ๋‚˜ ์ €๋Ÿฌ๋‚˜ Secret ์˜ค๋ธŒ์ ํŠธ๋Š” ๊ฐ’์„ ์•”ํ˜ธํ™” ํ•˜๋Š”๋ฐ๋Š” ์กฐ๊ธˆ ๋ถ€์กฑํ•œ ๋…€์„์ด๋‹ค. ๊ทธ๋ž˜์„œ โ€œ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”(Encryption at Rest)โ€ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™” ํ•ด์„œ, Secret์˜ ์ทจ์•ฝ์ ์„ ๋ณด์™„ํ•ด์•ผ ํ•œ๋‹ค.

์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”(Encryption at Rest)

etcd์— ์ €์žฅ๋œ, โ€œat restโ€ ์ƒํƒœ์˜ Secret ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™” ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. Udemy ๊ฐ•์ขŒ์—์„œ๋Š” etcdctl์„ ํ†ตํ•ด etcd ํด๋Ÿฌ์Šคํ„ฐ์— ์ ‘์†ํ•ด์„œ ์‹ค์ œ ํ‰๋ฌธ๊ฐ’์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ๋„ ๋ณด์—ฌ์คฌ์ง€๋งŒ, ์—ฌ๊ธฐ์„œ๋Š” ํŒจ-์Šค ํ•˜๊ฒ ๋‹ค!

์›๋ฆฌ๋Š” ๊ฐ„๋‹จํ•˜๋‹ค. ConfigMap/Secret ์˜ค๋ธŒ์ ํŠธ์˜ ๊ฐ’์„ etcd์— ์ €์žฅํ•  ๋•Œ ์•”ํ˜ธํ™”ํ•ด์„œ ์ €์žฅํ•  ๊ฒƒ์ด๋‹ค. ๋‹จ, api-server๋Š” Encryption Provider๋ฅผ ํ†ตํ•ด ์•”ํ˜ธํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด๋…ํ•  ์ˆ˜ ์žˆ๋‹ค.

Encryption Configuration ์ƒ์„ฑ

etcd ์•”ํ˜ธํ™” ๋ฐฉ์‹์„ ์ •์˜ํ•˜์ž.

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
    providers:
      - identity: {}
      - aescbc: # ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜
          keys:
            - name: key1
              secret: cGFzc293cmQxMjMK # (base64) password123

api-server์— Encryption Provider ์„ค์ •

api-server์˜ .yaml ํŒŒ์ผ์„ ์—ด์–ด์„œ Encryption Provider๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.

...
spec:
  containers:
    - command:
        - kube-apiserver
        ...
        - --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
        ...
      volumeMounts:
        - name: enc
          mountPath: /etc/kubernetes/enc
          readonly: true
        ...
  volumes:
    - name: enc
      hostPath:
        path: /etc/kubernetes/enc
        type: DirectoryOrCreate

kube-apiserver ์ปค๋งจ๋“œ์˜ ์ธ์ž๋กœ --encryption-provider-config๋„ ๋„˜๊ฒจ์ค˜์•ผ ํ•˜๊ณ , ๋ณผ๋ฅจ๊ณผ ๋ณผ๋ฅจ ๋งˆ์šดํŠธ๋กœ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

api-server์˜ .yaml ํŒŒ์ผ ์ˆ˜์ •ํ•ด์ฃผ๋ฉด, api-server์˜ Static Pod์ด ์žฌ์ƒ์„ฑ๋˜์–ด ์ ์šฉ๋œ๋‹ค.

Encryption ์ฒดํฌ

์ž˜ ๋˜์—ˆ๊ฒ ์ง€!

๋‹จ, ๊ธฐ์กด์— ์ด๋ฏธ ์žˆ๋˜ ConfigMap/Secret์ด ์•”ํ˜ธํ™”๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. api-server ์žฌ์ƒ์„ฑ ํ›„์— ๋งŒ๋“ค์–ด์ง„ ConfigMap/Secret๋งŒ ์•”ํ˜ธํ™” ๋˜์–ด etcd์— ์ €์žฅ๋˜๋Š” ๊ฒƒ!


References