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

asu*_*rem 3 kubernetes kubernetes-service kubernetes-networking

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

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

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

Run Code Online (Sandbox Code Playgroud)

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

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

mar*_*rio 5

虽然LoadBalancer是无可否认的推荐解决方案(尤其是在云环境中),但值得一提的是NodePort也具有负载均衡功能

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

正如您可以在NodePort服务规范中阅读的那样:

每个节点都会将该端口(每个节点上的相同端口号)代理到您的Service.

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

因此,NodePortService 能够使用简单的循环算法将客户端请求路由到集群中的所有 pod 。

您可以使用以下内容轻松验证它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: {}
Run Code Online (Sandbox Code Playgroud)

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

kubectl scale deployment nginx-deployment --replicas=9
Run Code Online (Sandbox Code Playgroud)

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

kubectl get pods -o wide
Run Code Online (Sandbox Code Playgroud)

列出所有节点:

kubectl get nodes -o wide
Run Code Online (Sandbox Code Playgroud)

并选择要用于访问 pod 的节点的 IP 地址。

现在您可以通过运行来公开Deployment

kubectl expose deployment nginx-deployment --type NodePort --port 80 --target-port 80
Run Code Online (Sandbox Code Playgroud)

或者,如果您想自己指定端口号,例如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
Run Code Online (Sandbox Code Playgroud)

然后尝试NodePort使用先前选择的节点的 IP 来访问通过 Service 公开的 pod。您可能需要尝试正常模式和私有/隐身模式,甚至不同的浏览器(简单的刷新可能不起作用),但最终您会看到不同的请求落在不同节点上安排的 Pod 上。

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