쿠버네티스 클러스터 내부를 코드로 구성하기 위해 FluxCD를 사용하고 있다.
GitHub 레포지토리에 yaml 파일들을 올리고 FluxCD에 GitRepository CR 추가하면
주기적으로 코드를 가져와서 내부 구성을 자동 관리해주도록 설정해뒀다.
근데 문제는 진행중인 프로젝트(오픈소스) 특성상 레포지토리를 Public으로 열어둬야하고,
일부 툴들은 helm value는 마스터 키나 크레덴셜 입력을 필수로 해줘야해서 크레덴셜 키가 인터넷에 노출된다는 점이었다.
이런 문제를 해결하는 여러 방법이 있지만 제일 가벼운(?) 방식으로 해결하기로 했다.
AGE를 통해 암호화 키를 생성하고, SOPS(Secrets OPerationS)를 사용해서 해당 키를 사용해 크레덴셜 부분만 암호화 (Public/ Private key 사용)
** SOPS : YAML, JSON, ENV, INI 등 다양한 포맷의 설정 파일 내 민감 정보(비밀번호, API 키 등)를 암호화하여 저장하는 오픈소스 CLI 도구, age는 gpg랑 비슷한 포지션인데 더 가볍고 빠르고 직관적이라 sops 공식 문서에서도 해당 옵션을 권장한다고 함
그리고 FluxCD가 암호화된 파일을 그대로 가져가서 알고 있는 Private key로 클러스터 내부에서 '복호화 -> 자동 구성' 하는 방식임.
이렇게 하면 민감한 정보가 포함된 yaml파일들을 public으로 올릴 수도 있고 별도의 서비스나 툴을 새로 구성할 필요없어서 좋은거 같음
맥북 기준으로 사용 방법 좀 설명하면, 우선 brew로 age, sops 설치해주고
brew install age sops
age 키를 생성해준다.
생성된 키 보면 public key랑 AGE-SECRET-KEY~ 가 있는데, AGE-SECRET-KEY는 외부로 노출되면 안됨
age-keygen -o age.agekey

쿠버네티스 secret에 파일 통째로 등록
cat age.agekey | kubectl create secret generic sops-age \
--namespace=flux-system \
--from-file=age.agekey=/dev/stdin
확인해보면 잘 등록된 거 같다.
ubuntu@k3s:~$ k get secret -n flux-system | grep sops
sops-age Opaque 1 82s
ubuntu@k3s:~$ k describe secret sops-age -n flux-system
Name: sops-age
Namespace: flux-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
age.agekey: 75 bytes
이제 클러스터에서 할 수 있는건 다 했고,
FluxCD 한테도 어떤 파일이 암호화되었는지 어디를 복호화해야하는지 알려줘야 한다.
Flux가 참조하는 레포지토리 루트에 .sops.yaml 파일을 생성해주고
creation_rules:
- path_regex: cluster/.*secret.*\.yaml
age: age1z4t56we62raeue0w02lcykg7pxt3phtq3j5laju8fng7jlw7lers0hvnpq (위에서 생성된 키)
Flux 사용해서 Git Repository 연결하면 커밋되는 파일들(gotk-sync.yaml)이 있는데, 내 프로젝트에서는 프로비저닝 순서를 보장하기위해 layer.yaml을 추가해줘서 거기에 복호화 관련 옵션들을 추가해줬다. (decryption 부분)
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: cluster-infrastructure
namespace: flux-system
spec:
dependsOn:
- name: cluster-system-configs
interval: 10m
path: ./cluster/infrastructure
prune: true
sourceRef:
kind: GitRepository
name: flux-system
decryption: # 이 부분
provider: sops
secretRef:
name: sops-age # 아까 클러스터에서 생성해둔 age 키의 secret 이름
wait: true
timeout: 5m
프로젝트 루트 경로에서 아래 명령어로 파일 지정해서 암호화해주고 커밋해준다.
sops -e -i cluster/infrastructure/lago/secret.yaml
직접 암호화해서 깃에 올리는 방식이라 사람이 실수로 올릴 수도 있어서 주의가 필요함.
방지하려면 secret.yaml 을 .gitginore에 추가해서 막고 암호화된 파일명만 바꿔서 올리던지 PR 생성하면 action으로 자동 수정해주는 등으로 처리해야 될 거 같다.
로컬에서 복호화하는 방법은 아래 더보기 참고
암호화에 사용한 age.agekey 파일은 ~/.config/sops/age 에 옮겨두거나 환경변수에 경로를 지정해주면 됨
sops -d cluster/infrastructure/lago/secret.yaml
그리고 -i 옵션 없으면 결과가 파일에 적용 되지 않고 출력으로만 나온다.
sops -d cluster/infrastructure/lago/secret.yaml > cluster/infrastructure/lago/secret.decrypted.yaml
반대로 암호화도 이렇게 해주면
sops -e cluster/infrastructure/lago/secret.decrypted.yaml > cluster/infrastructure/lago/secret.yaml
secret.decrypted.yaml만 .gitignore에 추가해두고 사용할 수 있다.
| opencsp 서비스 다운타임 없이(?) 도메인 변경하기 (0) | 2026.05.27 |
|---|---|
| GitHub 레포지토리 PR Merge 관련 옵션 (0) | 2026.03.24 |