Kubernetes學習之路(十三)之Pod控制器--DaemonSet

1、什麼是DaemonSet?

DaemonSet 確保所有(或者一些)Node 上運行一個 Pod 的副本。當有 Node 加入集羣時,也會爲他們新增一個 Pod 。當有 Node 從集羣移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它建立的全部 Pod。html

使用 DaemonSet 的一些典型用法:node

  • 運行集羣存儲 daemon,例如在每一個 Node 上運行 glusterdceph
  • 在每一個 Node 上運行日誌收集 daemon,例如fluentdlogstash
  • 在每一個 Node 上運行監控 daemon,例如 Prometheus Node Exportercollectd、Datadog 代理、New Relic 代理,或 Ganglia gmond

一個簡單的用法是,在全部的 Node 上都存在一個 DaemonSet,將被做爲每種類型的 daemon 使用。 一個稍微複雜的用法多是,對單獨的每種類型的 daemon 使用多個 DaemonSet,但具備不一樣的標誌,和/或對不一樣硬件類型具備不一樣的內存、CPU要求。nginx

2、編寫DaemonSet Spec

(1)必需字段git

和其它全部 Kubernetes 配置同樣,DaemonSet 須要 apiVersionkind 和 metadata字段。github

[root@k8s-master ~]# kubectl explain daemonset
KIND:     DaemonSet
VERSION:  extensions/v1beta1

DESCRIPTION:
     DEPRECATED - This group version of DaemonSet is deprecated by
     apps/v1beta2/DaemonSet. See the release notes for more information.
     DaemonSet represents the configuration of a daemon set.

FIELDS:
   apiVersion    <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata    <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

   spec    <Object>
     The desired behavior of this daemon set. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

   status    <Object>
     The current status of this daemon set. This data may be out of date by some
     window of time. Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

(2)Pod模板redis

.spec 惟一必需的字段是 .spec.templatedocker

.spec.template 是一個 Pod 模板。 它與 Pod 具備相同的 schema,除了它是嵌套的,並且不具備 apiVersion 或 kind 字段。數據庫

Pod 除了必須字段外,在 DaemonSet 中的 Pod 模板必須指定合理的標籤(查看 pod selector)。json

在 DaemonSet 中的 Pod 模板必需具備一個值爲 Always 的 RestartPolicy,或者未指定它的值,默認是 Alwaysvim

[root@k8s-master ~]# kubectl explain daemonset.spec.template.spec

 (3)Pod Seletor

.spec.selector 字段表示 Pod Selector,它與 Job 或其它資源的 .sper.selector 的原理是相同的。

spec.selector 表示一個對象,它由以下兩個字段組成:

  • matchLabels - 與 ReplicationController 的 .spec.selector 的原理相同。
  • matchExpressions - 容許構建更加複雜的 Selector,能夠經過指定 key、value 列表,以及與 key 和 value 列表的相關的操做符。

當上述兩個字段都指定時,結果表示的是 AND 關係。

若是指定了 .spec.selector,必須與 .spec.template.metadata.labels 相匹配。若是沒有指定,它們默認是等價的。若是與它們配置的不匹配,則會被 API 拒絕。

若是 Pod 的 label 與 selector 匹配,或者直接基於其它的 DaemonSet、或者 Controller(例如 ReplicationController),也不能夠建立任何 Pod。 不然 DaemonSet Controller 將認爲那些 Pod 是它建立的。Kubernetes 不會阻止這樣作。一個場景是,可能但願在一個具備不一樣值的、用來測試用的 Node 上手動建立 Pod。

(4)Daemon Pod通訊

與 DaemonSet 中的 Pod 進行通訊,幾種可能的模式以下:

  • Push:配置 DaemonSet 中的 Pod 向其它 Service 發送更新,例如統計數據庫。它們沒有客戶端。
  • NodeIP 和已知端口:DaemonSet 中的 Pod 能夠使用 hostPort,從而能夠經過 Node IP 訪問到 Pod。客戶端能經過某種方法知道 Node IP 列表,而且基於此也能夠知道端口。
  • DNS:建立具備相同 Pod Selector 的 Headless Service,而後經過使用 endpoints 資源或從 DNS 檢索到多個 A 記錄來發現 DaemonSet。
  • Service:建立具備相同 Pod Selector 的 Service,並使用該 Service 訪問到某個隨機 Node 上的 daemon。(沒有辦法訪問到特定 Node)

 3、建立redis-filebeat的DaemonSet演示

(1)編輯daemonSet的yaml文件
能夠在同一個yaml文件中定義多個資源,這裏將redis和filebeat定在一個文件當中

[root@k8s
-master mainfests]# vim ds-demo.yaml apiVersion: apps/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: selector: matchLabels: app: filebeat release: stable template: metadata: labels: app: filebeat release: stable 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
(2)建立pods [root@k8s
-master mainfests]# kubectl apply -f ds-demo.yaml deployment.apps/redis created daemonset.apps/filebeat-ds created

(3)暴露端口 [root@k8s
-master mainfests]# kubectl expose deployment redis --port=6379 service/redis exposed [root@k8s-master mainfests]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d myapp NodePort 10.106.67.242 <none> 80:32432/TCP 13d nginx ClusterIP 10.106.162.254 <none> 80/TCP 14d redis ClusterIP 10.107.163.143 <none> 6379/TCP 4s [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 5m filebeat-ds-vwx7d 1/1 Running 0 5m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 36s (4)測試redis是否收到日誌 [root@k8s-master mainfests]# kubectl exec -it redis-5b5d6fbbbd-v82pw -- /bin/sh /data # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN tcp 0 0 :::6379 :::* LISTEN /data # nslookup redis.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: redis.default.svc.cluster.local Address 1: 10.107.163.143 redis.default.svc.cluster.local /data # redis-cli -h redis.default.svc.cluster.local redis.default.svc.cluster.local:6379> KEYS *  #因爲redis在filebeat後面才啓動,日誌可能已經發走了,因此查看key爲空 (empty list or set) [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 14m filebeat-ds-vwx7d 1/1 Running 0 14m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 9m [root@k8s-master mainfests]# kubectl exec -it filebeat-ds-rpp9p -- /bin/sh / # cat /etc/filebeat/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/containers/*.log" - "/var/log/docker/containers/*.log" - "/var/log/startupscript.log" - "/var/log/kubelet.log" - "/var/log/kube-proxy.log" - "/var/log/kube-apiserver.log" - "/var/log/kube-controller-manager.log" - "/var/log/kube-scheduler.log" - "/var/log/rescheduler.log" - "/var/log/glbc.log" - "/var/log/cluster-autoscaler.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" [root@k8s-master mainfests]# kubectl get pods -l app=filebeat -o wide NAME READY STATUS RESTARTS AGE IP NODE filebeat-ds-rpp9p 1/1 Running 0 16m 10.244.2.12 k8s-node02 filebeat-ds-vwx7d 1/1 Running 0 16m 10.244.1.15 k8s-node01

4、DaemonSet的滾動更新

DaemonSet有兩種更新策略類型:

  • OnDelete:這是向後兼容性的默認更新策略。使用 OnDelete更新策略,在更新DaemonSet模板後,只有在手動刪除舊的DaemonSet pod時纔會建立新的DaemonSet pod。這與Kubernetes 1.5或更早版本中DaemonSet的行爲相同。
  • RollingUpdate:使用RollingUpdate更新策略,在更新DaemonSet模板後,舊的DaemonSet pod將被終止,而且將以受控方式自動建立新的DaemonSet pod。

要啓用DaemonSet的滾動更新功能,必須將其設置 .spec.updateStrategy.typeRollingUpdate

(1)查看當前的更新策略:

[root@k8s-master mainfests]# kubectl get ds/filebeat-ds -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}'
RollingUpdate

(2)更新DaemonSet模板

RollingUpdateDaemonSet的任何更新.spec.template將觸發滾動更新。這能夠經過幾個不一樣的kubectl命令來完成

聲明式命令方式:

若是使用配置文件進行更新DaemonSet,能夠使用kubectl aapply:

kubectl apply -f ds-demo.yaml

補丁式命令方式:

kubectl edit ds/filebeat-ds
kubectl patch ds/filebeat-ds -p=<strategic-merge-patch>

僅僅更新容器鏡像還能夠使用如下命令:

kubectl set image ds/<daemonset-name> <container-name>=<container-new-image>

下面對filebeat-ds的鏡像進行版本更新,以下:

[root@k8s-master mainfests]# kubectl set image daemonsets filebeat-ds filebeat=ikubernetes/filebeat:5.6.6-alpine
daemonset.extensions/filebeat-ds image updated
[root@k8s
-master mainfests]# kubectl get pods -w  #觀察滾動更新狀態 NAME READY STATUS RESTARTS AGE filebeat-ds-rpp9p 1/1 Running 0 27m filebeat-ds-vwx7d 0/1 Terminating 0 27m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 23m filebeat-ds-vwx7d 0/1 Terminating 0 27m filebeat-ds-vwx7d 0/1 Terminating 0 27m filebeat-ds-s466l 0/1 Pending 0 0s filebeat-ds-s466l 0/1 ContainerCreating 0 0s filebeat-ds-s466l 1/1 Running 0 13s filebeat-ds-rpp9p 1/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-rpp9p 0/1 Terminating 0 28m filebeat-ds-hxgdx 0/1 Pending 0 0s filebeat-ds-hxgdx 0/1 ContainerCreating 0 0s filebeat-ds-hxgdx 1/1 Running 0 28s [root@k8s-master mainfests]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 0 2m filebeat-ds-s466l 1/1 Running 0 2m pod-demo 2/2 Running 6 5d redis-5b5d6fbbbd-v82pw 1/1 Running 0 25m

從上面的滾動更新,能夠看到在更新過程當中,是先終止舊的pod,再建立一個新的pod,逐步進行替換的,這就是DaemonSet的滾動更新策略!

相關文章
相關標籤/搜索