How to get a service's NodePort and external IP in a Helm chart template?

2/5/2021

My Helm chart (run by Rancher pipeline)'s structure is:

charts/web/0.3.0/templates
  deployment.yaml
  service.yaml
  ingress.yaml
  webinspect-runner.yaml

The deployment.yaml deploys a web server (say flask-restful or django), and I set a service to it:

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "web.name" . }}-svc
  labels:
    {{- include "iiidevops.labels" . | nindent 4 }}
spec:
  type: NodePort
  selector:
    app: {{ include "web.name" . }}
  ports:
      - port: {{ .Values.web.port }}
        protocol: TCP

And I want to create a web scan (by webinspect) service to scan it, so I write this:

webinspect-runner.yaml

apiVersion: batch/v1
kind: Job
metadata:
  annotations:
    "helm.sh/hook": post-install,post-upgrade,post-rollback
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
  name: "{{ .Release.Name }}-webinspect-{{ .Values.pipeline.sequence }}"
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}-webinspect-{{ .Values.pipeline.sequence }}"
      labels:
        {{- include "iiidevops.labels" . | nindent 8 }}
    spec:
      containers:
        - name: "webinspect-runner-{{ .Values.pipeline.sequence }}"
          image: "{{ .Values.harbor.host }}/{{ .Values.harbor.cache }}/iiiorg/webinspect-runner:{{ .Values.webinspect.runnerVersion }}"
          command: ['sh', '-c', 'cd /usr/src/app; node /usr/src/app/app.js;']
          env:
            - name: inspect_url
              value: http://{{ .Release.Name }}.{{ .Values.ingress.externalHost }}{{ .Values.webinspect.startPath }}
...
   restartPolicy: Never
  backoffLimit: 4

The point is inspect_url env. I now use an external domain and ingress to redirect it, but it requires a domain name.

Since kubectl can get the service's IP and port like http://10.50.40.99:32147, can I also write something to let inspect_url also become http://10.50.40.99:32147?

-- Romulus Urakagi Ts'ai
kubernetes
kubernetes-helm

1 Answer

2/5/2021

I'm not sure if you need the scan to be external or if you are okay with an internal scan as well, but either way, you could obtain IP and port by manually requesting them at creation time.

If it is okay to use internal IP and port:

First, for the ClusterIP assigned to a service, it is possible to manually require it (https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address)

You just need to specify the .spec.clusterIP field of the Service resource.

Second, for the port you can just use the internal one, the one that you define with:

- port: {{ .Values.web.port }}

If you want to scan it externally at the NodePort port:

First, you can scan the service at whichever node of the cluster, since the NodePort service will expose the communication on all nodes IP Addresses. For the IP you can then just choose one of the cluster's nodes address.

Instead, for the external port, you can specify it manually, simply by adding the optional field:

# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: your_port_here

in the Service declaration.

-- AndD
Source: StackOverflow