볼트 in 쿠버네티스

개요

쿠버네티스에서 볼트를 활용하는 방법에 대해 알아보자.
일단 이 방식은 볼트를 클러스터에 설치한 상황을 이야기한다.
흔히 헬름으로 설치한 상황으로 받아들이면 되겠다.

볼트에서는 클러스터에서 볼트를 효율적으로 활용할 수 있도록 세 가지 정도의 통합 방식을 지원한다.

Agent Injector

워크로드가 볼트의 시크릿을 사용해야 하는 경우 사용하는 방식이다.
에이전트를 워크로드의 사이드카로 주입하여 이 에이전트가 시크릿을 받아오는 역할을 수행하게 한다.

보다시피 Mutating Admission Webhook으로 사이드카가 파드에 주입되고, 이 파드가 각종 볼트에서 시크릿을 가져오는 역할을 수행한다.
사이드카 인젝터가 동작하게 하려면 어노테이션 세팅을 해주면 된다.

vault.hashicorp.com/agent-inject: true
vault.hashicorp.com/agent-inject-secret-<unique-name>: /path/to/secret
vault.hashicorp.com/agent-inject-template-foo: |
  {{- with secret "database/creds/db-app" -}}
  postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable
  {{- end }}
vault.hashicorp.com/role: 'db-app'

이런 식으로 필요한 스펙들을 전부 어노테이션으로 넣어준다..
dp-app이란 앱롤을 이용할 거고, <unique-name>의 시크릿을 어떤 경로에 넣으라는 식이다.
넣을 때는 위처럼 템플릿 형태로 넣는 것도 가능하다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.hcl: |
    "auto_auth" = {
      "method" = {
        "config" = {
          "role" = "db-app"
        }
        "type" = "kubernetes"
      }

      "sink" = {
        "config" = {
          "path" = "/home/vault/.token"
        }

        "type" = "file"
      }
    }

    "exit_after_auth" = false
    "pid_file" = "/home/vault/.pid"

    "template" = {
      "contents" = "{{- with secret \"database/creds/db-app\" -}}postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable{{- end }}"
      "destination" = "/vault/secrets/db-creds"
    }

    "vault" = {
      "address" = "https://vault.demo.svc.cluster.local:8200"
      "ca_cert" = "/vault/tls/ca.crt"
      "client_cert" = "/vault/tls/client.crt"
      "client_key" = "/vault/tls/client.key"
    }

이런 식으로 원하는 설정을 ConfigMap으로 만든 후에 이걸 어노테이션으로 명시하는 것도 가능하다.

        vault.hashicorp.com/agent-configmap: 'my-configmap'

이런 식으로 말이다.

Vault Secret Operator

Vault Secret Operator는 말 그대로 볼트를 오퍼레이터로 만들어낸 것이다.

Vault CSI Provider

볼트를 CSI로 활용하는 방식!

이것도 어플리케이션 레벨에서 보면 위의 에이전트 인젝팅 방식보다 조금 더 번거로울 수도 있는 방식.
대신에 이번에는 워크로드마다 에이전트가 주입되는 것이 아니라 노드의 데몬셋으로 스토리지 프로바이더가 배포돼 있고, 파드에서 이걸 스토리지로서 활용하면 해당 시크릿을 가져와서 넣어주는 방식이다.
이 시크릿은 쿠버의 시크릿으로서 만들어져서 파드에 마운팅되는데, 이건 처음 봤지만 시크릿을 csi로 사용하는 방식이 또 있나보다.[1]

image.png
개인적으로 평하자면, 에이전트 주입 방식은 프로세스가 더 띄워지는 격이므로 컴퓨팅 리소스를 조금 더 소모한다는 점에서 아쉽다.
그러나 위 방식은 쿠버의 시크릿으로서 데이터를 불필요하게 클러스터에 잠시라도 남겨야만 하고, 모든 노드의 데몬셋 파드가 띄워져 있어야만 한다는 점에서 에이전트 주입 방식보다 더 아쉽게 느껴진다.
최소한 에이전트는 프로세스가 떠 있는 만큼 토큰 갱신이라던가 하는 작업을 잘 해줄 수 있지만, CSI 방식은 그런 것도 없는 것으로 보인다.
이 방식이 좋을 수 있는 경우는 다른 사이드카가 볼트를 활용하는 경우가 아닐까 하는 생각이 들었는데, 사이드카 컨테이너를 이용하면 사실 컨테이너 순서 보장도 가능해서 굳이..?

apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  name: vault-db-creds
spec:
  provider: vault
  parameters:
    roleName: 'app'
    objects: |
      - objectName: "dbUsername"
        secretPath: "database/creds/db-app"
        secretKey: "username"
      - objectName: "dbPassword"
        secretPath: "database/creds/db-app"
        secretKey: "password"

아무튼 이렇게 먼저 시크릿 프로바이더 클래스를 지정한다.

      volumes:
        - name: vault-db-creds
          csi:
            driver: 'secrets-store.csi.k8s.io'
            readOnly: true
            volumeAttributes:
              secretProviderClass: 'vault-db-creds'

그 다음에 워크로드에서는 이렇게 csi 임시 볼륨 형태로 사용한다.

관련 문서

이름 noteType created
볼트 in 쿠버네티스 knowledge 2025-04-14
Vault Secret Operator knowledge 2025-04-14
10W - Vault를 활용한 CICD 보안 published 2025-04-16
7W - 이스티오 메시 스케일링 published 2025-06-09
E-이스티오 메시 스케일링 topic/explain 2025-06-08

참고


  1. https://github.com/kubernetes-sigs/secrets-store-csi-driver ↩︎