【问题标题】:How to access kind control plane port from another docker container?如何从另一个 docker 容器访问 kind control plane 端口?
【发布时间】:2022-12-23 04:40:06
【问题描述】:

我正在使用 kind create cluster --name kind 创建一个 kind 集群,我想从另一个 docker 容器访问它,但是当我尝试从容器 (kubectl apply -f deployment.yml) 应用 Kubernetes 文件时,我收到了这个错误:

The connection to the server 127.0.0.1:6445 was refused - did you specify the right host or port?

事实上,当我尝试从容器中卷曲 kind control-plane 时,它​​是无法访问的。

> docker run --entrypoint curl curlimages/curl:latest 127.0.0.1:6445
curl: (7) Failed to connect to 127.0.0.1 port 6445 after 0 ms: Connection refused

然而,善良的控制平面正在发布到正确的端口,但只发布到本地主机。

> docker ps --format "table {{.Image}}\t{{.Ports}}"
IMAGE                  PORTS
kindest/node:v1.23.4   127.0.0.1:6445->6443/tcp

目前我找到的唯一解决方案是设置主机网络模式。

> docker run --network host --entrypoint curl curlimages/curl:latest 127.0.0.1:6445
Client sent an HTTP request to an HTTPS server.

该解决方案看起来不是最安全的。有没有另一种方法,比如将 kind 网络连接到我的容器或我错过的类似方法?

【问题讨论】:

  • stackoverflow.com/q/30545023/1563297 这是否回答了您的问题?
  • 我不一定会尝试将 Docker 容器与 Kubernetes 环境连接起来。您可以改为在 KinD 环境中将 Kubernetes API 客户端程序作为 pod 运行吗?

标签: docker kubernetes networking kind


【解决方案1】:

我不知道你为什么要这样做。但没问题,我认为这可以帮助你:

首先,让我们拉取你的 docker 镜像:

❯ docker pull curlimages/curl

在我的 kind 集群中,我有 3 个控制平面节点和 3 个工作节点。以下是我的 kind 集群的 pod:

❯ docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED          STATUS          PORTS                       NAMES
39dbbb8ca320   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       127.0.0.1:35327->6443/tcp   so-cluster-1-control-plane
62b5538275e9   kindest/haproxy:v20220207-ca68f7d4   "haproxy -sf 7 -W -d…"   7 days ago       Up 7 days       127.0.0.1:35625->6443/tcp   so-cluster-1-external-load-balancer
9f189a1b6c52   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       127.0.0.1:40845->6443/tcp   so-cluster-1-control-plane3
4c53f745a6ce   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       127.0.0.1:36153->6443/tcp   so-cluster-1-control-plane2
97e5613d2080   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       0.0.0.0:30081->30080/tcp    so-cluster-1-worker2
0ca64a907707   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       0.0.0.0:30080->30080/tcp    so-cluster-1-worker
9c5d26caee86   kindest/node:v1.23.5                 "/usr/local/bin/entr…"   7 days ago       Up 7 days       0.0.0.0:30082->30080/tcp    so-cluster-1-worker3

我们在这里感兴趣的容器是 haproxy 容器 (kindest/haproxy:v20220207-ca68f7d4),它的作用是对进入节点的流量进行负载均衡(在我们的示例中,尤其是控制平面节点。)我们可以看到我们主机的端口 35625 映射到 haproxy 容器的端口 6443。 (127.0.0.1:35625->6443/tcp)

所以,我们的集群端点是https://127.0.0.1:35625,我们可以在我们的 kubeconfig 文件 (~/.kube/config) 中确认这一点:

❯ cat .kube/config
apiVersion: v1
kind: Config
preferences: {}
users:
  - name: kind-so-cluster-1
    user:
        client-certificate-data: <base64data>
        client-key-data: <base64data>
clusters:
  - cluster:
        certificate-authority-data: <certificate-authority-dataBase64data>
        server: https://127.0.0.1:35625
    name: kind-so-cluster-1
contexts:
  - context:
        cluster: kind-so-cluster-1
        user: kind-so-cluster-1
        namespace: so-tests
    name: kind-so-cluster-1
current-context: kind-so-cluster-1

让我们在后台运行 curl 容器:

❯ docker run -d --network host curlimages/curl sleep 3600
ba183fe2bb8d715ed1e503a9fe8096dba377f7482635eb12ce1322776b7e2366

正如预期的那样,我们无法通过 HTTP 请求侦听 HTTPS 端口的端点:

❯  docker exec -it ba curl 127.0.0.1:35625
Client sent an HTTP request to an HTTPS server.

我们可以尝试使用我们的 kubeconfig 中“certificate-authority-data”字段中的证书来检查它是否改变了什么(它应该): 让我们创建一个名为 my-ca.crt 的文件,其中包含证书的字符串数据:

base64 -d <<<  <certificate-authority-dataBase64dataFromKubeConfig> > my-ca.crt 

由于 curl docker 镜像的工作目录是“/”,让我们将我们的证书复制到容器中的这个位置并验证它是否确实存在:

docker cp my-ca.crt ba183fe:/

❯ docker exec -it ba sh
/ $ ls my-ca.crt
my-ca.crt

让我们再次尝试我们的 curl 请求,但使用证书:

❯ docker exec -it ba curl --cacert my-ca.crt https://127.0.0.1:35625
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User "system:anonymous" cannot get path "/"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

您可以通过在 curl 请求中添加“--insecure”标志来获得相同的结果:

❯  docker exec -it ba curl https://127.0.0.1:35625 --insecure
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User "system:anonymous" cannot get path "/"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

但是,我们无法使用匿名用户访问我们的集群!因此,让我们从 kubernetes 获取令牌(cf https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/):

# Create a secret to hold a token for the default service account
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: default-token
  annotations:
    kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF

一旦令牌控制器用令牌填充了秘密:

# Get the token value
❯ kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode
eyJhbGciOiJSUzI1NiIsImtpZCI6InFSTThZZ05lWHFXMWExQlVSb1hTcHNxQ3F6Z2Z2aWpUaUYwd2F2TGdVZ0EifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJzby10ZXN0cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzYzY0OTg1OS0xNzkyLTQzYTQtOGJjOC0zMDEzZDgxNjRmY2IiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6c28tdGVzdHM6ZGVmYXVsdCJ9.VLfjuym0fohYTT_uoLPwM0A6u7dUt2ciWZF2K9LM_YvQ0UZT4VgkM8UBVOQpWjTmf9s2B5ZxaOkPu4cz_B4xyDLiiCgqiHCbUbjxE9mphtXGKQwAeKLvBlhbjYnHb9fCTRW19mL7VhqRgfz5qC_Tae7ysD3uf91FvqjjxsCyzqSKlsq0T7zXnzQ_YQYoUplGa79-LS_xDwG-2YFXe0RfS9hkpCILpGDqhLXci_gwP9DW0a6FM-L1R732OdGnb9eCPI6ReuTXQz7naQ4RQxZSIiNd_S7Vt0AYEg-HGvSkWDl0_DYIyHShMeFHu1CtfTZS5xExoY4-_LJD8mi

现在让我们直接使用令牌执行 curl 命令!

❯ docker exec -it ba curl -X GET https://127.0.0.1:35625/api --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InFSTThZZ05lWHFXMWExQlVSb1hTcHNxQ3F6Z2Z2aWpUaUYwd2F2TGdVZ0EifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJzby10ZXN0cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzYzY0OTg1OS0xNzkyLTQzYTQtOGJjOC0zMDEzZDgxNjRmY2IiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6c28tdGVzdHM6ZGVmYXVsdCJ9.VLfjuym0fohYTT_uoLPwM0A6u7dUt2ciWZF2K9LM_YvQ0UZT4VgkM8UBVOQpWjTmf9s2B5ZxaOkPu4cz_B4xyDLiiCgqiHCbUbjxE9mphtXGKQwAeKLvBlhbjYnHb9fCTRW19mL7VhqRgfz5qC_Tae7ysD3uf91FvqjjxsCyzqSKlsq0T7zXnzQ_YQYoUplGa79-LS_xDwG-2YFXe0RfS9hkpCILpGDqhLXci_gwP9DW0a6FM-L1R732OdGnb9eCPI6ReuTXQz7naQ4RQxZSIiNd_S7Vt0AYEg-HGvSkWDl0_DYIyHShMeFHu1CtfTZS5xExoY4-_LJD8mi" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "172.18.0.5:6443"
    }
  ]
}

有用 ! 我仍然不知道你为什么要这样做,但我希望这对你有所帮助。

因为这不是你想要的,因为我在这里使用主机网络,你可以使用这个:How to communicate between Docker containers via "hostname" 建议@SergioSantiago 感谢你的评论!

猜测

【讨论】:

  • 谢谢您的回答。这不是我想要的,因为您正在使用主机网络。但是就像@SergioSantiago 所说的那样,我尝试使用这种桥接网络连接我的容器,使用它的名称作为主机,我将集群服务器更改为so-cluster-1-control-plane:6443,它成功了。对于其余部分,我使用了您的答案,它也可以正常工作。如果您在不使用 curl 容器的主机网络的情况下编辑您的答案,我将接受您的答案。谢谢 !
  • (你可以在我的最后找到你想要的答案)
【解决方案2】:

没有足够的代表评论其他答案,但想评论最终对我有用的东西。

外卖

  • 在自己的桥接网络中运行的集群kind
  • Kubernetes 客户端服务在另一个容器中运行,并安装了 kube 配置卷
  • 如上所述,除非您希望您的服务在host 网络中运行,否则容器需要位于同一网络中。
  • kubeconfig 的服务器地址是容器名称 + 内部端口,例如kind-control-plane:6443。该端口不是下面示例中的暴露端口 6443不是38669
    CONTAINER ID   IMAGE                                PORTS
    7f2ee0c1bd9a   kindest/node:v1.25.3                 127.0.0.1:38669->6443/tcp
    

容器的 Kube 配置

# path/to/some/kube/config
apiVersion: v1
clusters:
  - cluster:
      insecure-skip-tls-verify: true # Don't use in Prod equivalent of --insecure on cli
      server: https://<kind-control-plane container name>:6443 # NOTE port is internal container port
    name: kind-kind # or whatever
contexts:
  - context:
      cluster: kind-kind
      user: <some-service-account>
    name: kind-kind # or whatever
current-context: kind-kind
kind: Config
preferences: {}
users:
  - name: <some-service-account>
    user:
      token: <TOKEN>

Docker容器的东西

  • 如果使用 docker-compose,您可以将 kind 网络添加到容器中,例如:

    #docker-compose.yml
    services:
      foobar:
        build:
          context: ./.config
        networks:
          - kind # add this container to the kind network
        volumes:
          - path/to/some/kube/config:/somewhere/in/the/container
    networks:
      kind: # define the kind network
        external: true # specifies that the network already exists in docker
    
  • 如果运行新容器:

    docker run --network kind -v path/to/some/kube/config:/somewhere/in/the/container <image>
    
  • 容器已经运行?

    docker network connect kind <container name>
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多