Kubernetes의 Secret은 Container의 구동에 필요한 민감 정보를 저장하기 위한 오브젝트입니다.
그래서 Secret 오브젝트는 DB Password 등의 민감 정보를 담고 있지만 데이터를 base64로 인코딩하기 때문에 정보가 누출될 수 있다는 위험이 존재합니다.
이 때문에 Kubernetes Secret은 Gitops 기반의 배포 방식을 사용할 경우에도 Secret manager 등 별개의 저장소에 따로 저장해서 사용해야 하는 불편점이 있었습니다.
AWS ASM, Hashicorp Vault 등의 Secret manager 서비스를 사용하지 못하는 환경이라면 Kubernetes Secret을 관리할 수 있는 선택지가 더 좁아지는 셈입니다.
그래서 Kubernetes Secret을 Secret manager 서비스를 사용하지 않으며, Gitops 기반의 배포 방식을 그대로 이용해 Secret을 관리할 수 있는 방법에 대하여 포스팅하려고 합니다.
1. Sealed Secret
Gitops 기반의 Secret 관리를 위해서 필요한 도구는 Sealed Secret입니다.
Sealed Secret은 Kubernetes Secret에 대한 암호화 및 복호화 기능을 가지고 있는 OSS 도구입니다.
다음과 같은 기능을 제공합니다.
- 비대칭 키를 사용한 Kubernets Secret 오브젝트 암호화
- 위 기능으로 생성된 오브젝트를 복호화
- Secret 자동 업데이트
- Key Rotation
Sealed secret은 Client에서 사용하는 kubeseal CLI와 Server에서 사용하는 sealed secret controller로 구성되어 있습니다.
사용자는 kubeseal 명령어를 사용해 Secret 오브젝트를 공개 키로 암호화할 수 있습니다.
위 과정으로 생성된 SealedSecret 오브젝트는 민감 정보가 암호화되어 있어 레포지토리에서 관리할 수 있게 됩니다.
SealedSecret 오브젝트를 배포하면 sealed secret controller가 이를 감지해 저장된 비밀 키로 복호화를 수행합니다.
위 과정으로 생성된 Secret 오브젝트는 최초의 Secret이 담고 있는 정보를 그대로 가지고 있습니다.
이 Secret을 기존 Secret과 동일하게 사용 및 관리할 수 있습니다.
2. Reloader
Reloader는 Kubernetes Secret 및 Configmap이 변경될시 Deployment, Statefulset, Daemonset에 rolling update를 수행하는 OSS 도구입니다.
Reloader는 Sealed Secret으로 생성된 Secret 오브젝트 생성시 어플리케이션이 이를 자동으로 반영하도록 해주는 역할을 합니다.
다음과 같은 기능을 제공합니다.
- Secret 및 Configmap 변경시 이를 참조하는 오브젝트에 대한 Rolling update 수행
- 특정 Secret 및 Configmap에 대한 변경만을 감지하는 기능 제공
- 특정 Deployment, Statefulset, Daemonset만을 업데이트하는 기능 제공
Reloder는 Sealed Secret과 원활하게 연계가 가능합니다.
사용자가 암호화된 SealedSecret 오브젝트를 배포하면 Reloader는 복호화된 Secret의 변화를 감지해 이를 참조하는 오브젝트들에게 Rolling update를 명령합니다.
3. Architecture
위에서 소개한 Sealed Secret과 Reloader를 기반으로 Gitops 기반의 Secret 배포 아키텍쳐를 알아보겠습니다.
Kubernetes 오브젝트 배포에는 OSS Continuous Deployment 도구인 ArgoCD를 사용했습니다.
아키텍쳐 다이어그램은 아래와 같습니다.
위 아키텍쳐의 작업 플로우는 아래와 같습니다.
- Github 레포지토리의 Application yaml 코드를 기반으로 서비스 Application을 배포합니다.
- Github 레포지토리의 Application yaml 코드를 기반으로 Sealed Secret, Reloader Helm chart를 배포합니다.
- kubeseal CLI 명령어로 Kubernetse Secret을 암호화한 SealedSecret yaml 코드를 생성합니다.
- 기존의 Secret 대신 생성한 SealedSecret yaml 코드를 Github 레포지토리에 저장합니다.
- ArgoCD에서 Sync를 수행해 SealedSecret을 배포합니다.
- Sealed Secret Controller가 SealedSecret 오브젝트를 복호화해 Secret 오브젝트를 생성합니다.
- Reloader가 기존의 Secret을 사용하던 애플리케이션을 재시작해 새로 생성된 Secret을 사용하도록 합니다.
4. 장점 및 단점
위에서 제시한 방안을 사용해 Kubernetes Secret을 배포하면 다음과 같은 이점이 있습니다.
- Gitops 방식의 관리 가능 :
위 방식은 Sealed Secret을 사용해 Secret을 비대칭 키로 암호화하기 때문에 오픈된 레포지토리에 저장해도 정보가 노출되지 않습니다.
따라서 Kubernets Secret을 다른 오브젝트와 같이 Gitops 방식으로 관리 및 배포할 수 있다는 장점이 존재합니다. - 자동화 구현 :
기존에는 Secret을 업데이트하면 이를 참조하는 Application이 이를 즉시 반영하지 못해 수동으로 Rollout restart를 해줘야 했던 불편함이 있었습니다.
하지만 Reloader와 Sealed Secret을 사용하면 복호화된 Secret 오브젝트를 감지한 즉시 Pod를 Rollout restart하기 때문에 변경된 정보를 자동으로 반영할 수 있습니다. - 리소스 관리의 통일성 :
Secret은 정보가 노출되는 단점을 보완하기 위해 Secret manager와 같은 저장소에 따로 저장해야 했습니다.
이러한 방법은 Gitops 방식을 사용할 경우 Git 레포지토리와 Secret Manager 두 가지의 저장소를 관리해야 한다는 단점이 있었습니다.
하지만 위 방법은 Secret을 Git 레포지토리에 저장 및 관리할 수 있기 때문에 기존의 Gitops 방식을 유지하면서 관리 포인트를 하나로 유지할 수 있다는 장점이 존재합니다.
5. DEMO
위에서 소개한 아키텍쳐를 기반으로 구현한 DEMO를 보도록 하겠습니다.
5-1. Sealed Secret 및 Reloader 설치
다음 ArgoCD Application 매니페스트를 사용해 Helm chart 기반으로 Sealed Secret과 Reloader를 클러스터에 설치합니다.
application-reloader.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: reloder
namespace: argocd
spec:
project: default
source:
chart: reloader
targetRevision: 1.0.40
repoURL: https://stakater.github.io/stakater-charts
helm:
releaseName: reloader
destination:
name: miles-test
namespace: kube-system
|
cs |
application-sealed-secret.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sealed-secrets
namespace: argocd
spec:
project: default
source:
chart: sealed-secrets
targetRevision: 2.12.0
repoURL: https://bitnami-labs.github.io/sealed-secrets
helm:
releaseName: sealed-secrets
parameters:
- name: "fullnameOverride"
value: sealed-secrets-controller
destination:
name: miles-test
namespace: kube-system
|
cs |
위 매니페스트를 사용하여 Sealed Secret과 Reloader가 설치된 모습입니다.
5-2. Secret 오브젝트 암호화
Sealed Secret의 구성요소인 kubeseal CLI 도구를 사용해 배포하고자 하는 Kubernetes Secret을 암호화합니다.
sample-secret.yaml
1
2
3
4
5
6
7
8
|
apiVersion: v1
data:
password: MXEydzNlNHI= # base64 인코딩된 "1q2w3e4r"
kind: Secret
metadata:
name: sample-secret
namespace: default
type: Opaque
|
cs |
다음 명령어를 통해 sample-secret.yaml을 암호화한 sealedsecret.yaml 을 생성합니다.
1
|
kubeseal < sample-secret.yaml > sealedsecret.yaml
|
cs |
sealedsecret.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: sample-secret
namespace: default
spec:
encryptedData:
password: AgBt7oIM6Q+kIGsis7r6g9e4V8k0evxP64GZSlA1jThPlNTMCKJ9KVI+ZjVc+kD6taSKIm3AduT/G8WbZnV1+GYJ1kQUorzrc9rUUw4Xht1Mq9VMoDJH67bFWz5yFla1uBvs+kUjOyVm4KqMEpHoNYkRkdgGuLQ1zhoSt...
# 암호화된 password 값
template:
metadata:
creationTimestamp: null
name: sample-secret
namespace: default
type: Opaque
|
cs |
5-3. Git repository 저장
이전 과정에서 생성한 sealedsecret과 Secret을 사용할 Deployment를 Git 레포지토리에 저장합니다.
deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
reloader.stakater.com/auto: "true"
name: nginx-deployment
spec:
replicas: 3 # 배포할 파드의 개수
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest # 사용할 Nginx 도커 이미지
ports:
- containerPort: 80 # Nginx가 수신 대기할 포트
volumeMounts:
- name: sample-secret
mountPath: /temp/password
subPath: password
volumes:
- name: sample-secret
secret:
secretName: sample-secret
items:
- key: password
path: password
|
cs |
Github을 SCM으로 사용할 경우, 아래와 같이 두 yaml 파일을 레포지토리에 저장합니다.
5-4. ArgoCD 배포
위에서 생성한 Deployment와 SealedSecret을 클러스터에 배포합니다.
sample-application.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sample-application
namespace: argocd
spec:
destination:
namespace: default # Nginx를 배포할 대상 네임스페이스
name : miles-test
project: default # ArgoCD 프로젝트 이름
source:
repoURL: https://github.com/mileslee-nsuslab/sample-argocd # 애플리케이션 소스 코드가 저장된 Git 리포지토리 URL
path: ./yaml # 리포지토리 내의 애플리케이션 경로
targetRevision: HEAD # 배포할 리비전 (브랜치, 태그 또는 커밋 해시)
syncPolicy:
automated:
prune: true # 더 이상 사용되지 않는 리소스 삭제
selfHeal: true # 실패한 배포를 자동으로 복구
|
cs |
배포시 다음과 같이 오브젝트들이 생성되는 것을 확인할 수 있습니다.
Pod에 접속시 다음과 같이 Password 값이 구성되어 있는 것을 확인할 수 있습니다.
5-5. Secret 업데이트
다음으로 Secret의 정보를 업데이트하면 수행되는 작업을 확인해보겠습니다.
아래와 같이 기존 Secret 오브젝트의 정보를 변경합니다.
sample-secret.yaml
1
2
3
4
5
6
7
8
|
apiVersion: v1
data:
password: bmV3LXBhc3N3b3JkCg== # base64 인코딩된 "new-password"
kind: Secret
metadata:
name: sample-secret
namespace: default
type: Opaque
|
cs |
다음 명령어를 실행해 변경된 Secret을 암호화한 SealedSecret 오브젝트를 생성합니다.
1
|
kubeseal -o yaml< sample-secret.yaml > sealedsecret.yaml
|
cs |
sealedsecret.yaml
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: sample-secret
namespace: default
spec:
encryptedData:
password: AgA2ZUovSETI4CV6mmyVFvR/cLvQxRhDWFqWPvF9fCsiXrK01EiGLXA1ZjLXBEhrKOzbMuUqzQXPe7HkwlWD6J62N10PHRqOLc5WpAz75fujK7vkQeP3bSMLrUeDRGHGfpQ+UJnhWsMNf8oCcmnDKA2wvGfqH9Apk25LKshzOZ0S7Ia7nsoWX2NC3ffUjir64NW3b/A4HrQVeXRIcFHOOCgdRH0WcPu3Ny3id0MCL1fxDRqZ60di9C2Z//KBWjh960Kcfb9Rksqndz6warFGxprNWvzKKSuI/lOCTOM586ifi/TXCwMuimgxj2Bt+lIOxjAAF/7D2d4zFdCrpiNtdIQDvfW3Yg31uImx9SBzIKD5XmMoOHFCfGZeujwAs7oDvecvl/SSVhUMDFRMFPN721EoGc7VhxGWyFQX9KsBXJ3sGkdRNKEfbdaQc/MN/qUItTYo58iwbnvU7ib1H0JTHqNoSZiegEhaRou+xm/cq60DO0DYbMlT0DMQbRZ4veoAXgd2cfH2xJaw7liCxA9Kn/pjDr5onbIhGyTRthAMXKkXwqzwOwmR+...
name: sample-secret
namespace: default
type: Opaque
|
cs |
sealedsecret.yaml 파일의 변경분을 Github repository에 반영합니다.
ArgoCD에서 Sync 수행시 새 Secret이 생성되며, Deployment에 Rolling update가 수행되는 것을 확인할 수 있습니다.
Pod에 접속시 다음과 같이 새 Password 값으로 변경되어 있는 것을 확인할 수 있습니다.
6. 마무리
지금까지 Sealed Secret과 Reloader를 활용한 Gitops 기반의 Secret 배포 방법에 대해서 알아봤습니다.
Sealed Secret의 비대칭 키 기반의 암호화를 사용해 Secret 오브젝트를 Git 레포지토리에 저장하고, 생성된 Secret을 Reloader가 감지해 자동으로 배포하는 과정이었습니다.
이러한 방식으로 Secret을 배포 및 관리할시, Secret manager와 같은 별개의 저장소를 사용하지 않아도 되며, ArgoCD와 같은 Gitops 기반의 배포를 사용할 수도 있기 때문에 고려할법한 Secret 배포 방법이라고 생각합니다.
이 포스팅을 보시는 분들이 Secret 관리에 인사이트를 얻어가셨으면 합니다.
'Devops' 카테고리의 다른 글
Kubecost로 Kubernetes 환경의 FinOps를 구현해보자 (0) | 2023.11.29 |
---|---|
Clean Code를 구현하기 위해 Sonarqube로 정적 코드 분석을 해보자 (2) | 2023.10.28 |
Argo 사용해보기 (2) Standalone DEX로 Argo Workflow에서 SSO 구현하기 (0) | 2023.05.09 |
Argo 사용해보기 (1) Argo Project로 CI/CD Pipeline을 구성해보자 (0) | 2023.04.29 |
컨테이너 빌드 도구 선택을 위한 특성 및 성능 비교 (Kaniko, Buildah, Buildkit) (5) | 2023.03.26 |