Skip to content

Harcoded spec.type in template api-service.yaml #356

@FMBIoT

Description

@FMBIoT

Information
I was trying to install vernemq using the Helm Chart and enabling the HTTP API to allow Prometheus to collect metrics.
For development purposes, I needed to use NodePort, so I used the following values:

image:
  tag: 1.13.0
service:
  type: NodePort
  mqtt:
    enabled: 'true'
    nodePort: '31883'
  ws:
    enabled: 'true'
    nodePort: '30080'
  api:
    enabled: 'true'
additionalEnv:
- name: DOCKER_VERNEMQ_ALLOW_ANONYMOUS
  value: 'on'
- name: DOCKER_VERNEMQ_ACCEPT_EULA
  value: 'yes'
- name: DOCKER_VERNEMQ_LISTENER__MAX_CONNECTIONS
  value: '65000'

As you can see, the api is enabled and the service.type is NodePort.

Problem
After running the helm install command (helm install vernemq vernemq/vernemq -f values.yaml), an error seems to occur:
Error: INSTALLATION FAILED: Service "edb-vernemq-api" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when type is 'ClusterIP'

If I run the helm install with the flag --dry-run , the output shows the problem:

# Source: vernemq/templates/api-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: vernemq-api
  labels:
    app.kubernetes.io/name: vernemq
    helm.sh/chart: vernemq-1.9.0
    app.kubernetes.io/instance: vernemq
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 8888
      targetPort: api
      name: api
      nodePort: 38888
  selector:
    app.kubernetes.io/name: vernemq
    app.kubernetes.io/instance: vernemq

The spec.type does not change. Verifying this in the Helm template on GitHub confirms my suspicion:

spec:
  type: ClusterIP
  {{- if .Values.service.clusterIP }}
  clusterIP: {{ .Values.service.clusterIP }}
  {{- end }}
{{- if .Values.service.api.sessionAffinity }}
  sessionAffinity: {{ .Values.service.api.sessionAffinity }}
  {{- if .Values.service.api.sessionAffinityConfig }}
  sessionAffinityConfig:
    {{ toYaml .Values.service.api.sessionAffinityConfig | nindent 4 }}
  {{- end -}}
{{- end }}
  ports:
    - port: {{ .Values.service.api.port }}
      targetPort: api
      name: api
      {{- if eq .Values.service.type "NodePort" }}
      nodePort: {{ .Values.service.api.nodePort }}
      {{- end }}

The spec.type is hardcoded, while the ports have the possibility to use NodePort.

Solution

If I am not wrong, the solution is to use an if-else statement as shown in the service.yaml

{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }}
  type: ClusterIP
  {{- if .Values.service.clusterIP }}
  clusterIP: {{ .Values.service.clusterIP }}
  {{- end }}
{{- else if eq .Values.service.type "LoadBalancer" }}
  type: {{ .Values.service.type }}
  {{- if .Values.service.loadBalancerIP }}
  loadBalancerIP: {{ .Values.service.loadBalancerIP }}
  {{- end }}
  {{- if .Values.service.loadBalancerSourceRanges }}
  loadBalancerSourceRanges:
    {{ toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
  {{- end -}}
{{- else }}
  type: {{ .Values.service.type }}
{{- end }}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions