1. 程式人生 > >kubernetes -- helm charts 開發: 2、 編寫daemonset

kubernetes -- helm charts 開發: 2、 編寫daemonset

1 概要介紹

DaemonSet:
特點:
確保全部Node上執行一個Pod副本(單副本)
Node加入叢集,則新增Pod;移除,則回收
刪除Daemonset,刪除建立的Pod

2編寫

2.1 必須欄位

apiVersion:
可用值: extensions/v1beta1
kind :
可用值:DaemonSet
metadata:
例如:name: nova-compute
.spec:
唯一必須的欄位:
.spec.template
例如:
    metadata:
      labels:
{{ tuple $envAll .Chart.Name $daemonset | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
      annotations:
        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}

.spec.template:
含義:是Pod模板。Pod有明確的格式。Pod中必須指明標籤合重啟策略,預設always。
具體參見:
https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#pod-template


2.2 Pod Selector

.spec.selector:
表示Pod Selector.是物件,包含:
matchLabels:
matchEx[ressions:

終於發現不能執行的原因:
zabbix-damonset:
{{ tuple $envAll "zabbix_agent" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}

nova-daemonset:
{{ tuple $envAll $daemonset | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}

ceilometer現在寫的是:
{{ tuple $envAll | include "helm-toolkit.snippets.kubernetes_upgrades_deployment" | indent 2 }}

如果指定spec.selector必須和.spec.template.metadata.labels
匹配,目前沒有發現spec.selector

2.3 .spec.template.spec.nodeSelector

如果指定.spec.template.spec.nodeSelector,則Daemonset Controller將在能夠匹配上Node Selector的Node上建立Pod,在能夠匹配上的Node Affinity的Node上建立Pod。
目前nova:
      nodeSelector:
        {{ .Values.labels.agent.compute.node_selector_key }}: {{ .Values.labels.agent.compute.node_selector_value }}

沒有affinity,所以會在所有Node上建立Pod

ceilometer:
      nodeSelector:
        {{ .Values.labels.compute.node_selector_key }}: {{ .Values.labels.compute.node_selector_value }}
      affinity:
{{ tuple $envAll "ceilometer" "compute" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}

3 如何排程Daemon Pod

Pod執行在哪個機器是由Kubernetes排程器進行選擇的,Daemon Controller建立的Pod已經確定在哪個機器上。

4 與Daemon Pod通訊

模式:
Push: Pod向其他Service傳送更新
NodeIP和的埠:使用hostPort,可通過Node IP訪問到Pod
客戶端知道Node IP列表
DNS:建立相同Pod Selector的Headless Service.通過endpoints資源檢索
Service:建立具有相同Pod Selector的Service,用該Service訪問到隨機Node上的daemon

5 更新DaemonSet

修改Node Label,DaemonSet向新匹配的Node新增Pod

6 init指令碼

通過直接在Node上啟動daemon程序。

7 一個ceilometer-compute的daemonset例子

7.1修改檔案統計

values.yaml
daemonset-compute.yaml

7.2 values.yaml

manifest部分:
  daemonset_compute: true
  deployment_notification: true

lifecycle部分:
新增:
      daemonsets:
        pod_replacement_strategy: RollingUpdate
        compute:
          enabled: true
          min_ready_seconds: 0
          max_unavailable: 1


replicas部分:
刪除,容易遺漏,因為daemonset沒有副本數的概念,deployment才有
    compute: 3

7.3 daemonset-compute.yaml

判斷部分:
{{- if .Values.manifests.daemonset_compute }}
appversion:
apiVersion: extensions/v1beta1
kind:
kind: DaemonSet
affinity:
刪除(其他都沒有)
daemonset模板
{{ tuple $envAll "compute" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}

7.4 最終的ceilometer-compute的daemonset樣例

{{- if .Values.manifests.daemonset_compute }}
{{- $envAll := . }}
{{- $dependencies := .Values.dependencies.compute }}
{{- $mounts_ceilometer_compute := .Values.pod.mounts.ceilometer_compute.ceilometer_compute }}
{{- $mounts_ceilometer_compute_init := .Values.pod.mounts.ceilometer_compute.init_container }}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ceilometer-compute
spec:
{{ tuple $envAll "compute" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
  selector:
    matchLabels:
{{ tuple $envAll "ceilometer" "compute" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
  template:
    metadata:
      labels:
{{ tuple $envAll "ceilometer" "compute" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
      annotations:
        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
    spec:
      hostNetwork: true
      hostPID: true
      dnsPolicy: ClusterFirstWithHostNet
      nodeSelector:
        {{ .Values.labels.compute.node_selector_key }}: {{ .Values.labels.compute.node_selector_value }}
      initContainers:
{{ tuple $envAll $dependencies $mounts_ceilometer_compute_init | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
      containers:
        - name: ceilometer-compute
          image: {{ .Values.images.tags.ceilometer_compute }}
          imagePullPolicy: {{ .Values.images.pull_policy }}
{{ tuple $envAll $envAll.Values.pod.resources.compute | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
          command:
            - /tmp/ceilometer-compute.sh
          volumeMounts:
            - name: pod-etc-ceilometer
              mountPath: /etc/ceilometer
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/ceilometer.conf
              subPath: ceilometer.conf
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/api_paste.ini
              subPath: api_paste.ini
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/policy.json
              subPath: policy.json
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/event_definitions.yaml
              subPath: event_definitions.yaml
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/event_pipeline.yaml
              subPath: event_pipeline.yaml
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/pipeline.yaml
              subPath: pipeline.yaml
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/gnocchi_resources.yaml
              subPath: gnocchi_resources.yaml
              readOnly: true
            - name: ceilometer-etc
              mountPath: /etc/ceilometer/mapping.json
              subPath: mapping.json
              readOnly: true
            - name: ceilometer-bin
              mountPath: /tmp/ceilometer-compute.sh
              subPath: ceilometer-compute.sh
              readOnly: true
            - name: varlibnova
              mountPath: /var/lib/nova
            - name: varliblibvirt
              mountPath: /var/lib/libvirt
            - name: run
              mountPath: /run
            - name: cgroup
              mountPath: /sys/fs/cgroup
            - name: machine-id
              mountPath: /etc/machine-id
              readOnly: true
{{ if $mounts_ceilometer_compute.volumeMounts }}{{ toYaml $mounts_ceilometer_compute.volumeMounts | indent 12 }}{{ end }}
      volumes:
        - name: pod-etc-ceilometer
          emptyDir: {}
        - name: ceilometer-etc
          configMap:
            name: ceilometer-etc
            defaultMode: 0444
        - name: ceilometer-bin
          configMap:
            name: ceilometer-bin
            defaultMode: 0555
        - name: varlibnova
          hostPath:
            path: /var/lib/nova
        - name: varliblibvirt
          hostPath:
            path: /var/lib/libvirt
        - name: run
          hostPath:
            path: /run
        - name: cgroup
          hostPath:
            path: /sys/fs/cgroup
        - name: machine-id
          hostPath:
            path: /etc/machine-id
{{ if $mounts_ceilometer_compute.volumes }}{{ toYaml $mounts_ceilometer_compute.volumes | indent 8 }}{{ end }}
{{- end }}


8 總結

daemonset相比較於deployment的最大區別就是當有新的節點加入進來的時候,daemonset會自動新建該daemonset的pod,這種場景往往適用於需要從每個新加入的節點獲取某種資訊。典型的例子就是: nova-compute, ceilometer-compute,因為當新增計算節點的時候,nova-compute和ceilometer-compute需要從新新增的計算節點上獲取虛機資訊。

參考:
[1] https://jimmysong.io/kubernetes-handbook/concepts/daemonset.html