Kubernetes 叢集的監控和日誌管理對於系統穩定性和效能至關重要。Prometheus Operator 提供了 Kubernetes 原生的監控解決方案,而 Ansible 則可以自動化佈署和管理流程。本文將介紹如何結合 Prometheus Operator 和 Ansible,實作 Kubernetes 監控和日誌管理的自動化,並探討節點管理的 Taint、Drain、Cordon 和 Uncordon 等操作,讓讀者能更有效地管理 Kubernetes 叢集。此方法能有效提升維運效率,確保系統穩定執行。透過 Ansible 的自動化能力,可以簡化佈署和管理流程,降低人為錯誤的風險。

Kubernetes 監控與日誌管理:Prometheus 與 Ansible 的整合應用

在現代化的 Kubernetes 環境中,監控和日誌管理是確保系統穩定性和效能的關鍵。本篇文章將探討如何使用 Prometheus Operator 和 Ansible 來佈署和管理 Kubernetes 叢集的監控與日誌收集。

使用 Prometheus Operator 進行 Kubernetes 監控

Prometheus Operator 是 Kubernetes 原生的解決方案,允許使用者佈署和管理 Prometheus 及其相關元件,如 Alertmanager 和 Grafana。它提供了宣告式的組態方式,讓使用者可以指定監控堆積疊的期望狀態,並由 Operator 確保其始終保持最新狀態。

佈署 Prometheus Operator

佈署 Prometheus Operator 的最簡單方法是使用 kube-prometheus 專案。kube-prometheus 專案透過佈署 Prometheus Operator 來實作端對端的 Kubernetes 叢集監控。

  1. 下載 kube-prometheus 專案

    $ git clone https://github.com/prometheus-operator/kube-prometheus.git
    
  2. 佈署 kube-prometheus

    $ kubectl create -f manifests/setup
    $ kubectl create -f manifests/
    
  3. 轉發 Prometheus、Alertmanager 和 Grafana 的埠

    $ kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090
    $ kubectl --namespace monitoring port-forward svc/alertmanager-main 9093
    $ kubectl --namespace monitoring port-forward svc/grafana 3000
    

使用 Ansible 自動化佈署 Prometheus

Ansible 是另一種佈署和管理 Prometheus 的有效工具。你可以使用 Ansible Galaxy 中的 prometheus.prometheus Collection 來自動化安裝 Prometheus。

  1. 安裝 prometheus.prometheus Collection

    $ ansible-galaxy collection install prometheus.prometheus
    
  2. 建立 Playbook(例如 prometheus.yml):


  • name: install prometheus hosts: all roles:
    • prometheus.prometheus.prometheus vars: prometheus_targets: node:
      • targets:
        • k8s.ansiblepilot.com:9100 labels: env: ansible-examples

3. **執行 Playbook**:
```bash
$ ansible-playbook -i inventory prometheus.yml

使用 Helm Chart 佈署 Prometheus Operator

另一個佈署 Prometheus Operator 的方法是使用 Helm Chart。你可以重用之前的 Ansible Playbook,並透過命令列指定額外的變數來啟用 Helm 倉函式庫並安裝 kube-prometheus-stack

  1. 啟用 Helm 倉函式庫

    $ ansible-playbook -i inventory -e "helm_chart_name=prometheus-community" -e "helm_chart_url=https://prometheus-community.github.io/helm-charts" helm_repo_present.yml
    
  2. 安裝 kube-prometheus-stack

    $ ansible-playbook -i inventory -e "chart_name=kube-prometheus-stack" -e "chart_ref=prometheus-community/kube-prometheus-stack" helm_present.yml
    

從 Kubernetes 資源中取得日誌

要手動從 Kubernetes 資源中取得日誌,可以使用 kubectl logs 命令。這個命令允許你檢視 Pod 中容器的日誌,或者檢索 Deployment、StatefulSet 或 CronJob 等資源的日誌。

使用 Ansible Playbook 取得日誌

你也可以編寫 Ansible Playbook 來自動化日誌收集的過程。以下是一個範例 Playbook,用於從指定的 Pod 或其他資源中取得日誌:

---
- name: k8s log
  hosts: all
  vars:
    myproject: "ansible-examples"
    myname: "nginx-server"
    mykind: "Deployment"
  tasks:
    - name: get log from resource
      kubernetes.core.k8s_log:
        api_version: apps/v1
        kind: "{{ mykind }}"
        namespace: "{{ myproject }}"
        name: "{{ myname }}"
      register: log
    - name: display log
      ansible.builtin.debug:
        var: log

執行這個 Playbook:

$ ansible-playbook -i inventory log_resource.yml

使用Ansible管理Kubernetes資源

套用JSON Patch操作

JSON Patch是一種描述JSON檔案變更的格式。要手動將JSON patch操作套用到現有的Kubernetes物件,可以使用kubectl patch命令。此命令需要兩個引數:物件名稱和JSON patch檔案。

patch檔案應包含一個或多個操作,以JSON或YAML格式表示,您希望將這些操作套用到物件上。例如,要為現有的pod新增一個新的標籤,可以建立一個包含以下YAML的patch檔案,如清單6-23所示。

清單6-23. patch-file.yaml檔案

- op: add
  path: /metadata/labels/new-label
  value: new-value

然後,可以使用以下命令將此patch套用到nginx-server pod物件:

$ kubectl patch pod nginx-server --patch "$(cat patch-file.yaml)"

這將為pod新增新的標籤。您可以使用相同的命令和不同的patch檔案對叢集中的其他物件進行更改。

也可以使用如清單6-24所示的Ansible Playbook自動執行上述操作。

清單6-24. patch.yml檔案

---
- name: k8s patch
  hosts: all
  vars:
    mypod: "nginx-server"
    myproject: "ansible-examples"
  tasks:
  - name: patch a Pod
    kubernetes.core.k8s_json_patch:
      kind: Pod
      namespace: "{{ myproject }}"
      name: "{{ mypod }}"
      patch:
      - op: add
        path: /metadata/labels/new-label
        value: new-value

程式碼解析:

此Ansible Playbook定義了一個名為k8s patch的遊戲,目標主機為all。在vars段中定義了兩個變數:mypodmyproject,分別代表pod的名稱和專案的名稱。在tasks段中,定義了一個名為patch a Pod的任務,使用kubernetes.core.k8s_json_patch模組對指定的pod進行patch操作。

使用localhost inventory執行此程式碼,如清單6-25所示。

清單6-25. Inventory檔案

localhost ansible_connection=local

執行patch.yml Ansible Playbook:

$ ansible-playbook -i inventory patch.yml

成功執行的輸出包括:

  • Play recap狀態:ok=2 changed=1
  • Task狀態:TASK [patch a Pod] changed: [localhost]

複製檔案和目錄到和從Pod

在Kubernetes中,將檔案和目錄複製到和從pod中是非常有用的,尤其是在開發的早期階段或進行一些調查時。對於手動操作,可以使用kubectl cp命令。此命令允許您在pod和本地檔案系統之間複製檔案和目錄。命令的語法是kubectl cp <source> <destination>,其中source可以是pod或本地檔案系統,destination可以是pod或本地檔案系統。

例如,要將檔案從pod複製到本地檔案系統,可以使用以下命令:

$ kubectl cp <pod-name>:/path/to/file /local/destination/path

同樣地,要將檔案從本地檔案系統複製到pod,可以使用以下命令:

$ kubectl cp /local/source/path <pod-name>:/path/to/destination

您可以使用kubernetes.core.k8s_cp Ansible模組自動執行此操作。引數state定義了您想要的預設操作是將資料從本地複製到pod(to_pod選項)還是從pod複製到本地(from_pod選項)。

清單6-26中的Ansible Playbook將資料從名為nginx-server的pod中的/data目錄複製到名為/tmp/data的本地資料夾。

清單6-26. cp.yml檔案

---
- name: k8s copy
  hosts: all
  vars:
    mypod: "nginx-server"
    myproject: "ansible-examples"
    remote_path: "/data"
    local_path: "/tmp/data"
    direction: "from_pod"
  tasks:
  - name: copy data
    kubernetes.core.k8s_cp:
      namespace: "{{ myproject }}"
      pod: "{{ mypod }}"
      remote_path: "{{ remote_path }}"
      local_path: "{{ local_path }}"
      state: "{{ direction }}"

程式碼解析:

此Ansible Playbook定義了一個名為k8s copy的遊戲,目標主機為all。在vars段中定義了五個變數:mypodmyprojectremote_pathlocal_pathdirection,分別代表pod的名稱、專案的名稱、遠端路徑、本地路徑和複製方向。在tasks段中,定義了一個名為copy data的任務,使用kubernetes.core.k8s_cp模組進行檔案複製。

使用如清單6-27所示的localhost inventory執行此程式碼。

清單6-27. Inventory檔案

localhost ansible_connection=local

執行您的cp.yml Ansible Playbook:

$ ansible-playbook -i inventory cp.yml

成功執行的輸出包括:

  • Play recap狀態:ok=2 changed=1
  • Task狀態:TASK [copy data] changed: [localhost]

管理Kubernetes上的服務

要管理Kubernetes上的服務,可以使用kubectl命令列工具。此工具允許您在Kubernetes叢集中建立、編輯、刪除和檢視服務。

要建立服務,可以使用kubectl expose命令,該命令將佈署或pod作為引數。

要編輯服務,可以使用將在編輯器中開啟服務定義的 kubectl edit 命令。

要刪除服務,可以使用 kubectl delete 命令,該命令將服務名稱和名稱空間作為引數。

要檢視服務,可以使用 kubectl get 命令,該命令將服務名稱和名稱空間作為引數。

您還可以使用 kubectl describe 命令來檢視有關服務的詳細資訊。

您可以使用如清單6-28所示的Ansible Playbook自動管理Kubernetes叢集上的服務。

清單6-28. service.yml檔案

---
- name: k8s service
  hosts: all
  tasks:
  - name: expose https port with ClusterIP
    kubernetes.core.k8s_service:
      state: present
      name: port-https
      namespace: default
      ports:
      - port: 443
        protocol: TCP
      selector:
        key: special

程式碼解析:

此Ansible Playbook定義了一個名為 k8s service 的遊戲,目標主機為 all. 在 tasks. 中定義了一個名為 expose https port with ClusterIP. 的任務. 使用 kubernetes.core.k8s_service. 對指定的服務進行操作.

透過指定 localhost. 在inventory中執行此程式碼,如 清單6-29. 所示。

清單6-29. Inventory檔案

localhost ansible_connection=local 

執行您的service.yml Ansible Playbook:

$ ansible-playbook -i inventory service.yml 

Kubernetes 節點管理:Taint、Drain、Cordon 與 Uncordon 操作詳解

在 Kubernetes 叢集管理中,維護節點的狀態對於確保系統的穩定性和可靠性至關重要。為了達到這一目的,Kubernetes 提供了多種工具和操作,包括 Taint、Drain、Cordon 和 Uncordon。本文將探討這些操作的原理、應用場景以及如何使用 Ansible Playbook 來自動化這些操作。

Taint Nodes:節點汙染

Taint 是 Kubernetes 中用於標記節點的一種機制,目的是避免不符合特定條件的 Pod 被排程到這些節點上。典型的應用場景包括將具有特殊硬體(如 GPU)的節點保留給需要這些資源的 Pod,或者在進行節點維護時避免新的 Pod 被排程到該節點。

使用 Ansible Taint 節點

以下是一個使用 Ansible Playbook 對節點進行 Taint 操作的範例(taint.yml 檔案):

---
- name: k8s taint
  hosts: all
  vars:
    mynode: "k8s.ansiblepilot.com"
  tasks:
  - name: taint node
    kubernetes.core.k8s_taint:
      state: present
      name: "{{ mynode }}"
      taints:
      - effect: NoExecute
        key: "key1"
        value: "value1"
      - effect: NoSchedule
        key: "key1"
        value: "value1"

內容解密:

  1. state: present 表示如果 Taint 不存在,則建立它。
  2. name: "{{ mynode }}" 指定要進行 Taint 操作的節點。
  3. taints 部分定義了 Taint 的詳細資訊,包括 effect(影響)、key(鍵)和 value(值)。
    • effect 可以是 NoScheduleNoExecute,前者阻止新的 Pod 被排程到節點上,後者除了阻止排程,還會驅逐現有的 Pod。
    • keyvalue 用於標識 Taint 的具體內容。

執行該 Playbook 的命令如下:

$ ansible-playbook -i inventory taint.yml

Drain、Cordon 和 Uncordon Nodes:節點維護操作

Drain:安全驅逐 Pod

Drain 操作用於在維護節點之前安全地驅逐其上的 Pod。它會嘗試刪除節點上的所有 Pod,除了由 ReplicationController、Job 或 DaemonSet 管理的映象 Pod。

Cordon:標記節點為不可排程

Cordon 操作將節點標記為不可排程,防止新的 Pod 被排程到該節點上,但不會影響現有的 Pod。

Uncordon:還原節點的可排程狀態

Uncordon 操作與 Cordon 相反,它將節點還原為可排程狀態,允許新的 Pod 被排程到該節點上。

使用 Ansible Playbook 執行 Drain、Cordon 和 Uncordon 操作

以下是使用 Ansible Playbook 執行這些操作的範例:

  • Drain 操作drain.yml 檔案):
---
- name: k8s drain
  hosts: all
  vars:
    mynode: "k8s.ansiblepilot.com"
    grace_period: 600
  tasks:
  - name: drain node
    kubernetes.core.k8s_drain:
      state: drain
      name: "{{ mynode }}"
      delete_options:
        terminate_grace_period: "{{ grace_period }}"

內容解密:

  1. state: drain 表示要執行 Drain 操作。
  2. name: "{{ mynode }}" 指定目標節點。
  3. delete_options 中的 terminate_grace_period 設定了刪除 Pod 時的優雅終止週期。
  • Cordon 操作cordon.yml 檔案):
---
- name: k8s cordon
  hosts: all
  vars:
    mynode: "k8s.ansiblepilot.com"
  tasks:
  - name: cordon node
    kubernetes.core.k8s_drain:
      state: cordon
      name: "{{ mynode }}"

內容解密:

  1. state: cordon 表示將節點標記為不可排程。
  • Uncordon 操作uncordon.yml 檔案):
---
- name: k8s uncordon
  hosts: all
  vars:
    mynode: "k8s.ansiblepilot.com"
  tasks:
  - name: uncordon node
    kubernetes.core.k8s_drain:
      state: uncordon
      name: "{{ mynode }}"

內容解密:

  1. state: uncordon 表示還原節點的可排程狀態。

執行這些 Playbook 的命令與 Taint 操作類別似,只需替換相應的 Playbook 檔名即可。