Development Artist

클라우드 네이티브 시대의 설정 분리: Kubernetes에서의 네임스페이스, ConfigMap, 그리고 Secret 본문

Research/Devops

클라우드 네이티브 시대의 설정 분리: Kubernetes에서의 네임스페이스, ConfigMap, 그리고 Secret

JMcunst 2025. 4. 13. 15:57
728x90

서론

쿠버네티스(Kubernetes)는 단지 컨테이너 오케스트레이션 시스템이 아니다. 그것은 복잡한 분산 시스템의 ‘논리적 질서(logical order)’를 추구하는 운영 체계이자 철학이다. 이 철학의 핵심에는 다음 세 가지 리소스가 있다: 네임스페이스(Namespace), 컨피그맵(ConfigMap), 그리고 시크릿(Secret).

 

이 글에서는 해당 세 리소스가 어떻게 쿠버네티스의 구조적 복잡성을 통제하고, 실제 운영 환경에서 어떤 가치를 제공하는지 학문적으로 탐구하고자 한다.


1. Namespace: 멀티테넌시와 격리의 시작점

1.1 정의

Kubernetes에서 Namespace는 리소스를 논리적으로 분리하는 단위이다. 리눅스에서의 chroot나 가상 메모리 공간처럼, 네임스페이스는 쿠버네티스 클러스터 내에서 다중 프로젝트, 팀, 환경을 격리한다.

1.2 특징

  • 동일 클러스터 내의 리소스를 논리적으로 구분
  • 리소스 할당량 제한 (ResourceQuota)
  • 네임스페이스 기반 RBAC(Role-Based Access Control)
  • NetworkPolicy와 연동 시 네트워크 수준 격리 가능

1.3 예제

kubectl create namespace ml-platform
kubectl get all -n ml-platform

1.4 실무 활용

실제 운영에서는 dev, staging, prod 와 같은 환경 분리를 위해 네임스페이스를 사용한다. CI/CD 파이프라인을 namespace 단위로 설계하면 충돌 없는 테스트와 배포가 가능하다.

1.4.1 환경별 격리

  • dev, stage, prod 네임스페이스를 만들어 서로 다른 설정과 리소스를 독립적으로 관리.
  • QA 환경에서 테스트 중 장애가 나도 prod에 영향 없음.
kubectl create namespace dev
kubectl apply -n dev -f deployment.yaml

1.4.2 팀 단위 멀티테넌시

  • 데이터팀, ML팀, 프론트엔드팀 별로 네임스페이스를 분리하고, 각 팀에게만 read/write 권한을 부여.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ml-dev-binding
  namespace: ml-dev
subjects:
  - kind: User
    name: ml-user1
roleRef:
  kind: Role
  name: admin
  apiGroup: rbac.authorization.k8s.io

1.4.3 리소스 할당 제한

  • 개발자가 과도하게 리소스를 점유하지 못하도록 ResourceQuota 설정.
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-limit
  namespace: dev
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi

2. ConfigMap: 애플리케이션의 환경을 외부화하다

2.1 정의

ConfigMap은 환경변수, 설정파일, 커맨드라인 인자와 같은 비밀이 아닌 구성 정보를 파드에서 분리해 관리하는 리소스이다.

2.2 사용 시나리오

  • .env 파일을 클러스터에 저장
  • 파드의 환경변수로 주입
  • 설정 파일을 마운트하여 제공

2.3 예제

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_MODE: production
  LOG_LEVEL: info
ConfigMap은 코드 변경 없이도 설정을 유연하게 바꿀 수 있게 해준다. 단, 변경이 즉시 파드에 반영되지는 않으므로 configMap 업데이트 후 롤링 업데이트 전략을 적용해야 한다.

2.4 실무 활용

2.4.1 설정파일 외부화

  • Spring Boot나 Django에서 application.properties, settings.py에 들어갈 값을 외부 설정으로 분리.
apiVersion: v1
kind: ConfigMap
metadata:
  name: webapp-config
data:
  LOG_LEVEL: DEBUG
  FEATURE_FLAG: true
# Deployment.yaml
envFrom:
  - configMapRef:
      name: webapp-config

2.4.2 공통 설정 공유

  • 여러 파드에서 공통으로 쓰는 설정 (예: Kafka host, Redis 주소) 를 ConfigMap으로 관리하여 일괄 업데이트 가능.
data:
  KAFKA_BROKER: kafka:9092

 

configMap을 수정하면 기존 Pod에는 자동 반영되지 않기 때문에 kubectl rollout restart deployment로 재시작 필요.

2.5 마운트 vs 환경변수

방식 장점 단점
환경변수 주입 단순, lightweight 긴 문자열, 구조적 데이터에는 부적합
Volume 마운트 복잡한 설정파일 대응 가능 파일 권한 및 디렉토리 구조 고려 필요

 3. Secret: 설정의 민감한 영역을 보호하다

3.1 정의

Secret은 비밀번호, 인증 토큰, TLS 인증서 등 민감한 정보를 저장하기 위한 리소스이다. ConfigMap과 유사한 구조이지만, base64 인코딩된 데이터와 별도의 접근 제어가 특징이다.

3.2 보안 설계 포인트

  • 기본적으로 base64 인코딩 (암호화 아님)
  • etcd를 암호화하지 않으면 단순 텍스트로 저장됨
  • RBAC을 통해 읽기 권한 엄격히 제한
  • 노드의 메모리에만 상주하는 방식도 설정 가능
쿠버네티스에서 Secret은 이름만 보면 안전해 보이지만, 기본 설정만으로는 완벽하지 않다. etcd-level encryption 활성화, Secrets CSI 드라이버 사용, AWS KMS, GCP KMS와의 통합 등을 고려해야 진정한 보안이 확보된다.

3.3 실무 활용

3.3.1 DB 인증 정보 관리

  • 데이터베이스 사용자명과 비밀번호를 Secret에 저장하고, 파드에서는 환경변수로 주입받아 사용.
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_USER: YWRtaW4=        # admin
  DB_PASS: MWYyZDFlMg==     # mypassword
env:
  - name: DB_USER
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: DB_USER

3.3.2 TLS 인증서 관리

  • HTTPS용 인증서와 키를 tls 타입의 Secret으로 저장 후, Ingress에서 참조.
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: (base64 encoded)
  tls.key: (base64 encoded)
# Ingress
tls:
  - hosts:
      - example.com
    secretName: tls-secret

3.3.3 외부 KMS 연동 (고급 사례)

  • AWS KMS 또는 HashiCorp Vault와 통합하여 Secret을 자동 암호화 및 자동 갱신.
Secret은 기본적으로 암호화되어 있지 않으며 단순 base64 인코딩이기 때문에, etcd encryption, Sealed Secrets, 또는 Vault 도입이 권장됨.

4. Sealed Secret, External Secrets Operator, Vault 심층 비교

기본 Kubernetes Secret는 base64 인코딩된 값을 etcd에 저장한다. 이는 “보안”보다는 “기능적 편의성”에 가깝다. 클러스터 외부 유출, Git 커밋 사고, 복잡한 운영환경에서의 일관성 부족 등으로 인해, 기본 Secret만으로는 운영환경의 보안 기준을 만족시키기 어렵다.

 

이에 따라, 다음과 같은 고급 솔루션들이 등장했다.

  • Git 커밋 보안: Sealed Secret
  • 외부 Vault 및 클라우드 키 관리 시스템 연동: External Secrets Operator
  • 보안 통제 및 중앙화된 비밀 관리 시스템: HashiCorp Vault

4.1 Sealed Secret – GitOps를 위한 Git 안전장치

개요

Git에 커밋 가능한 암호화된 Secret 리소스

복호화는 오직 클러스터 내부 컨트롤러에서만 가능

  • 암호화 방식: 비대칭 키 암호화
  • 컨트롤러: Sealed Secrets Controller
  • 명령어: kubeseal

장점

항목 내용
Git 커밋 안전성 암호화된 상태로 저장됨
GitOps 친화적 YAML로 관리 가능
사용 용이성 DevOps 입문자도 쉽게 적용 가능

단점

항목 내용
환경별 키 분리 클러스터 간 이식 어려움
복호화 위치 고정 해당 클러스터에서만 복호화 가능
복잡한 키 로테이션 별도 키 재생성 작업 필요
Sealed Secret은 GitOps를 사용하는 조직이라면 “기본값”으로 채택해야 할 방식이다. 단, 환경 이동이 많거나, 중앙 보안 팀에서 비밀을 통제하는 구조에선 제한적일 수 있다.

4.2 External Secrets Operator (ESO) – 클라우드 Secret 연동

개요

AWS Secrets Manager, GCP Secret Manager, SSM Parameter Store 등 외부 시스템의 Secret을 Kubernetes에 자동 주입

  • 연동 가능 서비스: AWS, GCP, Azure, HashiCorp Vault, Akeyless 등
  • 리소스 구성: SecretStore / ExternalSecret
  • 배포 방식: Helm / GitOps

장점

항목 내용
중앙 집중형 Secret 관리 보안팀 또는 플랫폼팀의 단일 관리 가능
CI/CD 없이도 Secret 최신화 외부 변경 사항 자동 반영
KMS 암호화 혜택 사용 가능 AWS/GCP의 키 관리 통합 가능

단점

항목 내용
의존성 증가 외부 서비스 장애 시 영향 가능성
복잡한 IAM 권한 관리 IRSA, OIDC 연동 필요
보안 경계 구분 필요 쿠버네티스 RBAC 외에 클라우드 IAM도 관리해야 함
멀티테넌시 환경, 클라우드 기반 플랫폼에서는 필수적인 Secret 연동 방식이다. 특히 Vault 없이 AWS KMS 기반 보안을 구축하고 싶을 때 가장 현실적인 옵션이다.

4.3 HashiCorp Vault – 보안 통제의 끝판왕

개요

중앙에서 인증, 권한, Secret 생성·회수를 통제하는 기업용 비밀 관리 시스템

  • 인증 방식: JWT, AppRole, LDAP 등 다수 지원
  • 통합 기능: PKI, TLS 자동 발급, Secret 동적 생성, 로깅, 감사
  • 쿠버네티스 연동: Vault Agent Injector, CSI Driver, Vault Secrets Operator

장점

항목 내용
완전한 중앙 통제 인증, 키 생성, 폐기, 만료, 감사 로그 등 통합
동적 Secret 생성 DB 계정/비밀번호를 실시간 발급
고급 정책 TTL, lease renewal, max versions 등 세밀한 통제 가능

단점

항목 내용
학습 곡선 존재 설정 복잡, 팀 간 협업 필요
고가용성 요구 Vault 자체 HA 구성 필요
비용과 관리 운영 리소스 및 Vault 인프라 필요 (Vault Enterprise는 유료)
금융, 의료, 글로벌 SaaS 같은 규제가 강한 환경에서는 Vault는 선택이 아니라 필수다. 팀 규모가 크고 보안 팀과 DevOps 팀이 분리되어 있다면 가장 적합하다.

4.4 비교 요약

 

항목 Sealed Secret External Secrets Operator Vault
Git 안전성 매우 강함 외부 저장 외부 저장
환경 이식성 키 고정 클라우드 기반 중앙화
외부 연동 X AWS/GCP/KMS 등 모든 시스템
운영 복잡도 낮음 중간 높음
동적 Secret X X 가능
대상 사용자 DevOps 팀, GitOps 조직 클라우드 기반 플랫폼팀 보안 중심

5. 다양한 실전 팁

5.1 GitHub Actions × OIDC × AWS 인증 자동화 가이드

5.1.1 목표

  • GitHub Actions에서 aws-actions/configure-aws-credentials를 사용하여
  • AWS IAM Role에 OIDC 기반으로 안전하게 Assume 하도록 설정
  • Access Key 없이도 GitHub Actions가 AWS에 인증 가능
  • 쿠버네티스 배포, S3 배포, EKS 권한 접근 등 다양한 작업 가능

5.1.2 아키텍처 흐롬

GitHub Actions Workflow -> GitHub OIDC Identity Token 발급 (JWT) -> AWS IAM Identity Provider (GitHub 등록됨) -> AssumeRole (조건부로 허용된 GitHub 리포지토리/브랜치만 허용) -> Temporary AWS credentials in GitHub Actions

5.1.3 설정 예시

 IAM OIDC Identity Provider 설정

aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1

 

IAM Role 생성 (GitHub에서 Assume할 대상 Role)

aws iam create-role --role-name GitHubOIDCRole \
  --assume-role-policy-document file://trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:<GitHubOrg>/<RepoName>:ref:refs/heads/main"
        }
      }
    }
  ]
}

 

IAM Role에 권한 정책 연결

aws iam attach-role-policy \
  --role-name GitHubOIDCRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

 

GitHub Actions 워크플로우 작성

name: Deploy to AWS via OIDC

on:
  push:
    branches: [main]

permissions:
  id-token: write       # OIDC 토큰을 요청할 수 있는 권한
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS credentials using OIDC
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/GitHubOIDCRole
          aws-region: ap-northeast-2

      - name: Verify identity
        run: aws sts get-caller-identity

      - name: Deploy to S3
        run: aws s3 cp ./static/ s3://my-bucket/ --recursive

5.1.4 고려 사항

전략 설명
리포지토리 단위로 접근 제한 token.actions.githubusercontent.com:sub 조건 사용
브랜치 제한 ref:refs/heads/main 등 명시
역할 분리 read-only, deploy-only 역할 분리로 최소 권한 원칙 적용
ID 토큰 로그 제거 워크플로우에서 AWS_ACCESS_KEY_ID와 달리 민감정보 출력 걱정 없음

5.2 조직 내 Kubernetes Secret 전략 설계안 및 GitOps 운영 정책 가이드라인

5.2.1 Secret 관리 전략: 계층별 설계

Secret 유형 분류

유형 예시 처리 방식
환경 구성용 비밀 DB 패스워드, API 키, 토큰 Git 커밋 X, 외부 저장소 필요
TLS 인증서 서비스별 HTTPS 인증서 자동 갱신 또는 vault 연동
단기 인증 AWS STS, GCP OAuth Token 동적 발급 및 TTL 관리 필요
개발용/테스트용 비밀 테스트 크레덴셜 별도 격리, 낮은 권한 유지

리소스별 Secret 도구 적용 기준

시나리오 도구 비고
GitOps로 관리되는 마이크로서비스 설정 Sealed Secret Git 커밋 보안 가능, GitOps 친화
클라우드 리소스 접근 토큰 External Secrets Operator (ESO) AWS/GCP Secrets Manager 연동
고보안/규제 환경 HashiCorp Vault 인증, 감사, TTL, PKI 등 완전 제어 가능

암호화 및 키 관리 정책

  • etcd는 반드시 Encryption Provider 사용
  • Secret 리소스 접근은 최소 RBAC 적용 (read/write 분리)
  • 키 로테이션은 다음 중 하나로 자동화:
    • Sealed Secret 공개키 재배포 (cronjob)
    • Vault TTL/lease 정책
    • AWS Secrets Manager rotation policy

5.2.2 GitOps 운영 정책

Secret 리소스 관리 원칙

항목 가이드라인
Git에 평문 Secret 금지 반드시 SealedSecret or ExternalSecret
환경별 분리 overlays/dev, overlays/prod 별도 Secret 적용
SecretStore 등 외부 참조 리소스 base에 정의, 환경에 따라 override
CI 파이프라인에서 Secret 생성 OIDC 기반 인증 활용 (Access Key 금지)

GitOps 도구 설정 (ArgoCD 기준)

  • 자동 동기화 허용: syncPolicy.automated: true
  • Self-heal 활성화: 의도치 않은 수동 변경 방지
  • SealedSecret ↔ Secret 감시 제외: SealedSecret만 Git에 존재하고, Secret은 클러스터 내 생성됨
  • Kustomize with patches: 환경별 Secret 참조값 override

5.2.3 CI/CD 연동 방안

GitHub Actions + OIDC 인증 활용

- uses: aws-actions/configure-aws-credentials@v2
  with:
    role-to-assume: arn:aws:iam::<acct>:role/GitHubOIDCRole
    aws-region: ap-northeast-2

AWS Secrets Manager/SSM을 통해 ExternalSecret으로 전달

Secret 자동화 파이프라인

단계 동작
Step 1 kubectl create secret ... + kubeseal
Step 2 SealedSecret Git에 커밋
Step 3 ArgoCD가 SealedSecret 적용 → Secret 생성
Step 4 Deployment가 Secret mount 후 배포 완료

5.2.4 감사 및 정책 준수

  • 모든 Secret 생성/갱신은 Git 로그 또는 Vault 로그를 통해 추적 가능
  • Secret 접근 권한은 Namespace 단위 RBAC 또는 IRSA로 제한
  • Sealed Secret 키는 최소 90일 주기로 교체
  • Vault 사용 시 audit device 반드시 설정
  • GitHub PR 리뷰 시 Secret 유출 방지용 Secret Scanning 도구 (ex. truffleHog) 실행

5.3 AWS KMS 기반 External Secrets Operator (ESO) 통합

5.3.1 목표

  • AWS Secrets Manager / SSM Parameter Store → Kubernetes Secret 자동 주입
  • 쿠버네티스 클러스터에 External Secrets Operator 설치
  • AWS IAM 인증 연동 (IRSA 권한 연결)
  • GitOps 파이프라인 통합 준비

5.3.2 예제

Secret 생성

aws secretsmanager create-secret \
  --name /prod/db/password \
  --secret-string "mysecurepassword"
aws ssm put-parameter \
  --name /prod/db/password \
  --value "mysecurepassword" \
  --type SecureString \
  --key-id alias/aws/secretsmanager

IAM Policy 생성

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SecretsManagerAccess",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "ssm:GetParameter",
        "ssm:GetParameters"
      ],
      "Resource": "*"
    }
  ]
}

 

Resource 제한을 걸어보안성을 높인다. ("arn:aws:secretsmanager:region:acct-id:secret:/prod/*" 등)

IRSA (IAM Role for Service Account) 연동

eksctl create iamserviceaccount \
  --name external-secrets-sa \
  --namespace external-secrets \
  --cluster my-eks-cluster \
  --attach-policy-arn arn:aws:iam::xxxx:policy/ExternalSecretsAccess \
  --approve

 

External Secrets Operator 설치

helm repo add external-secrets https://charts.external-secrets.io
helm repo update

helm install external-secrets external-secrets/external-secrets \
  --namespace external-secrets \
  --create-namespace

 

Kubernetes 리소스 정의

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secret-store
  namespace: default
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-password
  namespace: default
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secret-store
    kind: SecretStore
  target:
    name: db-secret
    creationPolicy: Owner
  data:
    - secretKey: password
      remoteRef:
        key: /prod/db/password
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: bXlzZWN1cmVwYXNzd29yZA==  # base64 encoded

 

Pod에서 Secret 사용 예시

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: password

 

GitOps에 통합할 때

  • SecretStore, ExternalSecret 정의 파일을 Git에 저장
  • ArgoCD or Flux가 추적하도록 경로 설정
  • GitOps 파이프라인에서 Secret 값을 직접 포함하지 않음 → 오직 참조만 존재

5.4 GitHub Actions를 이용한 SecretStore 자동화 실습

5.4.1 목표

  • GitHub Actions가 SecretStore, ExternalSecret 등의 YAML을 쿠버네티스 클러스터에 자동 배포
  • AWS IAM 권한은 IRSA로 사전에 연결되어 있어야 함
  • GitHub Actions에 kubeconfig 또는 OIDC 인증을 통한 접근 권한 부여

5.4.2 예제

GitHub Actions 워크플로우 정의

name: Deploy SecretStore and ExternalSecret

on:
  push:
    paths:
      - "manifests/**"
    branches:
      - main

env:
  KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_DATA }}

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up kubectl
        run: |
          echo "$KUBE_CONFIG_DATA" | base64 -d > kubeconfig
          export KUBECONFIG=$PWD/kubeconfig
          kubectl version --client
          kubectl config get-contexts

      - name: Apply SecretStore
        run: |
          kubectl apply -f manifests/secret-store.yaml
          kubectl apply -f manifests/external-secret.yaml

GitHub Secrets 설정

GitHub 저장소의 Settings > Secrets and variables > Actions 에 아래 추가:

이름
KUBE_CONFIG_DATA base64로 인코딩된 kubeconfig
cat ~/.kube/config | base64 | pbcopy
혹은 EKS 인증을 위해 GitHub Actions OIDC + IAM Role 연결 방식을 사용할 수도 있다.

SecretStore와  ExternalSecret YAML 정의 예시

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secret-store
  namespace: default
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-password
  namespace: default
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secret-store
    kind: SecretStore
  target:
    name: db-secret
    creationPolicy: Owner
  data:
    - secretKey: password
      remoteRef:
        key: /prod/db/password
  • GitHub에 PR 또는 push 발생
  • Actions 워크플로우가 kubectl apply로 리소스를 클러스터에 적용
  • ExternalSecrets Operator가 AWS Secrets Manager에서 값 가져와 Secret 생성
kubeconfig를 넣는 대신 EKS + OIDC 기반의 federated IAM role을 사용하는 방식이 보안상 권장된다.
ExternalSecret의 key 이름은 Git에 공개되므로, 민감한 path는 최소화하자.
refreshInterval을 짧게 설정할 경우 API 비용이 증가하니 주의한다.

마무리

Kubernetes의 Namespace, ConfigMap, Secret은 단순한 리소스가 아니다. 그들은 시스템 구성의 철학적 경계선이며, 운영의 혼란을 제어하고 보안을 유지하기 위한 수단이다.

 

이들을 잘 활용하는 것은 클러스터에 “질서와 규율”을 세우는 것과 같다. 결국 성숙한 클라우드 네이티브 환경은 이 세 가지 리소스를 얼마나 구조화되게 운용하느냐에 달려 있다고 해도 과언이 아니다.

728x90
Comments