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

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

端口和targetPort有什么区别?


当前回答

我认为形象是最好的描述。

其他回答

目标器端口说明

# pod file
apiVersion: v1
kind: Pod
metadata: 
  name: pod_name
  labels: 
     name: pod_ref
spec: 
  containers:
  - name: docker-container
    image: python:3:11
    ports: 
    - containerPort: 5000 # this is the target port which we need to access (target) from service file

---
apiVersion: v1
kind: Service
metadata: 
   name: service_config
   labels: 
     name: service_config_ref
spec:
   type: NodePort
   selector:
     name: pod_ref  # same as pod metadata match labels 
     ports:
      - targetPort: 5000 # this is where the pod is listening 
        port: 80 # this is where this service (this file) is going to listen. 
                 # If you call the port 80, it will reach the service, then the service will forward the port to port:5000


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

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

公开部署

  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:服务对外访问的端口。

希望这是答案。

案例1:

让我们假设没有nodPort或port,现在你想运行你的应用程序并将其暴露给外部,你将需要:

一个Ingress控制器,它将使用servicePort根据路由重定向到我们想要的服务。 一个集群IP服务,其中定义了到应用程序端口的目标(也称为targetPort) 用于标识计算机上运行的应用程序或服务的网络端口(换句话说就是应用程序端口)。

所以,要从外部进入,我们需要三个端口。

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

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

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

假设服务X通过使用nodePort服务暴露在外部,在收到请求后,X服务希望与Y服务通信。

Y服务需要以下端口

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

端口=== any

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');
});

由于人们已经在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:监听nodeip:nodeport上所有工作节点上的外部请求,并将请求转发到port。

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

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

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

所以流量流入——>服务——>端点(基本上有POD IP)——>POD