Hashicorp Consul - 如何在 Kubernetes 集群中从 Pods 验证 TLS
Hashicorp Consul - How to do verified TLS from Pods in Kubernetes cluster
我在理解 Consul 端到端 TLS 时遇到一些困难。作为参考,我在 Kubernetes 中使用 Consul(通过 hashicorp/consul Helm 图表)。只有一个数据中心和 Kubernetes 集群 - 没有外部各方或顾虑。
我已经像这样配置了覆盖 values.yaml 文件:
global:
datacenter: sandbox
gossipEncryption:
secretName: "consul"
secretKey: "CONSUL_GOSSIP_ENCRYPTION_KEY"
tls:
enabled: true
httpsOnly: true
enableAutoEncrypt: true
serverAdditionalDNSSANs: ["'consul.service.consul'"]
server:
replicas: 3
bootstrapExpect: 3
storage: 20Gi
dns:
clusterIP: 172.20.53.53
ui:
service:
type: 'LoadBalancer'
syncCatalog:
enabled: true
所有其他值都是 values.yaml 文件中的默认值。
这有效,Consul 客户端日志表明所有代理区域都使用 TLS 很好地连接,相关证书和密钥由(据我了解)Auto-encryption Consul 的特点
我不明白的是如何启动从 Kubernetes 上的应用程序、运行 Pod 中的应用程序到 Consul 服务器的 HTTPS 连接。由于 Pod 的容器(可能)在其信任库中没有 Consul 根 CA 证书,所有 HTTPS 调用都会失败,根据下面的 wget 示例:
# Connect to Pod:
laptop$> kubectl exec -it my-pod sh
# Attempt valid HTTPS connection:
my-pod$> wget -q -O - https://consul.service.consul:8501
Connecting to consul.service.consul:8501 (10.110.1.131:8501)
ssl_client: consul.service.consul: certificate verification failed: unable to get local issuer certificate
wget: error getting response: Connection reset by peer
# Retry, but ignore certificate validity issues:
my-pod$> wget --no-check-certificate -q -O - https://consul.service.consul:8501/v1/status/leader
"10.110.1.131:8300"
如果容器不认为证书有效,我应该如何强制从我在 Kubernetes 上的应用程序到 Consul 的端到端(已验证)HTTPS 连接?
我对证书传播有什么误解吗?
非常感谢 - 亚伦
解决了,感谢 Hashicorp 的 Consul discussion forum。
- 使用名为 CONSUL_GOSSIP_ENCRYPTION_KEY 的密钥和适当的加密密钥值创建名为 consul 的 Kubernetes 秘密。
- 使用
consul keygen
生成值
- 使用 values-override.yaml 安装 hashicorp/consul Helm 图表,如下所示:
global:
datacenter: sandbox
gossipEncryption:
secretName: "consul"
secretKey: "CONSUL_GOSSIP_ENCRYPTION_KEY"
tls:
enabled: true
httpsOnly: true
enableAutoEncrypt: true
serverAdditionalDNSSANs: ["'consul.service.consul'"]
server:
replicas: 3
bootstrapExpect: 3
storage: 20Gi
dns:
clusterIP: 172.20.53.53
ui:
service:
type: 'LoadBalancer'
syncCatalog:
enabled: true
- 创建一个示例 Pod 规范来表示我们的应用程序。
- 确保它安装了 Consul 服务器 CA 证书密码。
- 确保 Pod 的容器 HOST_IP 公开为环境变量。
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: test-pod
spec:
volumes:
- name: consul-consul-ca-cert
secret:
secretName: consul-consul-ca-cert
hostNetwork: false
containers:
- name: consul-test-pod
image: alpine
imagePullPolicy: IfNotPresent
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
command: ["/bin/sh"]
args: ["-c", "while true; do sleep 24h; done"]
volumeMounts:
- name: consul-consul-ca-cert
mountPath: /consul/tls/ca
- 创建 Pod 后,
kubectl exec
进入其中,并确保安装了 ca-certificates 和 curl 包(在此示例中我使用的是 Alpine Linux)。
- (curl纯粹是为了测试目的)
#> apk update
#> apk add ca-certificates curl
- 复制挂载的Consul服务器CA证书到/usr/local/share/ca-certificates/执行
update-ca-certificates
添加到系统根CA存储
#> cp /consul/tls/ca/tls.crt /usr/local/share/ca-certificates/consul-server-ca.crt
#> update-ca-certificates # might give a trivial warning - ignore it
- Consul 服务器 现在可以通过 HTTPS 访问(和信任)如下:
#> curl https://consul.service.consul:8501/v1/status/leader
## No TLS errors ##
- 出于性能原因,我们还想通过 HTTPS 与 Consul 客户端(而不是服务器)通信。
- 由于 Consul 客户端有自己的 CA 证书,我们需要从服务器检索它。
- 这需要 consul-k8s 二进制文件,因此我们需要获取它。
#> cd /usr/local/bin
#> wget https://releases.hashicorp.com/consul-k8s/0.15.0/consul-k8s_0.15.0_linux_amd64.zip # (or whatever latest version is)
#> unzip consul-k8s_0.15.0_linux_amd64.zip
#> rm consul-k8s_0.15.0_linux_amd64.zip
- 获取 Consul client CA 证书并通过
update-ca-certificates
安装它:
#> consul-k8s get-consul-client-ca -server-addr consul.service.consul -server-port 8501 -output-file /usr/local/share/ca-certificates/consul-client-ca.crt
#> update-ca-certificates # might give a trivial warning - ignore it
- Consul 客户端 现在可以通过 HTTPS 访问(和信任)如下:
#> curl https://$HOST_IP:8501/v1/status/leader
## No TLS errors ##
- 我们也可以毫无问题地从客户端访问Consul KV服务:
#> curl https://$HOST_IP:8501/v1/kv/foo/bar/baz
## No TLS errors ##
当然,以上所有内容都应该由实施者自动化。这些手动步骤仅用于演示目的。
我在理解 Consul 端到端 TLS 时遇到一些困难。作为参考,我在 Kubernetes 中使用 Consul(通过 hashicorp/consul Helm 图表)。只有一个数据中心和 Kubernetes 集群 - 没有外部各方或顾虑。
我已经像这样配置了覆盖 values.yaml 文件:
global:
datacenter: sandbox
gossipEncryption:
secretName: "consul"
secretKey: "CONSUL_GOSSIP_ENCRYPTION_KEY"
tls:
enabled: true
httpsOnly: true
enableAutoEncrypt: true
serverAdditionalDNSSANs: ["'consul.service.consul'"]
server:
replicas: 3
bootstrapExpect: 3
storage: 20Gi
dns:
clusterIP: 172.20.53.53
ui:
service:
type: 'LoadBalancer'
syncCatalog:
enabled: true
所有其他值都是 values.yaml 文件中的默认值。
这有效,Consul 客户端日志表明所有代理区域都使用 TLS 很好地连接,相关证书和密钥由(据我了解)Auto-encryption Consul 的特点
我不明白的是如何启动从 Kubernetes 上的应用程序、运行 Pod 中的应用程序到 Consul 服务器的 HTTPS 连接。由于 Pod 的容器(可能)在其信任库中没有 Consul 根 CA 证书,所有 HTTPS 调用都会失败,根据下面的 wget 示例:
# Connect to Pod:
laptop$> kubectl exec -it my-pod sh
# Attempt valid HTTPS connection:
my-pod$> wget -q -O - https://consul.service.consul:8501
Connecting to consul.service.consul:8501 (10.110.1.131:8501)
ssl_client: consul.service.consul: certificate verification failed: unable to get local issuer certificate
wget: error getting response: Connection reset by peer
# Retry, but ignore certificate validity issues:
my-pod$> wget --no-check-certificate -q -O - https://consul.service.consul:8501/v1/status/leader
"10.110.1.131:8300"
如果容器不认为证书有效,我应该如何强制从我在 Kubernetes 上的应用程序到 Consul 的端到端(已验证)HTTPS 连接? 我对证书传播有什么误解吗?
非常感谢 - 亚伦
解决了,感谢 Hashicorp 的 Consul discussion forum。
- 使用名为 CONSUL_GOSSIP_ENCRYPTION_KEY 的密钥和适当的加密密钥值创建名为 consul 的 Kubernetes 秘密。
- 使用
consul keygen
生成值
- 使用
- 使用 values-override.yaml 安装 hashicorp/consul Helm 图表,如下所示:
global:
datacenter: sandbox
gossipEncryption:
secretName: "consul"
secretKey: "CONSUL_GOSSIP_ENCRYPTION_KEY"
tls:
enabled: true
httpsOnly: true
enableAutoEncrypt: true
serverAdditionalDNSSANs: ["'consul.service.consul'"]
server:
replicas: 3
bootstrapExpect: 3
storage: 20Gi
dns:
clusterIP: 172.20.53.53
ui:
service:
type: 'LoadBalancer'
syncCatalog:
enabled: true
- 创建一个示例 Pod 规范来表示我们的应用程序。
- 确保它安装了 Consul 服务器 CA 证书密码。
- 确保 Pod 的容器 HOST_IP 公开为环境变量。
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: test-pod
spec:
volumes:
- name: consul-consul-ca-cert
secret:
secretName: consul-consul-ca-cert
hostNetwork: false
containers:
- name: consul-test-pod
image: alpine
imagePullPolicy: IfNotPresent
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
command: ["/bin/sh"]
args: ["-c", "while true; do sleep 24h; done"]
volumeMounts:
- name: consul-consul-ca-cert
mountPath: /consul/tls/ca
- 创建 Pod 后,
kubectl exec
进入其中,并确保安装了 ca-certificates 和 curl 包(在此示例中我使用的是 Alpine Linux)。- (curl纯粹是为了测试目的)
#> apk update
#> apk add ca-certificates curl
- 复制挂载的Consul服务器CA证书到/usr/local/share/ca-certificates/执行
update-ca-certificates
添加到系统根CA存储
#> cp /consul/tls/ca/tls.crt /usr/local/share/ca-certificates/consul-server-ca.crt
#> update-ca-certificates # might give a trivial warning - ignore it
- Consul 服务器 现在可以通过 HTTPS 访问(和信任)如下:
#> curl https://consul.service.consul:8501/v1/status/leader
## No TLS errors ##
- 出于性能原因,我们还想通过 HTTPS 与 Consul 客户端(而不是服务器)通信。
- 由于 Consul 客户端有自己的 CA 证书,我们需要从服务器检索它。
- 这需要 consul-k8s 二进制文件,因此我们需要获取它。
#> cd /usr/local/bin
#> wget https://releases.hashicorp.com/consul-k8s/0.15.0/consul-k8s_0.15.0_linux_amd64.zip # (or whatever latest version is)
#> unzip consul-k8s_0.15.0_linux_amd64.zip
#> rm consul-k8s_0.15.0_linux_amd64.zip
- 获取 Consul client CA 证书并通过
update-ca-certificates
安装它:
#> consul-k8s get-consul-client-ca -server-addr consul.service.consul -server-port 8501 -output-file /usr/local/share/ca-certificates/consul-client-ca.crt
#> update-ca-certificates # might give a trivial warning - ignore it
- Consul 客户端 现在可以通过 HTTPS 访问(和信任)如下:
#> curl https://$HOST_IP:8501/v1/status/leader
## No TLS errors ##
- 我们也可以毫无问题地从客户端访问Consul KV服务:
#> curl https://$HOST_IP:8501/v1/kv/foo/bar/baz
## No TLS errors ##
当然,以上所有内容都应该由实施者自动化。这些手动步骤仅用于演示目的。