Which ports are supposed to be exposed in a Helm Chart when TWO ports are exposed in the docker image?

Viewed 2108

When working with helm charts (generated by helm create <name>) and specifying a docker image in values.yaml such as the image "kubernetesui/dashboard:v2.4.0" in which the exposed ports are written as EXPOSE 8443 9090 I found it hard to know how to properly specify these ports in the actual helm chart-files and was wondering if anyone could explain a bit further on the topic.

By my understanding, the EXPOSE 8443 9090 means that hostPort "8443" maps to containerPort "9090". It in that case seems clear that service.yaml should specify the ports in a manner similar to the following:

spec:
  type: {{ .Values.service.type }}
  ports:
    - port: 8443
      targetPort: 9090

The deployment.yaml file however only comes with the field "containerPort" and no port field for the 8443 port (as you can see below) Should I add some field here in the deployment.yaml to include port 8443?

spec:
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          ports:
            - name: http
              containerPort: 9090
              protocol: TCP

As of now when I try to install the helm charts it gives me an error message: "Container image "kubernetesui/dashboard:v2.4.0" already present on machine" and I've heard that it means the ports in service.yaml are not configured to match the docker images exposed ports. I have tested this with simpler docker image which only exposes one port and just added the port everywhere and the error message goes away so it seems to be true, but I am still confused about how to do it with two exposed ports.

I would really appreciate some help, thank you in advance if you have any experience of this and is willing to share.

1 Answers

A Docker image never gets to specify any host resources it will use. If the Dockerfile has EXPOSE with two port numbers, then both ports are exposed (where "expose" means almost nothing in modern Docker). That is: this line says the container listens on both port 8443 and 9090 without requiring any specific external behavior.

In your Kubernetes Pod spec (usually nested inside a Deployment spec), you'd then generally list both ports as containerPorts:. Again, this doesn't really say anything about how a Service uses it.

# inside templates/deployment.yaml
ports:
  - name: http
    containerPort: 9090
    protocol: TCP
  - name: https
    containerPort: 8443
    protocol: TCP

Then in the corresponding Service, you'd republish either or both ports.

# inside templates/service.yaml
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: 80           # default HTTP port
      targetPort: http   # matching name: in pod, could also use 9090
    - port: 443          # default HTTP/TLS port
      targetPort: https  # matching name: in pod, could also use 8443

I've chosen to publish the unencrypted and TLS-secured ports on their "normal" HTTP ports, and to bind the service to the pod using the port names.

None of this setup is Helm-specific; in this the only Helm template reference is the Service type: (for if the operator needs to publish a NodePort or LoadBalancer service).

Related