天天看點

關于 Kubernetes中DeamonSet的一些筆記daemonset

寫在前面

  • 學習

    k8s

    遇到整理筆記
  • 感覺不管是

    dev

    還是

    ops

    ,離不開生命周期,鈎子,守護程序這些,還是要看看底層的東西.
  • DeamonSet

    可以了解為特殊的

    ReplicaSet

    ,即確定每個節點隻運作一個

    pod副本

    pod Set

  • 生命周期

    與叢集中nodes節點的周期相同
  • 類似 系統中的守護程序

    systemd

人生真難,但不配讓我認輸 ---沃金(知乎)

*

daemonset

DaemonSet

確定全部節點上運作一個 Pod 的副本。 當有節點加入叢集時, 也會為他們新增一個

Pod

。 當有節點從叢集移除時,這些

Pod

也會被回收。删除

DaemonSet

将會删除它建立的所有

Pod

。即單執行個體,每個節點隻跑一個

pod

DaemonSet

應用場景

DaemonSet 的一些典型用法:

  • 在每個Node上運作一個

    GlusterFS存儲

    或者

    Ceph存儲

    Daemon程序

  • 日志采集程式

    ,例如

    Fluentd

    Logstach

    .
  • 性能監控程式

    ,采集該

    Node

    運作性能資料

    PrometheusNode Exporter

    ,

    collectd

    , New Relic agent或者Ganglia gmond等。

一種簡單的用法是為每種類型的守護程序在所有的節點上都啟動一個 DaemonSet。 一個稍微複雜的用法是為同一種守護程序部署多個 DaemonSet;每個具有不同的标志, 并且對不同硬體類型具有不同的記憶體、CPU 要求。這句話不太懂,以後再研究下

DaemonSet

Pod排程政策

RC類似

,除了使用系統内置的算法在每台Node上進行排程,也可以在

Pod

的定義中使用

NodeSelector

NodeAffinity

來指定滿足條件的

Node

範圍進行排程。

學習環境準備

┌──[[email protected]]-[~/ansible]
└─$dir=k8s-daemonset-create;mkdir $dir;cd $dir
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl config current-context
kubernetes-admin@kubernetes
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl  create ns liruilong-dameonset-create
namespace/liruilong-dameonset-create created
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl config set-context $(kubectl config current-context) --namespace=liruilong-daemonset-create
Context "kubernetes-admin@kubernetes" modified.           

kubeadm中的deamonset

使用kubeadm安裝的k8s環境中是使用的DaemonSet,calico是網路相關,所有節點都需要有,kube-proxy是代理相關,用于負載均衡等操作

┌──[[email protected]]-[~/ansible/k8s-ReplicationController]
└─$kubectl  get ds -A
NAMESPACE     NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   calico-node   3         3         3       3            3           kubernetes.io/os=linux   4d23h
kube-system   kube-proxy    3         3         3       3            3           kubernetes.io/os=linux   4d23h
┌──[[email protected]]-[~/ansible/k8s-ReplicationController]
└─$           

Demonset的建立

這裡要說明的是

deamonset

deployment

隻有在

kind

的位置不同,可以拷貝

deployment

的模闆進行修改

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
 #replicas: 1
  selector:
    matchLabels:
      app: myds1
 #strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
#status: {}           
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl create deployment  myds1 --image=nginx --dry-run=client -o yaml > deamonset.yaml
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$vim deamonset.yaml           

我們建立一個deamonset,目前隻有master節點和一個node節點正常工作

因為master節點有污點,是以會發現這裡隻允許一個deamonset

┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl apply -f deamonset.yaml
daemonset.apps/myds1 created
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl  get nodes
NAME                         STATUS     ROLES                  AGE     VERSION
vms81.liruilongs.github.io   Ready      control-plane,master   4d22h   v1.22.2
vms82.liruilongs.github.io   Ready      <none>                 4d22h   v1.22.2
vms83.liruilongs.github.io   NotReady   <none>                 4d22h   v1.22.2
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl  get pods
NAME          READY   STATUS    RESTARTS   AGE
myds1-fbmhp   1/1     Running   0          35s
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$           

節點加入叢集自動新增節點pod

我們在啟動一台機器,會發現,新加入的

vms83.liruilongs.github.io

節點自動運作一個deamonset

┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl get nodes
NAME                         STATUS   ROLES                  AGE     VERSION
vms81.liruilongs.github.io   Ready    control-plane,master   4d22h   v1.22.2
vms82.liruilongs.github.io   Ready    <none>                 4d22h   v1.22.2
vms83.liruilongs.github.io   Ready    <none>                 4d22h   v1.22.2
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
myds1-prldj   1/1     Running   0          6m13s
myds1-pvwm4   1/1     Running   0          10m           

Deamonset污點節點加入pod

下面我們從新修改deamonset資源檔案,容忍有污點的節點

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
 #replicas: 1
  selector:
    matchLabels:
      app: myds1
 #strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      terminationGracePeriodSeconds: 0
      tolerations:
      - operator: Exists
      containers:
      - image: nginx
        name: nginx
        resources: {}
#status: {}           
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl  apply  -f deamonsettaint.yaml
daemonset.apps/myds1 created
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS              RESTARTS   AGE
myds1-8tsnz   0/1     ContainerCreating   0          3s
myds1-9l6d9   0/1     ContainerCreating   0          3s
myds1-wz44b   0/1     ContainerCreating   0          3s           

會發現每個節點都運作一個deamontset相關的pod

┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl describe  nodes vms81.liruilongs.github.io | grep Taint
Taints:             node-role.kubernetes.io/master:NoSchedule
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl run pod1 --image=nginx --dry-run=server -o yaml | grep -A 6 terminationGracePeriodSeconds
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute           

當然,如果我們不想是以有污點的節點都運作deamonset相關pod,那麼我們可以使用另一種指定kye的方式

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
  selector:
    matchLabels:
      app: myds1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      terminationGracePeriodSeconds: 0
      tolerations:
      - operator: Exists
        key: node-role.kubernetes.io/master
        effect: "NoSchedule"
      containers:
      - image: nginx
        name: nginx
        resources: {}           

會發現deamonset可以運作在master和node節點

┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl apply -f deamonsetaint.yaml
daemonset.apps/myds1 created
┌──[[email protected]]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS              RESTARTS   AGE
myds1-f7hbb   0/1     ContainerCreating   0          4s
myds1-hksp9   0/1     ContainerCreating   0          4s
myds1-nnmzp   0/1     ContainerCreating   0          4s           

Daemon Pods 是如何被排程的

DaemonSet

確定所有符合條件的節點都運作該 Pod 的一個副本。 通常,運作

Pod

的節點由

Kubernetes

排程器選擇。 不過,

DaemonSet Pods

DaemonSet

控制器建立和排程。這就帶來了以下問題:

Pod 行為的不一緻性:正常 Pod 在被建立後等待排程時處于 Pending 狀态, DaemonSet Pods 建立後不會處于 Pending 狀态下。

Pod 搶占 由預設排程器處理。啟用搶占後,DaemonSet 控制器将在不考慮 Pod 優先級和搶占 的情況下制定排程決策。這裡的預設排程器即k8s中排程器。

ScheduleDaemonSetPods

允許您使用預設排程器而不是

DaemonSet

控制器來排程

DaemonSets,

方法是将

NodeAffinity

條件而不是

.spec.nodeName

條件添加到

DaemonSet Pods

。 預設排程器接下來将

Pod

綁定到目标主機。

如果

DaemonSet Pod

的節點親和性配置已存在,則被替換 (原始的節點親和性配置在選擇目标主機之前被考慮)。

DaemonSet

控制器僅在建立或修改

DaemonSet Pod

時執行這些操作, 并且不會更改

DaemonSet

spec.template

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name           

與 Daemon Pods 通信

DaemonSet 中的 Pod 進行通信的幾種可能模式如下:

推送(Push)

:配置 DaemonSet 中的 Pod,将更新發送到另一個服務,例如統計資料庫。 這些服務沒有用戶端。

NodeIP 和已知端口

:DaemonSet 中的 Pod 可以使用 hostPort,進而可以通過節點 IP 通路到 Pod。用戶端能通過某種方法擷取節點 IP 清單,并且基于此也可以擷取到相應的端口。

DNS:建立具有相同

Pod 選擇算符的 無頭服務, 通過使用 endpoints 資源或從 DNS 中檢索到多個 A 記錄來發現 DaemonSet。

Service

:建立具有相同 Pod 選擇算符的服務,并使用該服務随機通路到某個節點上的 守護程序(沒有辦法通路到特定節點)。

更新 DaemonSet

如果節點的标簽被修改,DaemonSet 将立刻向新比對上的節點添加 Pod, 同時删除不比對的節點上的 Pod。你可以修改 DaemonSet 建立的 Pod。不過并非 Pod 的所有字段都可更新。 下次當某節點(即使具有相同的名稱)被建立時,DaemonSet 控制器還會使用最初的模闆。

你可以修改

DaemonSet

建立的 Pod。不過并非

Pod

的所有字段都可更新。 下次當某節點(即使具有相同的名稱)被建立時,DaemonSet 控制器還會使用最初的模闆。

您可以删除一個 DaemonSet。如果使用 kubectl 并指定 --cascade=orphan 選項, 則 Pod 将被保留在節點上。接下來如果建立使用相同選擇算符的新 DaemonSet, 新的 DaemonSet 會收養已有的 Pod。 如果有 Pod 需要被替換,DaemonSet 會根據其 updateStrategy 來替換。

DaemonSet 的替代方案

init 腳本

直接在節點上啟動守護程序(例如使用

init、upstartd

systemd

)的做法當然是可行的。 不過,基于

DaemonSet

來運作這些程序有如下一些好處:

  • 像所運作的其他應用一樣,

    DaemonSet

    具備為守護程序提供監控和日志管理的能力。
  • 為守護程序和應用所使用的配置語言和工具(如 Pod 模闆、kubectl)是相同的。
  • 在資源受限的容器中運作守護程序能夠增加守護程序和應用容器的隔離性。 然而,這一點也可以通過在容器中運作守護程序但卻不在 Pod 中運作之來實作。 例如,直接基于 Docker 啟動。

裸 Pod

直接建立

Pod

并指定其運作在特定的節點上也是可以的。 然而,DaemonSet 能夠替換由于任何原因(例如節點失敗、例行節點維護、核心更新) 而被删除或終止的

Pod

。 由于這個原因,你應該使用 DaemonSet 而不是單獨建立 Pod。

靜态 Pod

通過在一個指定的、受

kubelet

監視的目錄下編寫檔案來建立

Pod

也是可行的。 這類

Pod

被稱為靜态 Pod。 不像

DaemonSet

,靜态 Pod 不受

kubectl

和其它

Kubernetes API

用戶端管理。 靜态 Pod 不依賴于 API 伺服器,這使得它們在啟動引導新叢集的情況下非常有用。 此外,靜态 Pod 在将來可能會被廢棄。

Deployments

DaemonSet

Deployments

非常類似, 它們都能建立 Pod,并且

Pod

中的程序都不希望被終止(例如,Web 伺服器、存儲伺服器)。建議為無狀态的服務使用

Deployments

,比如前端服務。 對這些服務而言,對副本的數量進行擴縮容、平滑更新,比精确控制 Pod 運作在某個主機上要重要得多。 當需要

Pod

副本總是運作在全部或特定主機上,并且當該

DaemonSet

提供了節點級别的功能(允許其他 Pod 在該特定節點上正确運作)時, 應該使用

DaemonSet。

例如,網絡插件通常包含一個以

DaemonSet

運作的元件。 這個

DaemonSet

元件確定它所在的節點的叢集網絡正常工作

┌──[[email protected]]-[~/ansible/k8s-ReplicationController]
└─$kubectl  get ds -A
NAMESPACE     NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   calico-node   3         3         3       3            3           kubernetes.io/os=linux   4d23h
kube-system   kube-proxy    3         3         3       3            3           kubernetes.io/os=linux   4d23h
┌──[[email protected]]-[~/ansible/k8s-ReplicationController]
└─$           

繼續閱讀