我如何在 kubernetes 中使用单个服务设置对多个节点的访问?

How would I set up access to multiple Nodes with a single Service in kubernetes?

我正在尝试使用单个服务 yaml 在多个节点上设置对 Pods 的访问。 Pods 都具有相同的标签(例如,label:app),但分布在多个节点上,而不是在单个节点上。

据我所知,我可以设置一个服务来通过 NodePort 转发对 Pod 的访问,例如:

spec:
  type: NodePort
  selector:
    label: app
  ports:
    targetPort: 5000
    nodePort: 30000 

其中访问节点上的端口 30000 转发到 pod 上的端口 5000。

如果我在多个节点上有 pods,客户端是否可以访问单个端点,例如服务本身,以循环方式获得任何 pod?或者客户端是否需要访问特定节点上的一组 pods,使用该节点的 IP,如 xx.xx.xx.xx:30000?

如果您正在寻找您的应用程序服务的单一入口点并且它在云基础设施中 运行 那么您可以使用 Load balancer 服务(而不是节点端口),它将分配一个外部 IP用于您的服务,可用于从外部系统访问您的服务。

spec:
  ports:
    - name: httpsPort
      port: 443
      protocol: TCP
      targetPort: 443
  selector:
    label: app
  type: LoadBalancer

如果您在同一个集群中有多个服务需要从外部系统访问,那么您可以使用 Ingress.

谢谢 基鲁巴

虽然LoadBalancer is an undeniably recommended solution (especially in cloud environment), it's worth mentioning that NodePort也有负载均衡能力

您在特定节点上访问 NodePort 服务这一事实并不意味着您只能通过这种方式访问​​已安排在该特定节点上的 Pods

如您在 NodePort 服务 specification 中所读:

Each node proxies that port (the same port number on every Node) into your Service.

因此,通过访问一个特定节点上的端口 30080,您的请求不会直接发送到某个随机 Pod,安排在该节点上。它被代理到 Service 对象,这是一个跨越所有节点的抽象。这可能是这里的关键点,因为您的 NodePort 服务没有以任何方式绑定到您用来访问 pods.

的节点的 IP

因此 NodePort 服务能够使用简单的 循环算法 .

将客户端请求路由到集群中的所有 pods

您可以使用以下内容轻松验证它 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
      - name: init-myservice
        image: nginx:1.14.2
        command: ['sh', '-c', "echo $MY_NODE_NAME > /usr/share/nginx/html/index.html"]
        env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: cache-volume
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}

这将允许您测试您的 http 请求将发送到哪个节点。您可能还需要稍微扩展一下 Deployment 以确保使用所有节点:

kubectl scale deployment nginx-deployment --replicas=9

然后验证您的 pods 是否安排在不同的节点上:

kubectl get pods -o wide

列出您的所有节点:

kubectl get nodes -o wide

并选择您要用来访问您的 pods 的节点的 IP 地址。

现在您可以通过 运行:

公开 Deployment
kubectl expose deployment nginx-deployment --type NodePort --port 80 --target-port 80

或者如果您想自己指定端口号,例如作为 30080,应用以下 NodePort 服务定义作为 kubectl expose 不允许您指定确切的 nodePort 值:

apiVersion: v1
kind: Service
metadata:
  name: nginx-deployment
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

然后尝试使用先前选择的节点的 IP 访问通过 NodePort 服务公开的 pods。您可能需要同时尝试正常模式和 private/incognito 模式,甚至需要尝试不同的浏览器(简单的刷新可能无法正常工作),但最终您会看到不同的请求落在 pods 上,安排在不同的节点上。

请记住,如果您决定使用 NodePort,您将无法使用 众所周知的端口 。实际上它甚至可能是可行的,因为您可以使用 --service-node-port-range 选项将 kube-apiserver 配置中的默认端口范围 (30000-32767) 更改为类似 1-1024 的内容,但不推荐这样做可能会导致一些意想不到的问题。