KubeSphere 日志備份與恢復實踐


為什么需要日志備份

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

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

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

前提條件

執行存儲快照前,我們需要在 ElasticSearch 集群中注冊存放快照文件的倉庫。快照倉庫可以使用共享文件系統,比如 NFS。其他存儲類型,如 AWS S3,需要單獨安裝 repository 插件 支持。

我們以 NFS 為例。共享快照倉庫需要掛載到 ElasticSearch 的所有主節點和數據節點,並在 elasticsearch.yaml 中配置 path.repo 參數。NFS 支持 ReadWriteMany 訪問模式,所以使用 NFS 非常合適。

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

然后在 KubeSphere 環境上准備 NFS 類型的 StorageClass,后面我們為快照倉庫申請 Persistent Volume 的時候會用到。本文環境已經在安裝時配置了 NFS 存儲,所以無需額外操作。有安裝需要的讀者請參考 KubeSphere 官方文檔,修改 conf/common.yaml 並重新執行 install.sh 腳本。

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 准備持久化卷:

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。

在這一步特別需要注意的是,我們無法直接 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/kubesphere) 是一個開源的以應用為中心的容器管理平台,支持部署在任何基礎設施之上,並提供簡單易用的 UI,極大減輕日常開發、測試、運維的復雜度,旨在解決 Kubernetes 本身存在的存儲、網絡、安全和易用性等痛點,幫助企業輕松應對敏捷開發與自動化監控運維、端到端應用交付、微服務治理、多租戶管理、多集群管理、服務與網絡管理、鏡像倉庫、AI 平台、邊緣計算等業務場景。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM