KubeSphere 日誌備份與恢復實踐

爲何須要日誌備份

KubeSphere 日誌系統使用 Fluent Bit + ElasticSearch 的日誌採集存儲方案,並經過 Curator 實現對 Index 的生命週期管理,按期清理久遠日誌。對於有日誌審計和災備需求的場景來講,KubeSphere 默認的 7 天日誌保留策略遠遠不夠,僅備份 ElasticSearch 數據盤並不能保證數據可恢復性和完整性html

ElasticSearch 開源社區提供了 SnapShot API 幫助咱們實現長期的存儲快照和恢復。本文介紹如何針對 KubeSphere(版本 2.1.0)內置 ElasticSearch (版本 6.7.0)組件進行改造,實踐日誌備份,以知足審計和災備的需求。git

注:若是是數據量較小、帶查詢條件的日誌導出場景,可使用 KubeSphere 一鍵導出功能,或嘗試使用 elasticsearch-dump 工具。外接商業版 ElasticSearch 的 KubeSphere 用戶也能夠直接開啓 ElasticSearch X-Pack 中提供的 SnapShot Lifecycle Management 功能。

前提條件

執行存儲快照前,咱們須要在 ElasticSearch 集羣中註冊存放快照文件的倉庫。快照倉庫可使用共享文件系統,好比 NFS。其餘存儲類型,如 AWS S3,須要單獨安裝 repository 插件 支持。github

咱們以 NFS 爲例。共享快照倉庫須要掛載到 ElasticSearch 的全部主節點和數據節點,並在 elasticsearch.yaml 中配置 path.repo 參數。NFS 支持 ReadWriteMany 訪問模式,因此使用 NFS 很是合適。json

第一步,咱們首先準備一個 NFS 服務端,例如本教程中使用的 QingCloud vNAS 服務,共享目錄路徑爲 /mnt/shared_dir。segmentfault

而後在 KubeSphere 環境上準備 NFS 類型的 StorageClass,後面咱們爲快照倉庫申請 Persistent Volume 的時候會用到。本文環境已經在安裝時配置了 NFS 存儲,因此無需額外操做。有安裝須要的讀者請參考 KubeSphere 官方文檔,修改 conf/common.yaml 並從新執行 install.sh 腳本。api

1. ElasticSearch Setup

在 KubeSphere 中,ElasticSearch 主節點爲有狀態副本集 elasticsearch-logging-discovery,數據節點爲 elasticsearch-logging-data,本教程環境爲一主兩從:安全

$ kubectl get sts -n kubesphere-logging-system
NAME                              READY   AGE
elasticsearch-logging-data        2/2     18h
elasticsearch-logging-discovery   1/1     18h

第一步,咱們爲 ElasticSearch 集羣 snapshot repository 準備持久化卷:bash

cat <<EOF | kubectl create -f -
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: elasticsearch-logging-backup
  namespace: kubesphere-logging-system
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 100Gi
  # 根據你的環境填充 storageClassName 字段
  storageClassName: nfs-client
EOF

第二步,修改 elasticsearch.yml 配置文件,將 NFS 目錄路徑註冊到各個主從節點。在 KubeSphere 中,elasticsearch.yml 配置在 ConfigMap elasticsearch-logging 裏能夠找到。在最後一行,添加 path.repo: ["/usr/share/elasticsearch/backup"]網絡

第三步,修改 StatefulSet YAML,將存儲卷掛載到 ElasticSearch 各節點,並經過 chown 命令,在 initContainer
啓動時,初始化快照倉庫文件夾的全部者用戶和用戶組爲 elasticsearch。app

在這一步特別須要注意的是,咱們沒法直接 kubectl edit 修改 Stateful,須要先把 yaml 內容備份下來,修改完後再 kubectl apply 從新應用。

kubectl get sts -n kubesphere-logging-system elasticsearch-logging-data -oyaml > elasticsearch-logging-data.yml
kubectl get sts -n kubesphere-logging-system elasticsearch-logging-discovery -oyaml > elasticsearch-logging-discovery.yml

修改 yaml 文件,以修改上面生成的 elasticsearch-logging-data.yml 爲例,主節點的 yaml 文件同樣修改。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    # 因爲篇幅緣由,此處省略
    # ...
  name: elasticsearch-logging-data
  namespace: kubesphere-logging-system  
  # -------------------------------------------------
  #   註釋或刪除非 labels、name、namespace 的元信息字段   
  # ------------------------------------------------- 
  # resourceVersion: "109019"
  # selfLink: /apis/apps/v1/namespaces/kubesphere-logging-system/statefulsets/elasticsearch-logging-data
  # uid: 423adffe-271f-4657-9078-1a75c387eedc
spec:
  # ...
  template:
    # ...
    spec:
      # ...
      containers:
      - name: elasticsearch
        # ...
        volumeMounts:
        - mountPath: /usr/share/elasticsearch/data
          name: data
        # --------------------------
        #   添加 backup Volume 掛載   
        # --------------------------
        - mountPath: /usr/share/elasticsearch/backup
          name: backup  
        - mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
          name: config
          subPath: elasticsearch.yml
        # ...
      initContainers:
      - name: sysctl
        # ...
      - name: chown
        # --------------------------------------
        #   修改 command,調整快照倉庫文件夾擁有者   
        # --------------------------------------
        command:
        - /bin/bash
        - -c
        - |
          set -e; set -x; chown elasticsearch:elasticsearch /usr/share/elasticsearch/data; for datadir in $(find /usr/share/elasticsearch/data -mindepth 1 -maxdepth 1 -not -name ".snapshot"); do
            chown -R elasticsearch:elasticsearch $datadir;
          done; chown elasticsearch:elasticsearch /usr/share/elasticsearch/logs; for logfile in $(find /usr/share/elasticsearch/logs -mindepth 1 -maxdepth 1 -not -name ".snapshot"); do
            chown -R elasticsearch:elasticsearch $logfile;
          done; chown elasticsearch:elasticsearch /usr/share/elasticsearch/backup; for backupdir in $(find /usr/share/elasticsearch/backup -mindepth 1 -maxdepth 1 -not -name ".snapshot"); do
            chown -R elasticsearch:elasticsearch $backupdir;
          done
        # ...
        volumeMounts:
        - mountPath: /usr/share/elasticsearch/data
          name: data
        # --------------------------
        #   添加 backup Volume 掛載   
        # --------------------------
        - mountPath: /usr/share/elasticsearch/backup
          name: backup  
      # ...
      tolerations:
      - key: CriticalAddonsOnly
        operator: Exists
      - effect: NoSchedule
        key: dedicated
        value: log
      volumes:
      - configMap:
          defaultMode: 420
          name: elasticsearch-logging
        name: config
      # -----------------------
      #   指定第一步中建立的 PVC   
      # -----------------------
      - name: backup
        persistentVolumeClaim:
          claimName: elasticsearch-logging-backup
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
      storageClassName: nfs-client
      volumeMode: Filesystem
# --------------------------------------
#   註釋或刪除 status 字段   
# --------------------------------------
#     status:
#       phase: Pending
# status:
#   ...

修改完後,能夠刪除 ElasticSearch StatefulSet,並從新應用新 yaml:

kubectl delete sts -n kubesphere-logging-system elasticsearch-logging-data
kubectl delete sts -n kubesphere-logging-system elasticsearch-logging-discovery

kubectl apply -f elasticsearch-logging-data.yml
kubectl apply -f elasticsearch-logging-discovery.yml

最後一步,等待 ElasticSearch 所有節點啓動後,調用 Snapshot API 建立出一個名爲 ks-log-snapshots 的 repository,並開啓壓縮功能:

curl -X PUT "elasticsearch-logging-data.kubesphere-logging-system.svc:9200/_snapshot/ks-log-snapshots?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/usr/share/elasticsearch/backup",
    "compress": true
  }
}
'

返回 "acknowledged": true 表示成功。至此,ElasticSearch 集羣快照功能的準備工做已經就緒。後面只須要定時的調用 Snapshot API 實現增量備份便可。ElasticSearch 自動化增量備份能夠藉助 Curator 來完成。

2. 使用 Curator 定時快照

ElasticSearch Curator 能幫助管理 ElasticSearch 索引和快照。接下來,咱們使用 Curator 來實現自動化定時日誌備份。KubeSphere 日誌組件默認包含了 Curator(被部署爲一個 CronJob,天天凌晨 1 點執行)來管理索引,咱們能夠藉助同一個 Curator。Curator 的執行規則在 ConfigMap 中能夠找到。

這裏咱們須要在 action_file.yml 字段值中增長兩個 action:snapshot 和 delete_snapshots。並把這個規則優先級提升到 delete_indices 前。該配置規定了 snapshot 建立命名方式爲 snapshot-%Y%m%d%H%M%S,保留 45 天的 snapshots。具體參數含義可參考 Curator Reference。

actions:
  1:
    action: snapshot
    description: >-
      Snapshot ks-logstash-log prefixed indices with the default snapshot 
      name pattern of 'snapshot-%Y%m%d%H%M%S'.
    options:
      repository: ks-log-snapshots
      name: 'snapshot-%Y%m%d%H%M%S'
      ignore_unavailable: False
      include_global_state: True
      partial: False
      wait_for_completion: True
      skip_repo_fs_check: False
      # If disable_action is set to True, Curator will ignore the current action
      disable_action: False
    filters:
    - filtertype: pattern
      kind: prefix
      # You may change the index pattern below to fit your case
      value: ks-logstash-log-
  2: 
    action: delete_snapshots
    description: >-
      Delete snapshots from the selected repository older than 45 days
      (based on creation_date), for 'snapshot' prefixed snapshots.
    options:
      repository: ks-log-snapshots
      ignore_empty_list: True
      # If disable_action is set to True, Curator will ignore the current action
      disable_action: False
    filters:
    - filtertype: pattern
      kind: prefix
      value: snapshot-
      exclude:
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y%m%d%H%M%S'
      unit: days
      unit_count: 45
  3:
    action: delete_indices
    # 原有內容不變
    # ...

3. 日誌恢復與查看

當咱們須要回顧某幾天前的日誌時,咱們能夠經過快照恢復,好比 11 月 12 日的日誌。首先咱們須要檢查最新的 Snapshot:

curl -X GET "elasticsearch-logging-data.kubesphere-logging-system.svc:9200/_snapshot/ks-log-snapshots/_all?pretty"

而後經過最新的 Snapshot 恢復指定日期的索引(也能夠選擇恢復所有)。這個 API 會恢復日誌索引到數據盤,因此請確保數據盤的存儲空間足夠充足。另外,你也能夠直接備份對應的 PV(Snapshot 倉庫對應的存儲卷是能夠直接被用來備份的),掛載到其餘 ElasticSearch 集羣,將日誌恢復到其餘 ElasticSearch 集羣中使用。

curl -X POST "elasticsearch-logging-data.kubesphere-logging-system.svc:9200/_snapshot/ks-log-snapshots/snapshot-20191112010008/_restore?pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "ks-logstash-log-2019.11.12",
  "ignore_unavailable": true,
  "include_global_state": true,
}
'

根據日誌量的大小,須要等到的時間幾分鐘不等。咱們就能夠經過 KubeSphere 日誌 Dashboard 查看日誌了。

參考文檔

ElasticSearch Reference: Snapshot And Restore

Curator Reference: snapshot

Meetup 預告


KubeSphere (https://github.com/kubesphere... 是一個開源的以應用爲中心的容器管理平臺,支持部署在任何基礎設施之上,並提供簡單易用的 UI,極大減輕平常開發、測試、運維的複雜度,旨在解決 Kubernetes 自己存在的存儲、網絡、安全和易用性等痛點,幫助企業輕鬆應對敏捷開發與自動化監控運維、端到端應用交付、微服務治理、多租戶管理、多集羣管理、服務與網絡管理、鏡像倉庫、AI 平臺、邊緣計算等業務場景。

相關文章
相關標籤/搜索