DevOps/👾 Kubernetes

[EKS] external secret 이란

키깡 2024. 11. 19.
728x90

개요

Kubernetes는 Secrets 리소스를 통해 애플리케이션의 민감한 정보를 안전하게 저장하고 관리할 수 있는 기능을 제공한다. 하지만 Kubernetes Secrets는 이름과 달리 완벽하게 안전하지 않은데, Secrets는 Kubernetes 클러스터의 etcd 데이터베이스에 base64로 인코딩된 평문 형태로 저장되기 때문에, 보안 위협에 노출될 가능성이 있다.

이러한 한계를 극복하기 위해 AWS Secrets Manager, Google Secret Manager, HashiCorp Vault 등 외부 Secret 관리 서비스를 Kubernetes와 연동할 수 있는 방법이 필요하며, External Secrets Operator(ESO)**는 이를 가능하게 하는 오픈소스 도구이다. 외부 서비스의 비밀 정보를 Kubernetes 클러스터에 자동으로 주입하고 관리할 수 있도록 도와준다.

ESO의 동작방식

https://github.com/external-secrets/kubernetes-external-secrets

  • ExternalSecrets가 클러스터에 추가됨 (kubectl apply -f external-secret-example.yml 명령어 실행)
  • 컨트롤러가 Kubernetes API를 사용하여 ExternalSecrets를 가져옴.
  • 컨트롤러가 ExternalSecrets를 사용해 외부 제공자(예: AWS Secrets Manager)에서 secret 값을 가져옴.
  • 컨트롤러가 가져온 데이터를 기반으로 Kubernetes Secrets를 업데이트하거나 생성.
  • 이렇게 Pod는 Kubernetes Secrets에 접근가능하게 됨.

특장점

  1. Custom Resource Definition(CRD):
    • SecretStoreExternalSecrets라는 두 가지 CRD를 통해 외부 Secret 제공자 및 데이터를 정의한다.
    • 클러스터 전역 적용을 위한 ClusterSecretStoreClusterExternalSecret 리소스도 제공한다.
  2. 유연한 아키텍처:
    • NodeJS 기반으로 개발된 컨트롤러가 SecretStore에서 데이터를 가져와 Kubernetes Secrets에 동기화한다.
    • 기존 애플리케이션을 변경하지 않고도 외부 Secret을 활용할 수 있다.
  3. 다양한 백엔드 지원:
    • AWS Secrets Manager, Google Secret Manager, HashiCorp Vault, Azure Key Vault 등과 연동 가능하며, 필요 시 IAM 역할과 권한을 설정할 수 있다.

설치방법

  • Helm Chart를 사용해 Kubernetes 클러스터에 ESO를 설치
  • helm repo add external-secrets https://charts.external-secrets.io helm install external-secrets \ external-secrets/external-secrets \ -n external-secrets \ --create-namespace
  • AWS Secrets Manager 연동
    • 이름은 my-secret으로 만든다 치자. 
    • aws secretsmanager create-secret --name my-secret --secret-string '{"username":"<username>","password":"<패스워드>"}'
  • service account 및 IAM Role 설정
    • Kubernetes 클러스터가 AWS Secrets Manager에 접근하려면 IAM 권한이 당연히 필요함. (시크릿 매니저 접근 권한이 있는!)
    • IRSA(IAM Role for Service Account)를 생성하고 ServiceAccount와 연결한다.
  • 필요 최소 정책
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:ap-northeast-2:<계정넘버>:secret:*"
    }
  ]
}
  • role 만들기: 이름은 뭐 eso-irsa라고 하자.
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<계정넘버>:role/eso-role
  name: eso-irsa

SecretStore와 ExternalSecret 생성

  • SecretStore
  • apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: aws-secretstore spec: provider: aws: service: SecretsManager region: ap-northeast-2 auth: jwt: serviceAccountRef: name: eso-irsa
  • ExternalSecret
  • apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: my-app-secret spec: secretStoreRef: name: aws-secretstore //시크릿스토어 이름 target: name: my-app-secret //시크릿 매니저에 저장 이름 data: - secretKey: username remoteRef: key: my-secret property: username - secretKey: password remoteRef: key: my-secret property: password

위와 같이 설정하면 AWS Secrets Manager의 데이터가 Kubernetes Secrets로 동기화

pod 생성 시 참조 방법

  • pod 내부에서 환경변수로 Secret 값을 확인할 수 있다.
apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: app-container
    image: nginx
    env:
    - name: APP_USERNAME
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: username
    - name: APP_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: password

댓글