在Kubernetes中,您为应用程序公开端口的方式是首先使用EXPOSE
在Dockerfile中公开它,然后在部署yaml文件中设置containerPort
设置,最后在服务yaml文件中设置targetPort
。我认为这些都必须是相同的值,例如7214
。
然而,我刚刚注意到,我有一个不正确的端口暴露在我的应用程序Dockerfile作为7124
(但有正确的端口在其他两个文件),像这样:
Dockerfile
expose 7124 #This is incorrect
Deployment.yaml
ports:
- containerPort: 7214
Service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
ports:
- port: 7214
targetPort: 7214
然而,我的其他应用程序都很好地击中了服务,请求被转发到端口7214
的应用程序,没有问题。
为什么这个工作?我不需要在Dockerfile中暴露端口吗?containerPort
优先还是什么?这个用户回答了一个类似的问题,说暴露的端口不必匹配,但没有解释为什么。
当端口绑定在代码中发生时,进程正在侦听的端口只有该进程的开发人员知道。EXPOSE
和containerPort
是与外界沟通的方式。
EXPOSE
指令在Dockerfile中不做任何事情,除了作为文档的人阅读你的Dockerfile,以了解容器中的进程可能正在监听哪个端口,并为一些UI目的,当你运行docker ps
命令。这就像dockerfile的作者和另一个可能正在使用您的图像或修改您的dockerfile的人之间的通信。
甚至是部署中的containerPort
部分。Yaml对任何东西都没有影响。它还可以作为文档,让读取您的清单的人员了解您的进程在pod中的哪些端口可能正在侦听。另一种用法是,您可以使用name
字段为端口指定一个名称,然后您可以在其他地方(如服务对象)通过名称引用该端口。
唯一重要的是您的进程在容器中侦听的实际端口,并确保端口在服务端口的targetPort
字段中使用。
Dockerfile中的EXPOSE
选项仅作为文档,它是不暴露官方文档中规定的端口:
EXPOSE指令实际上并不发布端口。它的作用是在构建映像的人和运行容器的人之间作为一种文档,关于打算发布哪些端口。
在Kubernetes中,相当于EXPOSE
的是spec.containers.ports.containerPort
。您可以将这两个值设置为您想要的任何值,这根本不会改变任何东西。就当是评论吧
对于Service
对象,这有点不同,值确实很重要。Service
包含spec.ports.port
和spec.ports.targetPort
。如果你没有指定targetPort
,那么Kubernetes会将其值设置为与port
中指定的值相同(这是必需的)。
然而,targetPort
和' port不一定是相同的,事实上它们确实有不同的用途:
port
指定Service
的端口targetPort
指定Pod
的端口
一般流程是这样的:
call to <service-name>:port
->转发到标签为foo: bar
->Pod在targetPort
上接收呼叫
下面是一个例子:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 12345
导致:
curl my-service:80
->转发到标签为app: MyApp
->Pod在12345
上收到请求。
在您的情况下,您在端口7214
上与您的服务通信,它将请求转发到Pod也转发到端口7214
,这就是为什么无论您为EXPOSE
或containerPort
设置什么,它都将继续工作。