Kubernetes下各种资源的每日定期备份

这个问题其实比较有意思,同事早上用k9s修改Deployment的时候误删了一个deployment,这下麻烦了。那其实自己也有过类似操作,迁移的时候误删过influxdb,最后考古才弄回来,也误删过一个ns的secret,都是大麻烦!

其实系统是有velero备份的,但是从那里面去弄出单独一个ns的deploy进行恢复,怎么也来不及,那幸好有每日资源备份,直接拿过来重建即可。分享一下脚本,那注意一下,因为主节点的etcd也是非常要命的东西,也必须备一下,防止主节点脑裂,到时候可以用备份进行恢复。

 1#!/bin/bash
 2
 3export KUBECONFIG=/root/.kube/config
 4export PATH=/usr/local/bin:$PATH
 5
 6# K8s 资源备份脚本
 7# 目标:遍历所有命名空间,将 Deployment, Secret, Ingress, 和 Service 导出为 YAML 文件。
 8
 9# 设置输出目录
10OUTPUT_DIR="/root/k8s_deployments_backup/$(date +%Y%m%d)"
11# 要备份的资源类型及其对应的 kubectl 别名
12# 注意:Secret 资源会备份所有类型,包括自动生成的 Service Account Tokens。
13RESOURCE_TYPES=("deployments" "secrets" "ingresses" "services")
14
15# 确保脚本在遇到错误时立即退出
16set -e
17
18echo "--- 正在创建输出目录: $OUTPUT_DIR ---"
19mkdir -p "$OUTPUT_DIR"
20
21# ----------------------------------------------------
22# 核心函数:备份指定类型的资源
23# 参数: $1 = 资源类型 (如 deployment), $2 = 命名空间, $3 = 输出目录
24# ----------------------------------------------------
25backup_resource() {
26    local TYPE=$1
27    local NAMESPACE=$2
28    local DIR=$3
29
30    # 获取当前命名空间中所有该类型资源的名称
31    # 使用 2>/dev/null 隐藏找不到资源时的错误信息
32    local RESOURCES=$(kubectl get "$TYPE" -n "$NAMESPACE" -o jsonpath='{.items[*].metadata.name}' 2>/dev/null)
33
34    if [ -z "$RESOURCES" ]; then
35        echo "  [信息] 命名空间 $NAMESPACE 中未找到 $TYPE。"
36        return
37    fi
38
39    echo "  -> 找到 ${#RESOURCES[@]}$TYPE,正在导出..."
40
41    # 遍历每个资源并保存 YAML
42    for RESOURCE in $RESOURCES; do
43        # 文件名格式: namespace-resource_type-resourcename.yaml
44        local FILE_NAME="${NAMESPACE}-${TYPE}-${RESOURCE}.yaml"
45        local FILE_PATH="$DIR/$FILE_NAME"
46
47        # 使用 kubectl get 获取 YAML,并通过管道和 sed 清理元数据字段
48        kubectl get "$TYPE" "$RESOURCE" -n "$NAMESPACE" -o yaml --ignore-not-found |
49          # 清理元数据字段,使 YAML 更干净,便于重新应用
50          sed '/^  creationTimestamp:/d' |
51          sed '/^  resourceVersion:/d' |
52          sed '/^  uid:/d' |
53          sed '/^  selfLink:/d' |
54          sed '/^  status:/d' \
55          > "$FILE_PATH"
56
57        # 检查 Secret 是否为 Service Account Token,如果是,则发出警告
58        if [ "$TYPE" == "secrets" ] && grep -q 'kubernetes.io/service-account.name' "$FILE_PATH"; then
59             echo "    [警告] Secret $RESOURCE 是 Service Account Token,通常不需要备份。"
60        fi
61    done
62}
63
64# 1. 获取所有命名空间 (Namespace)
65NAMESPACES=$(kubectl get ns -o jsonpath='{.items[*].metadata.name}')
66
67if [ -z "$NAMESPACES" ]; then
68    echo "错误:未找到任何命名空间。请检查 kubectl 配置和集群连接。"
69    exit 1
70fi
71
72echo "找到以下命名空间: $NAMESPACES"
73echo "----------------------------------------------------"
74
75# 2. 遍历每个命名空间和资源类型
76for NAMESPACE in $NAMESPACES; do
77    echo "--- 处理命名空间: $NAMESPACE ---"
78    
79    for TYPE in "${RESOURCE_TYPES[@]}"; do
80        backup_resource "$TYPE" "$NAMESPACE" "$OUTPUT_DIR"
81    done
82    
83    echo "--- 命名空间 $NAMESPACE 处理完成 ---"
84done
85
86ETCDCTL_API=3 etcdctl \
87--endpoints=https://10.10.240.3:2379 \
88--cacert=/etc/ssl/etcd/ca.pem \
89--cert=/etc/ssl/etcd/etcd-client.pem \
90--key=/etc/ssl/etcd/etcd-client-key.pem \
91snapshot save $OUTPUT_DIR/etcd-`date +%Y%m%d`-snapshot.db
92
93echo "===================================================="
94echo "✅ 所有指定资源已成功备份到目录: $OUTPUT_DIR"
95echo "===================================================="
96
97exit 0

AWS 放错在Private子网的机器如何用公网IP连进去
comments powered by Disqus