I have a Deployment with 5 replicas. All have ssh and telnet. They should not be load balanced. I would like each to select from a predictable list of 5.
Here is my Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
replicas: 5
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- name: ssh
protocol: TCP
containerPort: 22
- name: telnet
protocol: TCP
containerPort: 23
This is my Service with invalid nodePort values for illustrative purposes.
apiVersion: v1
kind: Service
metadata:
name: myapp
labels:
app: myapp
spec:
type: NodePort
ports:
- name: ssh
port: 22
nodePort: [30022, 30122, 30222, 30322, 30422, 30522]
- name: telnet
port: 23
nodePort: [30023, 30123, 30223, 30323, 30423, 30523]
I am hoping to be able to accomplish 2 things:
Thank you!
Consider that the concept of "Replica" means that is going to be the same as the others; a clone.
Based on your question, you need to have unique objects, based on a template, so neither Deployment
nor StatefulSet
could help as these rely on a ReplicaSet
.
As for the StatefulSet
labels approach, I'd rather say that is more like a many-to-one relationship, meaning that the whole Service
is going to be linked to a particular pod. This means that all the ports mapped in the NodePort
service are going to serve an specific pod in the set. If my understanding is correct, you rather want a one-to-one relationship between exposed ports and pods.
Since services act like a load balancer, routing incoming requests to the exact same target (port) on each backend (replica from a deployment), the kind of uniquess that you need might be best approached having each separately, as Deployment
or StatefulSet
with their corresponding NodePort
service and mapping your ports according to your need for each case.
This approach of course has a high operational overhead but can cope with the level of uniqueness that your use case requires.
You can use a StatefulSet instead of a Deployment:
Like a Deployment, a StatefulSet manages Pods that are based on an identical container spec. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of their Pods. These pods are created from the same spec, but are not interchangeable: each has a persistent identifier that it maintains across any rescheduling.
The particularly useful feature of StatefulSets is that you will get a unique label predictably generated for each pod:
When the StatefulSet controller creates a Pod, it adds a label,
statefulset.kubernetes.io/pod-name
, that is set to the name of the Pod. This label allows you to attach a Service to a specific Pod in the StatefulSet. [source]
Then you would create five distinct Services, one for each pod, of the following form:
apiVersion: v1
kind: Service
metadata:
name: myapp-${n}
labels: { ... } # whatever you want
spec:
type: NodePort
selector:
statefulset.kubernetes.io/pod-name: myapp-${n} # assuming you keep the name
# "myapp" and just switch kind
# from Deployment to StatefulSet
ports:
- name: ssh
port: 22
nodePort: 30${n}22
- name: telnet
port: 23
nodePort: 30${n}23
replacing ${n}
with 0
through 4
.