3-5、Pod控制器-Daemonset

DaemonSet

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时,会为他们新增一个 Pod。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。



DaemonSet 的一些典型用法:

在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。

在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。

在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、Flowmill、Sysdig 代理、collectd、Dynatrace OneAgent、AppDynamics 代理、Datadog 代理、New Relic 代理、Ganglia gmond 或者 Instana 代理。

一个简单的用法是在所有的节点上都启动一个 DaemonSet,并作为每种类型的 daemon 使用。



一个稍微复杂的用法是单独对每种 daemon 类型使用一种DaemonSet。这样有多个 DaemonSet,但具有不同的标识,并且对不同硬件类型具有不同的内存、CPU 要求

DaemonSet

vi daemonset-demo.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
    name: filebeat-ds
    namespace: default
spec:
    replicas: 2
    selector:
        matchLabels:
            app: filebeat
            release: canary
    template:
        metadata:
           labels:
            app: filebeat
            release: canary
        spec:
            containers:
            - name: filebeat
              image: ikubernetes/filebeat:5.6.5-alpine
              env:
              - name: REDIS_HOST
                value: redis.default.svc.cluster.local
              - name: REDIS_LOG_LEVEL
                value: info

查看镜像的信息:
# docker image inspect ikubernetes/filebeat:5.6.5-alpine

# kubectl apply -f daemonset-demo.yml
# kubectl get pods
NAME                            READY   STATUS             RESTARTS   AGE
myapp-ds-c8h2w                  1/1     Running            0          11s

查看其日志信息:
# kubectl logs myapp-ds-c8h2w    
2019/04/14 10:52:52.162394 beat.go:297: INFO Home path: [/usr/local/bin] Config path: [/usr/local/bin] Data path: [/usr/local/bin/data] Logs path: [/usr/local/bin/logs]

一个yml文件中定义多个资源:
apiVersion: v1
kind: Deployment
metadata:
  name: redis
  namespace: default
spec:
  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:
    replicas: 2
    selector:
        matchLabels:
            app: filebeat
            release: canary
    template:
        metadata:
           labels:
            app: filebeat
            release: canary
        spec:
            containers:
            - name: filebeat
              image: ikubernetes/filebeat:5.6.5-alpine
              env:
              - name: REDIS_HOST
                value: redis.default.svc.cluster.local
              - name: REDIS_LOG_LEVEL
                value: info

将redis端口暴露出来:
# kubectl expose deployment redis --port=6379


daemonset示例2:
运行fluentd-elasticsearch image:
cat daemonset.yaml
apiVersion: apps/v1

kind: DaemonSet

metadata:

  name: fluentd-elasticsearch

  namespace: kube-system

  labels:

    k8s-app: fluentd-logging

spec:

  selector:

    matchLabels:

      name: fluentd-elasticsearch

  template:

    metadata:

      labels:

        name: fluentd-elasticsearch

    spec:

      tolerations:

      - key: node-role.kubernetes.io/master

        effect: NoSchedule

      containers:

      - name: fluentd-elasticsearch

        image: k8s.gcr.io/fluentd-elasticsearch:1.20

        resources:

          limits:

            memory: 200Mi

          requests:

            cpu: 100m

            memory: 200Mi

        volumeMounts:

        - name: varlog

          mountPath: /var/log

        - name: varlibdockercontainers

          mountPath: /var/lib/docker/containers

          readOnly: true

      terminationGracePeriodSeconds: 30

      volumes:

      - name: varlog

        hostPath:

          path: /var/log

      - name: varlibdockercontainers

        hostPath:

          path: /var/lib/docker/containers
#kubectl apply -f daemonset.yaml

DaemonSet同样会受到Taint的抵制,如果不在配置中加入匹配的Toleration,那么DaemonSet不会在拥有Taint属性的node上部署pod。上例中有如下内容:



tolerations:

      - key: node-role.kubernetes.io/master

        effect: NoSchedule

原因就是系统默认为master节点增加了 “node-role.kubernetes.io/master”的Taint,以抵制普通pod部署,使master成为专用节点。因为我们预期上例DaemonSet在集群内全局部署,因此需要加入相匹配的Toleration。



如果预期DaemonSet只在特定节点上运行,可以在上述配置文件中加入.spec.template.spec.nodeSelector字段。.

spec.template.spec.nodeSelector字段内加入节点选择器(node selector)或者亲和选择器(node affinity),则DaemonSet只会在满足条件的node上部署pod。总之,可以通过Taint、Toleration、Affinity、node label控制DaemonSet部署pod的节点范围。

系统如何调度DaemonSet pod?
默认情况下DaemonSet在创建pod时,为其增加spec.nodeName字段,也就是说所创建的pod运行在那个节上在创建阶段就已经确定,所以DaemonSet中的pod实际上没有接受kubernetes scheduler的调度,它不需要调度,因此产生以下两个特性:
DaemonSet中的pod不遵从节点的unreachable条件,也就是即使节点被系统判定为不可达,DaemonSet仍然试图在其上部署pod。
在集群引导阶段,即使kubernetes scheduler还没有部署生效,DaemonSet仍然可以将pod部署到集群中的任何节点,此特性主要是在集群引导阶段使用。
因为DaemonSet不同于常规pod的调度特性,它带来两个问题:
pod行为不一致。普通pod被创建以后等待调度的阶段称为pending,因为DaemonSet中的pod无需调度,因而无此状态,用户会因此产生迷惑。
pod优先级特性由kubernetes scheduler实现,DaemonSet无此特性。当系统打开pod优先级功能时,pod优先级特性会被DaemonSet中的pod忽略。

为了解决以上两个问题,kubernetes增加了通过设置允许DaemonSet使用kurbernetes scheduler的功能,并在1.11的 alpha版本中成为稳定特性。其实现机制是DaemonSet在创建pod时,不再自动添加.spec.nodeName,而是以nodeAffinity取而代之,示例如下:
nodeAffinity:

  requiredDuringSchedulingIgnoredDuringExecution:

    nodeSelectorTerms:

    - matchFields:

      - key: metadata.name

        operator: In

        values:

        - target-host-name
其中"target-host-name"就是原来.spec.nodeName的值,这样pod就会被kubernetes scheduler调度。通过以上操作解决了上述两个问题。但DaemonSet的调度有自己因有的特性,在上文中提到的“不受节点unreachable条件限制”,为了使DaemonSet在使用kubernetes scheduler时仍然保持此特性需要打开集群的"TaintNodesByCondition"特性,如果DaemonSet使用主机网络那么必需在DaemonSet中添加如下的Toleration:



node.kubernetes.io/network-unavailable:NoSchedule

 

posted @ 2022-11-14 23:46  Sky-wings  阅读(71)  评论(0编辑  收藏  举报