1. 程式人生 > >Kubernetes 1.2 新功能介紹:DaemonSet

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,看我們至少有以下幾種方法:

  1. 將fluentd採集端整合到每個java應用的docker映象中,隨著應用啟動而啟動
  2. 將fluentd採集端和java應用執行在一個pod內,隨著pod的建立而啟動
  3. 將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