179 lines
7.6 KiB
Bash
179 lines
7.6 KiB
Bash
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
# ==================== 配置参数(可按需修改)====================
|
||
JENKINS_NAME="jenkins-enterprise"
|
||
USER_ID="1001"
|
||
GROUP_ID="1001"
|
||
MEMORY_LIMIT="8g"
|
||
CPU_LIMIT="4"
|
||
HTTP_PORT="8080"
|
||
AGENT_PORT="50000"
|
||
DATA_DIR="/opt/jenkins" # 数据持久化目录(版本共享核心)
|
||
IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jenkins/jenkins:lts-jdk21"
|
||
TZ="Asia/Shanghai"
|
||
JAVA_OPTS="-Xms4g -Xmx6g -Dhudson.model.DirectoryBrowserSupport.CSP=''"
|
||
|
||
# ==================== 前置检查 ====================
|
||
check_dependency() {
|
||
local cmd=$1
|
||
if ! command -v $cmd &> /dev/null; then
|
||
echo "❌ 错误:未安装 $cmd,请先安装后重试!"
|
||
echo " 安装指引:"
|
||
if [[ $cmd == "nerdctl" ]]; then
|
||
echo " - Debian/Ubuntu: apt install containerd nerdctl"
|
||
echo " - CentOS/RHEL: dnf install containerd nerdctl"
|
||
elif [[ $cmd == "stat" ]]; then
|
||
echo " - Debian/Ubuntu: apt install coreutils"
|
||
echo " - CentOS/RHEL: dnf install coreutils"
|
||
fi
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 检查依赖命令
|
||
check_dependency "nerdctl"
|
||
check_dependency "stat"
|
||
check_dependency "sudo"
|
||
|
||
# 检查 containerd 服务是否运行
|
||
if ! systemctl is-active --quiet containerd; then
|
||
echo "⚠️ containerd 服务未启动,正在启动..."
|
||
sudo systemctl start containerd
|
||
sudo systemctl enable containerd
|
||
fi
|
||
|
||
# ==================== 环境准备 ====================
|
||
prepare_environment() {
|
||
echo "🔧 正在准备运行环境..."
|
||
|
||
# 创建数据目录并配置权限(版本共享核心:目录持久化)
|
||
sudo mkdir -p ${DATA_DIR}/{home,logs,backup}
|
||
sudo chown -R ${USER_ID}:${GROUP_ID} ${DATA_DIR}
|
||
sudo chmod -R 755 ${DATA_DIR}
|
||
echo "✅ 数据目录 ${DATA_DIR} 已创建并配置权限"
|
||
|
||
# 检查 1001 用户组是否存在,不存在则创建
|
||
if ! getent group ${GROUP_ID} &> /dev/null; then
|
||
sudo groupadd -g ${GROUP_ID} jenkins
|
||
echo "✅ 已创建组 ID: ${GROUP_ID}"
|
||
fi
|
||
if ! id -u ${USER_ID} &> /dev/null; then
|
||
sudo useradd -m -u ${USER_ID} -g ${GROUP_ID} jenkins
|
||
echo "✅ 已创建用户 ID: ${USER_ID}"
|
||
fi
|
||
|
||
# 清理旧容器(避免冲突)
|
||
if nerdctl ps -a | grep -q ${JENKINS_NAME}; then
|
||
echo "⚠️ 发现旧容器 ${JENKINS_NAME},正在删除..."
|
||
sudo nerdctl rm -f ${JENKINS_NAME}
|
||
fi
|
||
}
|
||
|
||
# ==================== 启动 Jenkins ====================
|
||
start_jenkins() {
|
||
echo "🚀 正在启动 Jenkins 容器..."
|
||
|
||
# 获取 containerd.sock 组 ID(允许容器内访问宿主机容器引擎)
|
||
CONTAINERD_SOCK_GID=$(stat -c %g /var/run/containerd/containerd.sock)
|
||
|
||
# 执行启动命令
|
||
sudo nerdctl run -d \
|
||
--name ${JENKINS_NAME} \
|
||
--restart always \
|
||
--user ${USER_ID}:${GROUP_ID} \
|
||
--memory ${MEMORY_LIMIT} \
|
||
--cpus ${CPU_LIMIT} \
|
||
-p ${HTTP_PORT}:8080 \
|
||
-p ${AGENT_PORT}:50000 \
|
||
-v ${DATA_DIR}/home:/var/jenkins_home \
|
||
-v ${DATA_DIR}/logs:/var/log/jenkins \
|
||
-v ${DATA_DIR}/backup:/var/jenkins_backup \
|
||
-v /var/run/containerd/containerd.sock:/var/run/docker.sock:ro \
|
||
-v /etc/localtime:/etc/localtime:ro \
|
||
-e TZ="${TZ}" \
|
||
-e JAVA_OPTS="${JAVA_OPTS}" \
|
||
--security-opt=no-new-privileges \
|
||
--cap-drop=ALL \
|
||
--cap-add=NET_BIND_SERVICE \
|
||
--group-add ${CONTAINERD_SOCK_GID} \
|
||
${IMAGE}
|
||
|
||
# 等待容器启动(最多等待 30 秒)
|
||
echo "⌛ 等待 Jenkins 初始化(约 30 秒)..."
|
||
for ((i=0; i<30; i++)); do
|
||
if sudo nerdctl logs ${JENKINS_NAME} | grep -q "initialAdminPassword"; then
|
||
echo "✅ Jenkins 启动成功!"
|
||
return 0
|
||
fi
|
||
sleep 1
|
||
done
|
||
|
||
echo "⚠️ Jenkins 启动超时,可能正在初始化,请稍后查看日志确认"
|
||
}
|
||
|
||
# ==================== 打印运维指南 ====================
|
||
print_operation_guide() {
|
||
echo -e "\n=================================================="
|
||
echo -e "🎉 Jenkins 一键安装完成!"
|
||
echo -e "=================================================="
|
||
echo -e "📌 基础访问信息:"
|
||
echo -e " - 访问地址:http://$(hostname -I | awk '{print $1}'):${HTTP_PORT}"
|
||
echo -e " - 初始密码:sudo cat ${DATA_DIR}/home/secrets/initialAdminPassword"
|
||
echo -e " - 容器名称:${JENKINS_NAME}"
|
||
echo -e " - 数据目录:${DATA_DIR}(核心!删除会丢失所有配置)"
|
||
echo -e "\n📌 运维常用操作:"
|
||
echo -e "\n【1. 插件加速(解决安装慢/失败)】"
|
||
echo -e " 方法1:替换 Jenkins 插件源(推荐清华源)"
|
||
echo -e " 1) 进入 Jenkins 管理界面 → 系统管理 → 插件管理 → 高级"
|
||
echo -e " 2) 替换「升级站点」URL 为:"
|
||
echo -e " https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json"
|
||
echo -e " 3) 点击「提交」→ 「立即获取」"
|
||
echo -e ""
|
||
echo -e " 方法2:手动修改配置文件(容器外操作)"
|
||
echo -e " sudo sed -i 's#https://updates.jenkins.io/update-center.json#https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json#' ${DATA_DIR}/home/hudson.model.UpdateCenter.xml"
|
||
echo -e " sudo nerdctl restart ${JENKINS_NAME}"
|
||
echo -e "\n【2. 版本共享(数据持久化)】"
|
||
echo -e " - 核心原理:${DATA_DIR}/home 目录存储所有配置、插件、任务数据"
|
||
echo -e " - 升级/重建容器:保留该目录,数据不丢失(版本共享核心)"
|
||
echo -e " - 迁移 Jenkins:复制 ${DATA_DIR} 到新服务器,启动命令不变即可"
|
||
echo -e "\n【3. 备份与恢复】"
|
||
echo -e " 🔸 手动备份(推荐每日执行):"
|
||
echo -e " sudo tar -zcvf ${DATA_DIR}/backup/jenkins_backup_$(date +%Y%m%d).tar.gz -C ${DATA_DIR}/home ."
|
||
echo -e ""
|
||
echo -e " 🔸 恢复数据(需先停止容器):"
|
||
echo -e " sudo nerdctl stop ${JENKINS_NAME}"
|
||
echo -e " sudo rm -rf ${DATA_DIR}/home/*"
|
||
echo -e " sudo tar -zxvf ${DATA_DIR}/backup/[备份文件名].tar.gz -C ${DATA_DIR}/home"
|
||
echo -e " sudo nerdctl start ${JENKINS_NAME}"
|
||
echo -e "\n【4. 版本升级/回滚】"
|
||
echo -e " 🔸 升级 Jenkins 版本:"
|
||
echo -e " 1) 拉取新版本镜像:sudo nerdctl pull ${IMAGE/:lts-jdk21/:lts-jdk21-new}" # 替换为目标版本
|
||
echo -e " 2) 停止旧容器:sudo nerdctl stop ${JENKINS_NAME}"
|
||
echo -e " 3) 重建容器(保留数据目录):重新执行本脚本或启动命令"
|
||
echo -e ""
|
||
echo -e " 🔸 回滚版本:"
|
||
echo -e " sudo nerdctl pull ${IMAGE} # 拉取原版本镜像"
|
||
echo -e " sudo nerdctl stop ${JENKINS_NAME} && sudo nerdctl rm ${JENKINS_NAME}"
|
||
echo -e " 重新执行本脚本(数据目录不变,配置不丢失)"
|
||
echo -e "\n【5. 常用排查命令】"
|
||
echo -e " - 查看容器状态:sudo nerdctl ps -a | grep ${JENKINS_NAME}"
|
||
echo -e " - 查看实时日志:sudo nerdctl logs -f ${JENKINS_NAME}"
|
||
echo -e " - 重启 Jenkins:sudo nerdctl restart ${JENKINS_NAME}"
|
||
echo -e " - 查看资源占用:sudo nerdctl stats ${JENKINS_NAME}"
|
||
echo -e " - 进入容器终端:sudo nerdctl exec -it ${JENKINS_NAME} bash"
|
||
echo -e "\n=================================================="
|
||
}
|
||
|
||
# ==================== 主流程执行 ====================
|
||
main() {
|
||
echo "=================================================="
|
||
echo "📦 Jenkins 一键安装脚本(nerdctl 容器化版)"
|
||
echo "=================================================="
|
||
prepare_environment
|
||
start_jenkins
|
||
print_operation_guide
|
||
}
|
||
|
||
# 启动主流程
|
||
main |