Kubernetes 1.2 新功能介紹:DaemonSet
如果您正在使用kubernetes構建你的生產環境,如果您正在尋找如何在每臺計算節點上執行一個守護程序(Pod),恭喜您,
什麼是DaemonSet
DaemonSet能夠讓所有(或者一些特定)的Node節點運行同一個pod。當節點加入到kubernetes叢集中,pod會被(DaemonSet)排程到該節點上執行,當節點從kubernetes叢集中被移除,被(DaemonSet)排程的pod會被移除,如果刪除DaemonSet,所有跟這個DaemonSet相關的pods都會被刪除。
在使用kubernetes來執行應用時,很多時候我們需要在一個區域(zone)或者所有Node上運行同一個守護程序(pod),例如如下場景:
- 每個Node上執行一個分散式儲存的守護程序,例如glusterd,ceph
- 執行日誌採集器在每個Node上,例如fluentd,logstash
- 執行監控的採集端在每個Node,例如prometheus node exporter,collectd等
在簡單的情況下,一個DaemonSet可以覆蓋所有的Node,來實現Only-One-Pod-Per-Node這種情形;在有的情況下,我們對不同的計算幾點進行著色,或者把kubernetes的叢集節點分為多個zone,DaemonSet也可以在每個zone上實現Only-One-Pod-Per-Node。
如何使用DaemonSet
在具體介紹如何使用DaemonSet之前,我們先來這樣的一個場景:
- java應用已經容器化並執行在kubernetes叢集中
- 需要實時採集java應用的日誌並做相關分析,對業務監控和預警
- 日誌採集使用fluentd + kafka + elastic search + kibana實現
- EFK技術棧都已容器化並執行在kubernetes中
在這樣一個具體場景下我們如何對java日誌採集?假設現在沒有DaemonSet,看我們至少有以下幾種方法:
- 將fluentd採集端整合到每個java應用的docker映象中,隨著應用啟動而啟動
- 將fluentd採集端和java應用執行在一個pod內,隨著pod的建立而啟動
- 將fluentd執行在每個計算節點(Node)上,把java應用的輸出直接輸出到控制檯,fluentd根據規則採集所有應用的日誌
比較上述三種方法,第一種很笨重,應用和fluentd耦合太緊,修改fluentd的配置,就要重新構建映象;第二種很複雜,不同的應用日誌對應不同的fluentd採集規則,耦合的因素仍在;第三種方式最為簡單和優雅,但是如何才能將fluentd排程到每臺計算節點上?對,就是DaemonSet。
apiVersion: extensions/v1beta1 kind:DaemonSet metadata: name: fluentd namespace:default spec:template: metadata: labels: app: fluentd spec: dnsPolicy:"ClusterFirst" restartPolicy:"Always" containers:- name: fluentd image: fluentd:v0.1.0 imagePullPolicy:"Always" env:- name: ES_HOST value: http://elasticsearch- name: ES_PORT value:"9200" volumeMounts:- mountPath:/var/lib/docker/containers name: docker-container volumes:- hostPath: path:/var/lib/docker/containers name: docker-container
建立DaemonSet:
kubectl create -f fluentd.yaml kubectl get ds NAME DESIRED CURRENT NODE-SELECTOR AGE fluentd 44<none>2h kubectl get nodes NAME STATUS AGE 10.254.4.144Ready3d10.254.5.143Ready3d10.254.6.106Ready3d10.254.7.106Ready3d kubectl get pods NAME READY STATUS RESTARTS AGE fluentd-29xri1/1Running02h fluentd-j5z1k 1/1Running02h fluentd-oxzki 1/1Running02h fluentd-rsw8f 1/1Running02h
如何維護DaemonSet的生命週期?
使用命令列工具kubectl來建立、刪除、查詢、修改DaemonSet:
- 使用kubectl create -f [daemonset file]來建立DaemonSet
- 使用kubectl get/describe [daemonsets name]來檢視Daemon
- 在刪除DaemonSet時,如果設定級聯刪除(—casecade=true)時,要先停掉所有被DaemonSet控制的pods;如果按照預設刪除方式,先刪除DaemonSet,然後再刪除所有的pods
在某種程度上,DaemonSet承擔了Repliaction Controller的功能,它也能保證相關pods持續執行,如果一個DaemonSet的Pod被殺死、停止、或者崩潰,那麼DaemonSet將會重新建立一個新的副本在這臺計算節點上
幾個簡單的DaemonSet例子:
Google serve_hostname 事例:返回每個幾點的hostname:
apiVersion: extensions/v1beta1 kind:DaemonSet metadata:namespace:default name: daemons-demo spec:template: metadata: labels: demo: daemons spec: containers:- name: hostname image: gcr.io/google_containers/serve_hostname:1.1
Nginx-Ingress-Controller的例子:
apiVersion: extensions/v1beta1 kind:DaemonSet metadata: name: nginx-ingress-lb spec:template: metadata: labels: name: nginx-ingress-lb spec: containers:- image: gcr.io/google_containers/nginx-ingress-controller:0.4 name: nginx-ingress-lb imagePullPolicy:Always livenessProbe: httpGet: path:/healthz port: 10249 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 # use downward API env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 4444 args: - /nginx-ingress-controller ---default-backend-service=default/default-http-backend