镜像备份参考

1、提前准备好备份镜像存放地方
2、根据实际情况使用K8S定时任务还是Linux定时任务
3、根据实际节点数量进行备份

备份脚本

docker 方式

ConfigMap

apiVersion: v1
data:
  backup.sh: |-
    #!/usr/bin/env sh

    # 如果不存在 images 目录,则创建
    [ -d ./images ] || mkdir ./images

    # 获取所有的 Docker 镜像列表,排除 REPOSITORY、rancher 和 <none> 的条目
    docker images | grep -v REPOSITORY | grep -v rancher | grep -v "<none>" | while read -r line; do
        # 获取镜像名和版本号
        name=$(echo "$line" | awk '{print $1}')
        version=$(echo "$line" | awk '{print $2}')

        # 生成镜像文件名
        filename="${name##*/}-$version.tar"

        # 检查镜像文件是否已存在
        if [ -f "./images/$filename" ]; then
            echo "跳过:$filename"
        else
            echo "导出:$name:$version 为 ./images/$filename"
            docker save -o "./images/$filename" "$name:$version"
        fi
    done
kind: ConfigMap
metadata:
  name: pai-image-backup-conf
  namespace: pai-cloud

containerd 方式

ConfigMap

apiVersion: v1
data:
  backup.sh: |-
    #!/usr/bin/env sh

    # 如果不存在 images 目录,则创建
    [ -d ./images ] || mkdir ./images

    # 获取所有的 Docker 镜像列表,排除 REPOSITORY、rancher 和 <none> 的条目
    crictl images | grep -v IMAGE | grep -v rancher | grep -v "<none>" | while read -r line; do
        # 获取镜像名和版本号
        name=$(echo "$line" | awk '{print $1}')
        version=$(echo "$line" | awk '{print $2}')

        # 生成镜像文件名
        filename="${name##*/}-$version.tar"

        # 检查镜像文件是否已存在
        if [ -f "./images/$filename" ]; then
            echo "跳过:$filename"
        else
            echo "导出:$name:$version 为 ./images/$filename"
            ctr -n k8s.io i export "./images/$filename" "$name:$version"
        fi
    done
kind: ConfigMap
metadata:
  name: pai-image-backup-conf
  namespace: pai-cloud

定时任务

工作负载

apiVersion: batch/v1
kind: CronJob
metadata:
  annotations:
    k8s.kuboard.cn/displayName: 镜像备份
  labels:
    k8s.kuboard.cn/name: pai-image-backup
  name: pai-image-backup
  namespace: pai-cloud
spec:
  concurrencyPolicy: Forbid
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      creationTimestamp: null
      labels:
        k8s.kuboard.cn/name: pai-image-backup
    spec:
      backoffLimit: 1
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
            - command:
                - sh
                - /home/backup.sh
              image: 'centos:centos7.9.2009'
              imagePullPolicy: IfNotPresent
              name: pai-image-backup
              resources: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /data
                  name: volume-backup
                - mountPath: /home/backup.sh
                  name: volume-sh
                  subPath: backup.sh
                - mountPath: /etc/localtime
                  name: host-time
                - mountPath: /usr/bin/docker
                  name: docker
                - mountPath: /var/run/
                  name: dockersock
          dnsPolicy: ClusterFirst
          restartPolicy: Never
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
            - name: volume-backup
              nfs:
                path: /data/sdb/nfs/imagebackup
                server: 192.168.1.100
            - configMap:
                defaultMode: 420
                name: pai-image-backup-conf
              name: volume-sh
            - hostPath:
                path: /etc/localtime
                type: ''
              name: host-time
            - hostPath:
                path: /usr/bin/docker
                type: File
              name: docker
            - hostPath:
                path: /var/run/
                type: Directory
              name: dockersock
  schedule: 0 2 * * *
  successfulJobsHistoryLimit: 3
  suspend: false

Kubernets ETCD 数据库备份

可用于集群环境异常时偿试恢复,备份命令如下:

sealos etcd save --name etcd-202310250830.bak

# 默认输出在/opt/sealos/etcd-backup目录下

注意:备份出来的文件存放在安全的异地空间

定时yaml备份到NFS


---
apiVersion: v1
data:
  backup.sh: |-
    #!/bin/bash

    # Set the base directory for storing the backups
    base_dir="/data"
    log_dir="$base_dir/$(date +'%Y-%m-%d')"

    echo "Create the directory $log_dir if it doesn't exist"
    mkdir -p $log_dir

    echo Backup the deployments
    kubectl get deploy -n pai-cloud -oyaml > "$log_dir/deployment.yaml"

    echo Backup the services
    kubectl get svc -oyaml -n pai-cloud > "$log_dir/service.yaml"

    echo Backup the ingresses
    kubectl get ing -oyaml -n pai-cloud > "$log_dir/ingress.yaml"

    echo Backup the configmaps
    kubectl get configmap -n pai-cloud -oyaml > "$log_dir/configmap.yaml"

    echo Delete backups older than 1 month
    find $base_dir -mindepth 1 -type d -mtime +30 -exec rm -rf {} \;
kind: ConfigMap
metadata:
  name: pai-yaml-backup-conf
  namespace: pai-cloud


---
apiVersion: batch/v1
kind: CronJob
metadata:
  annotations:
    k8s.kuboard.cn/displayName: 工作负载定时备份
  labels:
    k8s.kuboard.cn/name: pai-yaml-backup
  name: pai-yaml-backup
  namespace: pai-cloud
spec:
  concurrencyPolicy: Forbid
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      labels:
        k8s.kuboard.cn/name: pai-yaml-backup
    spec:
      backoffLimit: 1
      template:
        spec:
          containers:
            - command:
                - sh
                - /home/backup.sh
              image: busybox
              imagePullPolicy: IfNotPresent
              name: pai-yaml-backup
              resources: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /home/backup.sh
                  name: volume-sh
                  subPath: backup.sh
                - mountPath: /data
                  name: volume-data
                - mountPath: /usr/bin/kubectl
                  name: volume-kubectl
                - mountPath: /root/.kube/config
                  name: volume-config
          dnsPolicy: ClusterFirst
          hostAliases:
            - hostnames:
                - apiserver.cluster.local
              ip: 192.168.10.2
          nodeName: k8s-master-1
          restartPolicy: Never
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
            - configMap:
                defaultMode: 420
                items:
                  - key: backup.sh
                    path: backup.sh
                name: pai-yaml-backup-conf
              name: volume-sh
            - name: volume-data
              nfs:
                path: /data/nfs/yaml
                server: 192.168.10.34
            - hostPath:
                path: /usr/bin/kubectl
                type: File
              name: volume-kubectl
            - hostPath:
                path: /root/.kube/config
                type: File
              name: volume-config
  schedule: 0 1 * * *
  successfulJobsHistoryLimit: 1
  suspend: false

数据库备份到NFS

---
apiVersion: v1
data:
  backup.sh: >-
    #!/usr/bin/env bash

    #保存数量
    BACKUP_NUMBER=30

    #当前日期
    DATE=$(date +%Y-%m-%d)
    BACKUP_ROOT=/data

    if [ ! -n $BACKUP_PATH ] ; then
      BACKUP_ROOT=$BACKUP_PATH
    fi  

    BACKUP_FILEDIR=$BACKUP_ROOT/$DATE
    #如果文件夹不存在则创建
    if [ ! -d $BACKUP_FILEDIR ] ; then     
        mkdir -p $BACKUP_FILEDIR;
    fi

    #查询所有数据库
    DATABASES=$(mysql -h$DATABASE_HOST -u$DATABASE_USER -p"$DATABASE_PASSWORD"
    -P$DATABASE_PORT -e "show databases" | grep -Ev
    "Database|sys|information_schema|performance_schema|mysql")

    #循环数据库进行备份
    for db in $DATABASES
    do
      echo
      if [[ "${db}" =~ "+" ]] || [[ "${db}" =~ "|" ]];then
        echo "jump over ${db}"
      else
        echo ----------$BACKUP_FILEDIR/${db}_$DATE.sql.gz $(date) BEGIN----------
        mysqldump -h$DATABASE_HOST -u$DATABASE_USER -p"$DATABASE_PASSWORD" -P$DATABASE_PORT --default-character-set=utf8 -q --lock-all-tables --flush-logs -E -R --triggers -B ${db} | gzip > $BACKUP_FILEDIR/${db}_$DATE.sql.gz
        echo ${db}
        echo ----------$BACKUP_FILEDIR/${db}_$DATE.sql.gz $(date) COMPLETE----------
        echo
      fi
    done

    #找出需要删除的备份
    delfile=`ls -l -crt $BACKUP_ROOT | awk '{print $9 }' | grep "-" | head -1`

    #判断现在的备份数量是否大于$BACKUP_NUMBER
    count=`ls -l -crt $BACKUP_ROOT | awk '{print $9 }' | grep "-" | wc -l`

    if [ $count -gt $BACKUP_NUMBER ] ;  then
      #删除最早生成的备份,只保留BACKUP_NUMBER数量的备份
      rm -rf $BACKUP_ROOT/$delfile
      #写删除文件日志
      echo "delete $delfile" >> $BACKUP_ROOT/log.txt
    fi  
kind: ConfigMap
metadata:
  name: pai-database-backup-conf
  namespace: pai-cloud

---
apiVersion: batch/v1
kind: CronJob
metadata:
  annotations:
    k8s.kuboard.cn/displayName: 数据库定时备份
  labels:
    k8s.kuboard.cn/name: pai-database-backup
  name: pai-database-backup
  namespace: pai-cloud
spec:
  concurrencyPolicy: Forbid
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      labels:
        k8s.kuboard.cn/name: pai-database-backup
    spec:
      backoffLimit: 1
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
            - command:
                - bash
                - /home/backup.sh
              env:
                - name: DATABASE_HOST
                  value: 192.168.10.21
                - name: DATABASE_USER
                  value: root
                - name: DATABASE_PORT
                  value: '3306'
                - name: DATABASE_PASSWORD
                  value: BHYG@root987
              image: 'mysql:8.0.30'
              imagePullPolicy: IfNotPresent
              name: pai-database-backup
              resources: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /etc/localtime
                  name: host-time
                - mountPath: /home/backup.sh
                  name: sh
                  subPath: backup.sh
                - mountPath: /data
                  name: backup
          dnsPolicy: ClusterFirst
          nodeName: k8s-master-1
          restartPolicy: Never
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          volumes:
            - hostPath:
                path: /etc/localtime
                type: ''
              name: host-time
            - configMap:
                defaultMode: 420
                items:
                  - key: backup.sh
                    path: backup.sh
                name: pai-database-backup-conf
              name: sh
            - name: backup
              nfs:
                path: /data/nfs/mysql
                server: 192.168.10.34
  schedule: 0 1 * * *
  successfulJobsHistoryLimit: 1
  suspend: false
文档更新时间: 2024-09-02 13:22   作者:姚连洲