介绍
DaemonSet就是让一个节点上只能运行一个Daemonset Pod应用,每个节点就只有一个。比如最常用的网络组件,存储插件,日志插件,监控插件就是这种类型的pod.如果集群中有新的节点加入,DaemonSet也会在新的节点创建出来。
DaemonSet如何保证每个节点,只有一个Pod副本运行呢?DaemonSet首先从Etcd获取所有Node的列表,然后它会去检查所有的Node,如果这个节点上没有所要运行的DaemonSet,就会启动一个出来。如果这个节点有1个以上的DaemonSet,那就会删除那个多余的DaemonSet。如果刚好只有一个运行,那这个节点就是正常的运行的。
DaemonSet例子
现在我们通过一个日志收集的例子来学习DaemonSet.根据上一篇的介绍,我们继续把那个nginx稍微修改一下,让它的日志目录映射出来。可以看出来和上一章的没太大区别,只是我们把nginx的日志目录映射到了宿主机的/tmp/log 目录。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22.1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
- name: varlog
mountPath: /var/log/nginx
volumes:
- name: varlog
hostPath:
path: /tmp/log
volumeClaimTemplates:
- metadata:
name: www
spec:
storageClassName: rook-ceph-block
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
这样我们在宿主机的/tmp/log 目录,看到nginx产生的日志。
现在我们生成一个日志收集的DaemonSet。收集的日志保存在redis中。先看yaml文件。所有涉及的容器镜像可以在这里下载 提取码: 6bqe
1.ConfigMap
由于我们用的FileBeat的来采集日志,这个名为filebeat-config的ConfigMap会在/etc/filebeat/目录生成一个filebeat.yml的配置文件,这个配置文件就是filebeat的配置文件。这个配置文件指定会在/var/log/nginx/目录下的所有log文件的内容,会推送到Redis中。
2.Redis
这里配置的Redis配置的是一个StatefulSet pod,并且还给它配置了一个headless service用户固定它的网络标识。
3. FileBeat DaemonSet
最下面的Yaml配置就是filebeat的配置,它会把上面nginx映射出来的宿主日志目录/tmp/log作为Volume又挂接到DaemonSet的 /var/log/nginx/目录,同时它也把Redis的网络标识redis-0.rediservice.default.svc.cluster.local放入配置中。这样整个DaemonSet就能把日志推送到redis中。
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: default
data:
filebeat.yml: |-
filebeat.registry_file: /var/log/containers/filebeat_registry
filebeat.idle_timeout: 5s
filebeat.spool_size: 2048
logging.level: info
filebeat.prospectors:
- input_type: log
paths:
- "/var/log/nginx/*.log"
symlinks: true
json.message_key: log
json.keys_under_root: true
json.add_error_key: true
multiline.pattern: '^\s'
multiline.match: after
document_type: kube-logs
tail_files: true
fields_under_root: true
output.redis:
hosts: ${REDIS_HOST:?No Redis host configured. Use env var REDIS_HOST to set host.}
key: "filebeat"
---
apiVersion: v1
kind: Service
metadata:
name: rediservice
labels:
app: redis
spec:
ports:
- port: 6379
name: redis
clusterIP: None
selector:
app: redis
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: default
spec:
serviceName: "rediservice"
replicas: 1
selector:
matchLabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerPort: 6379
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
namespace: default
spec:
selector:
matchLabels:
app: filebeat
release: stable
template:
metadata:
labels:
app: filebeat
release: stable
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
volumeMounts:
- name: filebeat-config
mountPath: /etc/filebeat
- name: nginx-logs
mountPath: /var/log/nginx/
env:
- name: REDIS_HOST
value: redis-0.rediservice.default.svc.cluster.local
- name: REDIS_LOG_LEVEL
value: debug
volumes:
- name: filebeat-config
configMap:
name: filebeat-config
- name: nginx-logs
hostPath:
path: /tmp/log
把上面的yaml通过kubectl apply -f 的形式运行到K8s.运行完成后,会生成下面的pod。可以看到每个node节点只有一个filebeat运行。
接下来我们通过,curl命令生成一些nginx日志。我们直接对web-1的nginx产生日志。
for i in {1..4096} ; do curl 10.244.2.24 ; done
执行完成后,我们进入redis,看日志是否有生成。
kubectl exec -it redis-0 /usr/local/bin/redis-cli
进入redis我们通过keys *的命令看到产生了一个filebeat的键值,里面保存的就是日志,但是里面的日志是list类型的。我们通过lrange filebeat 1 2可以查看到刚才产生的日志信息。
其实DaemonSet和Deployment一样都是可以版本管理的。通过下面的命令我们可以看到filebeat-ds的历史版本,现在的版本只有1个。
kubectl rollout history daemonset filebeat-ds
现在我们把filebeat的版本升级一下,升级到filebeat:5.6.6-alpine。filebeatupdateimage.yaml 升级的yaml文件如下
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
namespace: default
spec:
selector:
matchLabels:
app: filebeat
release: stable
template:
metadata:
labels:
app: filebeat
release: stable
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.6-alpine
volumeMounts:
- name: filebeat-config
mountPath: /etc/filebeat
- name: nginx-logs
mountPath: /var/log/nginx/
env:
- name: REDIS_HOST
value: redis-0.rediservice.default.svc.cluster.local
- name: REDIS_LOG_LEVEL
value: debug
volumes:
- name: filebeat-config
configMap:
name: filebeat-config
- name: nginx-logs
hostPath:
path: /tmp/log
升级版本,可以看到filebeat的pod id都发生了变化。并且历史版本多出一个版本。
kubectl apply -f filebeatupdateimage.yaml
如果我们要回到1号版本,我们可以运行如下命令,同时看到pod又重新新建了。
kubectl rollout undo daemonset filebeat-ds --to-revision=1
那这些版本是如何被维护以及记录的呢?是通过一个叫ControllerRevision API对象,我们可以通过这个查看版本是怎么保存的。通过下面的命令我们可以看到filebeat-ds有一个2,3的版本,原来的1没看见了,那是因为我们回滚到了1版本。但是回滚到的1版本是现在的新版本3,所以才会有2,3.