A Kubernetes Developer Quick Guide to Tricky Manifests. Part 1: Selectors and Labels

Isidro Hernandez
The Startup
Published in
3 min readApr 25, 2020

While working with Kubernetes you were undoubtedly impressed by the flexibility and scalability of this orchestration platform. You probably by now created a few pods, services, and tinkered with Nginx enough to feel dangerous.

As I was preparing for my CKAD exam I spent a lot of time comparing manifests and noticing the subtle differences for each resource. I’m not going to cover all of the nuances of the API or kubectl. What I will cover are the core resource manifests and their quirks.

Have you ever wondered why you can’t mount a volume? You spent hundreds of seconds reviewing the error message and another hundred seconds to look up the API documentation and update your YAML file. I hope to simplify those hiccups for you and me both.

How do deployments select other resources(pods or replica sets)?

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels: # the deployment itself has a label here
app: nginx
spec:
replicas: 3
selector: # this selector will apply to any pod with the matching labels.
matchLabels:
app: nginx
template: # this is starting to configure the pods within
metadata: # they have to have their own labels defined here.
labels:
app: nginx
spec:
containers:
— name: nginx
image: nginx:1.14.2
ports:
— containerPort: 80

Selector

deployment.spec.selector.matchLabelsLabel selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment.

This defines the label selector for any pods or ReplicaSets with the matching labels.

If you need to tag your pods within your Deployment then you would do that here(within yaml manifest):

deployment.spec.template.metadata.labels

How do you apply a service resource to a deployment, pod, or ReplicaSet?

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector: # Notice that here we only use 'selector'
app: MyApp
ports:
— protocol: TCP
port: 80
targetPort: 9376

It's important to notice that when creating a service object that other resources are going to consume that the label declaration is a bit different than in Deployments. Here we will only require that we define the labels using:

service.spec.selector

In this example, the app=MyApp label will be used as a selector. It's easy to get these first two resource objects confused.

How can we label a pod so that Selectors from other object resources can find it?

apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels: # this is very is to do. labels are nested under metadata.
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

A simple label can be defined inside:

pod.metadata.labels

To add a quick label with kubectl:

kubectl label pod $PODNAME key=value

Test this with:

kubectl get pods -l key=value

How can we apply a NetworkPolicy to a resource?

A NetworkPolicy can be hard to remember. They aren't using the same rules we observed above. Let's take a look at the API reference using:

$ kubectl explain networkpolicy.specpodSelector <Object> -required-
Selects the pods to which this NetworkPolicy object applies. The array of ingress rules is applied to any pods selected by this field. Multiple network policies can select the same set of pods. In this case, the ingress rules for each are combined additively. This field is NOT optional and follows standard label selector semantics. An empty podSelector matches all pods in this namespace.

We find that in order to implement a NetworkPolicy we will need to define a PodSelector YAML object. Let's see what a sample YAML manifest looks like for this resource:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db

Now we can see that this manifest is asking for something slightly different with the same principles in mind. We now know where to define the selector labels in this manifest:

networkpolicy.spec.podSelector.matchLabels

This concludes Part 1.

--

--