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-certificatescurl 包(在此示例中我使用的是 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 ##

当然,以上所有内容都应该由实施者自动化。这些手动步骤仅用于演示目的。