Kubernetes에서 Vault를 시크릿 매니저로 사용해 Consul 배포
Kubernetes에서 Vault를 시크릿 매니저로 사용해 Consul 배포 (Vault + K8s)
Vault를 시크릿 매니저로 사용해 Kubernetes에 Consul을 안전하게 배포하는 방법을 설명하는 문서예요. Vault는 Consul 에이전트에 제공할 시크릿을 안전하게 저장하고 중앙에서 관리할 수 있어요.
출처: 문서
본문
이 페이지는 Vault를 시크릿 매니저로 사용해 Kubernetes에 Consul을 안전하게 배포하는 방법을 설명해요. Vault는 Consul 에이전트에 제공할 시크릿을 안전하게 저장하고 중앙에서 관리할 수 있어요. 이러한 시크릿에는 가십 암호화 키, TLS 인증서, 서비스 메시 인증서 등이 포함되며 이에 국한되지 않아요.
Kubernetes에서 Vault를 Consul과 함께 배포하는 방법에 대한 자세한 내용은 시크릿 백엔드로서의 Vault를 참고하세요.
다음 아키텍처 다이어그램은 원하는 결과를 보여줘요.
워크플로 (Workflow)
다음 단계는 Consul on Kubernetes에 대한 Vault 시크릿 관리의 특정 작업을 설명해요:
- Vault에 엔터프라이즈 라이선스 저장
- Vault에 Consul gossip 키 저장
- TLS 및 서비스 메시 CA용 PKI 시크릿 엔진 설정
- Kubernetes 인증 구성
- Vault를 시크릿 매니저로 사용하도록 Consul Helm 차트 구성
참고
이 문서는 Consul의 기본값인 데이터센터 이름
dc1과 기본 도메인consul을 사용한다고 가정해요. Consul을 다른 데이터센터 및 도메인 값으로 배포했다면 다음 예시 명령의 관련 값을 그에 맞게 조정하세요.
Vault 사전 요구 사항 (Vault prerequisites)
네트워크에 실행 중인 Vault 클러스터가 필요해요. 기존 Vault 배포가 없다면 "dev" 모드의 Vault 서버를 사용할 수 있어요. "dev" 모드의 Vault 서버는 프로덕션용으로는 적합하지 않다는 점을 참고하세요.
VAULT_ADDR, VAULT_CACERT, VAULT_TOKEN을 환경 변수로 설정해 터미널이 Vault 클러스터와 상호 작용하도록 구성하세요.
다음으로 consul/ 경로에 key/value v2 시크릿 엔진을 활성화해요.
$ vault secrets enable -path=consul kv-v2
Success! Enabled the kv-v2 secrets engine at: consul/
Vault에 엔터프라이즈 라이선스 저장 (Store Enterprise license in Vault)
Consul Enterprise 라이선스를 Vault에 안전하게 저장하고, 초기화 중에 Consul 에이전트가 라이선스를 Vault에서 가져오도록 구성할 수 있어요.
kv 시크릿 엔진의 consul/ 인스턴스를 사용해 로컬 파일 consul.hclic의 라이선스를 Vault에 저장해요.
$ vault kv put consul/secret/enterpriselicense key="$(cat ./consul.hclic)"
Key Value
--- -----
created_time 2022-03-22T16:25:14.073090874Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
Consul 라이선스를 Vault kv 시크릿 엔진에 저장한 후, 라이선스를 저장한 경로에 대한 접근을 허용하는 정책을 정의해요.
$ vault policy write enterpriselicense-policy - <<EOF
path "consul/data/secret/enterpriselicense" {
capabilities = ["read"]
}
EOF
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Uploaded policy: enterpriselicense-policy
마지막으로 Consul Helm 차트 값 파일을 편집해 엔터프라이즈 라이선스가 저장된 Vault 경로와 키를 참조해요.
global:
##...
enterpriseLicense:
secretName: 'consul/data/secret/enterpriselicense'
secretKey: 'key'
##...
Vault에 Consul gossip 키 저장 (Store Consul gossip key in Vault)
먼저 암호화 키를 생성하고 Vault에 저장해요.
$ vault kv put consul/secret/gossip gossip="$(consul keygen)"
Key Value
--- -----
created_time 2022-03-16T18:18:52.389731147Z
deletion_time n/a
destroyed false
version 1
gossip 암호화를 저장한 경로에 대한 접근을 허용하는 정책을 정의해요.
$ vault policy write gossip-policy - <<EOF
path "consul/data/secret/gossip" {
capabilities = ["read"]
}
EOF
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Uploaded policy: gossip-policy
그런 다음 Consul Helm 차트 값 파일을 편집해 gossip 키가 저장된 Vault 경로와 키를 참조해요.
global:
gossipEncryption:
secretName: consul/data/secret/gossip
secretKey: gossip
TLS 및 서비스 메시 CA용 PKI 시크릿 엔진 설정 (Setup PKI secrets engine for TLS and service mesh CA)
Vault는 TLS 인증서를 생성하는 데 사용할 수 있는 pki 시크릿 엔진을 제공해요. 이 인증서를 사용해 서버용 TLS 암호화용 CA와 서비스용 서비스 메시 리프 인증서를 구성할 수 있어요.
먼저 PKI 시크릿 엔진(pki)이 아직 활성화되지 않았다면 Vault에서 활성화해요.
$ vault secrets enable -path=pki pki
Success! Enabled the pki secrets engine at: pki/
Consul CA용 루트 인증서를 생성해요. 이 명령은 consul_ca.crt 파일에 인증서를 저장해요. Consul 데이터센터와 상호 작용해야 할 때 Consul CLI의 환경 변수를 구성하는 데 이 인증서를 사용하게 돼요.
$ vault write -field=certificate pki/root/generate/internal common_name="dc1.consul" | tee consul_ca.crt
명령은 다음과 비슷한 출력을 반환해야 해요.
-----BEGIN CERTIFICATE-----
MIIDMjCCAhqgAwIBAgIUGnHzuETSKLBqYz7CnW9iDdFbGVAwDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAxMKZGMxLmNvbnN1bDAeFw0yMjAzMTcxMDQwNTlaFw0zMjAz
MTQxMDQxMjlaMBUxEzARBgNVBAMTCmRjMS5jb25zdWwwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDPUSYAR+iHHSQlc0qUmWvix3GZIrc+yMg9RZPbaSCH
ttBd0p71weYXbMjNg8Ob0CY6umEdycXtCGOZBCkBBGPRisMrVoF9RIrWBII9XGbR
36bggYaOTtw9FYfVqVCcO1ZilcnRUpBFrtVCDVd3TZXvEPWv7j0cQ0FwqbSur3Db
VCNYPuCKt/lwill+6wlTo8yFOMRaxkBDKDGFnDKIV2gHw34xZ5vrqt2Vdeif5HSI3X3r
+zr6YAdWuwiJP+S4aTXohRinFLqHw1NMjrzbzqb8mRkuchyDfnjZBur5gxj1Z9Xs
o7fpfmWzFIleOjYHREmHtcjMcu8tti2LuGjJUAVnVg5hAgMBAAGjejB4MA4GA1Ud
DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR8hhn7L3Lze5LN
aYAWszT/oo4C6TAfBgNVHSMEGDAWgBR8hhn7L3Lze5LNaYAWszT/oo4C6TAVBgNV
HREEDjAMggpkYzEuY29uc3VsMA0GCSqGSIb3DQEBCwUAA4IBAQAddNVes5f4vmO0
zh03ShJPxH929IXFLs09uwEU3lnCQuiEhEY86x01kvSGqVnSxyBH+Xtn5va2bPCd
PQsr+9dj6J2eCV1gee6YNtKIEly4NHmYU+3ReexoGLl79guKUvOh1PG1MfHLQQun
+Y74z3s5YW89rdniWK/KdORPr63p+XQvbiuhZLfveY8BLk55mVlojKMs9HV5YOPh
znOLQNTJku04vdltNGQ4yRMDswPM2lTtUVdIgzI6S7j3DDK+gawDHLFa90zq87qY
Qux7KBBlN1VEaRQas4FrvqeRR3FtqFTzn3p+QLpOHXw3te1/6fl5oe4Cch8ZROVB
5U3wt2Em
-----END CERTIFICATE-----
다음으로 인증서 구성을 정의하는 역할(role)을 만들어요. allowed_domains 매개변수를 Consul 데이터센터 및 도메인 구성에 맞게 조정하세요.
$ vault write pki/roles/consul-server \
allowed_domains="dc1.consul,consul-server,consul-server.consul,consul-server.consul.svc" \
allow_subdomains=true \
allow_bare_domains=true \
allow_localhost=true \
generate_lease=true \
max_ttl="720h"
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: pki/roles/consul-server
다음으로 Consul 서비스 메시용 루트 CA로 사용할 connect-root 경로에 Vault의 PKI 시크릿 엔진을 활성화해요.
$ vault secrets enable -path connect-root pki
Success! Enabled the pki secrets engine at: connect-root/
Consul 서버 정책 (Consul server policy)
Consul 서버는 TLS 인증서(pki/issue/consul-server)를 생성하고 CA 인증서(pki/cert/ca)를 가져올 수 있어야 해요. 이러한 경로에 대한 접근을 허용하는 consul-server라는 Vault 정책을 만들어요.
$ vault policy write consul-server - <<EOF
path "kv/data/consul-server"
{
capabilities = ["read"]
}
path "pki/issue/consul-server"
{
capabilities = ["read","update"]
}
path "pki/cert/ca"
{
capabilities = ["read"]
}
EOF
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Uploaded policy: consul-server
Consul CA 접근 정책 (Consul CA access policy)
ca-policy 정책은 Consul 에이전트와 서비스가 서비스 메시에 사용되는 인증서가 진짜인지 검증할 수 있도록 Consul 루트 CA에 대한 접근을 허용해요.
$ vault policy write ca-policy - <<EOF
path "pki/cert/ca" {
capabilities = ["read"]
}
EOF
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Uploaded policy: ca-policy
Consul 서비스 메시 CA 정책 (Consul service mesh CA policy)
다음 Vault 정책은 서비스 메시 인증서를 생성하기 위한 루트 및 중간 PKI 시크릿 엔진을 만들고 관리할 수 있게 Consul에 허용해요. PKI 시크릿 엔진 생성과 구성을 Vault에 대한 전체 제어 위임보다는 Vault에서 직접 제어하는 것을 선호한다면 Vault CA 프로바이더 문서를 참고하세요.
이 배포에서 RootPKIPath는 connect-root이고 IntermediatePKIPath는 connect-intermediate-dc1이에요. 이 값을 자신의 특정 Vault 환경을 반영하도록 업데이트하세요.
$ vault policy write connect - <<EOF
path "/sys/mounts/connect-root" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
path "/sys/mounts/connect-intermediate-dc1" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
path "/sys/mounts/connect-intermediate-dc1/tune" {
capabilities = [ "update" ]
}
path "/connect-root/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
path "/connect-intermediate-dc1/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
path "auth/token/renew-self" {
capabilities = [ "update" ]
}
path "auth/token/lookup-self" {
capabilities = [ "read" ]
}
EOF
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Uploaded policy: connect
Kubernetes 인증 구성 (Configure Kubernetes authentication)
Vault는 클라이언트가 Kubernetes Service Account Token으로 인증할 수 있게 해주는 Kubernetes 인증 방법을 제공해요. Kubernetes 인증을 사용하면 Vault는 서비스 어카운트를 사용해 Consul 에이전트를 식별하고, Consul 데이터센터에 조인하는 데 필요한 시크릿에 대한 접근을 부여해요.
Kubernetes 인증 방법을 활성화해요.
$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/
다음으로 이 Kubernetes 인증 방법의 매개변수(서비스 어카운트용 JSON Web Token(JWT), Kubernetes CA 인증서, Kubernetes 호스트 URL)를 정의해요. Helm 차트는 Vault가 Kubernetes와 통신하도록 활성화하는 데 사용할 vault라는 Kubernetes 서비스 어카운트를 구성해요. vault 서비스 어카운트의 JSON Web Token(JWT)을 가져와 token_reviewer_jwt 환경 변수로 설정해요.
$ export token_reviewer_jwt=$(kubectl get secret \
$(kubectl get serviceaccount vault -o jsonpath='{.secrets[0].name}') \
-o jsonpath='{ .data.token }' | base64 --decode)
서비스 어카운트의 Kubernetes 인증 기관을 가져와 kubernetes_ca_cert 환경 변수로 설정해요.
$ export kubernetes_ca_cert=$(kubectl get secret \
$(kubectl get serviceaccount vault -o jsonpath='{.secrets[0].name}') \
-o jsonpath='{ .data.ca\.crt }' | base64 --decode)
Kubernetes 클러스터 엔드포인트를 가져와 kubernetes_host_url 환경 변수로 설정해요.
$ export kubernetes_host_url=$(kubectl config view --raw --minify --flatten \
-o jsonpath='{.clusters[].cluster.server}')
서비스 어카운트 토큰을 사용하도록 Vault Kubernetes 인증 방법을 구성해요.
$ vault write auth/kubernetes/config \
token_reviewer_jwt="${token_reviewer_jwt}" \
kubernetes_host="${kubernetes_host_url}" \
kubernetes_ca_cert="${kubernetes_ca_cert}"
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/config
Kubernetes 인증 방법의 구성이 Vault에서 변경되었는지 확인해요.
$ vault read auth/kubernetes/config
Key Value
--- -----
disable_iss_validation true
disable_local_ca_jwt false
issuer n/a
kubernetes_ca_cert -----BEGIN CERTIFICATE-----
##...
-----END CERTIFICATE-----
kubernetes_host https://66606BBB5881313742471313182BBB90999.gr7.us-east-1.eks.amazonaws.com
pem_keys []
Kubernetes 인증 방법을 구성하고 리소스에 대한 접근을 허용하는 다양한 정책을 정의했습니다. 이제 Kubernetes 서비스 어카운트와 Vault 정책 사이의 연결을 정의할 수 있어요.
Consul 서버 에이전트, Consul 클라이언트 에이전트, Consul CA 인증서 접근에 필요한 정책을 연결하는 Vault 역할을 만들 거예요.
Vault에서 Kubernetes 인증용 Consul 서버 역할 구성 (Configure Consul server role)
Vault에서 consul-server라는 Kubernetes 인증 역할을 만들어 Kubernetes 서비스 어카운트(consul-server)와 네임스페이스(consul)를 Vault 정책 gossip-policy, consul-server, connect와 연결해요. 인증 후 반환되는 토큰은 24시간 동안 유효해요.
Consul OSS
$ vault write auth/kubernetes/role/consul-server \
bound_service_account_names=consul-server \
bound_service_account_namespaces=consul \
policies="gossip-policy,consul-server,connect" \
ttl=24h
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/role/consul-server
Consul Enterprise
Consul Enterprise를 사용할 때는 역할을 enterpriselicense-policy와도 연결해야 해요.
$ vault write auth/kubernetes/role/consul-server \
bound_service_account_names=consul-server \
bound_service_account_namespaces=consul \
policies="gossip-policy,consul-server,connect,enterpriselicense-policy" \
ttl=24h
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/role/consul-server
Vault에서 Kubernetes 인증용 Consul 클라이언트 역할 구성 (Configure Consul client role)
Vault에서 consul-client라는 Kubernetes 인증 역할을 만들어 Kubernetes 서비스 어카운트(consul-client)와 네임스페이스(consul)를 Vault 정책 gossip-policy와 ca-policy와 연결해요. 인증 후 반환되는 토큰은 24시간 동안 유효해요.
Consul OSS
$ vault write auth/kubernetes/role/consul-client \
bound_service_account_names=consul-client \
bound_service_account_namespaces=consul \
policies="gossip-policy,ca-policy" \
ttl=24h
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/role/consul-client
Consul Enterprise
Consul Enterprise를 사용할 때는 역할을 enterpriselicense-policy와도 연결해야 해요.
$ vault write auth/kubernetes/role/consul-client \
bound_service_account_names=consul-client \
bound_service_account_namespaces=consul \
policies="gossip-policy,ca-policy,enterpriselicense-policy" \
ttl=24h
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/role/consul-client
Vault에서 Consul CA 루트 인증서 접근 구성 (Configure Consul CA root certificate access)
Vault에서 consul-ca라는 Kubernetes 인증 역할을 만들어 네임스페이스(consul)의 모든 Kubernetes 서비스 어카운트를 Vault 정책 ca-policy와 연결해요. 인증 후 반환되는 토큰은 1시간 동안 유효해요.
$ vault write auth/kubernetes/role/consul-ca \
bound_service_account_names="*" \
bound_service_account_namespaces=consul \
policies=ca-policy \
ttl=1h
명령은 다음과 비슷한 출력을 반환해야 해요.
Success! Data written to: auth/kubernetes/role/consul-ca
다음 다이어그램은 만든 구성의 요약을 제공해요.
Vault를 시크릿 매니저로 사용하도록 Consul Helm 차트 구성 (Configure Consul Helm chart to use Vault as secrets manager)
마지막으로 Consul Helm 차트 값 파일을 편집해 PKI 시크릿 엔진이 구성된 Vault 경로와 키를 참조해요.
consul-values.yaml
global:
##...
secretsBackend:
vault:
enabled: true
consulServerRole: consul-server
consulClientRole: consul-client
consulCARole: consul-ca
connectCA:
address: $VAULT_PRIVATE_ADDR
rootPKIPath: connect-root/
intermediatePKIPath: connect-intermediate-dc1/
additionalConfig: "{\"connect\": [{ \"ca_config\": [{ \"namespace\": \"admin\"}]}]}"
agentAnnotations: |
"vault.hashicorp.com/namespace": "admin"
##...
다음 단계 (Next steps)
Consul Helm 차트와 조정 가능한 값에 대한 자세한 내용은 Helm 차트 참조 문서를 참고하세요.
Vault Kubernetes 인증에 대해 더 알아보려면 Kubernetes와 함께하는 Vault Agent와 Amazon Elastic Kubernetes Service와 함께하는 HCP Vault Dedicated를 확인하세요.