2023-02-07 12:19:01 +11:00
..
2021-05-02 12:53:19 +10:00
2021-05-02 12:53:19 +10:00
2021-05-02 12:53:19 +10:00
2021-05-02 12:53:19 +10:00
2023-02-07 12:19:01 +11:00

Kubernetes Daemonsets

k8s-daemonset

We need a Kubernetes cluster

Lets create a Kubernetes cluster to play with using kind
Because a Daemonset is all about running pods on every node, lets create a 3 node cluster:

cd kubernetes/daemonsets
kind create cluster --name daemonsets --image kindest/node:v1.20.2 --config kind.yaml

Test our cluster:

kubectl get nodes
NAME                       STATUS     ROLES                  AGE   VERSION
daemonsets-control-plane   Ready      control-plane,master   65s   v1.20.2
daemonsets-worker          Ready      <none>                 31s   v1.20.2
daemonsets-worker2         Ready      <none>                 31s   v1.20.2
daemonsets-worker3         NotReady   <none>                 31s   v1.20.2

Introduction

Kubernetes provide documentation for what a Daemonset is with examples.

Basic Daemonset

Let's deploy a daemonset that runs a pod on each node and collects the name of the node

kubectl apply -f daemonset.yaml

kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP           NODE                       NOMINATED NODE   READINESS GATES
example-daemonset-8lcr5   1/1     Running   0          3m21s   10.244.2.4   daemonsets-worker          <none>           <none>
example-daemonset-9jhgx   1/1     Running   0          81s     10.244.3.4   daemonsets-worker2         <none>           <none>
example-daemonset-lvvsd   1/1     Running   0          2m41s   10.244.1.4   daemonsets-worker3         <none>           <none>
example-daemonset-xxcv9   1/1     Running   0          119s    10.244.0.7   daemonsets-control-plane   <none>           <none>

We can see the logs of any pod

kubectl logs <example-daemonset-xxxx>

Cleanup:

kubectl delete ds example-daemonset

Basic Daemonset: Exposing HTTP

Let's deploy a daemonset that runs a pod on each node and exposes an HTTP endpoint on each node.
In this demo we'll use a simple NGINX on port 80

kubectl apply -f daemonset-communication.yaml
kubectl get pods

Communicating with Daemonset Pods

https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#communicating-with-daemon-pods

Let's deploy a pod that can talk to our daemonset

kubectl apply -f pod.yaml

kubectl exec -it pod -- bash

Service Type: ClusterIP or LoadBalancer

Let's deploy a service of type ClusterIP

kubectl apply -f ./services/clusterip-service.yaml

while true; do curl http://daemonset-svc-clusterip; sleep 1s; done
Hello from daemonsets-worker2
Hello from daemonsets-control-plane
Hello from daemonsets-worker2
Hello from daemonsets-worker3
Hello from daemonsets-worker
Hello from daemonsets-worker

Node IP and Node Port

We can add the nodePort field to the pods port section to expose a port on the node.

Let's expose the node port in the pod spec:

ports:
- containerPort: 80
  hostPort: 80
  name: "http"

This means we can contact the daemonset pod using the Node IP and port:

# get the node ips
kubectl get nodes -owide

NAME                       STATUS   ROLES                  AGE    VERSION   INTERNAL-IP   EXTERNAL-IP       KERNEL-VERSION                CONTAINER-RUNTIME
daemonsets-control-plane   Ready    control-plane,master   112m   v1.20.2   172.18.0.4    <none>
daemonsets-worker          Ready    <none>                 111m   v1.20.2   172.18.0.3    <none>
daemonsets-worker2         Ready    <none>                 111m   v1.20.2   172.18.0.2    <none>
daemonsets-worker3         Ready    <none>                 111m   v1.20.2   172.18.0.6    <none>

#example:

bash-5.1# curl http://172.18.0.4:80
Hello from daemonsets-control-plane
bash-5.1# curl http://172.18.0.2:80
Hello from daemonsets-worker2

Service: Headless service

Let's deploy a headless service where clusterIP: None

kubectl apply -f ./services/headless-service.yaml

There are a few ways to discover our pods:

  1. Discover the DNS records via the "Headless" services
apk add --no-cache bind-tools
dig daemonset-svc-headless.default.svc.cluster.local

Notice it resolves to multiple DNS records for each pod:


;; ANSWER SECTION:
daemonset-svc-headless.default.svc.cluster.local. 30 IN A 10.244.0.5
daemonset-svc-headless.default.svc.cluster.local. 30 IN A 10.244.2.2
daemonset-svc-headless.default.svc.cluster.local. 30 IN A 10.244.3.2
daemonset-svc-headless.default.svc.cluster.local. 30 IN A 10.244.1.2
  1. Discover pods endpoints by retrieving the endpoints for the headless service
kubectl describe endpoints daemonset-svc-headless

Example:

Addresses:          10.244.0.5,10.244.1.2,10.244.2.2,10.244.3.2

Get A records for each pod by using the following format:

<pod-ip-address>.<my-namespace>.pod.<cluster-domain.example>.

#examples:

10-244-0-5.default.pod.cluster.local
10-244-1-2.default.pod.cluster.local
10-244-2-2.default.pod.cluster.local
10-244-3-2.default.pod.cluster.local

Communicate with the pods over DNS:

curl http://10-244-0-5.default.pod.cluster.local
Hello from daemonsets-control-plane

Real world Examples:

Monitoring Nodes: Node-Exporter Daemonset


We clone the official kube-prometheus repo to get monitoring manifests for Kubernetes.
git clone https://github.com/prometheus-operator/kube-prometheus.git

Check the compatibility matrix here

For this demo, we will use the compatible version tag 0.8

git checkout v0.8.0

Deploy Prometheus Operator and CRDs

cd .\manifests\
kubectl create -f .\setup\

Deploy remaining resources including node exporter daemonset

kubectl create -f .

# wait for pods to be up
kubectl get pods -n monitoring

#access prometheus in the browser
kubectl -n monitoring port-forward svc/prometheus-k8s 9090

See the Daemonset communications on the Prometheus targets page

Checkout my monitoring guide for kubernetes for more in depth info

Monitoring: Logging via Fluentd

Take a look at my monitoring guide for Fluentd