Dockerfile EXPOSE 和 Kubernetes 服务/容器端口之间的关系?

use*_*784 11 docker kubernetes

我对 Kubernetes 的印象是,为应用程序公开端口的方式是首先使用 Dockerfile 在 Dockerfile 中公开它EXPOSE,然后containerPort在部署 yaml 文件中设置设置,最后targetPort在服务 yaml 文件中设置。我认为这些都必须具有相同的值,例如7214

但是我刚刚注意到我的应用程序 Dockerfile 中暴露了不正确的端口7124(但在其他两个文件中具有正确的端口),如下所示:

Dockerfile

expose 7124 #This is incorrect
Run Code Online (Sandbox Code Playgroud)

部署.yaml

ports:
  - containerPort: 7214
Run Code Online (Sandbox Code Playgroud)

服务.yaml

apiVersion: v1
kind: Service
metadata:
 name: my-service
spec:
 type: NodePort
 ports:
  - port: 7214
    targetPort: 7214
Run Code Online (Sandbox Code Playgroud)

然而,我的其他应用程序运行良好,并且请求正在端口转发到应用程序,7214没有问题。

为什么这有效?我根本不需要在 Dockerfile 中公开端口吗?是containerPort优先还是什么?该用户在类似问题上的回答说暴露的端口不必匹配,但没有解释原因。

Sha*_*k V 7

进程正在侦听的端口只有进程的开发人员知道,因为端口绑定发生在代码中。EXPOSE以及containerPort与外界沟通的方式。

EXPOSEDockerfile 中的指令除了充当阅读 dockerfile 的人的文档以了解容器中的进程可能正在侦听哪个端口以及在运行命令时用于某些 UI 目的之外,不会执行任何其他操作docker ps。这就像 dockerfile 的作者和可能使用您的映像或修改您的 dockerfile 的其他人之间的通信。

即使是containerPortdeployment.yaml 中的部分也不会产生任何影响。它还充当阅读清单的人员的文档,以了解 Pod 中的进程可能正在侦听哪些端口。另一个用途是,您可以使用该字段为端口命名name,然后您可以在其他地方(例如服务对象)通过名称引用该端口。

唯一重要的是您的进程在容器中侦听的实际端口,并确保该端口在targetPort服务端口的字段中使用。


F1k*_*1ko 7

The EXPOSE option in a Dockerfile serves merely as a documentation, it is not exposing the port as stated by the official documentation:

The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.

In Kubernetes the equivalent to EXPOSE is spec.containers.ports.containerPort. You can set both values to whatever you want and it will not change anything at all. Think of it as a comment.

With a Service object it is a little bit different, there the values do matter. A Service takes spec.ports.port and spec.ports.targetPort. If you don't specify the targetPort then Kubernetes will set its value to the same as specified in port (which is required).

However, it is not necessary for targetPort and `port to be the same, in fact they do have different purposes:

  • port specifies the port of the Service
  • targetPort specifies the port of the Pod

So the general flow looks something like this:

call to <service-name>:port -> forwards to a Pod with label foo: bar -> Pod receives the call on targetPort

Here is an example:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 12345
Run Code Online (Sandbox Code Playgroud)

Resulting in:

curl my-service:80 -> forwards to a Pod with label app: MyApp -> Pod receives the request on 12345.

In your case you communicate with your Service on port 7214 and it forwards the request to the Pod also to port 7214, that's why it will continue to work no matter what you set for EXPOSE or containerPort.