kubernetes服务定义中targetPort和端口之间的区别

Jac*_*cob 75 service port kubernetes

我正在尝试探索kubernetes服务.当我读取服务定义时,我发现有targetPort和port在服务定义中指定.

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
Run Code Online (Sandbox Code Playgroud)

这里kubernetes服务定义中port和targetPort的区别是什么?谁有人澄清这种困惑?

jul*_*256 87

它帮助我从服务的角度思考问题。

  • nodePort:外部流量将进入的节点上的端口
  • port:这个服务的端口
  • targetPort Pod 上要将流量转发到的目标端口

流量进来nodePort,转发到port服务,然后路由到targetPortpod(s)。

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

另外值得注意的是,如果targetPort未设置,它将默认为与port. 例如80:8080针对容器端口的服务端口80

  • 很好的总结,三言两语很好地回答了问题,谢谢! (9认同)
  • 我同意,我认为这是“最佳”答案,上面的答案打开了额外的领域和更广泛的主题,使其更难理解。干杯朱兹。 (3认同)
  • 同意。我发现其他答案令人困惑,但这个答案一语中的。 (2认同)
  • 人们想知道“port”和“targetPort”之间的区别。你确实消除了困惑。 (2认同)
  • 我认为值得强调的是,目标端口是 pod 中运行的目标容器的端口。这是 @Dasharth Mundkar 回答中提到的内容 (2认同)

小智 24

如果容器侦听端口 9376,则\n targetPort : 9376

\n

如果服务侦听端口 80,则\n端口: 80

\n

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

\n
ports:\n - protocol: TCP\n   port: 80\n   targetPort: 9376\n
Run Code Online (Sandbox Code Playgroud)\n

最后,请求收到到 service\xe2\x80\x99s port,并转发到targetPortpod 的

\n


Man*_*a P 21

服务:这会将流量引导到吊舱。

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 
Run Code Online (Sandbox Code Playgroud)

如果您点击my-service:8089,则流量将路由到容器(targetPort)的8080。同样,如果您命中my-service:8443,则它将重定向到容器(targetPort)的8085。

但是,此myservice:8089是kubernetes集群的内部组件,可以在一个应用程序想要与另一个应用程序通信时使用。因此,要从群集外部访问服务,需要有人公开运行kubernetes的主机上的端口,以便将流量重定向到容器的端口。在那可以使用nodePort。

在上面的示例中,您可以通过host_ip:Nodeport从群集外部(邮递员或任何restclient)访问服务

假设您的主机IP为10.10.20.20,则可以按10.10.20.20:30475,10.10.20.20:31261,10.10.20.20:30013访问http,metrics,health services

编辑:根据Raedwald注释进行编辑。

  • 感谢您的回复。我的意思是,在什么情况下让它们有所不同会有用? (8认同)
  • 允许“port”和“targetPort”不同有什么好处?例如,看看您的“health”示例,为什么将“port”设置为“8443”而不是“8085”?基本上,为什么有两个参数而不是仅仅公开服务上的所有“targetPort”? (7认同)
  • 嗨,Dan,您可以使用 8443 作为端口和健康目标端口。为了更好的解释,我使用了不同的数字。 (3认同)

Sau*_*abh 13

由于人们已经在 Kubernetes 服务定义中进行了解释porttargetPort我将添加有关DockerfileKubernetes 部署和 Kubernetes Ingress 如何出现的信息,因为它们是通用工作流程的一部分。

第 1 部分 - 应用程序及其Dockerfile

假设您在端口 3000 上运行 Flask 服务器,在端口 4000 上运行 Golang 服务器。当您使用 Docker 容器化这些应用程序时,您必须在它们的Dockerfiles 中公开端口 3000 和 4000:

Python

应用

...
...
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=3000)
Run Code Online (Sandbox Code Playgroud)

Dockerfile

FROM python:3.10-alpine

...

...

EXPOSE 3000

CMD ...
Run Code Online (Sandbox Code Playgroud)

戈兰

应用

FROM python:3.10-alpine

...

...

EXPOSE 3000

CMD ...
Run Code Online (Sandbox Code Playgroud)

Dockerfile

FROM golang:1.18-alpine

...

...

EXPOSE 4000

CMD ...
Run Code Online (Sandbox Code Playgroud)

第 2 部分 - Dockerfiles 和 Kubernetes 部署

s中公开的端口Dockerfile必须containerPort与部署清单中的端口相匹配。

Python 部署清单

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-flask-api
spec:
...
...
      app: flask-api
  template:
    metadata:
      labels:
        app: flask-api
    spec:
      containers:
        - name: flask-api
          image: ...
          ports:
            - containerPort: 3000
...
...
Run Code Online (Sandbox Code Playgroud)

Golang 部署清单

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-backend-api
spec:
...
...
      app: go-api
  template:
    metadata:
      labels:
        app: go-api
    spec:
      containers:
        - name: go-api
          image: ...
          ports:
            - containerPort: 4000
...
...
Run Code Online (Sandbox Code Playgroud)

第 3 部分 - Kubernetes 部署和服务

部署清单中的内容containerPort必须与targetPort服务清单中的内容相匹配

Python 服务清单

apiVersion: v1
kind: Service
metadata:
  name: flask-api-service
spec:
  type: NodePort
  selector:
    app: flask-api
  ports:
    - port: 80
      targetPort: 3000
Run Code Online (Sandbox Code Playgroud)

Golang 服务清单

apiVersion: v1
kind: Service
metadata:
  name: go-api-service
spec:
  type: NodePort
  selector:
    app: go-api
  ports:
    - port: 443
      targetPort: 4000
Run Code Online (Sandbox Code Playgroud)

第 4 部分 - Kubernetes 服务和入口

服务清单port中的端口必须与number入口中的端口相匹配

适用于 Python 和 Golang 应用程序的 AWS Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservice-app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - host: foo.biz.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: go-api-service
                port:
                  number: 443
    - host: bar.biz.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: flask-api-service
                port:
                  number: 80
Run Code Online (Sandbox Code Playgroud)

流动

  • 传入请求到达端口上的入口number

  • Ingress将此请求转发给服务port

  • 服务端口映射porttargetPort

  • 请求从服务targetPort转到部署containerPort

  • 部署containerPort是应用程序的 Docker 映像,该映像在其中公开了相应的端口Dockerfile

  • 最后,暴露的端口将Dockerfile请求发送给应用程序


小智 12

@Manikanta P 上面给出的答案是正确的。然而,“端口”的解释初读时可能有点不清楚。我会用一个例子来解释:

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

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

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

网络服务器 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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

另请注意,在httpd.confWeb 服务器的文件中,我们将编写将用户请求重定向到应用服务器的 IP。该 IP 将是:host_IP:5050.

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

  • 为什么网络服务器规范定义“端口:5050”?如果我理解正确的话,网络服务器会调用 appserver:5050,而不是相反......? (4认同)

Lor*_*ord 10

情况1:

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

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

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

  1. servicePort(入口控制器)
  2. targetPort(集群IP服务)
  3. 网络端口(应用程序端口)

使一切正常工作:servicePort === targetPort === networkPort

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

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

Y服务需要以下端口

  1. ClusterIP端口,X服务将通过该端口转发请求
  2. ClusterIP targetPort,Y 服务将通过该端口确定应用程序正在运行的端口。
  3. 应用程序端口

端口 === 任意

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]);
});
Run Code Online (Sandbox Code Playgroud)

服务Y的配置和内部

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
Run Code Online (Sandbox Code Playgroud)
app.listen(4009, () => {

  console.log('Listening on 4009');
});
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Das*_*kar 8

简而言之

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

port: 容器的内部集群服务端口,侦听来自节点端口的传入请求并转发到目标端口。

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

  • 这简直是​​这里最好的解释.. (3认同)
  • 这应该是公认的答案。投票数较高的实际上令人困惑。 (2认同)

Wol*_*son 6

除了其他答案之外,这个答案是参考 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 中的端口定义有名称,您可以在targetPortService的属性中引用这些名称。即使服务中混合了使用单个配置名称的 Pod,并且通过不同的端口号使用相同的网络协议,这也能正常工作。


Vij*_*Vat 6

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

nodeport:主要用于接受消费者请求。(例如:从消费者到容器中运行的 Web 服务器的 HTTP 请求)

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

port:kubernetes pod 网络内使用的端口,主要用于在 pod 之间交换请求。在这里,来自另一个 Pod 的请求也会被路由到相应 Pod 的容器目标端口。

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