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