Kubernetes 教學 第五篇(Cluster Monitoring 篇)
毫無疑問,在這邊我們主要會使用 Prometheus 來監控 Cluster,但是在這之前,我們要先介紹 k8s 的 DaemonSet
。
DaemonSet
DaemonSet 能確保 Cluster 中的每個滿足條件的 Node 上面都能運行一個特定的 Node,因此通常用於部署系統級別的服務,例如監控、Log 收集、CNI 插件等,這些服務理所應當的需要在每個 Node 上執行。
$ kubectl get daemonsets -A
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-system calico-node 1 1 1 1 1 kubernetes.io/os=linux 5d22h
calico-system csi-node-driver 1 1 1 1 1 kubernetes.io/os=linux 5d22h
metallb-system speaker 1 1 1 1 1 kubernetes.io/os=linux 13d
創建我們自己的 Node Exporter DaemonSet:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
labels:
app: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
containers:
- name: node-exporter
image: quay.io/prometheus/node-exporter:v1.8.2
args:
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
ports:
- name: metrics
containerPort: 9100
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
以及 Service:
apiVersion: v1
kind: Service
metadata:
name: node-exporter
namespace: monitoring
labels:
app: node-exporter
spec:
selector:
app: node-exporter
ports:
- name: metrics
port: 9100
targetPort: 9100
protocol: TCP
type: ClusterIP
我們就可以看到新建成功的樣子了:
$ kubectl get daemonset,deployment,pod,svc -n monitoring
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/node-exporter 1 1 1 1 1 <none> 41m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/grafana 1/1 1 1 6d19h
deployment.apps/prometheus-server 1/1 1 1 6d19h
NAME READY STATUS RESTARTS AGE
pod/grafana-6964b5687d-nts7c 1/1 Running 0 5d22h
pod/node-exporter-jq54f 1/1 Running 0 5m17s
pod/prometheus-server-65648cd94f-w7bzv 1/1 Running 0 26m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/grafana ClusterIP 10.152.183.109 <none> 3000/TCP 6d19h
service/node-exporter ClusterIP 10.152.183.62 <none> 9100/TCP 40m
service/prometheus-server ClusterIP 10.152.183.125 <none> 9090/TCP 6d19h
為 DaemonSet 配置 DNS
我們可以創建一個 Service,例如透過 selector 來匹配該 DaemonSet 的 Pod,然後將 Cluster-IP 設爲 None
(即 Headless Service),這樣我們就可以透過 <pod-name>.<service-name>.<namespace>.svc.cluster.local
來訪問每一個 Pod 了。
但這也會遇到問題,如果整個 DaemonSet 被重啓,那麽 Pod 的名稱也會改變,DNS 也會隨之改變,因此這方面的設定會很麻煩。
因此,遇到這種情況,直接使用 NodePort 或是 HostPort 將更方便,而且也更直觀:對應到某個 Node 的那個 Pod,就是在搜集那個 Node 的資訊。
其他監控 Kubernetes 的方式
剛才我們提及了使用 DaemonSet 開 Node Exporter 來監控 Cluster,但這個其實只是監控每個 Node 的主機狀況(因爲 Node Exporter 本身就是監控 Linux 主機的 Prometheus Exporter,不是針對 K8S 的),沒辦法帶我們很好的理解每個 Pod 的情況和網路運作狀況。
所以如果真的有監控每個 Pod 的需求,可以考慮使用 kube-state-metrics。
而監控網路的部分,很多 CNI 插件都已經提供了内建的 Prometheus Exporter,只需要開啓即可,例如 Monitor Calico component metrics。
而還有 Log 收集、分析的部分,就可以參考 Deploy ECK in your Kubernetes cluster,這篇文章是針對 Elastic Cloud on Kubernetes 而撰寫的,基本上就是 ELK stack,而其中的 Elasticsearch 恰好很適合我們下面介紹的 StatefulSet(分散式、長期資料儲存)。
淺談 K8S 中常用的 Controllers
除了我們之前一直在使用的 Deployment 和剛剛介紹的 DaemonSet,k8s 還提供了其他的 Controller。
比較常使用的還有例如 StatefulSet、CronJob 等。
有必要在此特別介紹 StatefulSet,顧名思義,他適合那些需要保持狀態的應用程式。這些應用程式通常需要穩定、一致的命名、網路配置(IP、DNS)和持久化 Storage。
不變的命名和網路配置很好理解,我們以往創建的那些 Pod 名字中基本上都帶有個隨機後綴。而 StatefulSet 創建的 Pod 則是規律的,按照流水號排下去。
而説到持久化 Storage,你可能會想到之前介紹過的 Persistent Volume Claim,也是為 Pod 創建一個穩定的 Storage,但兩者還是有本質上的區別。
StatefulSet 會為每一個 Pod 創建獨立的 PVC,即使 Pod 被刪除、調度,也會重新掛載最初分配的 PV,確保資料一致性;而一般 Deployment 通常是數個 Pods 共用同一個 PVC,又或是沒有嚴格的對應關係,導致每次 Pod 重啓,都可能會掛載到不同的 PV。
因此 StatefulSet 特別適合來開分散式資料庫服務,如 MySQL 或是 Redis 等。他們每個節點都需要自己維護一份獨立的資料庫來保證資料的一致性,他們也需要穩定的網路身份和命名來進行正確的通信以及確保主從關係。
不過因爲我這邊目前是沒有要部署這種應用程式的需求,所以只能在這邊粗淺的介紹一下。
