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

问题描述

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

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

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

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

如果我在多个节点上有Pod,客户端是否可以通过这种方式访问​​单个端点,例如服务本身,以便轮流使用任何吊舱?还是客户需要使用特定节点的IP来访问特定节点上的一组Pod,例如xx.xx.xx.xx:30000

解决方法

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

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

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

谢谢 基鲁巴

,

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

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

>

您可以在NodePort服务specification中阅读:

每个节点代理该端口(每个节点上的端口号相同) 进入您的Service

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

因此,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

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

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