Agent Injector 예제
Agent Injector 예제 (Examples)
다양한 배포 모델을 지원하는 Vault Agent Injector 구성 예제들을 소개합니다.
출처: 문서
본문
다음은 다양한 배포 모델을 지원하는 서로 다른 구성 예제들이에요.
흔한 실수는 Deployment나 다른 리소스에 어노테이션을 설정하는 것입니다. deployments, jobs, statefulsets 같은 상위 레벨 구성을 사용할 때는 injector 어노테이션을 반드시 파드 스펙에 지정해 주세요.
Vault Agent injector 사용 전에
Vault Agent 주입 어노테이션을 파드에 적용하기 전에 다음 요구사항을 충족해야 해요.
연결성 (Connectivity)
- 쿠버네티스 API가 포트 443에서 Vault Agent injector 서비스에 연결할 수 있고, injector가 쿠버네티스 API에 연결할 수 있어야 해요.
- Vault가 쿠버네티스 API에 연결할 수 있어야 해요.
- 쿠버네티스 클러스터의 파드가 Vault에 연결할 수 있어야 해요.
참고: 쿠버네티스 API는 보통 마스터 노드에서, Vault Agent injector는 쿠버네티스 클러스터의 워커 노드에서 실행돼요. 애그리게이터 라우팅이 활성화된 쿠버네티스 클러스터(예: GKE private clusters)에서는 쿠버네티스 API가 포트 8080의 injector 서비스 엔드포인트에 직접 연결합니다.
쿠버네티스와 Vault 구성
- 쿠버네티스 인증 방식이 Vault에서 구성·활성화되어 있어야 해요.
- 파드에 서비스 어카운트가 있어야 해요.
- 원하는 시크릿이 Vault 안에 존재해야 해요.
- 서비스 어카운트가 원하는 시크릿에 접근 권한을 주는 정책을 가진 Vault 역할에 바인딩되어야 해요.
Vault 쿠버네티스 인증 방식 구성에 대한 자세한 내용은 공식 문서를 참고하세요.
디버깅 (Debugging)
변경(mutation) 요청에서 오류가 발생하면 쿠버네티스는 오류를 파드의 소유자에게 붙여요. 다음을 확인해 오류를 찾아보세요.
- 파드가 deployment나 statefulset으로 만들어졌다면, 파드를 소유한 replicaset의 오류를 확인.
- 파드가 job으로 만들어졌다면, job의 오류를 확인.
기존 파드 패치 (Patching existing pods)
기존 파드에 패치를 적용해 필요한 어노테이션을 추가할 수 있어요. 패치를 적용하면 파드가 재스케줄링(리스케줄)됩니다.
먼저 패치를 만듭니다.
cat <<EOF > ./patch.yaml
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-status: "update"
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/db-app"
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/db-app" -}}
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/appdb?sslmode=disable
{{- end }}
vault.hashicorp.com/role: "db-app"
vault.hashicorp.com/ca-cert: "/vault/tls/ca.crt"
vault.hashicorp.com/client-cert: "/vault/tls/client.crt"
vault.hashicorp.com/client-key: "/vault/tls/client.key"
vault.hashicorp.com/tls-secret: "vault-tls-client"
EOF
다음으로 패치를 적용합니다.
kubectl patch deployment <DEPLOYMENT_NAME> --patch "$(cat patch.yaml)"
이제 파드가 추가 컨테이너와 함께 재스케줄링되어야 해요. 파드는 kubectl describe 명령으로 확인할 수 있습니다.
kubectl describe pod <POD_NAME>
Deployments, StatefulSets 등
Vault Agent 주입을 구성하는 어노테이션은 파드 스펙에 있어야 해요. Deployment 같은 상위 레벨 리소스는 파드 스펙 템플릿을 감싸기 때문에, Vault Agent Injector는 이런 모든 상위 레벨 구성에서도 쓸 수 있어요.
아래 Deployment 예제는 Vault Agent 주입을 활성화하는 방법을 보여줘요.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-example
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-example-deployment
spec:
replicas: 1
selector:
matchLabels:
app: app-example
template:
metadata:
labels:
app: app-example
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/db-app'
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/db-app" -}}
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/appdb?sslmode=disable
{{- end }}
vault.hashicorp.com/role: 'db-app'
vault.hashicorp.com/ca-cert: '/vault/tls/ca.crt'
vault.hashicorp.com/client-cert: '/vault/tls/client.crt'
vault.hashicorp.com/client-key: '/vault/tls/client.key'
vault.hashicorp.com/tls-secret: 'vault-tls-client'
spec:
containers:
- name: app
image: 'app:1.0.0'
serviceAccountName: app-example
ConfigMap 예제
다음 예제는 Vault Agent 구성 파일을 담은 쿠버네티스 ConfigMap을 마운트하는 deployment를 만듭니다. Vault Agent 구성 설정의 전체 목록은 Agent 문서를 참고하세요.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-example
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-example-deployment
spec:
replicas: 1
selector:
matchLabels:
app: app-example
template:
metadata:
labels:
app: app-example
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/agent-configmap: 'my-configmap'
vault.hashicorp.com/tls-secret: 'vault-tls-client'
spec:
containers:
- name: app
image: 'app:1.0.0'
serviceAccountName: app-example
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
config.hcl: |
"auto_auth" {
"method" "kubernetes" {
"config" = {
"role" = "db-app"
}
}
"sink" "file" {
"config" = {
"path" = "/home/vault/.token"
}
}
}
"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"
}
config-init.hcl: |
"auto_auth" {
"method" "kubernetes" {
"config" = {
"role" = "db-app"
}
}
"sink" "file" {
"config" = {
"path" = "/home/vault/.token"
}
}
}
"exit_after_auth" = true
"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"
}
환경 변수 예제
다음 예제는 템플릿으로 환경 변수를 만드는 방법을 보여줘요. Vault 시크릿을 환경 변수로 내보내는 템플릿을 만들고, 애플리케이션 컨테이너가 시작 시 그 파일들을 소스(source)하면 됩니다.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'web'
vault.hashicorp.com/agent-inject-secret-config: 'secret/data/web'
# 환경 변수 내보내기 템플릿
vault.hashicorp.com/agent-inject-template-config: |
{{- with secret "secret/data/web" -}}
export api_key="{{ .Data.data.payments_api_key }}"
{{- end }}
spec:
serviceAccountName: web
containers:
- name: web
image: alpine:latest
command:
['sh', '-c']
args:
['source /vault/secrets/config && <START_COMMAND>']
ports:
- containerPort: 9090
AppRole 인증
다음 예제는 Vault Agent가 시크릿을 가져오는 데 AppRole 인증 방식을 사용하는 방법을 보여줘요. 먼저 AppRole 시크릿 ID와 역할 ID를 담은 쿠버네티스 시크릿을 만들어야 합니다.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/agent-extra-secret: 'approle-example'
vault.hashicorp.com/auth-type: 'approle'
vault.hashicorp.com/auth-path: 'auth/approle'
vault.hashicorp.com/auth-config-role-id-file-path: '/vault/custom/role-id'
vault.hashicorp.com/auth-config-secret-id-file-path: '/vault/custom/secret-id'
vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/db-app'
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/db-app" -}}
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres.postgres.svc:5432/wizard?sslmode=disable
{{- end }}
vault.hashicorp.com/role: 'my-role'
vault.hashicorp.com/tls-secret: 'vault-tls'
vault.hashicorp.com/ca-cert: '/vault/tls/ca.crt'
spec:
serviceAccountName: web
containers:
- name: web
image: alpine:latest
args:
['sh', '-c', 'source /vault/secrets/config && <START_COMMAND>']
ports:
- containerPort: 9090
PKI 인증서 예제
다음 예제는 consul-template의 pkiCert 함수와 writeToFile 함수를 사용해 템플릿에서 두 파일을 만드는 방법을 보여줘요. 하나는 Vault의 PKI 시크릿 엔진이 생성한 인증서와 CA(cert.pem)이고, 다른 하나는 키(cert.key)입니다.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'web'
vault.hashicorp.com/agent-inject-secret-certs: 'pki/issue/cert'
vault.hashicorp.com/agent-inject-template-certs: |
{{- with pkiCert "pki/issue/cert" "common_name=test.example.com" "ttl=2h" -}}
{{ .Cert }}{{ .CA }}{{ .Key }}
{{ .Key | writeToFile "/vault/secrets/cert.key" "vault" "vault" "0644" }}
{{ .CA | writeToFile "/vault/secrets/cert.pem" "vault" "vault" "0644" }}
{{ .Cert | writeToFile "/vault/secrets/cert.pem" "vault" "vault" "0644" "append" }}
{{- end -}}
spec:
serviceAccountName: web
containers:
- name: web
image: nginx
크로스 네임스페이스 시크릿 공유
- Vault를 네임스페이스 간 시크릿 공유로 구성해요.
- 다음 파드 어노테이션으로
us-west-org네임스페이스의 쿠버네티스 방식에 인증하고,us-east-org네임스페이스의 시크릿을/vault/secrets/marketing파일로 렌더링해요.
---
apiVersion: v1
kind: Pod
metadata:
name: cross-namespace
namespace: client-nicecorp
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "cross-namespace-demo"
vault.hashicorp.com/auth-path: "us-west-org/auth/kubernetes"
vault.hashicorp.com/agent-inject-template-marketing: |
{{- with secret "us-east-org/kv-marketing/campaign" -}}
{{ range $k, $v := .Data.data }}{{ $k }}: {{ $v }}
{{ end }}{{- end -}}
spec:
serviceAccountName: mega-app
containers:
- name: campaign
image: nginx