Kubernetes Service定义中targetPort和port的区别

Posted

技术标签:

【中文标题】Kubernetes Service定义中targetPort和port的区别【英文标题】:Difference between targetPort and port in Kubernetes Service definition 【发布时间】:2018-10-03 12:42:53 【问题描述】:

Kubernetes Service 可以在服务定义中包含targetPortport

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

porttargetPort 有什么区别?

【问题讨论】:

这个问题可以参考***.com/questions/41963433/… 【参考方案1】:

targetport:容器在 pod 中侦听的一个或多个端口。

nodeport:主要用于接受消费者请求。 (例如:消费者向容器中运行的网络服务器发出的 HTTP 请求)

nodeport 在所有接口上的所有节点上被监听,即 0.0.0.0:nodeport。发送到 nodeport 的消费者服务请求被路由到容器的目标端口,以便容器可以满足请求。

端口:kubernetes pod 网络中使用的端口,主要用于在 pod 之间交换请求。同样,来自另一个 pod 的请求被路由到相应 pod 的容器目标端口。

摘要:所有请求最终都在目标端口。如果来自外部 k8s 网络的请求,则使用 nodeport,如果来自内部,则使用 port

【讨论】:

【参考方案2】:

这个答案是给绝对初学者的:

案例 1:

假设没有 nodPort 或端口,现在你想运行你的应用程序并将它暴露给外部,你需要什么:

    一个 Ingress 控制器,它将使用 servicePort 根据路由重定向到我们所需的服务。 一个集群 IP 服务,它为您的应用程序端口(也称为 targetPort)定义了目标 用于标识计算机上运行的应用程序或服务的网络端口(即应用程序端口)。

所以,为了从外部访问,我们发现需要三个端口。

    servicePort(入口控制器) targetPort(集群 IP 服务) networkPort(应用程序端口)

正常工作: servicePort === targetPort === networkPort

案例 2: 现在假设一个服务与我们集群中的另一个服务进行通信,或者假设一个服务接收到来自外部的请求并发出一个事件,该事件触发了我们集群内的另一个服务。

假设服务X通过nodePort服务暴露在外面,在收到请求后,X服务想与Y服务通信。

Y 服务需要以下端口

    一个 ClusterIP 端口,X 服务将通过该端口转发请求 一个 ClusterIP 目标端口,Y 服务将通过该端口确定应用程序在哪个端口中运行。 应用程序端口

端口 === 任何

targetPort === 应用程序端口

在服务 X 内部:

app.post('/posts/create', async (req, res) => 
  const id = randomBytes(4).toString('hex');
  const  title  = req.body;

  posts[id] = 
    id,
    title
  ;

  await axios.post('http://event-bus-srv:4010/events', 
    type: 'PostCreated',
    data: 
      id,
      title
    
  );

  res.status(201).send(posts[id]);
);

服务内部配置和内部

apiVersion: v1
kind: Service
metadata:
  name: event-bus-srv
spec:
  selector:
    app: event-bus
  type: ClusterIP
  ports:
    - name: event-bus
      protocol: TCP
      port: 4010
      targetPort: 4009
app.listen(4009, () => 

  console.log('Listening on 4009');
);

【讨论】:

【参考方案3】:

除了其他答案之外,此答案是参考 Kubernetes 的文档:

https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/:

targetPort: 是容器接受流量的端口,

port:是抽象出来的Service端口,可以是其他Pod访问Service的任意端口

https://kubernetes.io/docs/concepts/services-networking/service/:

Pod 中的端口定义具有名称,您可以在 Service 的 targetPort 属性中引用这些名称。即使 Service 中的 Pod 混合使用一个配置名称,也可以通过不同的端口号使用相同的网络协议。

【讨论】:

感谢您的简洁回答【参考方案4】:

这有助于我从服务的角度思考问题。

nodePort:节点上外部流量将进入的端口 port: 此服务的端口 targetPort pod(s) 上用于转发流量的目标端口

流量从nodePort 进入,转发到服务上的port,然后路由到吊舱上的targetPort

值得更多强调的是nodePort 是针对外部流量的。集群中可能需要访问该服务的其他 pod 将只使用 port,而不是 nodePort,因为它只能在内部访问该服务。

另外值得注意的是,如果没有设置targetPort,它将默认为与port相同的值。例如。 80:80 服务端口80 目标容器端口80

【讨论】:

【参考方案5】:

如果容器监听 9376 端口,那么 目标端口:9376

如果服务在端口 80 上侦听,则 端口:80

然后服务端口配置如下所示

ports:
 - protocol: TCP
   port: 80
   targetPort: 9376

最后,请求接收到服务的port,并在pod的targetPort上转发。

【讨论】:

超级简洁,但这实际上帮助我理解了两者之间的区别【参考方案6】:

简而言之

nodeport: 在 nodeip:port 上的所有工作节点上监听外部请求并将请求转发到端口。

port:容器内部集群服务端口,监听来自nodeport的请求并转发到targetPort。

targetPort: 从端口接收请求并转发到它正在侦听的容器 pod(port)。即使您没有指定,默认情况下也会分配与端口相同的端口号。

【讨论】:

这只是这里最好的解释.. 这应该是公认的答案。更多的投票实际上是令人困惑的。【参考方案7】:

“目标端口”是运行容器的端口。

端口:端口将流量从服务重定向到容器。

公开部署

  master $ kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE

nginx        1/1     1            1           31s
master $ kubectl expose deployment nginx --name=nginx-svc --port=8080 --target-port=80
service/nginx-svc exposed

master $ kubectl get svc

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

nginx-svc    ClusterIP   10.107.209.151   <none>        8080/TCP   5s

NodePort : 是服务对外访问的端口。

希望这个答案。

【讨论】:

【参考方案8】:

@Manikanta P 上面给出的答案是正确的。但是,初读时对“端口”的解释可能有点不清楚。我将举例说明:

考虑一个 Web 应用程序,其静态内容(首页、图像等)由 httpd 托管,动态内容(例如,对请求的响应等)由 tomcat 托管。 Webserver(或静态内容)由 httpd 在端口 80 提供服务,而 Appserver(或动态内容)由 tomcat 在端口 8080 提供服务。

开发人员想要什么:用户应该能够从外部访问 Web 服务器,但不能从外部访问 Appserver。

解决方案:webserver在service.yml中的service-type为NodePort,而Appserver在service.yml中的service-type为ClusterIP。

webserver 的 service.yml 代码:

spec:
  selector:
    app: Webserver
  type: NodePort        // written to make this service accessible from outside.
  ports:
    - nodePort: 30475   // To access from outside, type <host_IP>:30475 in browser.
      port: 5050        // (ignore for now, I will explain below).
      protocol: TCP
      targetPort: 80  // port where httpd runs inside the webserver pod.

Appserver 的 service.yml 代码

spec:
  selector:
    app: appserver
  type: ClusterIP        // written to make this service NOT accessible from outside.
  ports:
    - port: 5050         // port to access this container internally
      protocol: TCP
      targetPort: 8080   // port where tomcat runs inside the appserver pod.

另外请注意,在Webserver 的httpd.conf 文件中,我们将写入将用户请求重定向到appserver 的IP。此 IP 将是:host_IP:5050

这里到底发生了什么? 用户写hostIP:30475 并看到网络服务器的页面。这是因为它由 httpd 在端口 80 (targetport) 提供服务。当用户单击按钮时,会发出请求。此请求被重定向到 Appserver,因为在 httpd.conf 文件中,提到了端口 5050,这是 Appserver 的容器和 Webserver 的容器内部通信的端口。当应用服务器收到请求时,它能够为请求提供服务,因为它在端口8080 上运行了tomcat。

【讨论】:

为什么网络服务器规范定义“端口:5050”?如果我理解正确,网络服务器调用 appserver:5050,而不是相反......? 除了埃弗顿的问题,如果Tomcat服务于5050端口的内部请求,它需要开放8080端口有什么意义? 这个答案令人困惑。另外“因为在httpd.conf文件中提到了5050端口”中httpd.conf在哪里 @Polymerase httpd.conf 文件随您在系统上安装的 httpd 软件包一起提供。这是您必须配置的内部文件。路径:/etc/httpd/conf/http.conf @Stephen 在 tomcat/conf/server.xml 中,我们指定了 tomcat 服务将运行的端口。这与我们写为目标端口的端口号相同,以便 kubernetes 了解它必须在该端口上启动 tomcat 服务。如果我错了,请纠正我。【参考方案9】:

服务:这会将流量导向一个 pod。

TargetPort: 这是您的应用程序在容器内运行的实际端口。

端口: 有时,容器内的应用程序在不同的端口上提供不同的服务。

示例: 实际应用程序可以运行8080,并且此应用程序的健康检查可以在容器的8089 端口上运行。 因此,如果您在没有端口的情况下访问服务,它不知道应该将请求重定向到容器的哪个端口。服务需要有一个映射,以便它可以访问容器的特定端口。

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      nodePort: 30475
      port: 8089
      protocol: TCP
      targetPort: 8080
    - name: metrics
      nodePort: 31261
      port: 5555
      protocol: TCP
      targetPort: 5555
    - name: health
      nodePort: 30013
      port: 8443
      protocol: TCP
      targetPort: 8085 

如果您点击my-service:8089,流量将被路由到容器(targetPort)的8080。同样,如果您点击my-service:8443,那么它会被重定向到容器(targetPort)的8085。但是这个myservice:8089 是kubernetes 集群内部的,可以在一个应用程序想要与另一个应用程序通信时使用。因此,要从集群外部访问服务,需要在运行 kubernetes 的主机上公开端口 以便将流量重定向到容器的端口。这是node port(主机上暴露的端口)。 从上面的例子中,您可以通过host_ip:nodePort从集群外部(邮递员或任何休息客户端)访问服务

假设你的主机 ip 是10.10.20.20,你可以通过10.10.20.20:3047510.10.20.20:3126110.10.20.20:30013 访问http、metrics、health services。

编辑:根据Raedwald 评论编辑。

【讨论】:

允许porttargetPort 不同有什么好处?因此,例如查看您的health 示例,为什么要使用port 8443 而不是8085?基本上,为什么有两个参数而不是仅仅暴露服务上的所有targetPorts? 嗨,Dan,您可以使用 8443 作为端口和目标端口以确保健康。为了更好地解释,我使用了不同的数字。 感谢您的回复。我的意思是,在什么情况下让它们不同会有用? “在容器上运行”是什么意思?服务器内部容器使用的端口?或者客户端外部容器使用的端口? 我们可以为云服务中的主机(如 10.10.20.20)假设一个固定 IP 吗?例如,具有多节点部署情况的 Azure AKS?

以上是关于Kubernetes Service定义中targetPort和port的区别的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes——Service(SVC)服务

4.Kubernetes权威指南 --- 深入掌握Service

4.Kubernetes权威指南 --- 深入掌握Service

Kubernetes NodePort 自定义端口

云原生 | 从零开始学Kubernetes十八Kubernetes核心技术Service实战

Kubernetes笔记