ChatGPT解决这个技术问题 Extra ChatGPT

Kubernetes Service定义中targetPort和port的区别

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

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

porttargetPort 有什么区别?

你可以参考这个问题stackoverflow.com/questions/41963433/…

M
Manikanta P

服务:这会将流量引导到 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?基本上,为什么有两个参数而不是仅仅公开服务上的所有 targetPort
嗨,Dan,您可以使用 8443 作为端口和目标端口来保证健康。为了更好的解释,我使用了不同的数字。
感谢您的回复。我的意思是,在什么情况下使它们不同是有用的?
“在容器上运行”是什么意思?容器内的服务器使用的端口?还是容器外的客户端使用的端口?
我们可以为云服务中的主机(如 10.10.20.20)假设一个固定 IP 吗?例如,具有多节点部署情况的 Azure AKS?
j
julz256

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

nodePort:节点上将进入外部流量的端口

端口:此服务的端口

targetPort 将流量转发到的 Pod 上的目标端口

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

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

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


D
Dashrath Mundkar

简而言之

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

ClusterIP: 请求来自入口并指向服务名称和端口。

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

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

因此流量流向 Ingress-->Service-->Endpoint(Basically has POD IP)-->POD


这只是这里最好的解释..
这应该是公认的答案。更多赞成的实际上是令人困惑的。
W
Wolfson

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

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

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

解决方案:service.yml中Webserver的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.

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 并看到 Web 服务器的页面。这是因为它是由 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 服务。如果我错了,请纠正我。
u
user3651946

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

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

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

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

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


超级简洁,但这实际上帮助我理解了两者之间的区别
迄今为止最短,但令人惊讶的是最有帮助的解释。
W
Wolfson

除了其他答案之外,此答案还参考了 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 混合使用单个配置名称,也可以通过不同的端口号使用相同的网络协议,这仍然有效。


感谢您的简洁回答
R
Rafiq

情况1:

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

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

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

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

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

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

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

Y服务需要以下端口

ClusterIP 端口,X 服务将通过该端口转发请求 一个 ClusterIP targetPort,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]);
});

服务 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
app.listen(4009, () => {

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

https://i.stack.imgur.com/2bVEz.png


S
Saurabh

由于人们已经在 Kubernetes 服务定义中解释了 porttargetPort,我将添加有关 Dockerfile、Kubernetes Deployment 和 Kubernetes Ingress 的信息,因为它们是通用工作流程的一部分。

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

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

Python

应用

...
...
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=3000)

Dockerfile

FROM python:3.10-alpine

...

...

EXPOSE 3000

CMD ...

戈朗

应用

...
...
func main() {
    ...
    log.Fatal(http.ListenAndServe(":4000", nil))
}

Dockerfile

FROM golang:1.18-alpine

...

...

EXPOSE 4000

CMD ...

第 2 部分 - Dockerfile 和 Kubernetes 部署

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
...
...

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
...
...

第 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

Golang 服务清单

apiVersion: v1
kind: Service
metadata:
  name: go-api-service
spec:
  type: NodePort
  selector:
    app: go-api
  ports:
    - port: 443
      targetPort: 4000

第 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

流动

传入请求在端口号上命中入口

入口将此请求转发到服务端口

服务端口将端口映射到目标端口

从服务 targetPort 请求转到部署 containerPort

部署 containerPort 是应用程序的 Docker 镜像,它的 Dockerfile 中暴露了这个对应的端口

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


V
Vijayendar Gururaja

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

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

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

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

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


m
manoj

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

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

暴露部署

  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 :是使服务能够从外部访问的端口。

希望这个答案。


G
Gupta

我认为图像描述的最好。

https://i.stack.imgur.com/O9e5U.png