마루옵스서버 · 네트워크 · AI 기술 노트

소개문의

[Git·GitOps 23] 비밀 값 관리: Secret의 base64와 SOPS·age 암호화

모니터와 데스크톱 본체가 놓인 작업대

참고 사진 · 모니터와 데스크톱 본체가 놓인 작업대 · 사진: Mnicolois / 원본 / CC BY 4.0 · 목록용 크기 조정

Kubernetes Secret의 값을 base64로 바꾸면 화면에서 읽기 어려워집니다. 하지만 누구나 다시 디코딩할 수 있으므로 그것만으로 비밀이 보호되지는 않습니다. Git 저장소에 넣을 값과 복호화 권한을 어디에 둘지 따로 정해야 해요.

이 편은 SOPS와 age를 이용한 로컬 암호화 실습입니다. 실제 서비스 비밀번호 대신 training-only라는 예제 값만 씁니다. 21편의 Argo CD 설치에 암호화 파일을 추가하는 것만으로 자동 복호화가 생기지는 않습니다.

Git·GitOps 전체 연재 · 23 / 24

이 글의 목차

base64는 전송 표현이다

printf 'training-only' | base64
printf 'dHJhaW5pbmctb25seQ==' | base64 --decode

Kubernetes Secret의 data는 base64로 표현하며, stringData는 평문 입력을 받습니다. 저장 시 암호화 설정, API 접근 RBAC, etcd 백업과 애플리케이션이 읽는 경로는 별도의 보안 범위입니다. Secret을 읽을 수 있는 권한이 넓으면 데이터 표현만 바꿔도 해결되지 않습니다.

1. 도구와 개인 키 보관 위치를 준비한다

SOPS는 구조화된 파일의 값을 암호화하는 도구이고, age는 이 예제에서 키의 수신자와 복호화 방식을 제공합니다. 공식 릴리스에서 OS와 CPU 아키텍처에 맞는 파일과 검증 자료를 선택합니다. 2026년 10월 18일 확인한 릴리스는 SOPS 3.13.3, age 1.3.2입니다. 다운로드한 실행 파일을 바로 관리자 권한으로 실행하지 말고 공식 체크섬·서명 검증 절차를 따릅니다.

sops --version
age --version
umask 077
mkdir -p ~/.config/sops/age
# Use a new name if this file already exists. Do not overwrite an existing key.
age-keygen -o ~/.config/sops/age/git-training.agekey
age-keygen -y ~/.config/sops/age/git-training.agekey

마지막 출력은 공개 수신자 키인 age1...입니다. .agekey 파일에는 개인 키가 들어가므로 Git에 넣지 않습니다. 사용자 홈에 보관하는 것은 실습의 시작점이며 운영에서는 별도 비밀 저장소, 접근 제한과 복구용 보관 방식을 정합니다.

2. 예제 Secret 파일을 암호화한다

새 실습 폴더에서 아래 파일을 secret.example.yaml에 저장합니다. 실제 비밀번호로 바꾸지 않습니다. 이 파일은 로컬 암호화 동작을 배우는 자료이며 앞의 Application 경로인 environments/dev에는 넣지 않습니다.

apiVersion: v1
kind: Secret
metadata:
  name: demo-credentials
  namespace: gitops-demo
type: Opaque
stringData:
  demo-password: training-only

공개 키를 변수로 읽어 파일을 암호화합니다. 개인 키는 복호화할 때만 필요하고, 새 파일 암호화는 공개 수신자 키로 가능합니다.

recipient=$(age-keygen -y ~/.config/sops/age/git-training.agekey)
sops --encrypt --age "$recipient" \
  --encrypted-regex '^(data|stringData)$' \
  secret.example.yaml > secret.enc.yaml

secret.enc.yaml에서 stringData 아래 값이 ENC[...]로 바뀌고 SOPS 메타데이터가 추가되는지 확인합니다. 리소스 이름과 namespace 같은 일부 구조는 그대로 보일 수 있습니다. 파일 전체의 존재와 운영 구조까지 숨기는 도구라고 가정하지 않습니다.

3. 복호화는 키를 가진 경로에서만 한다

export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/git-training.agekey"
sops --decrypt secret.enc.yaml

출력에는 평문 값이 나타납니다. 실제 비밀 값이라면 CI 로그와 화면 공유에 노출하지 않습니다. 복호화한 파일을 작업 트리에 저장하는 습관보다 필요한 프로세스에 제한적으로 전달하는 경로를 설계합니다.

키를 잃으면 암호문이 남아 있어도 복구하지 못할 수 있습니다. 조직에서는 여러 수신자나 관리형 KMS를 고려하고, 접근 회수 시 새 키와 수신자로 재암호화하는 절차를 준비합니다. 과거 커밋의 암호문과 이전 키가 남은 범위도 검토해야 합니다.

Argo CD 연결에는 추가 설계가 필요하다

일반 Argo CD 설치는 SOPS 암호문을 자동 해독하지 않습니다. Config Management Plugin을 선택하면 플러그인 실행 권한과 repo-server의 비밀 접근 범위를 관리해야 합니다. 다른 접근으로 External Secrets 같은 컨트롤러가 외부 비밀 저장소를 참조하도록 구성할 수 있습니다.

암호화된 YAML을 그대로 Kubernetes Secret에 apply하면 원하는 비밀번호가 자동으로 만들어지는 것은 아닙니다. 이 연재에서는 로컬 왕복 암호화까지만 실습하고, 복호화 키를 Argo CD 저장소 자격 증명과 섞어 배포하지 않습니다. 팀의 키 관리 체계가 정해진 뒤 연동 방식을 선택합니다.

정의와 옵션은 Kubernetes Secret, SOPS 공식 저장소, age 공식 문서, 연동 경계는 Argo CD Secret Management를 참고했습니다.

이전 글 · [Git·GitOps 22] 변경 감지와 복구: 자동 Sync·selfHeal·prune·Git revert · 다음 글 · [Git·GitOps 24] Git·CI/CD·GitOps 운영 흐름 완성하기: 장애별 판단과 복구 · 연재 목록과 예제 파일

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

닉네임·이메일·댓글 내용·IP 주소·브라우저 정보는 댓글 게시 및 관리에 사용됩니다. 이메일과 접속 정보는 공개 댓글에 표시하지 않습니다. 개인정보 요청은 운영자 이메일로 보내 주세요. 개인정보처리방침