2

我在理解 Consul 端到端 TLS 时遇到了一些困难。作为参考,我在 Kubernetes 中使用 Consul(通过hashcorp/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 很好地连接,相关证书和密钥是由(据我了解)Consul的自动加密功能创建的。

我不明白的是如何从运行在 Pod 中的 Kubernetes 上的应用程序启动到 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 连接?我对证书传播有误解吗?

非常感谢 - 亚伦

4

1 回答 1

0

感谢 Hashicorp 在他们的领事讨论论坛上解决。

  • 使用名为CONSUL_GOSSIP_ENCRYPTION_KEY的密钥和适当的加密密钥值 创建一个名为consul的 Kubernetes 机密。
    • 使用产生价值consul keygen
  • 使用values-override.yaml安装hashcorp/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
  • 现在可以通过 HTTPS 访问(和信任)Consul服务器,如下所示:
#> 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客户端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
  • 现在可以通过 HTTPS 访问(和信任)Consul客户端,如下所示:
#> 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 ##

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

于 2020-05-31T00:11:28.643 回答