当前位置: 首页 > java >正文

Nexus仓库数据高可用备份与恢复方案(下)

#作者:闫乾苓

文章目录

    • Nexus服务中nexus-data 的数据(元数据)备份
      • 备份方式一,使用k8s cronjob定时备份nexus数据到minio
      • 备份方式一的故障模拟测试
      • 备份方式一的故障恢复验证
      • 备份方式二,配置实时同步备份
      • 备份方式二的故障恢复验证
  • 4、注意事项

Nexus服务中nexus-data 的数据(元数据)备份

注意:如果使用CephFS,GlusterFS等分布式文件系统作为nexus的持久化存储,本环节可以忽略。

因本例不具备CephFS,GlusterFS分布式文件存储环境,所以本章节将介绍如何对Nexus存储到 NFS中的数据进行有效的备份和恢复测试。

只要确保从NFS中备份出数据能在nfs-server 故障并有数据损坏时进行有效恢复,就能保证nexus的数据高可用。Blob Store中的数据由minio保障其高可用。

nexus-data 数据目录已经通过NFS storageClass 定义的pvc和pv进行了动态绑定,存储到NFS server中了,需要对这部分数据有效的备份。建议同时使用以下2中备份方式,以确保备份数据的有效性,

因绝大部分的的二级制构件数据都存储到了minio中,只有少部分的的元数据会存储到nexus-data目录,所以执行nexus-data目录数据的全量备份并不会占用大量的磁盘空间。

备份方式一,使用k8s cronjob定时备份nexus数据到minio

优点:
1.备份前停止服务,以确保数据的完整性
2.可根据实际业务需要,制定灵活的备份策略
3.每次均为全量备份
4.提供临时hostpath和minio两重冗余备份机制,增强备份数据的有效性

缺点:
1.备份期间须停止服务,会短暂中断业务
2.不能确保数据完全不丢失,最大的数据丢失间隔通常等于备份任务的时间间隔
CronJob备份策略及流程
本章节介绍使用k8s cronjob对nexus存储在nfs中的数据进行备份,可根据具体的业务数据高可用要求,制定不同的备份策略,比如:滚动备份最近7天的数据,每天1个全量备份
,流程如下:

  1. cronjob会按照cronjob YAML中设置的时间,生成jobs
  2. jobs会启动备份容器,启动后容器会挂载nexus服务YAML中定义pvc到容器中
  3. 容器中执行backup-script.sh脚本, 脚本使用kubect scale命令将replicas设置为0,即关闭nexus服务确保下一步打包备份数据时数据的有效性。
  4. nexus服务关闭后,使用tar命令打包备份nexus元数据并存放到临时目录
  5. 打包完成后为减少nexus服务不可用时间,立即使用kubectl scale将replicas设置为1,即启动nexus服务。
  6. 脚本使用minio的mc命令将tar备份文件上传到minio,以确保备份数据的安全性和有效性。
  7. 脚本自动删除超过7天的备份文件。

容器中执行nexus扩缩容的账号及权限
因为需要在cronjob定时备份启动的容器中执行nexus服务的关闭和启动(scale 0或1),所以需要配置账号的RBAC权限。
service-account.yaml

apiVersion: v1
kind: ServiceAccount
metadata:name: nexus-backup-cronjob-serviceaccountnamespace: nexus-2   # 替换为你的命名空间

role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: nexus-backup-cronjob-rolenamespace: nexus-2
rules:
- apiGroups: ["apps"]resources: ["deployments"]verbs: ["get", "update", "list"]
- apiGroups: ["apps"]resources: ["deployments/scale"]verbs: ["get", "update", "patch"]

role-binding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: cronjob-rolebindingnamespace: nexus-2  # 替换为你的命名空间
subjects:
- kind: ServiceAccountname: nexus-backup-cronjob-serviceaccountnamespace: nexus-2  # 替换为你的命名空间
roleRef:kind: Rolename: nexus-backup-cronjob-roleapiGroup: rbac.authorization.k8s.io

将YAML应用到系统中:

# kubectl apply -f service-account.yaml -f role.yaml -f role-binding.yaml
serviceaccount/nexus-backup-cronjob-serviceaccount created
role.rbac.authorization.k8s.io/nexus-backup-cronjob-role created
rolebinding.rbac.authorization.k8s.io/cronjob-rolebinding created

备份脚本
因为此脚本是在alpine容器中执行,alpine没有bash环境,所以此脚本首行改成/bin/sh
backup-script.sh

#!/bin/sh# 替换为你的 Deployment 名称和命名空间
DEPLOYMENT_NAME="devops-nexus"
NAMESPACE="nexus-2"
KUBECTL="/root/kubectl"stop_nexus() {
# 获取当前副本数
CURRENT_REPLICAS=$(${KUBECTL} get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.replicas}')# 检查当前副本数并执行相应的操作
if [ "$CURRENT_REPLICAS" -eq 1 ]; then# 如果当前副本数为1,则执行缩容到0的操作NEW_REPLICAS=0echo "Scaling $DEPLOYMENT_NAME in $NAMESPACE down from $CURRENT_REPLICAS to $NEW_REPLICAS replicas..."#/usr/local/bin/kubectl scale deployment $DEPLOYMENT_NAME -n $NAMESPACE --replicas=$NEW_REPLICAS${KUBECTL} scale deployment $DEPLOYMENT_NAME -n $NAMESPACE --replicas=$NEW_REPLICASif [ $? -eq 0 ]; thenecho "Scaled $DEPLOYMENT_NAME in $NAMESPACE to $NEW_REPLICAS replicas successfully."elseecho "Failed to scale $DEPLOYMENT_NAME in $NAMESPACE." >&2exit 1fi
else# 如果当前副本数不为1,则给出提示并以非0状态退出echo "Error: Cannot scale down $DEPLOYMENT_NAME in $NAMESPACE because current replicas is $CURRENT_REPLICAS (not 1)." >&2exit 1
fi
}start_nexus() {
# 获取当前副本数
CURRENT_REPLICAS=$(${KUBECTL} get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.replicas}')if  [ "$CURRENT_REPLICAS" -eq 0 ]; then# 如果需要扩容并且当前副本数为0,则执行扩容到1的操作NEW_REPLICAS=1echo "Scaling $DEPLOYMENT_NAME in $NAMESPACE up from $CURRENT_REPLICAS to $NEW_REPLICAS replicas..."${KUBECTL} scale deployment $DEPLOYMENT_NAME -n $NAMESPACE --replicas=$NEW_REPLICASif [ $? -eq 0 ]; thenecho "Scaled $DEPLOYMENT_NAME in $NAMESPACE to $NEW_REPLICAS replicas successfully."elseecho "Failed to scale $DEPLOYMENT_NAME in $NAMESPACE." >&2exit 1fi
else# 当前副本数不为0,则给出提示(如果需要的话)if [ "$CURRENT_REPLICAS" -ne 0 ]; thenecho "Error: Cannot scale up $DEPLOYMENT_NAME in $NAMESPACE because current replicas is $CURRENT_REPLICAS (not 0)." >&2exit 1fi
fi
}# 定义变量
SOURCE_DIR="/mnt/data"
MINIO_ENDPOINT="http://minio-service.minio.svc.cluster.local:29000"
MINIO_ACCESS_KEY="65WNgqImKSD3c0qX"
MINIO_SECRET_KEY="n7iXpeOECUX3u3OOmzGPmS9M7JT4Y2nd"
MINIO_BUCKET="nexus-data-backup"
DATE=$(date +%Y-%m-%d)
BACKUP_FILE="nexus-data-bak-${DATE}.tar.gz"
LOCAL_BACKUP_DIR="/tmp/backup"
MINIO_BACKUP_PATH="/${BACKUP_FILE}"# 创建本地备份目录(如果不存在)
mkdir -p ${LOCAL_BACKUP_DIR}# 为确保数据的完整性,备份数据前需要将nexus deployment 的replicas 设置为0,即关闭nexus服务。
stop_nexus# 执行备份
tar -czf ${LOCAL_BACKUP_DIR}/${BACKUP_FILE} -C ${SOURCE_DIR} .# 检查备份是否成功,如果失败脚本退出并恢复nexus服务。
if [ $? -ne 0 ]; thenecho "Backup failed " >&2# 即使在执行数据tar 打包失败,在脚本退出前,使用函数将nexus服务恢复start_nexusexit 1
fi# 备份成功,使用函数及时恢复nexus服务
start_nexus# 设置 MinIO 别名
mc alias set minio ${MINIO_ENDPOINT} ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY}# 检查别名设置是否成功
if [ $? -ne 0 ]; thenecho "Failed to set MinIO alias" >&2exit 1
fi# 上传备份文件到 MinIO
mc cp ${LOCAL_BACKUP_DIR}/${BACKUP_FILE} minio/${MINIO_BUCKET}/${MINIO_BACKUP_PATH}# 检查上传是否成功
if [ $? -ne 0 ]; thenecho "Upload to MinIO failed" >&2exit 1
fi# 计算7天前的日期(使用GNU date)
# 注意:确保您的系统支持GNU date,否则需要找到替代方法
SEVEN_DAYS_AGO=$(date -d "7 days ago" '+%Y-%m-%d')
SEVEN_DAYS_AGO_BACKUP="nexus-data-bak-${SEVEN_DAYS_AGO}.tar.gz"# 删除7天前的备份文件
mc rm minio/${MINIO_BUCKET}/${SEVEN_DAYS_AGO_BACKUP}
rm -f ${LOCAL_BACKUP_DIR}/${SEVEN_DAYS_AGO_BACKUP}echo "Backup and cleanup completed successfully"

CronJob中使用的images镜像的Dockerfile
Dockerfile

FROM alpine:latest# coreutils 用于提供完成的date命令
RUN apk add --no-cache tar curl coreutils# 安装 MinIO Client (mc)
RUN curl -L https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc && \chmod +x /usr/local/bin/mc# 创建备份目录
RUN mkdir -p /mnt/data /tmp/backupWORKDIR /root# 复制备份脚本、kubectl到容器中(用于执行nexus副本数的扩缩容)
COPY backup-script.sh kubectl .# 设置备份脚本为可执行
RUN chmod +x backup-script.sh kubectl# 设置容器启动时执行的命令
CMD ["./backup-script.sh"]

docker_build.sh

#!/bin/bashDATE=`date +%F-%H%M%S`#请自行修改harbo仓库地址
docker build -t 192.168.123.240:8011/yql/nexus-backup-cronjob:v${DATE} .
docker push 192.168.123.240:8011/yql/nexus-backup-cronjob:v${DATE}

CronJob YAML
cronjob.yaml

apiVersion: batch/v1
kind: CronJob
metadata:name: daily-full-backupnamespace: nexus-2
spec:schedule: "35 16 * * *"successfulJobsHistoryLimit: 7  # 保留7个成功的任务历史记录failedJobsHistoryLimit: 1  # 保留1个失败的任务历史记录jobTemplate:spec:template:metadata:labels:app: backupspec:# nodeName: 192.168.123.249 # 可以指定调度的node节点serviceAccountName: nexus-backup-cronjob-serviceaccountcontainers:- name: backup-containerimage: 192.168.123.240:8011/yql/nexus-backup-cronjob:v2024-11-20-163322imagePullPolicy: IfNotPresentvolumeMounts:- mountPath: /mnt/dataname: data-volume- mountPath: /tmp/backupname: backup-volume- mountPath: /etc/localtimename: localtimereadOnly: trueresources:limits:cpu: 1memory: 2Girequests:cpu: 0.5memory: 1GirestartPolicy: OnFailurevolumes:- name: data-volumepersistentVolumeClaim:claimName: nexus-pvc  # nexus-data源数据的 PVC 名称- name: backup-volumehostPath:path: /tmp/nexus-data-backup  # 指定宿主机上的路径type: DirectoryOrCreate- name: localtimehostPath:path: /etc/localtimetype: File
# kubectl apply -f cronjob.yaml

查看cronjob执行的过程
在这里插入图片描述
在这里插入图片描述
查看备份数据是否上传到minio
查看pod被调度到的节点临时文件目录是否有备份文件:
在这里插入图片描述
查看文件是否上传到minio
在这里插入图片描述

备份方式一的故障模拟测试

将正常运行的容器部署的nexus服务的NFS PVC绑定的PV中的数据删除,模拟元数据丢失。
在这里插入图片描述
在这里插入图片描述

备份方式一的故障恢复验证

使用k8s cronjob定时备份nexus数据到minio的备份包进行恢复。
在这里插入图片描述
将从minio中下载的备份包上传到nfs server 临时目录
在这里插入图片描述
注意:因nexus 数据丢失,k8s检测到nexus服务异常会自动重启nexus 的pod,nexus会重新初始化产生新的数据文件,此时需要先将pod副本数手动设置为0,停止服务,再将初始化的数据删除,再使用备份包进行数据恢复。

pod被k8s自动重启
在这里插入图片描述
手动设置pod副本数为0,关闭nexusf服务。
在这里插入图片描述
手动删除pod重启后重新初始化的数据文件
在这里插入图片描述
将备份数据包解压到nexus nfs pv目录
在这里插入图片描述
将pod副本数恢复成1
在这里插入图片描述
web页面查看nexus数据已恢复
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

备份方式二,配置实时同步备份

在nfs server上安装sersync(sersync是国人基于rsync+inotify-tools开发的文件实时同步工具,github地址:https://github.com/wsgzao/sersync),实时监视nexus nfs pvc中文件的变更,将文件实时同步到安装了rsyncd服务的目的备份服务器。

目的备份服务器安装配置rsyncd服务

检查服务器是否已安装rsync

# which rsync
/usr/bin/rsync

如何没有安装,使用yum 安装

# yum install rsync

创建配置文件 /etc/rsyncd.conf

dport = 873
uid = root
gid = root
use chroot = no
max connetctions = 200
timeout = 100
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
[backup]
path = /data/nexus-nfs-backup/
ignore errors
read only = false
list = false
hosts allow = 192.168.123.0/24
hosts deny = 0.0.0.0/32
auth users = rsync_backup
secrets file = /etc/rsync.passwor

创建配置文件中secrets file 指定的账号密码文件/etc/rsync.password
账号和密码在一行,中间用冒号分隔。

# cat /etc/rsync.password
rsync_backup:passwd123

需要将/etc/rsync.password 文件权限设置为600

# chmod 600 /etc/rsync.password
# ll /etc/rsync.password
-rw------- 1 root root 23 11月 22 09:28 /etc/rsync.password

创建存放备份数据的目录,与配置文件中path 参数指定一致

# mkdir /data/nexus-nfs-backup

启动服务

# rsync --daemon

查看服务进程及端口号

# ps -ef |grep "rsync --daemon"
root     17991     1  0 11:30 ?        00:00:00 rsync --daemon# netstat -ntlp |grep 873
tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      17991/rsync
tcp6       0      0 :::873                  :::*                    LISTEN      17991/rsync

关闭服务使用kill -9 xxx
关闭服务器后再启动服务器需要手动删除pid文件,否则不能启动,有提示。

# rm -f /var/run/rsyncd.pid

在nfs server安装配置sersync
sersync二进制包下载地址:https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz

解压:

# tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
# ll
drwxr-xr-x  2 root root 4.0K 10月 26  2011 GNU-Linux-x86# 移动到/opt目录
# mv GNU-Linux-x86/ /opt/sersync

配置文件confxml.xml修改如下:
在这里插入图片描述
配置文件中指定的保存密码的文件,只有密码,没有账号:

rsync.pass
passwd123

设置为600权限

# chmod 600 rsync.pass
# ls -l
-rw------- 1 root root   10 11月 22 09:33 rsync.pass

启动服务:

# nohup /opt/sersync/sersync2 -r -d /opt/sersync/confxml.xml > /opt/sersync/rsync.log

在查看数据同步
在这里插入图片描述
备份方式二的故障模拟测试
和备份方式一的故障模拟类似,也是将nexus nfs pvc绑定的pv中的数据手动删除,模拟元数据丢失。
在这里插入图片描述

备份方式二的故障恢复验证

将nexus pod副本数设置为0,停止nexus服务。
在这里插入图片描述
手动删除因k8s检测到nexus pod故障,自动重启pod后重新生成的初始化数据文件
在这里插入图片描述

将rsyncd备份服务器上备份数据同步回来到nexus nfs pvc绑定的pv目录
在这里插入图片描述
再将pod副本数恢复为1,启动nexus服务
在这里插入图片描述
通过web页面查看nexus数据已恢复
在这里插入图片描述
在这里插入图片描述

4、注意事项

1.nexus服务只部署1个pod副本,其本身的高可用依赖在pod中配置健康检查探针的方式由k8s deployment予以保障,具体配置细节请自行查找相关资料。
2.本方案只针对nexus保存在nfs pvc绑定的pv中的元数据进行高可用保证,二进制构件数据通过Blob Stores 保存在minio分布式文件存储系统,由minio确保二级制构件文件的数据高可用。
3.在出现nexus元数据丢失故障时,请优先使用sersync实时备份的数据进行恢复。如其不能正常恢复,再使用cronjob定时备份的数据进行恢复。使用此备份数据进行恢复,会造成备份间隔时段内的数据丢失。
4.实际生产环境中直接删除所有数据文件的情况应该比较少见,大部分情况应该为部分数据丢失或者损坏,在使用备份数据进行恢复前,请先对现存数据进行备份,以便在数据恢复失败时进行回滚操作。

http://www.xdnf.cn/news/9844.html

相关文章:

  • 苹果FINDMY和谷歌FIND HUB增强共享位置功能
  • offset 家族和 client 家族
  • 【第4章 图像与视频】4.1 图像的绘制
  • Next.js 布局(Layout)与模板(Template)深度解析:从原理到实战
  • 在VirtualBox中打造高效开发环境:CentOS虚拟机安装与优化指南
  • SQL正则表达式总结
  • Java面试实战:从Spring到大数据的全栈挑战
  • STM32中,如何理解看门狗
  • WebSocket与实时对话式AI服务的集成
  • MySQL ALTER TABLE 组合操作时导致的错误
  • GPU 图形计算综述 (二):固定管线
  • dto vo类为什么要序列化?
  • 相量法正弦稳态电路的分析(面向题目)
  • 从汇编的角度揭秘C++函数重载,原来这么简单
  • 【最小生成树】Prim 算法、Kruskal 算法
  • 基于vue框架的独居老人上门护理小程序的设计r322q(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 42道CSS高频题整理(附答案背诵版)
  • Java AQS(Abstract Queued Synchronized)深度解析
  • MyBatisPlus(2):常用注解
  • 【MATLAB例程】基于脉冲雷达的TDOA目标定位,适用于四个锚点、三维空间的环境,附代码下载链接
  • 亚远景-ASPICE与ISO 26262:适用范围与应用场景的差异分析
  • 国产化redis 替代产品tendis 安装
  • 1Panel v2 首发体验(alpha)
  • Ubuntu 24.04 LTS Chrome 中文输入法(搜狗等)失效?一行命令解决
  • 项目管理进阶:精读78页 IPD+CMMI+Scrum一体化研发管理解决方案【附全文阅读】
  • 初学python的我开始Leetcode题10-1
  • 递归与递推算法详解(C++版)教案——以斐波那契数列为例
  • MySQL高可用革命:Orchestrator实现零干预的故障转移与智能拓扑管理
  • 自动驾驶与智能交通:构建未来出行的智能引擎
  • LangFuse:开源LLM工程平台的革新实践