Harcoded spec.type in template api-service.yaml
FMBIoT opened this issue · 0 comments
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 }}