Cluster information:
Kubernetes version: 1.21
Cloud being used: AWS EKS
Installation method: AWS EKS
Host OS: Amazon Linux 2
CNI and version: AWS VPC CNI (latest with EKS 1.21)
CRI and version: Whatever is supplied with AWS EKS 1.21 on their latest Amazon Linux 2 AMI
Greetings all.
I have a pod that I want to autoscale with the HPA, but I would like to be able to address each pod explicitly and individually via a ingress (I’m using Nginx Ingress Controller to terminate TLS and some other sugar).
It has been suggested that a stateful set is most correct here (not a deployment) because I can still use the HPA and each pod is named with an incrementing ordinal. I have a working solution where I create a service for each pod ordinal in the stateful set using statefulset.kubernetes.io/pod-name
in the service selector, and then in my ingress I have a host rule defined for each service.
This seems somewhat overly verbose to me since the stateful set is able to make StatefulSet-ORDINAL.ServiceName.Namespace
resolve to the appropriate pod using a single service rather than N (where N is the maxReplicas that the HPA might scale the stateful set up to).
Is there some way I can route traffic from my ingress to each pod individual pod in the stateful set without having to create a service for each individual pod?
This is a simplified version of the Helm template that I am using to generate my current solution:
{{- $statefulSetReplicas := .Values.autoscaling.maxReplicas }}
{{- range $e, $i := until $statefulSetReplicas }}
{{- $fullyQualifiedHostname := printf "%s-%d.%s" "myapp" $i $.Values.global.domainName }}
{{- $ordinalName := printf "%s-%d" (include "foo.fullname" .) $i }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ $ordinalName }}
labels:
{{- include "foo.labels" $ | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
{{- include "foo.selectorLabels" $ | nindent 4 }}
statefulset.kubernetes.io/pod-name: {{ $ordinalName }}
{{- end }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "foo.fullname" . }}
labels:
{{- include "foo.labels" . | nindent 4 }}
annotations:
{{- with .Values.ingress.annotations }}
{{- tpl (toYaml .) $ | nindent 4 }}
{{- end }}
spec:
ingressClassName: "nginx"
tls:
- secretName: {{ .Values.ingress.tls.secretName }}
hosts:
{{- range $e, $i := until $statefulSetReplicas }}
{{- $fullyQualifiedHostname := printf "%s-%d.%s" "myapp" $i $.Values.global.domainName }}
- {{ $fullyQualifiedHostname | quote }}
{{- end }}
rules:
{{- range $e, $i := until $statefulSetReplicas }}
{{- $fullyQualifiedHostname := printf "%s-%d.%s" "myapp" $i $.Values.global.domainName }}
{{- $ordinalName := printf "%s-%d" (include "foo.fullname" .) $i }}
- host: {{ $fullyQualifiedHostname | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $ordinalName }}
port:
name: http
{{- end }}
{{- end }}