Kubernetes服务可以在服务定义中有一个targetPort和port:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
端口和targetPort有什么区别?
Kubernetes服务可以在服务定义中有一个targetPort和port:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
端口和targetPort有什么区别?
当前回答
它帮助我从服务的角度考虑问题。
nodePort:节点上外部流量进入的端口 port:该服务的端口 targetPort pod上转发流量的目标端口
流量从nodePort进入,转发到服务上的port,然后路由到pod上的targetPort。
值得强调的是,nodePort用于外部流量。集群中其他可能需要访问服务的pod将只使用port,而不是nodePort,因为它只在内部访问服务。
另外值得注意的是,如果没有设置targetPort,它将默认为与port相同的值。例如,80:80服务端口80针对集装箱端口80。
其他回答
案例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');
});
如果容器监听端口9376,那么 发送:9376
如果服务在端口80上侦听,则 端口:80
然后服务端口配置如下所示
ports:
- protocol: TCP
port: 80
targetPort: 9376
最后,请求接收到服务的端口,并在pod的targetPort上转发。
NodePort =将kubernetes服务对外公开到internet Port =将在集群中公开kubernetes服务,这样多个不同pod之间的通信就可以发生,并将请求重定向到TargetPort(因为不可能在同一个端口上运行多个pod, K8S引入了Port来处理可重用性) TargetPort =容器正在运行的实际端口
作为在docker-compose中指定的参考
ports:
- 8080:80
从上面你可以比较8080是主机端口代表端口,80是目标端口
由于人们已经在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中的公开端口将请求发送给应用程序
这个答案是参考Kubernetes的文档以及其他答案:
https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/:
targetPort:容器接收流量的端口,
port:是抽象的服务端口,它可以是其他pod用来访问服务的任何端口
https://kubernetes.io/docs/concepts/services-networking/service/:
Pods中的端口定义有名称,您可以在服务的targetPort属性中引用这些名称。即使服务中有使用单一配置名称的pod的混合物,通过不同的端口号使用相同的网络协议,这种方法也有效。