๐น ์ํฌ๋ฆฟ(Secret) ๊ด๋ฆฌ๋?
Kubernetes์์๋ ์ํฌ๋ฆฟ(Secret) ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ API ํค, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋น๋ฐ๋ฒํธ, ์ธ์ฆ ํ ํฐ ๋ฑ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
๊ทธ๋ฌ๋ Kubernetes์ ๊ธฐ๋ณธ Secret ๋ฆฌ์์ค๋ Base64 ์ธ์ฝ๋ฉ๋ ํํ๋ก ์ ์ฅ๋๋ฏ๋ก ๋ณด์์ ์ทจ์ฝํฉ๋๋ค.
โ
GitOps ํ๊ฒฝ์์ ์ํฌ๋ฆฟ์ ์์ ํ๊ฒ ๊ด๋ฆฌํ๋ ค๋ฉด?
โ Git ์ ์ฅ์์ ์ํฌ๋ฆฟ์ ์ง์ ์ ์ฅํ๋ฉด ์ ๋จ
โ GitOps ๊ธฐ๋ฐ์ CI/CD ํ์ดํ๋ผ์ธ์์๋ ๋ณด์์ฑ์ ์ ์งํด์ผ ํจ
โ ๋ณ๊ฒฝ๋ ์ํฌ๋ฆฟ์ด ์๋์ผ๋ก Kubernetes์ ๋ฐ์๋๋๋ก ๊ตฌ์ฑํด์ผ ํจ
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Sealed Secrets๊ณผ External Secrets ๊ฐ์ ์๋ฃจ์ ์ ํ์ฉํ ์ ์์ต๋๋ค.
๐น ๊ธฐ๋ณธ Kubernetes Secret์ ํ๊ณ
Kubernetes์ ๊ธฐ๋ณธ Secret ๋ฆฌ์์ค๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ฉ๋๋ค.
apiVersion: v1
kind: Secret
metadata:
name: my-secret
namespace: default
type: Opaque
data:
username: YWRtaW4= # "admin"์ Base64 ์ธ์ฝ๋ฉ
password: cGFzc3dvcmQ= # "password"๋ฅผ Base64 ์ธ์ฝ๋ฉ
โ
๋ฌธ์ ์ :
โ Base64 ์ธ์ฝ๋ฉ์ด๋ฏ๋ก ์ฝ๊ฒ ๋์ฝ๋ฉ ๊ฐ๋ฅ โ ๋ณด์ ์ทจ์ฝ
โ GitOps ํ๊ฒฝ์์ Secret์ Git์ ์ ์ฅํ ์ ์์
โ Secret ๋ณ๊ฒฝ ์ฌํญ์ด GitOps ํ์ดํ๋ผ์ธ์์ ์๋์ผ๋ก ๋ฐ์๋์ง ์์
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Sealed Secrets๊ณผ External Secrets์ ์ฌ์ฉํฉ๋๋ค.
๐น Sealed Secrets: Git ์ ์ฅ์์ ์์ ํ๊ฒ ์ํฌ๋ฆฟ ์ ์ฅ
Sealed Secrets๋ Bitnami์ Sealed Secrets ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ์ฌ Git ์ ์ฅ์์ ์์ ํ๊ฒ ์ํฌ๋ฆฟ์ ์ ์ฅํ๋ ๋ฐฉ์์
๋๋ค.
์ด ๋ฐฉ์์์๋ Kubernetes ํด๋ฌ์คํฐ์ ์ปจํธ๋กค๋ฌ๊ฐ ์ํธํ ๋ฐ ๋ณตํธํ ์์
์ ์ํํฉ๋๋ค.
โ 1. Sealed Secrets ์ปจํธ๋กค๋ฌ ์ค์น
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/latest/download/controller.yaml
โ ์ค์น ํ์ธ:
kubectl get pods -n kube-system | grep sealed-secrets
โ 2. ์ํฌ๋ฆฟ์ Sealed Secret์ผ๋ก ๋ณํํ๊ธฐ
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=mypassword -n default --dry-run=client -o yaml > my-secret.yaml
๐น Sealed Secrets๋ก ๋ณํ
kubeseal --controller-name=sealed-secrets --controller-namespace=kube-system --format=yaml < my-secret.yaml > my-sealed-secret.yaml
โ Git ์ ์ฅ์์ ์์ ํ๊ฒ ์ ์ฅํ ์ ์๋ Sealed Secret ์์ :
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-secret
namespace: default
spec:
encryptedData:
username: AgB0z...encrypted-value... # ์ํธํ๋ ๊ฐ
password: AgC2h...encrypted-value...
โ ๋ฐฐํฌ ํ Sealed Secret์ด ์๋ ๋ณตํธํ๋จ:
kubectl get secret my-secret -n default -o yaml
โ
Sealed Secrets์ ์ฅ์ :
โ GitOps์ ์๋ฒฝํ๊ฒ ํธํ๋จ
โ Git ์ ์ฅ์์ ์ ์ฅํด๋ ์์ ํจ (๋ณตํธํ ๋ถ๊ฐ๋ฅ)
โ Kubernetes ํด๋ฌ์คํฐ์์ ์๋ ๋ณตํธํ ๊ฐ๋ฅ
๐น External Secrets: ์ธ๋ถ ๋น๋ฐ ์ ์ฅ์์ ์ฐ๋
External Secrets์ AWS Secrets Manager, HashiCorp Vault, Azure Key Vault ๊ฐ์ ์ธ๋ถ ์ํฌ๋ฆฟ ์ ์ฅ์๋ฅผ Kubernetes ์ํฌ๋ฆฟ๊ณผ ์ฐ๋ํ๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ์ํฌ๋ฆฟ์ Kubernetes๊ฐ ์๋ ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ์ ์์ ํ ์ ์ฅ์์์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
โ 1. External Secrets Operator ์ค์น
kubectl apply -f https://github.com/external-secrets/external-secrets/releases/latest/download/install.yaml
โ ์ค์น ํ์ธ:
kubectl get pods -n external-secrets
โ 2. AWS Secrets Manager์ ์ฐ๋ ์์
โ AWS IAM ์ ์ฑ ์ถ๊ฐ (AWS CLI ์ฌ์ฉ)
aws iam attach-role-policy --role-name my-role --policy-arn arn:aws:iam::aws:policy/AmazonSecretsManagerReadOnly
โ Kubernetes์์ AWS Secrets Manager ์ฐ๋ ์ค์
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-external-secret
namespace: default
spec:
refreshInterval: 1h # 1์๊ฐ๋ง๋ค ์ํฌ๋ฆฟ์ ๋๊ธฐํ
secretStoreRef:
name: my-secret-store
kind: ClusterSecretStore
target:
name: my-secret # Kubernetes์์ ์์ฑ๋ ์ํฌ๋ฆฟ ์ด๋ฆ
data:
- secretKey: password # Kubernetes ์ํฌ๋ฆฟ์์ ์ฌ์ฉ๋ ํค
remoteRef:
key: my-secret-key # AWS Secrets Manager์ ํค
โ
External Secrets์ ์ฅ์ :
โ ์ํฌ๋ฆฟ์ Git ์ ์ฅ์์ ์ ์ฅํ ํ์ ์์
โ ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ์ ๋ณด์ ๊ธฐ๋ฅ์ ํ์ฉ ๊ฐ๋ฅ
โ ์๋ ๋๊ธฐํ๋ก ๋ณ๊ฒฝ ์ฌํญ์ด ์ฆ์ ๋ฐ์๋จ
๐น Argo CD์์ Sealed Secrets ๋ฐ External Secrets ๊ด๋ฆฌ
Argo CD๋ GitOps ๋ฐฉ์์ผ๋ก Sealed Secrets ๋ฐ External Secrets์ ์๋ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
โ Sealed Secrets ๊ด๋ฆฌ ์์
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sealed-secrets
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/repo.git
targetRevision: main
path: secrets
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
โ External Secrets ๊ด๋ฆฌ ์์
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-secrets
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/repo.git
targetRevision: main
path: external-secrets
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
๐น ๊ฒฐ๋ก : ์ด๋ฒ ๊ธ์์ ๋ฐฐ์ด ํต์ฌ ๋ด์ฉ ์ ๋ฆฌ
๐ข ๊ธฐ๋ณธ Kubernetes Secret์ ๋ณด์์ด ์ทจ์ฝํ์ฌ GitOps ํ๊ฒฝ์์ ๊ทธ๋๋ก ์ฌ์ฉํ๊ธฐ ์ด๋ ค์
๐ข Sealed Secrets๋ฅผ ์ฌ์ฉํ๋ฉด ์ํฌ๋ฆฟ์ Git ์ ์ฅ์์ ์์ ํ๊ฒ ์ ์ฅํ ์ ์์
๐ข External Secrets๋ AWS Secrets Manager, Vault ๋ฑ์ ์ธ๋ถ ์ํฌ๋ฆฟ ์ ์ฅ์์ Kubernetes๋ฅผ ์ฐ๋ํ์ฌ ๋ณด์์ ๊ฐํํ ์ ์์
๐ข Argo CD๋ Sealed Secrets ๋ฐ External Secrets๊ณผ ์๋ฒฝํ๊ฒ ํตํฉ๋์ด GitOps ํ๊ฒฝ์์ ์์ ํ ๋ฐฐํฌ๋ฅผ ์ง์