Kubernetes服务可以在服务定义中有一个targetPort和port:

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

端口和targetPort有什么区别?


当前回答

NodePort =将kubernetes服务对外公开到internet Port =将在集群中公开kubernetes服务,这样多个不同pod之间的通信就可以发生,并将请求重定向到TargetPort(因为不可能在同一个端口上运行多个pod, K8S引入了Port来处理可重用性) TargetPort =容器正在运行的实际端口

作为在docker-compose中指定的参考

ports:
  - 8080:80

从上面你可以比较8080是主机端口代表端口,80是目标端口

其他回答

服务:这将流量引导到一个豆荚。

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 

if you hit the my-service:8089 the traffic is routed to 8080 of the container(targetPort). Similarly, if you hit my-service:8443 then it is redirected to 8085 of the container(targetPort). But this myservice:8089 is internal to the kubernetes cluster and can be used when one application wants to communicate with another application. So to hit the service from outside the cluster someone needs to expose the port on the host machine on which kubernetes is running so that the traffic is redirected to a port of the container. This is node port(port exposed on the host machine). From the above example, you can hit the service from outside the cluster(Postman or any rest-client) by host_ip:nodePort

假设您的主机ip为10.10.20.20,您可以通过10.10.20.20:30475、10.10.20.20:31261、10.10.20.20:30013访问http、metrics、运行状况服务。

编辑:根据Raedwald的评论编辑。

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

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

开发者想要的:用户应该能够从外部访问web服务器,但不能从外部访问应用服务器。

解决方案:服务中的web服务器的服务类型。yml将是NodePort,而Appserver的service-type在其服务中。yml将是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文件中,我们将写入将用户请求重定向到应用服务器的IP。这个IP将是:host_IP:5050。

What exactly is happening here? A user writes hostIP:30475 and sees the Webserver's page. This is because it is being served by httpd at port 80 (targetport). When a user clicks a button, a request is made. This request is redirected to the Appserver because in httpd.conf file, the port 5050 is mentioned and this is the port where Appserver's container and Webserver's conatainer communicate internally. When the appserver receives the request, it is able to serve the request because of tomcat running inside it at port 8080.

由于人们已经在Kubernetes Service定义中解释了port和targetPort,我将添加关于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部分- Dockerfiles和Kubernetes部署

Dockerfiles中的公开端口必须与部署清单中的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服务和入口

服务清单中的端口必须与入口中的端口号匹配

适用于Python和Golang应用程序的AWS入口

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

Flow

传入请求命中端口号上的入节点 入口将此请求转发到服务端口 服务端口将该端口映射到targetPort 从服务targetPort请求到部署containerPort 部署containerPort是应用程序的Docker映像,它在Dockerfile中公开了相应的端口 最后,Dockerfile中的公开端口将请求发送给应用程序

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

nodePort:节点上外部流量进入的端口 port:该服务的端口 targetPort pod上转发流量的目标端口

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

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

另外值得注意的是,如果没有设置targetPort,它将默认为与port相同的值。例如,80:80服务端口80针对集装箱端口80。

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

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

Nodeport在所有接口上的所有节点上侦听,即0.0.0.0:Nodeport。发送到nodeport的使用者服务请求被路由到容器的targetport,以便容器能够满足该请求。

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

Summary:所有请求最终都到达targetport。如果请求来自k8s网络外部,则使用Nodeport;如果来自k8s网络内部,则使用port。