Skip to main content

Kubernetes ReplicaSets & DaemonSets: Overview, Example ReplicaSets and DaemonSets with and without NodeSelector & Node Labeling

1365 words·
Kubernetes Kubectl ReplicaSets DaemonSets NodeSelector
Kubernetes-Components - This article is part of a series.
Part 22: This Article

Overview
#

In this tutorial I’m using the following K3s cluster with 3 worker nodes:

NAME      STATUS   ROLES                  AGE   VERSION        INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu1   Ready    control-plane,master   10d   v1.30.5+k3s1   192.168.30.10   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu2   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.11   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu3   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.12   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu4   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.13   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2

Prerequisites
#

Create Namespace
#

# Create a "example-deployment" namespace for the example deployment
kubectl create ns example-deployment

ReplicaSets
#

ReplicaSet Overview
#

  • Ensures a specified number of pod replicas are running at all times. The placement of those pods across nodes is handled by Kubernetes.

  • Pods are scheduled regarding available resources on the Kubernetes nodes. It does not matter if the pods are distributed on all nodes. Only that the right number of pods running across the cluster counts.

  • Failed pods are terminated and it will start another pod to maintain the defined number of running pods.

Note: The “restartPolicy” in a pod only affects how the individual containers in the pod behave when they exit or fail, not the behavior of the ReplicaSet itself.


Example ReplicaSet (Without Node Selection)
#

Example Deployment
#

# Create a manifest for the deployment
vi example-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
  namespace: example-deployment
  labels:
    app: some-pod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: some-pod
  template:
    metadata:
      labels:
        app: some-pod
    spec:
      containers:
        - name: busybox
          image: busybox:latest
          command: ['sh', '-c', 'tail -f /dev/null']
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
# Apply the manifest
kubectl apply -f example-deployment.yaml

Verify Deployment
#

Verify the ReplicaSet:

# List the ReplicaSets in the "example-deployment" namespace
kubectl get replicaset -n example-deployment

# Shell output:
NAME                            DESIRED   CURRENT   READY   AGE
example-deployment-7fcf97b89d   3         3         3       7s

Verify the Pods:

# List pods in the "example-deployment" namespace
kubectl get pods -o wide -n example-deployment

# Shell output:
NAME                                  READY   STATUS    RESTARTS   AGE   IP           NODE      NOMINATED NODE   READINESS GATES
example-deployment-7fcf97b89d-bph8k   1/1     Running   0          77s   10.42.3.30   ubuntu4   <none>           <none>
example-deployment-7fcf97b89d-fsl72   1/1     Running   0          77s   10.42.2.29   ubuntu3   <none>           <none>
example-deployment-7fcf97b89d-t978k   1/1     Running   0          77s   10.42.1.28   ubuntu2   <none>           <none>

Verify all Resources:

# List resources in the "example-deployment" namespace
kubectl get all -n example-deployment

# Shell output:
NAME                                      READY   STATUS    RESTARTS   AGE
pod/example-deployment-7fcf97b89d-bph8k   1/1     Running   0          2m3s
pod/example-deployment-7fcf97b89d-fsl72   1/1     Running   0          2m3s
pod/example-deployment-7fcf97b89d-t978k   1/1     Running   0          2m3s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/example-deployment   3/3     3            3           2m3s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/example-deployment-7fcf97b89d   3         3         3       2m3s

Delete the Deployment
#

# Delete the deployment
kubectl delete deployment example-deployment -n example-deployment



Example ReplicaSet (With Node Selection)
#

Label Kubernetes Nodes
#

# List Kubernetes nodes
kubectl get nodes -o wide

# Shell output:
NAME      STATUS   ROLES                  AGE   VERSION        INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu1   Ready    control-plane,master   10d   v1.30.5+k3s1   192.168.30.10   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu2   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.11   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu3   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.12   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu4   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.13   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
# Label one or more of the Kubernetes nodes
kubectl label node ubuntu2 project=app-no-1

Verify Node Labels
#

# List "monitoring-enabled" label
kubectl get nodes -o custom-columns=NAME:.metadata.name,project:.metadata.labels.project

# Shell output:
NAME      project
ubuntu1   <none>
ubuntu2   app-no-1
ubuntu3   <none>
ubuntu4   <none

Example Deployment
#

# Create a manifest for the deployment
vi example-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
  namespace: example-deployment
  labels:
    app: some-pod
spec:
  replicas: 4
  selector:
    matchLabels:
      app: some-pod
  template:
    metadata:
      labels:
        app: some-pod
    spec:
      nodeSelector:
        project: "app-no-1"
      containers:
        - name: busybox
          image: busybox:latest
          command: ['sh', '-c', 'tail -f /dev/null']
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
# Apply the manifest
kubectl apply -f example-deployment.yaml

Verify Deployment
#

# List pods in "example-deployment" namespace
kubectl get pods -o wide -n example-deployment

# Shell output:
NAME                                 READY   STATUS    RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
example-deployment-f98f569bc-hdxvd   1/1     Running   0          20s   10.42.1.7   ubuntu2   <none>           <none>
example-deployment-f98f569bc-ktms9   1/1     Running   0          20s   10.42.1.4   ubuntu2   <none>           <none>
example-deployment-f98f569bc-kv4x5   1/1     Running   0          20s   10.42.1.6   ubuntu2   <none>           <none>
example-deployment-f98f569bc-vb65n   1/1     Running   0          20s   10.42.1.5   ubuntu2   <none>           <none>

Delete the Deployment
#

# Delete the deployment
kubectl delete deployment example-deployment -n example-deployment



DaemonSets
#

DaemonSet Overview
#

  • Ensures that a copy of a pod runs on every Kubernetes node.

  • New Kubernetes nodes that join the cluster will automatically start pods that are part of a DaemonSet.

  • Kubernetes will deschedule pods of a DaemonSet when nodes are deprovisioned.

  • DaemonSets are designed to run a Pod on every Node, also in situations that would normally be prevented. DaemonSet pods will still be scheduled even if a target Node is facing resource constraints or isn’t accepting new Pods.

  • DaemonSets are often used for node monitoring and log collection agents.


Example DaemonSet (All Nodes)
#

Example Deployment
#

# Create a manifest for the deployment
vi example-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
  namespace: example-deployment
spec:
  selector:
    matchLabels:
      app: some-pod
  template:
    metadata:
      labels:
        app: some-pod
    spec:
      containers:
        - name: busybox
          image: busybox:latest
          command: ['sh', '-c', 'tail -f /dev/null']
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
# Apply the manifest
kubectl apply -f example-daemonset.yaml

Verify Deployment
#

Verify the ReplicaSet:

# List the DaemonSet in the "example-deployment" namespace
kubectl get daemonset -n example-deployment

# Shell output:
NAME                DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
example-daemonset   4         4         4       4            4           <none>          2m21s

Verify the Pods:

# List pods in the "example-deployment" namespace
kubectl get pods -o wide -n example-deployment

# Shell output:
NAME                      READY   STATUS    RESTARTS   AGE     IP           NODE      NOMINATED NODE   READINESS GATES
example-daemonset-4zhgx   1/1     Running   0          2m31s   10.42.3.31   ubuntu4   <none>           <none>
example-daemonset-lsqrr   1/1     Running   0          2m31s   10.42.0.30   ubuntu1   <none>           <none>
example-daemonset-lwzdv   1/1     Running   0          2m31s   10.42.2.30   ubuntu3   <none>           <none>
example-daemonset-tk26c   1/1     Running   0          2m31s   10.42.1.29   ubuntu2   <none>           <none>

Verify all Resources:

# List resources in the "example-deployment" namespace
kubectl get all -n example-deployment

# Shell output:
NAME                          READY   STATUS    RESTARTS   AGE
pod/example-daemonset-4zhgx   1/1     Running   0          2m45s
pod/example-daemonset-lsqrr   1/1     Running   0          2m45s
pod/example-daemonset-lwzdv   1/1     Running   0          2m45s
pod/example-daemonset-tk26c   1/1     Running   0          2m45s

NAME                               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/example-daemonset   4         4         4       4            4           <none>          2m45s

Delete DaemonSet
#

# Delete the DaemonSet
kubectl delete daemonset example-daemonset -n example-deployment

Example DaemonSet (With Node Selection)
#

Label Kubernetes Nodes
#

List the Kubernetes nodes:

# List nodes
kubectl get nodes -o wide

# Shell output:
NAME      STATUS   ROLES                  AGE   VERSION        INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu1   Ready    control-plane,master   10d   v1.30.5+k3s1   192.168.30.10   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu2   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.11   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu3   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.12   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu4   Ready    worker                 10d   v1.30.5+k3s1   192.168.30.13   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2

Label Kubernetes nodes:

# Label some of the Kubernetes nodes
kubectl label node ubuntu2 monitoring-enabled=true
kubectl label node ubuntu3 monitoring-enabled=true

Verify Node Labels:
#

# List "monitoring-enabled" label
kubectl get nodes -o custom-columns=NAME:.metadata.name,MONITORING-ENABLED:.metadata.labels.monitoring-enabled

# Shell output:
NAME      MONITORING-ENABLED
ubuntu1   <none>
ubuntu2   true
ubuntu3   true
ubuntu4   <none>

Example Deployment
#

# Create a manifest for the deployment
vi example-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
  namespace: example-deployment
spec:
  selector:
    matchLabels:
      app: some-pod
  template:
    metadata:
      labels:
        app: some-pod
    spec:
      nodeSelector:
        monitoring-enabled: "true"
      containers:
        - name: busybox
          image: busybox:latest
          command: ['sh', '-c', 'tail -f /dev/null']
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
# Apply the manifest
kubectl apply -f example-daemonset.yaml

Verify Deployment
#

Verify the ReplicaSet:

# List the DaemonSet in the "example-deployment" namespace
kubectl get daemonset -n example-deployment

# Shell output:
NAME                DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR             AGE
example-daemonset   2         2         2       2            2           monitoring-enabled=true   6s

Verify the Pods:

# List pods in the "example-deployment" namespace
kubectl get pods -o wide -n example-deployment

# Shell output:
NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE      NOMINATED NODE   READINESS GATES
example-daemonset-526v9   1/1     Running   0          18s   10.42.1.30   ubuntu2   <none>           <none>
example-daemonset-mt5q6   1/1     Running   0          18s   10.42.2.31   ubuntu3   <none>           <none>

Verify all Resources:

# List resources in the "example-deployment" namespace
kubectl get all -n example-deployment

# Shell output:
NAME                          READY   STATUS    RESTARTS   AGE
pod/example-daemonset-526v9   1/1     Running   0          37s
pod/example-daemonset-mt5q6   1/1     Running   0          37s

NAME                               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR             AGE
daemonset.apps/example-daemonset   2         2         2       2            2           monitoring-enabled=true   37s

Delete DaemonSet
#

# Delete the DaemonSet
kubectl delete daemonset example-daemonset -n example-deployment

Kubernetes-Components - This article is part of a series.
Part 22: This Article