DaemonSet 守护式的进程
DaemonSet功能:
• 在每一个Node上运行一个Pod
• 新加入的Node也同样会自动运行一个Pod
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
DaemonSet 的典型应用场景有:(网络插件(kube-proxy、calico)、其他Agent)
-
在集群的每个节点上运行存储 Daemon,比如 glusterd 或 ceph。
-
在每个节点上运行日志收集 Daemon,比如 flunentd 或 logstash。
-
在每个节点上运行监控 Daemon,比如 Prometheus Node Exporter 或 collectd。
[root@k8s-master ~]# cat daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: myapp
namespace: default
labels:
app: daemonset-pod
spec:
selector:
matchLabels:
app: daemonset
template:
metadata:
labels:
app: daemonset
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
livenessProbe:
failureThreshold: 3
httpGet:
path: /index.html
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /index.html
port: 80
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
[root@k8s-master ~]# kubectl apply -f daemonset.yml
daemonset.apps/myapp created
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-h9t59 1/1 Running 0 2m4s 10.244.36.80 k8s-node1 <none> <none>
myapp-hjk6k 1/1 Running 0 2m4s 10.244.169.141 k8s-node2 <none> <none>
[root@k8s-master ~]# curl 10.244.36.80:80/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8s-master ~]# curl -I 10.244.36.80:80/index.html
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Mon, 21 Dec 2020 14:46:45 GMT
可以看到每个节点上面满足副本数为1。
[root@k8s-master ~]# kubectl delete pod myapp-hjk6k
pod "myapp-hjk6k" deleted
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-h87k6 1/1 Running 0 56s 10.244.169.142 k8s-node2 <none> <none>
myapp-h9t59 1/1 Running 0 5m31s 10.244.36.80 k8s-node1 <none> <none>
即使删除了也会保证该节点的副本数为1。上面因为master节点上有污点,所以master节点上不会运行该pod,如果要master上也运行该pod可以使用污点容忍,如下所示
[root@k8s-master ~]# kubectl describe node k8s-master
Taints: node-role.kubernetes.io/master:NoSchedule
[root@k8s-master ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master Ready master 36d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-node1 Ready <none> 36d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2 Ready <none> 36d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux
通过标签选择器和污点容忍使得master也可以运行一个pod
spec:
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-8lb2r 1/1 Running 0 2m14s 10.244.36.81 k8s-node1 <none> <none>
myapp-9cn8f 1/1 Running 0 3m4s 10.244.235.193 k8s-master <none> <none>
myapp-hvz2j 1/1 Running 0 112s 10.244.169.143 k8s-node2 <none> <none>
其实 Kubernetes 自己就在用 DaemonSet 运行系统组件。执行如下命令
[root@k8s-master ~]# kubectl get daemonset --namespace=kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-flannel-ds-amd64 3 3 3 3 3 <none> 51d
DaemonSet kube-flannel-ds
负责在每个节点上运行 flannel组件。
[root@k8s-master ~]# kubectl get pod -o wide -n kube-system
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-amd64-lb6vm 1/1 Running 0 51d 192.168.179.100 k8s-node1 <none> <none>
kube-flannel-ds-amd64-lxxdq 1/1 Running 0 51d 192.168.179.101 k8s-node2 <none> <none>
kube-flannel-ds-amd64-vl4fn 1/1 Running 0 51d 192.168.179.99 k8s-master <none> <none>
因为 flannel属于系统组件,需要在命令行中通过 --namespace=kube-system
指定 namespace kube-system
。如果不指定则只返回默认namespace default
中的资源。
apiVersion: apps/v1
kind: DaemonSet ##############
metadata:
name: kube-flannel-ds-arm64
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
- key: kubernetes.io/arch
operator: In
values:
- arm64
hostNetwork: true
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni
image: quay.io/coreos/flannel:v0.12.0-arm64
command:
- cp
- DaemonSet 配置文件的语法和结构与 Deployment 几乎完全一样,只是将
kind
设为DaemonSet
。 - hostNetwork 指定 Pod 直接使用的是 Node 的网络,相当于
docker run --network=host
。考虑到 flannel 需要为集群提供网络连接,这个要求是合理的。 containers
定义了运行 flannel 服务的容器。
运行自己的 DaemonSet
Prometheus 是流行的系统监控方案,Node Exporter 是 Prometheus 的 agent,以 Daemon 的形式运行在每个被监控节点上。
如果是直接在 Docker 中运行 Node Exporter 容器,命令为:
docker run -d \
-v "/proc:/host/proc" \
-v "/sys:/host/sys" \
-v "/:/rootfs" \
--net=host \
prom/node-exporter \
--path.procfs /host/proc \
--path.sysfs /host/sys \
--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"
将其转换为 DaemonSet 的 YAML 配置文件 node_exporter.yml:
① 直接使用 Host 的网络。
② 设置容器启动命令。
③ 通过 Volume 将 Host 路径 /proc
、/sys
和 /
映射到容器中。我们将在后面详细讨论 Volume。
执行 kubectl apply -f node_exporter.yml
:
DaemonSet node-exporter-daemonset
部署成功,k8s-node1 和 k8s-node2 上分别运行了一个 node exporter Pod。