【问题标题】:Kubernetes unable to access the kube-apiserver from inside pod on nodeKubernetes 无法从节点上的 pod 内部访问 kube-apiserver
【发布时间】:2016-04-22 22:08:32
【问题描述】:

我已经配置了一个 vagrant 支持的 kubernetes 集群,但是我无法从运行在节点上的 pod 中访问运行在 master 上的 kube-apiserver。我正在尝试通过 api 从 pod 中查找服务,但看起来 api 不断断开连接。

在 pod 中使用 curl 我得到以下输出

root@itest-pod-2:/# curl -v \
--insecure -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://$KUBERNETES_SERVICE_HOST:443/api/v1/namespaces/default/services?labelSelector=name%3Dtest-server
* Hostname was NOT found in DNS cache
*   Trying 10.245.0.1...
* Connected to 10.245.0.1 (10.245.0.1) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to 10.245.0.1:443 
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to 10.245.0.1:443 
root@itest-pod-2:/# 

但是,如果我通过简单地将所有节点组件安装到 master 上来配置单机环境,我就可以从 pod 中联系 api。

root@itest-pod-3:/# curl -v --insecure \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://$KUBERNETES_SERVICE_HOST:443/api/v1/namespaces/default/services?labelSelector=name%3Dtest-server
* Hostname was NOT found in DNS cache
*   Trying 10.245.0.1...
* Connected to 10.245.0.1 (10.245.0.1) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA
* Server certificate:
*    subject: CN=10.0.2.15@1452869292
*    start date: 2016-01-15 14:48:12 GMT
*    expire date: 2017-01-14 14:48:12 GMT
*    issuer: CN=10.0.2.15@1452869292
*    SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /api/v1/namespaces/default/services?labelSelector=name%3Dtest-server HTTP/1.1
> User-Agent: curl/7.38.0
> Host: 10.245.0.1
> Accept: */*
> Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tdDY3cXUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImIxNGI4YWE3LWJiOTgtMTFlNS1iNjhjLTA4MDAyN2FkY2NhZiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.HhPnit7Sfv-yUkMW6Cy9ZVbuiV2wt5PLaPSP-uZtaByOPagkb8d-8zBQE8Lx53lqxMFwBmjjxSWl-vKtSGa0ka6rEkq_xWtFJb8uDDlxz_R63R6IJBWB8YhwB7SzPVWgtHohj55D3pL8-r8NOQSQVXFAHaiGTlzmtwiE3CmJv3yBzBLALG0yvtW2YgwrO9jlxCGdFIOKae-5eduiOyZHUimxAgfBkbwSNfSzXYZTJNryfPiDBKZybh9c3Wd-pNsSZyw9gbBhbGFM7EiK9pWsdViQ__fZA2JbxX78YbajWE6CeL4FWLKFu4MuIlnmhLOvOXia_9WXz1B8XJ-MlzclZQ
> 
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 15 Jan 2016 16:37:40 GMT
< Content-Length: 171
< 
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/default/services",
    "resourceVersion": "1518"
  },
  "items": []
}
* Connection #0 to host 10.245.0.1 left intact

让我感到困惑的是,两种情况下的配置都是相同的,只是节点组件已安装到主服务器中,这让我认为这不是 ssl/https 的错误配置,而是与Kubernetes 网络配置。

我查看了 apiserver 的日志,但看不到与这些断开的连接相关的任何内容。

任何帮助将不胜感激。

【问题讨论】:

    标签: kubernetes


    【解决方案1】:

    我假设您通过 kubelet 工人/仆从证书/密钥对。

    api-server 证书是否包含指向主服务器的专有名称/备用名称(您的 openssl.conf 中的 subjectAltName 在生成 API 服务器证书时应该具有主服务器的 IP)

    这是我认为这个问题最常见的原因。

    创建您的 CA 密钥和证书 那么:

    cat <<EOT >openssl.cnf
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name
    [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = kubernetes
    DNS.2 = kubernetes.default
    IP.1 = ${K8S_SERVICE_IP}
    IP.2 = ${MASTER_HOST}
    EOT
    
    openssl genrsa -out apiserver-key.pem 2048
    openssl req -new -key apiserver-key.pem -out apiserver.csr -subj "/CN=kube-apiserver" -config ./openssl.cnf
    openssl x509 -req -in apiserver.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out apiserver.pem -days 365 -extensions v3_req -extfile ./openssl.cnf
    

    【讨论】:

    • 谢谢,我实际上没有使用任何证书或密钥,尽管看起来我应该使用。真的,此时我并不担心安全连接,因为我正在设置开发环境并且不想不必要地增加这种复杂性。我认为我真正需要的是获取不安全的 kube 服务主机和端口作为 pod 内的环境变量并使用它们。但据我所知,它们不可用。我仍然对如何在系统中没有单一证书/密钥的情况下通过其 https 接口访问 api-server 感到困惑。
    • 您是如何启动集群的?您遵循了什么教程或信息?我敢打赌,如果您使用了一些脚本,它会为您创建证书。
    • 可以分享一下 kubelet.service 和 kube-config.yaml 吗?
    • 嗨 MrE,我知道答案已经发布,但仍然对代理为什么尝试将安全请求代理到不安全端口感到好奇?
    【解决方案2】:

    问题是我们没有设置绑定地址 apiserver(我们设置了不安全的绑定地址,但没有设置 --bind-address) 我们认为这不是问题,因为默认情况下 apiserver 绑定在所有接口上。

    当所有接口调用绑定到 /api/v1/endpoints 时,将返回 apiserver 安全端口的 eth0 IP。在大多数情况下,这可能没问题 但是由于我们在虚拟机 vm 上运行 kubernetes eth0 是 virtualbox创建的NAT接口,只能通过 VBoxHeadless 正在侦听的主机端口。

    当传出流量离开 Pod 时,它会遇到一组 iptables 规则 匹配集群服务 ip 并重定向到代理上的端口 然后代理将请求转发到 集群。

    在这种情况下,kube-proxy 没有可用的 apiservice 的外部可访问 ip 而不是 virtualbox 使用的 eth0 地址。

    奇怪的是,虽然代理似乎随后尝试联系 api 在其不安全的端口上(它知道 由于它创建的 iptables 规则而请求)。由于我们的要求 在这种情况下是 https apiserver 在第一个客户端之后删除它 你好。

    通常在 curl 中是这样的

    root@app-master-0:/home/vagrant# curl -v --insecure \
    https://10.235.1.2:8080/api/v1/namespaces/default/services?labelSelector=name%3Dtest-server
    * Hostname was NOT found in DNS cache
    *   Trying 10.235.1.2...
    * Connected to 10.235.1.2 (10.235.1.2) port 8080 (#0)
    * successfully set certificate verify locations:
    *   CAfile: none
      CApath: /etc/ssl/certs
    * SSLv3, TLS handshake, Client hello (1):
    * error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
    * Closing connection 0
    curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown
    protocol
    

    但是当通过 kube 代理进行代理时,它看起来像这样

    root@itest-pod-2:/# curl -v --insecure \
    https://$KUBERNETES_SERVICE_HOST:443/api/v1/namespaces/default/services?labelSelector=name%3Dtest-server
    * Hostname was NOT found in DNS cache
    *   Trying 10.245.0.1...
    * Connected to 10.245.0.1 (10.245.0.1) port 443 (#0)
    * successfully set certificate verify locations:
    *   CAfile: none
      CApath: /etc/ssl/certs
    * SSLv3, TLS handshake, Client hello (1):
    * Unknown SSL protocol error in connection to 10.245.0.1:443
    * Closing connection 0
    curl: (35) Unknown SSL protocol error in connection to 10.245.0.1:443
    

    通过将--bind-address=xxxx 与外部可访问的 eth1 ip 添加到 apiserver 的 args 中,我们能够解决此问题。

    【讨论】:

      猜你喜欢
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2017-06-22
      • 2021-06-12
      • 1970-01-01
      • 2021-10-23
      相关资源
      最近更新 更多