ansible-devops/scripts/containerd.sh

326 lines
12 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
set -euo pipefail
# Containerd安装脚本已删除镜像加速配置
# 保留核心功能生成默认配置、替换华为云镜像源、配置Cgroup驱动、服务管理
# 适用: Ubuntu 20.04/22.04/24.04 LTS需确保系统已有containerd.io安装源
#######################################
# 配置参数(删除镜像加速相关路径)
#######################################
DEFAULT_VERSION="1.7.28-1"
ACTION=""
CONTAINERD_VERSION="$DEFAULT_VERSION"
LOG_FILE="/var/log/containerd_manage.log"
CONFIG_PATH="/etc/containerd/config.toml"
PACKAGE_NAME="containerd.io"
#######################################
# 日志函数
#######################################
log() {
local level=$1
local message=$2
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
#######################################
# 帮助信息
#######################################
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --install 安装containerd必填"
echo " --uninstall 卸载containerd必填"
echo " --version VERSION 指定版本如1.7.28-1默认$DEFAULT_VERSION"
echo " --help 显示帮助"
exit 1
}
#######################################
# 解析参数
#######################################
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--install)
if [[ "$ACTION" == "uninstall" ]]; then log "ERROR" "参数冲突(--install与--uninstall不可同时使用"; usage; fi
ACTION="install"
shift
;;
--uninstall)
if [[ "$ACTION" == "install" ]]; then log "ERROR" "参数冲突(--install与--uninstall不可同时使用"; usage; fi
ACTION="uninstall"
shift
;;
--version)
if [[ $# -lt 2 || "$2" == -* ]]; then log "ERROR" "--version需指定有效版本如1.7.28-1"; usage; fi
CONTAINERD_VERSION="$2"
shift 2
;;
--help)
usage
;;
*)
log "ERROR" "未知参数:$1"
usage
;;
esac
done
if [[ -z "$ACTION" ]]; then log "ERROR" "必须指定--install或--uninstall"; usage; fi
}
#######################################
# 前置检查
#######################################
pre_check() {
log "INFO" "前置环境检查"
# 检查root权限
if [[ "$(id -u)" -ne 0 ]]; then log "ERROR" "请使用root权限执行sudo"; exit 1; fi
# 检查Ubuntu系统
if ! grep -q "Ubuntu" /etc/os-release; then log "ERROR" "仅支持Ubuntu系统"; exit 1; fi
# 检查系统版本
local os_version=$(grep VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
if ! [[ "$os_version" =~ ^20\.04$ || "$os_version" =~ ^22\.04$ || "$os_version" =~ ^24\.04$ ]]; then
log "ERROR" "仅支持Ubuntu 20.04/22.04/24.04 LTS版本"; exit 1; fi
# 检查必要工具
local required_tools=("apt-get" "systemctl" "sed" "grep")
for tool in "${required_tools[@]}"; do
if ! command -v "$tool" &> /dev/null; then
log "INFO" "安装缺失工具:$tool"
apt-get update -qq >/dev/null
apt-get install -qq -y "$tool" >/dev/null
fi
done
log "INFO" "前置检查通过"
}
######################################
# 安装必要依赖(屏蔽冗余日志,仅捕错)
install_dependencies() {
log "INFO" "正在安装依赖工具"
# apt-get 静默执行,日志重定向到/dev/null仅保留错误输出
if ! apt-get update -qq >/dev/null 2>&1; then
log "ERROR" "更新软件源失败"
exit 1
fi
if ! apt-get install -qq -y ca-certificates curl gnupg lsb-release >/dev/null 2>&1; then
log "ERROR" "安装依赖ca-certificates/curl等失败"
exit 1
fi
log "INFO" "依赖工具安装完成"
}
# 添加Docker GPG密钥自动覆盖屏蔽日志
add_gpg_key() {
log "INFO" "正在添加Docker GPG密钥"
mkdir -p /etc/apt/keyrings
# curl+gpg 静默执行,自动覆盖现有文件
if ! curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg >/dev/null 2>&1; then
log "ERROR" "添加GPG密钥失败网络或密钥地址异常"
exit 1
fi
log "INFO" s "GPG密钥添加完成"
}
# 添加Docker源屏蔽日志
add_docker_repo() {
log "INFO" "正在配置Docker软件源"
# 写入源配置,更新源时静默执行
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list >/dev/null 2>&1
if ! apt-get update -qq >/dev/null 2>&1; then
log "ERROR" "更新Docker软件源失败"
exit 1
fi
log "INFO" "Docker软件源配置完成"
}
#######################################
# 验证版本可用性
#######################################
verify_version() {
log "INFO" "验证版本${CONTAINERD_VERSION}可用性"
# 提取源中可用的核心版本(忽略发行版后缀)
local available_versions=$(apt-cache madison "$PACKAGE_NAME" | awk '{print $3}' | sed 's/~ubuntu\.[0-9]\+\.[0-9]\+~[a-z]\+//' | sort -u)
if ! echo "$available_versions" | grep -qxF "$CONTAINERD_VERSION"; then
log "ERROR" "版本${CONTAINERD_VERSION}不可用,可用版本:"; echo "$available_versions" | tee -a "$LOG_FILE"; exit 1; fi
log "INFO" "版本验证通过"
}
#######################################
# 安装containerd匹配带后缀的完整版本
#######################################
install_containerd() {
log "INFO" "检查当前${PACKAGE_NAME}安装状态"
# 获取源中带后缀的完整版本
local full_version=$(apt-cache madison "$PACKAGE_NAME" | grep "$CONTAINERD_VERSION" | awk '{print $3}' | head -n 1)
if [[ -z "$full_version" ]]; then log "ERROR" "未找到与${CONTAINERD_VERSION}匹配的完整版本"; exit 1; fi
# 检查是否已安装目标版本
if dpkg -l "$PACKAGE_NAME" &>/dev/null; then
local installed_full_version=$(dpkg -l "$PACKAGE_NAME" | awk '/ii/ {print $3}')
if [[ "$installed_full_version" == "$full_version" ]]; then
log "INFO" "${PACKAGE_NAME} ${full_version}已安装,跳过安装"
return
fi
fi
# 安装完整版本
log "INFO" "安装${PACKAGE_NAME}=${full_version}"
if ! apt-get install -qq -y "${PACKAGE_NAME}=${full_version}" >/dev/null 2>&1; then
log "ERROR" "安装失败,手动执行以下命令查看详细错误:"; log "ERROR" "sudo apt-get install -y ${PACKAGE_NAME}=${full_version}"; exit 1; fi
log "INFO" "${PACKAGE_NAME}安装完成"
}
#######################################
# 核心配置仅保留生成默认配置、替换镜像源、Cgroup驱动
#######################################
configure_containerd() {
log "INFO" "开始配置containerd"
# 1. 生成默认配置文件
log "INFO" "执行containerd config default > $CONFIG_PATH"
if [[ -f "$CONFIG_PATH" ]]; then
log "INFO" "备份旧配置文件:${CONFIG_PATH}.bak"
cp "$CONFIG_PATH" "${CONFIG_PATH}.bak"
fi
if ! containerd config default > "$CONFIG_PATH" 2>&1; then
log "ERROR" "生成默认配置文件失败"; exit 1; fi
# 2. 替换镜像源registry.k8s.io -> 华为云)
log "INFO" "执行替换镜像源为华为云registry.k8s.io -> swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io"
if ! sed -i 's#registry.k8s.io#swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io#' "$CONFIG_PATH" 2>&1; then
log "ERROR" "镜像源替换失败"; exit 1; fi
# 3. 配置Cgroup驱动器SystemdCgroup = true
log "INFO" "执行配置Cgroup驱动器为SystemdCgroup = true"
if grep -q "SystemdCgroup \= false" "$CONFIG_PATH"; then
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' "$CONFIG_PATH"
log "INFO" "Cgroup驱动器已设置为SystemdCgroup = true"
else
if grep -q "SystemdCgroup \= true" "$CONFIG_PATH"; then
log "INFO" "Cgroup驱动器已为true跳过修改"
else
log "WARNING" "未找到SystemdCgroup配置项手动添加到runc.options区块"
sed -i '/\[plugins\."io\.containerd\.grpc\.v1\.cri"\.containerd\.runtimes\.runc\.options\]/a \ \ \ \ SystemdCgroup \= true' "$CONFIG_PATH"
fi
fi
# 重启服务应用配置
log "INFO" "重启containerd服务"
systemctl restart containerd >/dev/null 2>&1 || { log "ERROR" "containerd重启失败"; exit 1; }
log "INFO" "containerd配置完成"
}
#######################################
# 启动服务并设置开机自启
#######################################
start_service() {
log "INFO" "配置containerd服务自启"
if systemctl is-enabled --quiet containerd; then
log "INFO" "containerd已设置开机自启"
else
systemctl enable containerd >/dev/null 2>&1
log "INFO" "已设置containerd开机自启"
fi
# 确保服务处于运行状态
if systemctl is-active --quiet containerd; then
log "INFO" "containerd服务已运行"
else
systemctl start containerd >/dev/null 2>&1
log "INFO" "containerd服务已启动"
fi
}
#######################################
# 验证安装结果(删除镜像加速相关检查)
#######################################
verify_installation() {
log "INFO" "验证安装结果"
# 检查服务状态
if ! systemctl is-active --quiet containerd; then log "ERROR" "containerd服务未运行"; exit 1; fi
# 检查镜像源替换
if grep -q "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io" "$CONFIG_PATH"; then
log "INFO" "镜像源替换验证通过"
else
log "WARNING" "镜像源替换未生效,请检查$CONFIG_PATH"
fi
# 检查Cgroup配置
if grep -q "SystemdCgroup \= true" "$CONFIG_PATH"; then
log "INFO" "Cgroup驱动器配置验证通过"
else
log "WARNING" "Cgroup驱动器配置未生效请检查$CONFIG_PATH"
fi
# 检查版本
local installed_version=$(containerd --version | awk '/containerd/ {print $3}' | cut -d'+' -f1 | sed 's/^v//')
if [[ "$installed_version" == "${CONTAINERD_VERSION%-*}" ]]; then
log "INFO" "版本验证通过,当前版本:$installed_version"
else
log "WARNING" "版本不匹配:预期${CONTAINERD_VERSION%-*},实际$installed_version"
fi
log "INFO" "所有验证完成"
}
#######################################
# 卸载containerd删除镜像加速相关清理
#######################################
uninstall_containerd() {
log "INFO" "开始卸载containerd"
# 停止服务
if systemctl is-active --quiet containerd; then
log "INFO" "停止containerd服务"
systemctl stop containerd >/dev/null 2>&1
fi
# 卸载包
if dpkg -l "$PACKAGE_NAME" &>/dev/null; then
log "INFO" "卸载${PACKAGE_NAME}"
apt-get purge -qq -y "$PACKAGE_NAME" >/dev/null 2>&1
log "INFO" "清理无用依赖"
apt-get autoremove -qq -y >/dev/null 2>&1
else
log "INFO" "${PACKAGE_NAME}未安装,跳过卸载"
fi
# 清理配置和数据(删除镜像加速相关目录的清理)
log "INFO" "清理残留文件"
rm -rf "$CONFIG_PATH" "${CONFIG_PATH}.bak" /var/lib/containerd /var/log/containerd
# 重新加载systemd
systemctl daemon-reload >/dev/null 2>&1
log "INFO" "containerd卸载完成"
}
#######################################
# 主流程
#######################################
main() {
# 初始化日志
> "$LOG_FILE"
log "INFO" "===== Containerd管理脚本启动 ====="
# 解析参数
parse_args "$@"
# 通用前置检查
pre_check
# 分支执行
case "$ACTION" in
install)
install_dependencies
add_gpg_key
add_docker_repo
verify_version
install_containerd
configure_containerd # 仅含核心配置(无镜像加速)
start_service
verify_installation
;;
uninstall)
uninstall_containerd
;;
esac
log "INFO" "===== 操作完成 ====="
log "INFO" "详细日志路径:$LOG_FILE"
}
# 启动主程序
main "$@"