diff --git a/scripts/containerd.sh b/scripts/containerd.sh index d15adb7..8228f3a 100644 --- a/scripts/containerd.sh +++ b/scripts/containerd.sh @@ -1,24 +1,19 @@ #!/bin/bash set -euo pipefail -# Containerd安装脚本(Ubuntu专用) -# 集成配置:默认配置生成、镜像源替换、Cgroup驱动、镜像加速 -# 适用:Ubuntu 20.04/22.04/24.04 LTS +# 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" -DOCKER_REPO="https://download.docker.com/linux/ubuntu" -GPG_KEY_PATH="/etc/apt/keyrings/docker.gpg" -REPO_LIST_PATH="/etc/apt/sources.list.d/docker.list" CONFIG_PATH="/etc/containerd/config.toml" PACKAGE_NAME="containerd.io" -CERTS_D_PATH="/etc/containerd/certs.d" -DOCKER_IO_HOSTS="${CERTS_D_PATH}/docker.io/hosts.toml" ####################################### # 日志函数 @@ -50,17 +45,17 @@ parse_args() { while [[ $# -gt 0 ]]; do case "$1" in --install) - if [[ "$ACTION" == "uninstall" ]]; then log "ERROR" "参数冲突"; usage; fi + if [[ "$ACTION" == "uninstall" ]]; then log "ERROR" "参数冲突(--install与--uninstall不可同时使用)"; usage; fi ACTION="install" shift ;; --uninstall) - if [[ "$ACTION" == "install" ]]; then log "ERROR" "参数冲突"; usage; fi + if [[ "$ACTION" == "install" ]]; then log "ERROR" "参数冲突(--install与--uninstall不可同时使用)"; usage; fi ACTION="uninstall" shift ;; --version) - if [[ $# -lt 2 || "$2" == -* ]]; then log "ERROR" "需指定版本"; usage; fi + if [[ $# -lt 2 || "$2" == -* ]]; then log "ERROR" "--version需指定有效版本(如1.7.28-1)"; usage; fi CONTAINERD_VERSION="$2" shift 2 ;; @@ -73,7 +68,7 @@ parse_args() { ;; esac done - if [[ -z "$ACTION" ]]; then log "ERROR" "需指定--install或--uninstall"; usage; fi + if [[ -z "$ACTION" ]]; then log "ERROR" "必须指定--install或--uninstall"; usage; fi } ####################################### @@ -81,14 +76,16 @@ parse_args() { ####################################### pre_check() { log "INFO" "前置环境检查" - if [[ "$(id -u)" -ne 0 ]]; then log "ERROR" "需root权限"; exit 1; fi - if ! grep -q "Ubuntu" /etc/os-release; then log "ERROR" "仅支持Ubuntu"; exit 1; fi + # 检查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" - exit 1 - fi - local required_tools=("apt-get" "curl" "gpg" "lsb_release" "systemctl") + 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" @@ -100,179 +97,176 @@ pre_check() { } ####################################### -# 配置Docker源 -####################################### -configure_repo() { - log "INFO" "配置Docker源" - mkdir -p "$(dirname "$GPG_KEY_PATH")" - if [[ ! -f "$GPG_KEY_PATH" ]]; then - log "INFO" "下载Docker GPG密钥" - curl -fsSL --retry 3 --retry-delay 5 "${DOCKER_REPO}/gpg" | gpg --dearmor -o "$GPG_KEY_PATH" >/dev/null 2>&1 || { - log "ERROR" "GPG密钥下载失败" - exit 1 - } - chmod a+r "$GPG_KEY_PATH" - fi - local codename=$(lsb_release -cs) - if [[ "$codename" == "noble" ]]; then codename="jammy"; fi # 兼容24.04 - local repo_content="deb [arch=$(dpkg --print-architecture) signed-by=$GPG_KEY_PATH] $DOCKER_REPO $codename stable" - if [[ ! -f "$REPO_LIST_PATH" || "$(cat "$REPO_LIST_PATH")" != "$repo_content" ]]; then - echo "$repo_content" | tee "$REPO_LIST_PATH" >/dev/null - apt-get update -qq >/dev/null - fi - log "INFO" "Docker源配置完成" -} - -####################################### -# 验证版本可用性 +# 验证版本可用性(依赖系统已有源) ####################################### verify_version() { log "INFO" "验证版本${CONTAINERD_VERSION}可用性" - local available_versions=$(apt-cache madison "$PACKAGE_NAME" | awk '{print $3}' | sed 's/~ubuntu.*//' | sort -u) + # 提取源中可用的核心版本(忽略发行版后缀) + 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" "版本不可用,可用版本:$available_versions" - exit 1 - fi + log "ERROR" "版本${CONTAINERD_VERSION}不可用,可用版本:"; echo "$available_versions" | tee -a "$LOG_FILE"; exit 1; fi log "INFO" "版本验证通过" } ####################################### -# 安装containerd +# 安装containerd(匹配带后缀的完整版本) ####################################### install_containerd() { - log "INFO" "安装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" "未找到完整版本"; exit 1; fi - if dpkg -l "$PACKAGE_NAME" &>/dev/null && [[ "$(dpkg -l "$PACKAGE_NAME" | awk '/ii/ {print $3}')" == "$full_version" ]]; then - log "INFO" "已安装$full_version,跳过" - return + 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" "安装$full_version" - apt-get install -qq -y "${PACKAGE_NAME}=${full_version}" >/dev/null 2>&1 || { - log "ERROR" "安装失败,手动执行:sudo apt-get install -y ${PACKAGE_NAME}=${full_version}" - exit 1 - } + # 安装完整版本 + 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" 2>/dev/null || { - log "ERROR" "生成默认配置失败" - exit 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" "替换镜像源为华为云" - sed -i 's#registry.k8s.io#swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io#' "$CONFIG_PATH" || { - log "ERROR" "镜像源替换失败" - exit 1 - } + 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驱动器" - sed -i 's/SystemdCgroup\ =\ false/SystemdCgroup\ =\ true/g' "$CONFIG_PATH" || { - log "ERROR" "Cgroup配置失败" - exit 1 - } - - # 4. 配置镜像加速 - log "INFO" "配置镜像加速" - # 4.1 设置registry.config_path - local registry_block="[plugins.\"io.containerd.grpc.v1.cri\".registry]" - local config_path_line=' config_path = "/etc/containerd/certs.d"' - if ! grep -qxF "$config_path_line" "$CONFIG_PATH"; then - if ! grep -qxF "$registry_block" "$CONFIG_PATH"; then - echo -e "\n$registry_block" >> "$CONFIG_PATH" + 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 - sed -i "/$registry_block/a $config_path_line" "$CONFIG_PATH" fi - # 4.2 创建目录并写入加速配置 - mkdir -p "$(dirname "$DOCKER_IO_HOSTS")" - local hosts_content=$(cat << EOF -server = "https://docker.io" -[host."https://o2j0mc5x.mirror.aliyuncs.com"] - capabilities = ["pull", "resolve"] -server = "https://k8s.gcr.io" -[host."https://gcr.mirrors.ustc.edu.cn/google-containers/"] - capabilities = ["pull", "resolve"] -server = "https://quay.io" -[host."https://mirror.ccs.tencentyun.com"] - capabilities = ["pull", "resolve"] -EOF - ) - echo "$hosts_content" | tee "$DOCKER_IO_HOSTS" >/dev/null - - # 重启服务 - systemctl restart containerd >/dev/null 2>&1 - log "INFO" "配置完成,已重启服务" + # 重启服务应用配置 + log "INFO" "重启containerd服务" + systemctl restart containerd >/dev/null 2>&1 || { log "ERROR" "containerd重启失败"; exit 1; } + log "INFO" "containerd配置完成" } ####################################### -# 启动服务并设置开机启动 +# 启动服务并设置开机自启 ####################################### start_service() { - log "INFO" "设置开机自启并启动服务" - systemctl enable --now containerd >/dev/null 2>&1 || { - log "ERROR" "服务启动失败" - exit 1 - } + 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" "服务未运行"; exit 1; fi - if ! grep -q "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io" "$CONFIG_PATH"; then - log "WARNING" "镜像源替换未生效" + # 检查服务状态 + 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 - if ! grep -q "SystemdCgroup \= true" "$CONFIG_PATH"; then - log "WARNING" "Cgroup配置未生效" + # 检查Cgroup配置 + if grep -q "SystemdCgroup \= true" "$CONFIG_PATH"; then + log "INFO" "Cgroup驱动器配置验证通过" + else + log "WARNING" "Cgroup驱动器配置未生效,请检查$CONFIG_PATH" fi - if [[ ! -f "$DOCKER_IO_HOSTS" ]]; then - log "WARNING" "镜像加速配置不存在" + # 检查版本 + 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" "验证完成" + log "INFO" "所有验证完成" } ####################################### -# 卸载containerd +# 卸载containerd(删除镜像加速相关清理) ####################################### uninstall_containerd() { - log "INFO" "卸载containerd" - systemctl stop containerd >/dev/null 2>&1 || true - if dpkg -l "$PACKAGE_NAME" &>/dev/null; then - apt-get purge -qq -y "$PACKAGE_NAME" >/dev/null 2>&1 - apt-get autoremove -qq -y >/dev/null 2>&1 + log "INFO" "开始卸载containerd" + # 停止服务 + if systemctl is-active --quiet containerd; then + log "INFO" "停止containerd服务" + systemctl stop containerd >/dev/null 2>&1 fi - rm -rf "$CONFIG_PATH" "$CERTS_D_PATH" /var/lib/containerd /var/log/containerd + # 卸载包 + 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" "卸载完成" + log "INFO" "containerd卸载完成" } ####################################### # 主流程 ####################################### main() { + # 初始化日志 > "$LOG_FILE" - log "INFO" "===== 脚本启动 =====" + log "INFO" "===== Containerd管理脚本启动 =====" + + # 解析参数 parse_args "$@" + + # 通用前置检查 pre_check + # 分支执行 case "$ACTION" in install) - configure_repo verify_version install_containerd - configure_containerd # 执行你的所有配置步骤 + configure_containerd # 仅含核心配置(无镜像加速) start_service verify_installation ;; @@ -282,7 +276,8 @@ main() { esac log "INFO" "===== 操作完成 =====" - log "INFO" "日志:$LOG_FILE" + log "INFO" "详细日志路径:$LOG_FILE" } +# 启动主程序 main "$@"