1

So, I have a really simple Flask app that I'm deploying in a Kubernetes environment using helm. Now, I have the following defined in my values.yaml:

...
service:
  type: ClusterIP
  port: 5000
  targetPort: 5000
# can add
# flaskPort: "5000"
ingress:
...

I know that I can set environment variables in my helm install command by typing helm install python-service . --values values-dev.yaml --set flaskPort=5000 and in my python code just do :

PORT = os.environ.get("flaskPort")
app.run(port=PORT, debug=True, host=0.0.0.0)

I can also define in my values-dev.yaml and in my templates/deployment.yaml entries for this environment variable flaskPort. But what about the port and targetPort entries in my values-dev.yaml? Wouldn't that clash with whatever flaskPort I set? How do I modify my chart to make sure that whatever port I specify in my helm install command, my python app is started on that port. The python app is a small mock server which responds to simple GET/POST commands.

Saturnian
  • 1,686
  • 6
  • 39
  • 65

1 Answers1

2

Each Kubernetes pod has its own IP address inside the cluster, so you don't need to worry about port conflicts. Similarly, each service has its own IP address, distinct from the pod IP addresses, plus its own DNS name, so services can use the same ports as pods or other services without conflicts.

This means that none of this needs to be configurable at all:

  • Your application can listen on whatever port is the default for its framework; for Flask that is generally port 5000. (It does need to listen on the special "all interfaces" address 0.0.0.0.)
  • The pod spec should reflect the same (fixed) port number. It can help to give it a name.
    ports:
      - name: http
        containerPort: 5000
    
  • The service can use any port it likes; for an HTTP-based service I'd recommend the default HTTP port 80. The targetPort: can be a name, which would match the name: of the corresponding pod/container port.
    type: ClusterIP
    ports:
      - name: http
        port: 80
        targetPort: http
    
  • Calls to the service from within the cluster can use plain http://svcname.nsname/ URLs, without really caring how the service is implemented, what the pod IPs are, are what ports the pods happen to be using.

At a Helm level it can make sense to make details of the service configurable; in particular if it's a NodePort or LoadBalancer service (or neither) and any of the various cloud-provider-specific annotations. You don't need to configure the pod's port details, particularly if you've written both the application and the Helm chart. For example, if you run helm create, the template service that you get doesn't allow configuring the pod's port; it's fixed in the deployment spec and available to the service under the http name.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • I think I get what you're saying. So, my application can run on port 5000 within a container - I needn't configure that. Calls to the service within the cluster can use `http://svcname.nsname:80/` since `80` is defined as the port from which this service is accessible. If I change this to, say, `5000`, calls to this service from within the cluster would be to `http://svcname.nsname:5000/`, right? – Saturnian Jan 21 '21 at 20:02
  • Also, what does `targetPort: http` mean? I can understand `targetPort:8080` as the port on which your application within your container listens to. Does it refer to the `ports.containerPort` from the pod spec? Also, it's probably frowned upon because it modifies the yamls created by `helm create` but, I could modify the pod spec as `containerPort: {{ .Values.flaskPort | quote }}` right? – Saturnian Jan 21 '21 at 20:28
  • 2
    Instead of the service's `targetPort` matching the pod's `containerPort` number, it can match the port `name`. If you really wanted to, you could make the `containerPort` configurable like that (but it's a number, so don't `quote` it into a string). – David Maze Jan 22 '21 at 01:50