Following are the example which I encountered on k8s website.
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
selector: run: my-nginx Not able to figure out what is the rationale behind labeling it in spec and then applying same selector on the spec definition.Found plenty of example but no explanation for them.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
selector:
matchLabels:
run: load-balancer-example
replicas: 2
template:
metadata:
labels:
run: load-balancer-example
spec:
containers:
- name: hello-world
image: gcr.io/google-samples/node-hello:1.0
ports:
- containerPort: 8080
protocol: TCP
** selector:
matchLabels:
run: load-balancer-example**
Labels are there to group resources. Label selectors are there to target these grouped resources.
Depending on the resource, labels are used for one purpose or another. Deployments
use labels to know what pods are their children (no label selectors are involved here), Services
use labels to forward traffic to the backends (Pods
). Network Policies use labels to allow or deny traffic, etc.
Why using labels? The most clear example is with services. Pods die all the time. When they are re-created, they have a different IP address. You can't rely on the IP address of a Pod, as it can change at any moment. So you create a service and target a group of pods, according their labels. Services don't die, unless you delete them. A pod that has been re-created with a different IP address has the same labels, so the service gets the new IP address of the pod as possible endpoint, and the traffic can still flow.
This is one of the fundamental design concepts of Kubernetes:
Resources are linked by labels and selectors.
Resources such as a Service or Deployment that must refer to other resources have a selector which defines a set of labels. These resources select all those resources (of a specific type) that have labels matching this selector.
For example, a Deployment with a selector of a=b
refers to all Pods that happen to have the label a=b
.
That's why in your Deployment specification, you have to define the same label (run=load-balancer-example
) in the Pod template (template
section) as in the selector of the Deployment. Because you want the Deployment to manage these Pods:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
selector:
matchLabels:
run: load-balancer-example # <<<<<----- must match
replicas: 2
template: # <- you define a template for the Pods that will be created here
metadata:
labels:
run: load-balancer-example # <<<<------ must match
spec:
containers:
- name: hello-world
image: gcr.io/google-samples/node-hello:1.0
ports:
- containerPort: 8080
protocol: TCP
If you have any other Pods with the run=load-balancer-example
, the Deployment will manage these too. On the other hand, if the labels in the Pod template of the Deployment specification were different from the selector, the Deployment wouldn't manage these Pods because their labels don't match the selector of the Deployment.
In your first example, the label definitions within the Service specification are unrelated. The first one (labels
) is the label of the Service (you could omit it, if you want), the second one (selector
) is the selector of the Service:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx # <<<<<---- unrelated to the other 'run: my-nginx'
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx # <<<<<---- unrelated to the other 'run: my-nginx'
However, the selector is related to the labels of any Pods. In particular, this Service will apply to all Pods that have the run=my-nginx
label.