Development/Docker and k8s

Kubernetes Secrets: 보안 애플리케이션 관리 방법

juniz 2024. 12. 18. 13:23
반응형

현대 클라우드 네이티브 환경에서 보안은 가장 중요한 요소입니다. Kubernetes는 애플리케이션 관리를 간소화하지만, API 키, 인증 정보, 토큰과 같은 민감한 데이터를 처리할 때는 적절한 관리가 필수적입니다. Kubernetes의 Secrets는 이러한 민감한 정보를 저장하고 관리하기 위한 기본 메커니즘입니다. 하지만 기본 구현만으로는 충분하지 않습니다. 이 글에서는 Kubernetes Secrets가 무엇인지, 일반적인 문제점, 그리고 이를 안전하게 관리하기 위한 모범 사례를 살펴보겠습니다.
 

Kubernetes Secrets란?

Kubernetes Secrets는 비밀번호, OAuth 토큰, SSH 키와 같은 민감한 데이터를 안전하게 저장하는 리소스 유형입니다. ConfigMap과 달리 Secrets는 자격 증명 및 기타 기밀 정보를 위해 특별히 설계되었습니다.
기본적으로 Secret은

  • Base64로 인코딩(암호화는 아님)됩니다.
  • etcd(Kubernetes의 키-값 저장소)에 저장됩니다.
  • 네임스페이스 단위로 범위가 지정됩니다.

일반적인 Secret의 예는 다음과 같습니다:

apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
  namespace: my-namespace
type: Opaque
data:
  username: dXNlcm5hbWU=   # Base64로 인코딩된 "username"
  password: cGFzc3dvcmQ=   # Base64로 인코딩된 "password"

Kubernetes Secret의 종류

Kubernetes Secrets에는 여러 유형이 있으며, 목적에 따라 다르게 사용됩니다

  1. Opaque (기본 타입)
    • 용도: 임의의 키-값 쌍 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-opaque-secret
      type: Opaque
      data:
        username: dXNlcm5hbWU=
        password: cGFzc3dvcmQ=
      
  2. kubernetes.io/service-account-token
    • 용도: 서비스 계정 토큰 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-service-account-secret
        annotations:
          kubernetes.io/service-account.name: default
      type: kubernetes.io/service-account-token
      
  3. kubernetes.io/dockerconfigjson
    • 용도: Docker 레지스트리 인증 정보 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-docker-secret
      type: kubernetes.io/dockerconfigjson
      data:
        .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pb...  # Base64 인코딩된 JSON
      
  4. kubernetes.io/basic-auth
    • 용도: 사용자 이름과 비밀번호 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-basic-auth
      type: kubernetes.io/basic-auth
      stringData:
        username: admin
        password: password123
      
  5. kubernetes.io/ssh-auth
    • 용도: SSH 개인 키 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-ssh-key
      type: kubernetes.io/ssh-auth
      stringData:
        ssh-privatekey: |
          -----BEGIN OPENSSH PRIVATE KEY-----
          ...
          -----END OPENSSH PRIVATE KEY-----
      
  6. kubernetes.io/tls
    • 용도: TLS 인증서와 키 저장.
    • 예시:
      apiVersion: v1
      kind: Secret
      metadata:
        name: my-tls-secret
      type: kubernetes.io/tls
      data:
        tls.crt: BASE64_ENCODED_CERTIFICATE
        tls.key: BASE64_ENCODED_KEY
      
  7. bootstrap.kubernetes.io/token
    • 용도: 클러스터 노드 부트스트랩 토큰 저장.

RBAC로 Secret 관리하기

RBAC(Role-Based Access Control)을 사용하여 Secrets에 대한 접근을 세밀하게 관리할 수 있습니다.

1. 역할 생성하기

특정 Secret에 대한 읽기 권한만 부여하는 역할을 생성합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
  namespace: my-namespace
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["my-app-secret"]
    verbs: ["get"]

2. 역할 바인딩

ServiceAccount에 역할을 바인딩하여 접근 권한을 제공합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: secret-reader-binding
  namespace: my-namespace
subjects:
  - kind: ServiceAccount
    name: my-app-sa
    namespace: my-namespace
roleRef:
  kind: Role
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

이 설정은 my-app-sa ServiceAccount에만 Secret 읽기 권한을 부여합니다.


Secrets 회전 및 만료 관리

Secrets를 정기적으로 교체(회전)하면 보안 위험을 줄이고 데이터 유출 가능성을 최소화할 수 있습니다.

1. 수동 회전

  • 새 Secret을 생성하고 기존 Secret을 교체합니다.
  • 애플리케이션을 새 Secret을 참조하도록 재배포합니다.

2. 자동화된 회전

Kubernetes Job을 활용하여 Secret을 자동으로 회전할 수 있습니다.

apiVersion: batch/v1
kind: Job
metadata:
  name: secret-rotation-job
spec:
  template:
    spec:
      containers:
        - name: secret-rotator
          image: my-rotation-script:latest
      restartPolicy: Never

3. 외부 Secret 관리 도구 활용

  • HashiCorp Vault: 동적 Secret 생성 및 자동 만료 기능 제공.
  • Sealed Secrets: 암호화된 Secret을 Git에 안전하게 저장.
  • External Secrets Operator: 외부 비밀 저장소와 Kubernetes를 동기화.

Deploy에서 Kubernetes Secrets 활용

Kubernetes Secrets는 실제 애플리케이션 배포 시 환경 변수나 볼륨 형태로 주입하여 활용할 수 있습니다.

1. 환경 변수로 Secrets 주입하기

애플리케이션에 민감한 정보를 전달할 때 환경 변수로 주입하는 방법은 간단하고 효과적입니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: my-namespace
spec:
  containers:
    - name: app-container
      image: my-app:latest
      env:
        - name: APP_USERNAME
          valueFrom:
            secretKeyRef:
              name: my-app-secret
              key: username
        - name: APP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-app-secret
              key: password

2. 볼륨으로 Secrets 마운트하기

Secret 데이터를 파일 형태로 컨테이너 내부에 마운트하여 사용할 수도 있습니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: my-namespace
spec:
  containers:
    - name: app-container
      image: my-app:latest
      volumeMounts:
        - name: secret-volume
          mountPath: "/etc/secrets"
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: my-app-secret

3. Ingress에서 TLS Secret 활용하기

Ingress 리소스를 사용하여 HTTPS 트래픽을 처리할 때 TLS Secret을 활용할 수 있습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  namespace: my-namespace
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
    - hosts:
        - myapp.example.com
      secretName: my-tls-secret
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80

결론

Kubernetes Secrets는 민감한 데이터를 안전하게 관리하기 위한 강력한 도구입니다. 그러나 기본 설정만으로는 충분하지 않습니다. 보안 관행을 강화하기 위해 다음과 같은 추가 조치를 필요합니다.

  1. 암호화 저장 활성화
  2. RBAC으로 권한 최소화
  3. Secrets 회전 및 만료 자동화
  4. HashiCorp Vault 또는 Sealed Secrets 같은 외부 도구 사용
반응형