Post

[Kubernetes] Secret

๐Ÿ“Œ ๋“ค์–ด๊ฐ€๋ฉฐ

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํŒŒ๋“œ๊ฐ€ ์“ฐ๋Š” ๋ฏผ๊ฐ ์ •๋ณด(๋น„๋ฐ€๋ฒˆํ˜ธยท์ธ์ฆ์„œยทํ† ํฐ)๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฃจ๋Š” Secret์„ ์ •๋ฆฌํ•œ๋‹ค. ๋‹ค์–‘ํ•œ Secret ํƒ€์ž…, ํŒŒ๋“œ์— ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜๋“œ์‹œ ์ง€์ผœ์•ผ ํ•  ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ๊นŒ์ง€ ์‚ดํŽด๋ณธ๋‹ค.

Secret์ด๋ž€? ๋น„๋ฐ€๋ฒˆํ˜ธยท์ธ์ฆ์„œยทํ† ํฐ ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ์ €์žฅยท๊ด€๋ฆฌํ•˜๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฆฌ์†Œ์Šค. ์ฝ”๋“œ/์ด๋ฏธ์ง€์— ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ์•Š๊ณ  ๋ถ„๋ฆฌํ•˜๋ฉฐ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋˜๋Š” Volume์œผ๋กœ ํŒŒ๋“œ์— ์ฃผ์ž…ํ•œ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” base64๋กœ ์ธ์ฝ”๋”ฉ๋˜๊ณ (์•”ํ˜ธํ™” ์•„๋‹˜), etcd ๋ถ€ํ•˜๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด 1MB๋กœ ์ œํ•œ๋œ๋‹ค.


1. Secret ํƒ€์ž… ์ด์ •๋ฆฌ

type ํ•„๋“œ๋Š” โ€œ์ด ๋ด‰ํˆฌ์— ์–ด๋–ค ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋Š”์ง€โ€๋ฅผ ์‹œ์Šคํ…œ์— ์•Œ๋ ค์ค€๋‹ค.

ํƒ€์ž…๋น„์œ ์ฃผ์š” Key๋น„๊ณ 
Opaque๋นˆ ๋ด‰ํˆฌ(์‚ฌ์šฉ์ž ์ •์˜)๊ฐ€์žฅ ๋งŽ์ด ์”€(๊ธฐ๋ณธ)
kubernetes.io/tls์‹ ๋ถ„์ฆ ์„ธํŠธtls.crt, tls.key์ธ์ฆ์„œ ๋งŒ๋ฃŒ ๊ด€๋ฆฌ
service-account-token์‚ฌ์›์ฆtoken, ca.crtํŒŒ๋“œ์— ์ž๋™ ๋งˆ์šดํŠธ
kubernetes.io/basic-auth๋กœ๊ทธ์ธ ๋ฉ”๋ชจusername, passwordIngress ์ธ์ฆ
dockerconfigjson์ฐฝ๊ณ  ์—ด์‡ .dockerconfigjsonPrivate ์ด๋ฏธ์ง€ pull
helm.sh/release.v1์„ค์น˜ ์ด๋ ฅ์„œ(Helm ๋‚ด๋ถ€)๊ฑด๋“œ๋ฆฌ์ง€ ๋ง ๊ฒƒ ๐Ÿšซ

Opaque (์ผ๋ฐ˜ํ˜•)

์ •ํ•ด์ง„ ํ˜•์‹์ด ์—†๋Š” ์ž„์˜์˜ Key-Value. DB ๋น„๋ฐ€๋ฒˆํ˜ธยทAPI Key ๋“ฑ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ.

1
2
3
4
5
6
apiVersion: v1
kind: Secret
type: Opaque
data:
  db-pass: MWYyaZD...   # base64
  api-key: dXNlcnB...

kubernetes.io/tls (HTTPS ์ธ์ฆ์„œ)

Ingressยท์›น ์„œ๋ฒ„์˜ TLS/SSL ์ธ์ฆ์„œ ํ‘œ์ค€ ๊ทœ๊ฒฉ. tls.crt(๊ณต๊ฐœ ์ธ์ฆ์„œ)ยทtls.key(๊ฐœ์ธํ‚ค)๊ฐ€ ํ•„์ˆ˜.

1
kubectl create secret tls my-tls-secret --cert=tls.crt --key=tls.key -n default

dockerconfigjson (์ด๋ฏธ์ง€ ํ’€ ์‹œํฌ๋ฆฟ)

Private ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋กœ๊ทธ์ธ ์ •๋ณด. ํŒŒ๋“œ์˜ imagePullSecrets์— ์‚ฌ์šฉ.

1
2
3
kubectl create secret docker-registry my-registry-secret \
  --docker-server=hyperregistry.example.com \
  --docker-username=myuser --docker-password=mypassword -n default
1
2
3
4
5
6
spec:
  imagePullSecrets:
  - name: my-registry-secret
  containers:
  - name: app
    image: hyperregistry.example.com/myapp:1.0

โš ๏ธ helm.sh/release.v1์€ ์ ˆ๋Œ€ ์ˆ˜๋™ ์‚ญ์ œยท์ˆ˜์ • ๊ธˆ์ง€. Helm์ด ๋ฐฐํฌ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ „์šฉ ์‹œํฌ๋ฆฟ์ด๋ผ, ๊ฑด๋“œ๋ฆฌ๋ฉด Helm์ด ๋ฐฐํฌ๋œ ์•ฑ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค.


2. Secret ์ƒ์„ฑ & ์กฐํšŒ

1
2
3
4
5
6
7
8
9
# ๋ช…๋ น์–ด ์ƒ์„ฑ(Opaque)
kubectl create secret generic my-secret \
  --from-literal=db-password=mysecretpassword --from-literal=api-key=abc123 -n default

# ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ
kubectl create secret generic my-secret --from-file=config.json -n default

# YAML์€ base64 ์ธ์ฝ”๋”ฉ ํ•„์š”
echo -n 'mysecretpassword' | base64   # bXlzZWNyZXRwYXNzd29yZA==
1
2
3
# ์กฐํšŒ & ๋””์ฝ”๋”ฉ
kubectl get secret my-secret -n default -o yaml
kubectl get secret my-secret -n default -o jsonpath='{.data.db-password}' | base64 -d

3. ํŒŒ๋“œ์—์„œ ์‚ฌ์šฉ

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ฃผ์ž…

1
2
3
4
5
6
7
8
9
10
11
12
13
spec:
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: DB_PASSWORD            # ๋‹จ์ผ ํ‚ค
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: db-password
    envFrom:                       # ์ „์ฒด ์ฃผ์ž…
    - secretRef:
        name: my-secret

Volume์œผ๋กœ ๋งˆ์šดํŠธ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret
      items:
      - key: db-password
        path: db-password.txt      # /etc/secrets/db-password.txt

๐Ÿ’ก ์ธ์ฆ์„œยท์„ค์ • ํŒŒ์ผ์€ Volume, ์งง์€ ๊ฐ’์€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํŽธํ•˜๋‹ค. TLS ์ธ์ฆ์„œ์ฒ˜๋Ÿผ ํŒŒ์ผ๋กœ ์กด์žฌํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ Volume ๋งˆ์šดํŠธ, DB ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฐ™์€ ๋‹จ์ˆœ ๊ฐ’์€ secretKeyRef๋กœ ์ฃผ์ž…ํ•œ๋‹ค.


4. ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ (ํ•„์ˆ˜)

โš ๏ธ โ‘  Base64๋Š” ์•”ํ˜ธํ™”๊ฐ€ ์•„๋‹ˆ๋‹ค. kubectl get secret -o yaml์ด๋ฉด ๋ˆ„๊ตฌ๋‚˜ ๋””์ฝ”๋”ฉํ•ด ์›๋ณธ์„ ๋ณธ๋‹ค.

1
echo "bXlzZWNyZXRwYXNzd29yZA==" | base64 -d   # mysecretpassword

โš ๏ธ โ‘ก RBAC๋กœ ์กฐํšŒ ๊ถŒํ•œ ์ œํ•œ. ์•„๋ฌด๋‚˜ Secret์„ get/listํ•˜์ง€ ๋ชปํ•˜๋„๋ก Role์„ ์—„๊ฒฉํžˆ ๊ฑด๋‹ค.

1
2
3
4
5
6
kind: Role
rules:
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["my-secret"]   # ํŠน์ • Secret๋งŒ
  verbs: ["get"]

โš ๏ธ โ‘ข Git์— ์˜ฌ๋ฆฌ์ง€ ๋ง ๊ฒƒ. Secret YAML์„ ๊ทธ๋Œ€๋กœ ์ปค๋ฐ‹ํ•˜๋ฉด ์œ ์ถœ๋œ๋‹ค. Sealed SecretsยทExternal Secrets ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๊ณ , .gitignore์— *-secret.yaml์„ ์ถ”๊ฐ€ํ•œ๋‹ค.


๐Ÿ“ ์ •๋ฆฌ

1
2
3
4
5
Secret
โ”œโ”€ ๊ฐœ๋…   ๋ฏผ๊ฐ ์ •๋ณด ์ €์žฅ(base64ยท1MB ์ œํ•œ)
โ”œโ”€ ํƒ€์ž…   Opaque(๊ธฐ๋ณธ)/tls/dockerconfigjson/basic-auth...
โ”œโ”€ ์ฃผ์ž…   env(secretKeyRef) / Volume(๋งˆ์šดํŠธ)
โ””โ”€ ๋ณด์•ˆ   base64โ‰ ์•”ํ˜ธํ™” ยท RBAC ์ œํ•œ ยท Git ๊ธˆ์ง€
๊ฐœ๋…ํ•œ ์ค„ ์ •์˜
Secret๋ฏผ๊ฐ ์ •๋ณด ๊ด€๋ฆฌ ๋ฆฌ์†Œ์Šค
Opaque / tls๋ฒ”์šฉ / ์ธ์ฆ์„œ ํƒ€์ž…
base64์ธ์ฝ”๋”ฉ(์•”ํ˜ธํ™” ์•„๋‹˜)

Secret์˜ ํ•ต์‹ฌ์€ ๋ฏผ๊ฐ ์ •๋ณด๋ฅผ ์ฝ”๋“œ์—์„œ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, base64๋Š” ์•”ํ˜ธํ™”๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ๋ฐ˜๋“œ์‹œ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค. RBAC๋กœ ์ ‘๊ทผ์„ ์ขํžˆ๊ณ  Git ์œ ์ถœ์„ ๋ง‰๋Š” ์‹ค๋ฌด ์Šต๊ด€์ด Secret ์ž์ฒด๋ณด๋‹ค ์ค‘์š”ํ•˜๋‹ค.


๐Ÿ”— ์ฐธ๊ณ 

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.