1

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

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

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

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

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

4

2 回答 2

2

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

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

正如您在NodePort服务规范中所读到的:

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

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

因此,Service 能够使用简单的循环算法NodePort将客户端请求路由到集群中的所有 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: {}

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

kubectl scale deployment nginx-deployment --replicas=9

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

kubectl get pods -o wide

列出所有节点:

kubectl get nodes -o wide

并选择要用于访问 pod 的节点的 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

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

请记住,如果您决定使用NodePort您将无法使用众所周知的端口。实际上,它甚至可能是可行的,因为您可以30000-32767使用选项1-1024将默认端口范围(--service-node-port-range

于 2020-08-12T17:43:39.623 回答
1

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

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

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

谢谢基鲁巴岛

于 2020-08-11T20:26:35.723 回答