kubernetes - NodePort 服务并非在所有节点上都可用

标签 kubernetes kube-proxy

我正在尝试运行 3 节点 Kubernetes 集群。我已经启动并充分运行集群,以便在不同节点上运行服务。不幸的是,我似乎无法让基于 NodePort 的服务正常工作(正如我所理解的正确性......)。我的问题是我定义的任何 NodePort 服务仅在其 pod 运行的节点上外部可用,我的理解是它们应该在集群中的任何节点上外部可用。

一个例子是本地 Jira 服务,它应该在端口 8082(内部)和外部 32760 上运行。这是服务定义(只是服务部分):

apiVersion: v1
kind: Service
metadata:
  name: jira
  namespace: wittlesouth
spec:
  ports:
  - port: 8082
  selector:
    app: jira
  type: NodePort

这是 kubectl get service --namespace wittle south 的输出
NAME       TYPE           CLUSTER-IP      EXTERNAL-IP                       PORT(S)          AGE
jenkins    NodePort       10.100.119.22   <none>                            8081:31377/TCP   3d
jira       NodePort       10.105.148.66   <none>                            8082:32760/TCP   9h
ws-mysql   ExternalName   <none>          mysql.default.svc.cluster.local   3306/TCP         1d

这个服务的 pod 有一个 HostPort 设置为 8082。集群中的三个节点是 nuc1、nuc2、nuc3:
Eric:~ eric$ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
nuc1      Ready     master    3d        v1.9.2
nuc2      Ready     <none>    2d        v1.9.2
nuc3      Ready     <none>    2d        v1.9.2

以下是尝试通过主机和节点端口访问 Jira 实例的结果:
Eric:~ eric$ curl https://nuc1.wittlesouth.com:8082/
curl: (7) Failed to connect to nuc1.wittlesouth.com port 8082: Connection refused
Eric:~ eric$ curl https://nuc2.wittlesouth.com:8082/
curl: (7) Failed to connect to nuc2.wittlesouth.com port 8082: Connection refused
Eric:~ eric$ curl https://nuc3.wittlesouth.com:8082/
curl: (51) SSL: no alternative certificate subject name matches target host name 'nuc3.wittlesouth.com'
Eric:~ eric$ curl https://nuc3.wittlesouth.com:32760/
curl: (51) SSL: no alternative certificate subject name matches target host name 'nuc3.wittlesouth.com'
Eric:~ eric$ curl https://nuc2.wittlesouth.com:32760/
^C
Eric:~ eric$ curl https://nuc1.wittlesouth.com:32760/
curl: (7) Failed to connect to nuc1.wittlesouth.com port 32760: Operation timed out

根据我的阅读,cube-proxy 似乎没有做它应该做的。我尝试通读了对多维数据集代理进行故障排除的文档,它似乎有点过时了(当我在 iptables-save 中搜索主机名时,它什么也没找到)。以下是 Kubernetes 版本信息:
Eric:~ eric$ kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1", GitCommit:"3a1c9449a956b6026f075fa3134ff92f7d55f812", GitTreeState:"clean", BuildDate:"2018-01-04T11:52:23Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.2", GitCommit:"5fa2db2bd46ac79e5e00a4e6ed24191080aa463b", GitTreeState:"clean", BuildDate:"2018-01-18T09:42:01Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}

kube-proxy 似乎正在运行:
eric@nuc2:~$ ps waux | grep kube-proxy
root      1963  0.5  0.1  54992 37556 ?        Ssl  21:43   0:02 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf
eric      3654  0.0  0.0  14224  1028 pts/0    S+   21:52   0:00 grep --color=auto kube-proxy


Eric:~ eric$ kubectl get pods --namespace=kube-system
NAME                                      READY     STATUS    RESTARTS   AGE
calico-etcd-6vspc                         1/1       Running   3          2d
calico-kube-controllers-d669cc78f-b67rc   1/1       Running   5          3d
calico-node-526md                         2/2       Running   9          3d
calico-node-5trgt                         2/2       Running   3          2d
calico-node-r9ww4                         2/2       Running   3          2d
etcd-nuc1                                 1/1       Running   6          3d
kube-apiserver-nuc1                       1/1       Running   7          3d
kube-controller-manager-nuc1              1/1       Running   6          3d
kube-dns-6f4fd4bdf-dt5fp                  3/3       Running   12         3d
kube-proxy-8xf4r                          1/1       Running   1          2d
kube-proxy-tq4wk                          1/1       Running   4          3d
kube-proxy-wcsxt                          1/1       Running   1          2d
kube-registry-proxy-cv8x9                 1/1       Running   4          3d
kube-registry-proxy-khpdx                 1/1       Running   1          2d
kube-registry-proxy-r5qcv                 1/1       Running   1          2d
kube-registry-v0-wcs5w                    1/1       Running   2          3d
kube-scheduler-nuc1                       1/1       Running   6          3d
kubernetes-dashboard-845747bdd4-dp7gg     1/1       Running   4          3d

看来多维数据集代理正在为我的服务创建 iptables 条目:
eric@nuc1:/var/lib$ sudo iptables-save | grep hostnames
eric@nuc1:/var/lib$ sudo iptables-save | grep jira
-A KUBE-NODEPORTS -p tcp -m comment --comment "wittlesouth/jira:" -m tcp --dport 32760 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "wittlesouth/jira:" -m tcp --dport 32760 -j KUBE-SVC-MO7XZ6ASHGM5BOPI
-A KUBE-SEP-LP4GHTW6PY2HYMO6 -s 192.168.124.202/32 -m comment --comment "wittlesouth/jira:" -j KUBE-MARK-MASQ
-A KUBE-SEP-LP4GHTW6PY2HYMO6 -p tcp -m comment --comment "wittlesouth/jira:" -m tcp -j DNAT --to-destination 192.168.124.202:8082
-A KUBE-SERVICES ! -s 10.5.0.0/16 -d 10.105.148.66/32 -p tcp -m comment --comment "wittlesouth/jira: cluster IP" -m tcp --dport 8082 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.105.148.66/32 -p tcp -m comment --comment "wittlesouth/jira: cluster IP" -m tcp --dport 8082 -j KUBE-SVC-MO7XZ6ASHGM5BOPI
-A KUBE-SVC-MO7XZ6ASHGM5BOPI -m comment --comment "wittlesouth/jira:" -j KUBE-SEP-LP4GHTW6PY2HYMO6

不幸的是,此时我对 iptables 一无所知,所以我不知道这些条目是否正确。我怀疑我在 kubeadm init 期间的非默认网络设置可能与此有关,因为我试图将 Kubernetes 设置为不使用我网络的相同 IP 地址范围(基于 192.168)。我使用的 kubeadm init 语句是:
kubeadm init --pod-network-cidr=10.5.0.0/16 --apiserver-cert-extra-sans ['kubemaster.wittlesouth.com','192.168.5.10'

如果您注意到我使用的 calico 默认为 192.168.0.0 的 pod 网络池,我在创建 calico 服务时修改了 calico 的 pod 网络池设置(不确定是否相关)。

在这一点上,我得出的结论是,要么我不明白 NodePort 服务应该如何工作,要么我的集群配置有问题。任何有关下一步诊断的建议将不胜感激!

最佳答案

当你定义一个 NodePort 服务时,实际上有三个端口在起作用:

  • 容器端口:这是您的 pod 实际监听的端口,它仅在从集群内、pod 到 pod 直接访问您的容器时可用(JIRA 的默认端口为 8080)。您设置了 targetPort在您对该端口的服务中。
  • 服务端口:这是服务本身在集群内部公开的负载均衡端口。使用单个 Pod 时,没有负载平衡在起作用,但它仍然是您的服务的入口点。 port在您的服务定义中定义了这一点。如果您不指定 targetPort那么它假定 porttargetPort是相同的。
  • 节点端口:在路由到您的服务的每个工作节点上公开的端口。这是一个通常在 30000-33000 范围内的端口(取决于集群的配置方式)。这是您可以从集群外部访问的唯一端口。这是用 nodePort 定义的.

  • 假设您在标准端口上运行 JIRA,您需要一个类似于以下内容的服务定义:
    apiVersion: v1
    kind: Service
    metadata:
      name: jira
      namespace: wittlesouth
    spec:
      ports:
      - port: 80          # this is the service port, can be anything
        targetPort: 8080  # this is the container port (must match the port your pod is listening on)
        nodePort: 32000   # if you don't specify this it randomly picks an available port in your NodePort range
      selector:
        app: jira
      type: NodePort
    

    因此,如果您使用该配置,则对 NodePort 服务的传入请求将变为:NodePort (32000) -> service (80) -> pod (8080)。 (在内部,它实际上可能会绕过该服务,我对此不是 100% 确定,但您可以从概念上以这种方式考虑它)。

    您似乎还试图直接使用 HTTPS 访问 JIRA。您是否在 JIRA pod 中配置了证书?如果是这样,您需要确保它是 nuc1.wittlesouth.com 的有效证书。或告诉 curl 忽略证书验证错误 curl -k .

    关于kubernetes - NodePort 服务并非在所有节点上都可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48442485/

    相关文章:

    kubernetes - Ufw 防火墙阻止 kubernetes(使用 calico)

    dns - Kubernetes DNS/端点

    kubernetes - kube-proxy如何配置nodePort类型的服务?

    kubernetes - kube-proxy的代理模式中的userspace模式是什么意思?

    kubernetes - kube-proxy开放的端口是干什么用的,为什么会监听那么多端口?

    kubernetes - 如何更改 kube-proxy 配置?

    python - 如何访问作为输入工件传递到 argo 工作流程中的脚本模板的文件内容

    Azure 服务总线未经授权错误 : InvalidSignature: The token has an invalid signature inside Kubernetes cluster

    api - 来自 k8s 主节点的集群 IP 的连接受损/延迟

    Kubernetes kube-proxy 机制