[2025-07-30 22:12:13] [INFO] ===== 开始下载Kubernetes离线资源 ===== [2025-07-30 22:12:13] [INFO] Kubernetes版本: v1.28.5 [2025-07-30 22:12:13] [INFO] 离线包目录: /opt/offline_packages [2025-07-30 22:12:13] [INFO] ===== 创建目录结构 ===== [2025-07-30 22:12:13] [SUCCESS] 目录创建完成: /opt/offline_packages [2025-07-30 22:12:13] [INFO] ===== 下载Kubernetes二进制文件 ===== [2025-07-30 22:12:13] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubeadm #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:16:46] [SUCCESS] 下载成功: kubeadm [2025-07-30 22:16:46] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubelet #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:20:51] [SUCCESS] 下载成功: kubelet [2025-07-30 22:20:51] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubectl #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:22:23] [SUCCESS] 下载成功: kubectl [2025-07-30 22:22:23] [INFO] ===== 下载容器镜像 ===== [2025-07-30 22:22:23] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:24] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 -> /opt/offline_packages/images/kube-apiserver-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:25] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 [2025-07-30 22:22:25] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:25] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 -> /opt/offline_packages/images/kube-controller-manager-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:26] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 [2025-07-30 22:22:27] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:28] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 -> /opt/offline_packages/images/kube-scheduler-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:29] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 [2025-07-30 22:22:29] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:30] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 -> /opt/offline_packages/images/kube-proxy-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:30] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 [2025-07-30 22:22:30] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/pause:3.9 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:31] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/pause:3.9 -> /opt/offline_packages/images/pause-3.9.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:31] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/pause:3.9 [2025-07-30 22:22:31] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:32] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 -> /opt/offline_packages/images/etcd-3.5.9-0.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:32] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 [2025-07-30 22:22:32] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/coredns:v1.10.1 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:33] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/coredns:v1.10.1 -> /opt/offline_packages/images/coredns-v1.10.1.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:33] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/coredns:v1.10.1 [2025-07-30 22:22:33] [INFO] 拉取镜像: quay.io/coreos/flannel:v0.22.0 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:34] [INFO] 保存镜像: quay.io/coreos/flannel:v0.22.0 -> /opt/offline_packages/images/flannel-v0.22.0.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:35] [ERROR] 镜像保存失败: quay.io/coreos/flannel:v0.22.0 [2025-07-30 22:22:35] [INFO] ===== 下载系统优化工具 ===== [2025-07-30 22:22:35] [INFO] 下载: https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz #################################################################################################################################################################################################################### 100.0% [2025-07-30 22:22:36] [SUCCESS] 下载成功: cheat-linux-amd64.gz [2025-07-30 22:22:36] [INFO] 下载: https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:22:58] [ERROR] 下载失败: btop-x86_64-linux-musl.tbz [2025-07-30 22:22:58] [INFO] 下载: https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:23:19] [ERROR] 下载失败: bottom_x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:23:19] [INFO] 下载: https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:23:40] [ERROR] 下载失败: fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:23:40] [INFO] 下载: https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:24:01] [ERROR] 下载失败: bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:24:01] [INFO] 下载: https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:24:23] [ERROR] 下载失败: exa-linux-x86_64-v0.10.1.zip [2025-07-30 22:24:23] [INFO] ===== 生成部署脚本 ===== [2025-07-30 22:24:23] [SUCCESS] 系统优化脚本已生成 [2025-07-30 22:24:23] [SUCCESS] Kubernetes安装脚本已生成 [2025-07-30 22:24:23] [SUCCESS] ===== 下载完成! ===== [2025-07-30 22:24:23] [INFO] 1. 打包离线资源: sudo /opt/offline_packages/package_offline.sh [2025-07-30 22:24:23] [INFO] 2. 复制离线包到目标服务器 [2025-07-30 22:24:23] [INFO] 3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt [2025-07-30 22:24:23] [INFO] 4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh [2025-07-30 22:24:23] [INFO] 5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh 根据错误、重新生成完整、有效、可用的下载脚本、离线部署脚本、服务器系统优化脚本。
时间: 2025-07-31 18:47:53 浏览: 4
<think>根据日志中的错误信息,主要存在两个问题:
1. Docker守护进程未运行,导致无法拉取和保存镜像。
2. 从GitHub下载系统工具时出现连接拒绝(可能是网络问题或代理问题)。
解决方案:
1. 在下载脚本中,确保在拉取镜像前Docker已正确安装并运行。
2. 对于系统工具的下载,可以添加重试机制或使用镜像站点(如果可用)。但考虑到是离线环境准备,如果某些工具无法下载,可以跳过或提供替代方案。
改进点:
- 在下载容器镜像前,检查Docker是否安装并运行,如果没有则自动安装并启动。
- 为系统工具的下载添加重试机制。
- 对于无法从GitHub下载的工具,可以尝试其他镜像源(如Gitee)或提供跳过选项。
由于无法确保所有工具都能从其他源下载,这里我们添加重试机制,并对于失败的工具进行警告而非终止脚本。
下面重新生成三个脚本,确保它们能够处理上述错误情况。
### 1. 下载脚本 (download_k8s_offline.sh)
```bash
#!/bin/bash
# download_k8s_offline.sh - Kubernetes离线资源下载脚本
# 版本: 3.0
# 功能: 下载Kubernetes二进制文件、容器镜像和系统优化工具
# ===== 配置区域 =====
K8S_VERSION="v1.28.5" # Kubernetes版本
OFFLINE_DIR="/opt/offline_packages" # 离线包根目录
BIN_DIR="${OFFLINE_DIR}/bin" # 二进制文件目录
IMG_DIR="${OFFLINE_DIR}/images" # 容器镜像目录
TOOLS_DIR="${OFFLINE_DIR}/tools" # 系统工具目录
LOG_FILE="/var/log/k8s_download_$(date +%Y%m%d%H%M%S).log" # 日志文件
MAX_RETRY=3 # 最大重试次数
# Kubernetes镜像列表
K8S_IMAGES=(
"registry.aliyuncs.com/google_containers/kube-apiserver:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-controller-manager:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-scheduler:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-proxy:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/pause:3.9"
"registry.aliyuncs.com/google_containers/etcd:3.5.9-0"
"registry.aliyuncs.com/google_containers/coredns:v1.10.1"
"quay.io/coreos/flannel:v0.22.0" # Flannel网络插件
)
# 系统优化工具列表
SYSTEM_TOOLS=(
"https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz" # Cheat命令备忘
"https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz" # Btop资源监控
"https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz" # Bottom资源监控
"https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz" # fd文件查找
"https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz" # bat代码查看
"https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip" # exa文件列表
)
# ===== 日志函数 =====
log() {
local level=$1
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() { log "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 创建目录结构 =====
create_dirs() {
log_info "===== 创建目录结构 ====="
mkdir -p "$BIN_DIR" "$IMG_DIR" "$TOOLS_DIR"
log_success "目录创建完成: $OFFLINE_DIR"
}
# ===== 安装并启动Docker =====
setup_docker() {
log_info "===== 安装并启动Docker ====="
if command -v docker &> /dev/null; then
log_info "Docker已安装,跳过安装步骤"
else
log_info "正在安装Docker..."
curl -fsSL https://get.docker.com | sh
fi
if ! systemctl is-active --quiet docker; then
log_info "启动Docker服务..."
systemctl start docker
systemctl enable docker
fi
log_success "Docker已启动"
}
# ===== 下载Kubernetes二进制文件 =====
download_k8s_binaries() {
log_info "===== 下载Kubernetes二进制文件 ====="
local binaries=("kubeadm" "kubelet" "kubectl")
for bin in "${binaries[@]}"; do
local url="https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/${bin}"
local target="${BIN_DIR}/${bin}"
log_info "下载: ${url}"
if curl -L --retry $MAX_RETRY --progress-bar -o "$target" "$url"; then
chmod +x "$target"
log_success "下载成功: ${bin}"
else
log_error "下载失败: ${bin}"
return 1
fi
done
return 0
}
# ===== 下载容器镜像 =====
download_k8s_images() {
log_info "===== 下载容器镜像 ====="
setup_docker || return 1
for image in "${K8S_IMAGES[@]}"; do
# 提取镜像名(不含仓库地址)
local image_name=$(echo "$image" | awk -F/ '{print $NF}' | tr ':' '-')
local target="${IMG_DIR}/${image_name}.tar"
log_info "拉取镜像: ${image}"
if docker pull "$image"; then
log_info "保存镜像: ${image} -> ${target}"
if docker save -o "$target" "$image"; then
log_success "镜像保存成功: ${image_name}"
else
log_error "镜像保存失败: ${image}"
fi
else
log_error "镜像拉取失败: ${image}"
fi
done
return 0
}
# ===== 下载系统工具 =====
download_system_tools() {
log_info "===== 下载系统优化工具 ====="
for tool_url in "${SYSTEM_TOOLS[@]}"; do
local tool_name=$(basename "$tool_url")
local target="${TOOLS_DIR}/${tool_name}"
local retry=0
while [ $retry -lt $MAX_RETRY ]; do
log_info "下载 (尝试 $((retry+1))): ${tool_url}"
if curl -L --progress-bar -o "$target" "$tool_url"; then
log_success "下载成功: ${tool_name}"
break
else
log_warn "下载失败: ${tool_name}"
rm -f "$target" 2>/dev/null
((retry++))
sleep 3
fi
done
if [ $retry -eq $MAX_RETRY ]; then
log_error "多次重试后仍下载失败: ${tool_name}"
fi
done
return 0
}
# ===== 生成部署脚本 =====
generate_deployment_scripts() {
log_info "===== 生成部署脚本 ====="
# 生成系统优化脚本
cat > "${OFFLINE_DIR}/optimize_system.sh" <<'EOF'
#!/bin/bash
# optimize_system.sh - 服务器系统优化脚本
# 版本: 3.0
# ===== 配置区域 =====
OFFLINE_DIR="/opt/offline_packages"
TOOLS_DIR="${OFFLINE_DIR}/tools"
LOG_FILE="/var/log/system_optimization_$(date +%Y%m%d%H%M%S).log"
# 日志函数
log() {
local level=$1
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() { log "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 系统优化函数 =====
disable_selinux() {
log_info "===== [1/8] 禁用SELinux ====="
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
log_success "SELinux已禁用"
}
disable_firewall() {
log_info "===== [2/8] 禁用防火墙 ====="
systemctl stop firewalld
systemctl disable firewalld
log_success "防火墙已禁用"
}
disable_swap() {
log_info "===== [3/8] 禁用Swap ====="
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
log_success "Swap已禁用"
}
configure_kernel() {
log_info "===== [4/8] 配置内核参数 ====="
# 加载内核模块
cat > /etc/modules-load.d/k8s.conf <<EOL
overlay
br_netfilter
EOL
modprobe overlay
modprobe br_netfilter
# 设置sysctl参数
cat > /極/sysctl.d/k8s.conf <<EOL
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
vm.max_map_count = 262144
fs.file-max = 2097152
EOL
sysctl --system
log_success "内核参数已配置"
}
configure_limits() {
log_info "===== [5/8] 配置系统限制 ====="
cat > /etc/security/limits.d/99-k8s.conf <<EOL
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
* soft memlock unlimited
* hard memlock unlimited
root soft nofile 1048576
root hard nofile 1048576
root soft nproc 65535
root hard nproc 65535
root soft memlock unlimited
root hard memlock unlimited
EOL
log_success "系统限制已配置"
}
configure_chrony() {
log_info "===== [6/8] 配置时间同步 ====="
yum install -y chrony
cat > /etc/chrony.conf <<EOL
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOL
systemctl enable --now chronyd
chronyc sources
log_success "时间同步已配置"
}
install_tools() {
log_info "===== [7/8] 安装系统工具 ====="
# 安装基础工具
yum install -y epel-release
yum install -y htop iotop iftop net-tools jq lsof sysstat
# 安装离线工具
for tool in ${TOOLS_DIR}/*; do
[ -f "$tool" ] || continue
local tool_name=$(basename "$tool")
log_info "正在安装工具: ${tool_name}"
case "$tool_name" in
*cheat*)
gunzip -c "$tool" > /usr/local/bin/cheat
chmod +x /usr/local/bin/cheat
;;
*btop*)
tar -xjf "$tool" -C /tmp
cp /tmp/btop/bin/btop /usr/local/bin/
;;
*bottom*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 btm
;;
*fd*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 fd
;;
*bat*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 bat
;;
*exa*)
unzip -j "$tool" "bin/exa" -d /usr/local/bin/
;;
*)
log_warn "未知工具类型: ${tool_name}, 跳过安装"
;;
esac
if [ $? -eq 0 ]; then
log_success "工具安装成功: ${tool_name}"
else
log_error "工具安装失败: ${tool_name}"
fi
done
log_success "系统工具安装完成"
}
configure_ssh() {
log_info "===== [8/8] 优化SSH配置 ====="
sed -i 's/^#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/^#ClientAliveInterval.*/ClientAliveInterval 300/' /etc/ssh/sshd_config
sed -i 's/^#ClientAliveCountMax.*/ClientAliveCountMax 2/' /etc/ssh/sshd_config
sed -i 's/^#MaxSessions.*/MaxSessions 100/' /etc/ssh/sshd_config
sed -i 's/^#MaxStartups.*/MaxStartups 100:30:200/' /etc/ssh/sshd_config
echo "UseDNS no" >> /etc/ssh/sshd_config
systemctl restart sshd
log_success "SSH配置优化完成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始系统优化 ====="
log_info "主机名: $(hostname -f)"
log_info "IP地址: $(hostname -I | awk '{print $1}')"
log_info "优化日志: ${LOG_FILE}"
disable_selinux
disable_firewall
disable_swap
configure_kernel
configure_limits
configure_chrony
install_tools
configure_ssh
log_success "===== 系统优化完成! ====="
log_info "建议: 重启服务器使所有优化生效"
} 2>&1 | tee -a "$LOG_FILE"
}
main "$@"
EOF
chmod +x "${OFFLINE_DIR}/optimize_system.sh"
log_success "系统优化脚本已生成"
# 生成Kubernetes安装脚本
cat > "${OFFLINE_DIR}/install_k8s_offline.sh" <<'EOF'
#!/bin/bash
# install_k8s_offline.sh - Kubernetes离线部署脚本
# 版本: 4.0
# ===== 配置区域 =====
K8S_VERSION="v1.28.5"
OFFLINE_DIR="/opt/offline_packages"
BIN_DIR="${OFFLINE_DIR}/bin"
IMG_DIR="${OFFLINE_DIR}/images"
LOG_FILE="/var/log/k8s_install_$(date +%Y%m%d%H%M%S).log"
CRI="containerd" # docker 或 containerd
# 日志函数
log() {
local level=$极
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() { log "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 安装函数 =====
install_container_runtime() {
log_info "===== [1/6] 安装容器运行时 (${CRI}) ====="
if [ "$CRI" = "docker" ]; then
yum remove -y docker* containerd.io
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<EOL
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {"max-size": "100m"},
"storage-driver": "overlay2",
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
EOL
systemctl enable --now docker
elif [ "$CRI" = "containerd" ]; then
yum install -y containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|registry.k8s.io/pause|registry.aliyuncs.com/google_containers/pause|' /etc/containerd/config.toml
systemctl enable --now containerd
fi
# 加载离线镜像
for img in "${IMG_DIR}"/*.tar; do
[ -f "$img" ] || continue
if [ "$CRI" = "docker" ]; then
docker load -i "$img"
else
ctr -n=k8s.io images import "$img"
fi
log_info "已加载镜像: $(basename "$img")"
done
log_success "容器运行时安装完成"
}
install_k8s_components() {
log_info "===== [2/6] 安装Kubernetes组件 ====="
# 添加仓库
cat > /etc/yum.repos.d/kubernetes.repo <<EOL
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOL
# 安装基础包
yum install -y kubelet-${K8S_VERSION} kubeadm-${K8S_VERSION} kubectl-${K8S_VERSION} --disableexcludes=kubernetes
# 使用离线二进制
for bin in kubeadm kubelet kubectl; do
[ -f "${BIN_DIR}/${bin}" ] && install -m 0755 "${BIN_DIR}/${bin}" /usr/bin/
done
systemctl enable --now kubelet
log_success "Kubernetes组件安装完成"
}
init_control_plane() {
log_info "===== [3/6] 初始化控制平面 ====="
local NODE_IP=$(hostname -I | awk '{print $1}')
kubeadm init \
--apiserver-advertise-address=$NODE_IP \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=Swap \
--image-repository=registry.ali极s.com/google_containers \
--kubernetes-version=$K8S_VERSION | tee -a "$LOG_FILE"
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /root/.bashrc
source /root/.bashrc
log_success "控制平面初始化完成"
}
install_network_addon() {
log_info "===== [4/6] 安装网络插件 (Flannel) ====="
# 加载Flannel镜像
local flannel_img=$(find "${IMG_DIR}" -name "*flannel*.tar")
if [ -f "$flannel_img" ]; then
if [ "$CRI" = "docker" ]; then
docker load -i "$flannel_img"
else
ctr -n=k8s.io images import "$flannel_img"
fi
fi
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 等待网络插件就绪
log_info "等待网络插件启动..."
kubectl wait --for=condition=ready pod -l app=flannel -n kube-system --timeout=180s
log_success "网络插件安装完成"
}
install_metrics_server() {
log_info "===== [5/6] 安装Metrics Server ====="
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 修改配置以支持离线环境
kubectl patch deployment metrics-server -n kube-system --type=json \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'
log_info "等待Metrics Server启动..."
kubectl wait --for=condition=ready pod -l k8s-app=metrics-server -n kube-system --timeout=120s
log_success "Metrics Server安装完成"
}
install_dashboard() {
log_info "===== [6/6] 安装Kubernetes Dashboard ====="
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 创建管理员用户
kubectl apply -f - <<EOL
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOL
# 获取访问令牌
local token=$(kubectl -n kubernetes-dashboard create token admin-user)
log_info "Dashboard访问令牌: ${token}"
log_info "访问地址: https://$(hostname -I | awk '{print $1}'):30000"
log_success "Kubernetes Dashboard安装完成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始Kubernetes离线安装 ====="
log_info "主机名: $(hostname -f)"
log_info "IP地址: $(hostname -I | awk '{print $1}')"
log_info "Kubernetes版本: ${K8S_VERSION}"
log_info "容器运行时: ${CRI}"
log_info "日志文件: ${LOG_FILE}"
install_container_runtime
install_k8s_components
init_control_plane
install_network_addon
install_metrics_server
install_dashboard
log_success "===== Kubernetes安装成功! ====="
echo "加入节点命令:"
kubeadm token create --print-join-command
echo "验证集群状态: kubectl get nodes"
} 2>&1 | tee -a "$LOG_FILE"
}
main "$@"
EOF
chmod +x "${OFFLINE_DIR}/install_k8s_offline.sh"
log_success "Kubernetes安装脚本已生成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始下载Kubernetes离线资源 ====="
log_info "Kubernetes版本: ${K8S_VERSION}"
log_info "离线包目录: ${OFFLINE_DIR}"
create_dirs
download_k8s_binaries || { log_error "Kubernetes二进制文件下载失败"; exit 1; }
download_k8s_images || log_warn "容器镜像下载失败,请在离线环境中手动加载镜像"
download_system_tools
generate_deployment_scripts
# 创建打包脚本
cat > "${OFFLINE_DIR}/package_offline.sh" <<'EOF'
#!/bin/bash
# 打包离线资源
tar -czvf k8s-offline-pkg-$(date +%Y%m%d).tar.gz -C /opt offline_packages
echo "离线包已创建: k8s-offline-pkg-$(date +%Y%m%d).tar.gz"
EOF
chmod +x "${OFFLINE_DIR}/package_offline.sh"
log_success "===== 下载完成! ====="
log_info "1. 打包离线资源: sudo ${OFFLINE_DIR}/package_offline.sh"
log_info "2. 复制离线包到目标服务器"
log_info "3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt"
log_info "4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh"
log_info "5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh"
} 2>&1 | tee -a "$LOG_FILE"
}
main
```
### 2. 系统优化脚本 (optimize_system.sh)
保持不变,使用下载脚本中生成的那个。
### 3. Kubernetes离线部署脚本 (install_k8s_offline.sh)
保持不变,使用下载脚本中生成的那个。
### 改进说明
1. **Docker自动安装和启动**:
- 在下载容器镜像前,调用`setup_docker`函数确保Docker已安装并运行。
2. **下载重试机制**:
- 对于系统工具的下载,添加了最多3次的重试,每次失败后等待3秒。
3. **错误处理**:
- 容器镜像下载失败不会导致整个脚本退出,而是记录错误并继续,这样用户可以在离线环境中手动加载镜像(如果有备份)。
- Kubernetes二进制文件下载失败会终止脚本,因为这是核心组件。
4. **工具安装的健壮性**:
- 在系统优化脚本的`install_tools`函数中,增加了对工具文件类型的判断,避免因缺少某个工具导致脚本中断。
5. **日志清晰**:
- 每个步骤的日志更加详细,包括重试信息和跳过信息。
### 使用流程
与之前相同,但增加了对下载失败情况的处理。如果某些工具下载失败,系统优化时可能会缺少这些工具,但不会影响Kubernetes的安装。
### 注意事项
1. 如果容器镜像下载失败,用户需要手动获取这些镜像(例如从其他途径下载),并放置在`/opt/offline_packages/images`目录下。
2. 系统工具不是Kubernetes必需的,下载失败只会影响一些辅助工具的使用。
这样改进后,脚本在遇到部分失败时仍能继续执行,提高了健壮性,同时确保了核心组件(Kubernetes二进制文件)的可靠性。
§§相关问题§§:
1. 在Kubernetes集群中如何配置持久化存储(如NFS、Ceph)?
2. 如何安全地升级离线环境中的Kubernetes集群?
3. 如何备份和恢复Kubernetes集群状态(特别是etcd)?
4. 如何部署高可用(多控制平面)的Kubernetes集群?</think>根据日志中的错误信息,我改进了脚本以解决以下关键问题:
1. Docker服务未运行导致镜像下载失败
2. GitHub连接问题导致工具下载失败
3. 镜像保存失败问题
以下是完全修复后的脚本,包含重试机制、备用镜像源和更健壮的错误处理:
### 1. 修复后的下载脚本 (download_k8s_offline.sh)
```bash
#!/bin/bash
# download_k8s_offline.sh - Kubernetes离线资源下载脚本(修复版)
# 版本: 4.0
# 功能: 下载Kubernetes二进制文件、容器镜像和系统优化工具
# ===== 配置区域 =====
K8S_VERSION="v1.28.5" # Kubernetes版本
OFFLINE_DIR="/opt/offline_packages" # 离线包根目录
BIN_DIR="${OFFLINE_DIR}/bin" # 二进制文件目录
IMG_DIR="${OFFLINE_DIR}/images" # 容器镜像目录
TOOLS_DIR="${OFFLINE_DIR}/tools" # 系统工具目录
LOG_FILE="/var/log/k8s_download_$(date +%Y%m%d%H%M%S).log" # 日志文件
MAX_RETRY=3 # 最大重试次数
MIRROR_URL="https://mirror.ghproxy.com/" # GitHub镜像地址
# Kubernetes镜像列表
K8S_IMAGES=(
"registry.aliyuncs.com/google_containers/kube-apiserver:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-controller-manager:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-scheduler:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/kube-proxy:${K8S_VERSION}"
"registry.aliyuncs.com/google_containers/pause:3.9"
"registry.aliyuncs.com/google_containers/etcd:3.5.9-0"
"registry.aliyuncs.com/google_containers/coredns:v1.10.1"
"quay.io/coreos/flannel:v0.22.0" # Flannel网络插件
)
# 系统优化工具列表(使用镜像源)
SYSTEM_TOOLS=(
"${MIRROR_URL}https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz"
"${MIRROR_URL}https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz"
"${MIRROR_URL}https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz"
"${MIRROR_URL}https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz"
"${MIRROR_URL}https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown极inux-gnu.tar.gz"
"${MIRROR_URL}https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip"
)
# ===== 日志函数 =====
log() {
local level=$1
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() { log "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 工具函数 =====
retry_command() {
local cmd=$1
local description=$2
local retry=0
while [ $retry -lt $MAX_RETRY ]; do
log_info "尝试 $((retry+1)): $description"
if eval "$cmd"; then
return 0
else
((retry++))
sleep $((retry * 2))
fi
done
log_error "$description 失败 (重试 $MAX_RETRY 次)"
return 1
}
# ===== 创建目录结构 =====
create_dirs() {
log_info "===== 创建目录结构 ====="
mkdir -p "$BIN_DIR" "$IMG_DIR" "$TOOLS_DIR"
log_success "目录创建完成: $OFFLINE_DIR"
}
# ===== 安装并启动Docker =====
setup_docker() {
log_info "===== 安装并启动Docker ====="
if command -v docker &> /dev/null; then
log_info "Docker已安装"
else
log_info "正在安装Docker..."
curl -fsSL https://get.docker.com | sh
fi
if ! systemctl is-active --quiet docker; then
log_info "启动Docker服务..."
systemctl start docker
systemctl enable docker
fi
# 验证Docker运行状态
if docker info &> /dev/null; then
log_success "Docker运行正常"
else
log_error "Docker启动失败"
return 1
fi
}
# ===== 下载Kubernetes二进制文件 =====
download_k8s_binaries() {
log_info "===== 下载Kubernetes二进制文件 ====="
local binaries=("kubeadm" "kubelet" "kubectl")
for bin in "${binaries[@]}"; do
local url="https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/${bin}"
local target="${BIN_DIR}/${bin}"
retry_command \
"curl -L --progress-bar -o '$target' '$url'" \
"下载 $bin"
if [ $? -eq 0 ]; then
chmod +x "$target"
log_success "下载成功: ${bin}"
else
log_error "无法下载 ${bin}"
return 1
fi
done
return 0
}
# ===== 下载容器镜像 =====
download_k8s_images() {
log_info "===== 下载容器镜像 ====="
setup_docker || return 1
for image in "${K8S_IMAGES[@]}"; do
# 提取镜像名(不含仓库地址)
local image_name=$(echo "$image" | awk -F/ '{print $NF}' | tr ':' '-')
local target="${IMG_DIR}/${image_name}.tar"
# 拉取镜像
retry_command \
"docker pull '$image'" \
"拉取镜像 $image"
if [ $? -ne 0 ]; then
log_error "镜像拉取失败: ${image}"
continue
fi
# 保存镜像
if docker save -o "$target" "$image"; then
log_success "镜像保存成功: ${image_name}"
else
log_error "镜像保存失败: ${image}"
fi
done
return 0
}
# ===== 下载系统工具 =====
download_system_tools() {
log_info "===== 下载系统优化工具 ====="
for tool_url in "${SYSTEM_TOOLS[@]}"; do
local tool_name=$(basename "$tool_url")
local target="${TOOLS_DIR}/${tool_name}"
retry_command \
"curl -L --progress-bar -o '$target' '$tool_url'" \
"下载 $tool_name"
if [ $? -eq 0 ]; then
log_success "下载成功: ${tool_name}"
else
log_warn "下载失败: ${tool_name}"
fi
done
return 0
}
# ===== 生成部署脚本 =====
generate_deployment_scripts() {
log_info "===== 生成部署脚本 ====="
# 生成系统优化脚本
cat > "${OFFLINE_DIR}/optimize_system.sh" <<'EOF'
#!/bin/bash
# optimize_system.sh - 服务器系统优化脚本(修复版)
# 版本: 4.0
# ===== 配置区域 =====
OFFLINE_DIR="/opt/offline_packages"
TOOLS_DIR="${OFFLINE_DIR}/tools"
LOG_FILE="/var/log/system_optimization_$(date +%Y%m%d%H%M%S).log"
# 日志函数
log() {
local level=$1
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() {极 "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 系统优化函数 =====
disable_selinux() {
log_info "===== [1/8] 禁用SELinux ====="
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
log_success "SELinux已禁用"
}
disable_firewall() {
log_info "===== [2/8] 禁用防火墙 ====="
systemctl stop firewalld
systemctl disable firewalld
log_success "防火墙已禁用"
}
disable_swap() {
log_info "===== [3/8] 禁用Swap ====="
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
log_success "Swap已禁用"
}
configure_kernel() {
log_info "===== [4/8] 配置内核参数 ====="
# 加载内核模块
cat > /etc/modules-load.d/k8s.conf <<EOL
overlay
br_netfilter
EOL
modprobe overlay
modprobe br_netfilter
# 设置sysctl参数
cat > /etc/sysctl.d/k8s.conf <<EOL
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
vm.max_map_count = 262144
fs.file-max = 2097152
EOL
sysctl --system
log_success "内核参数已配置"
}
configure_limits() {
log_info "===== [5/8] 配置系统限制 ====="
cat > /etc/security/limits.d/99-k8s.conf <<EOL
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
* soft memlock unlimited
* hard memlock unlimited
root soft nofile 1048576
root hard nofile 1048576
root soft nproc 65535
root hard nproc 65535
root soft memlock unlimited
root hard memlock unlimited
EOL
log_success "系统限制已配置"
}
configure_chrony() {
log_info "===== [6/8] 配置时间同步 ====="
yum install -y chrony
cat > /etc/chrony.conf <<EOL
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOL
systemctl enable --now chronyd
chronyc sources
log_success "时间同步已配置"
}
install_tools() {
log_info "===== [7/8] 安装系统工具 ====="
# 安装基础工具
yum install -y epel-release
yum install -y htop iotop iftop net-tools jq lsof sysstat
# 安装离线工具
for tool in ${TOOLS_DIR}/*; do
[ -f "$tool" ] || continue
local tool_name=$(basename "$tool")
log_info "正在安装工具: ${tool_name}"
case "$tool_name" in
*cheat*)
gunzip -c "$tool" > /usr/local/bin/cheat
chmod +x /usr/local/bin/cheat
;;
*btop*)
tar -xjf "$tool" -C /tmp
cp /tmp/btop/bin/btop /usr/local/bin/
;;
*bottom*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 btm
;;
*fd*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 fd
;;
*bat*)
tar -xzf "$tool" -C /usr/local/bin --strip-components=1 bat
;;
*exa*)
unzip -j "$tool" "bin/exa" -d /usr/local/bin/
;;
*)
log_warn "未知工具类型: ${tool_name}, 跳过安装"
;;
esac
if [ $? -eq 0 ]; then
log_success "工具安装成功: ${tool_name}"
else
log_error "工具安装失败: ${tool_name}"
fi
done
log_success "系统工具安装完成"
}
configure_ssh() {
log_info "===== [8/8] 优化SSH配置 ====="
sed -i 's/^#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/^#ClientAliveInterval.*/ClientAliveInterval 300/' /etc/ssh/sshd_config
sed -i 's/^#ClientAliveCountMax.*/ClientAliveCountMax 2/' /etc/ssh/sshd_config
sed -i 's/^#MaxSessions.*/MaxSessions 100/' /etc/ssh/sshd_config
sed -i 's/^#MaxStartups.*/MaxStartups 100:30:200/' /etc/ssh/sshd_config
echo "UseDNS no" >> /etc/ssh/sshd_config
systemctl restart sshd
log_success "SSH配置优化完成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始系统优化 ====="
log_info "主机名: $(hostname -f)"
log_info "IP地址: $(hostname -I | awk '{print $1}')"
log_info "优化日志: ${LOG_FILE}"
disable_selinux
disable_firewall
disable_swap
configure_kernel
configure_limits
configure_chrony
install_tools
configure_ssh
log_success "===== 系统优化完成! ====="
log_info "建议: 重启服务器使所有优化生效"
} 2>&1 | tee -a "$LOG_FILE"
}
main "$@"
EOF
chmod +x "${OFFLINE_DIR}/optimize_system.sh"
log_success "系统优化脚本已生成"
# 生成Kubernetes安装脚本
cat > "${OFFLINE_DIR}/install_k8s_offline.sh" <<'EOF'
#!/bin/bash
# install_k8s_offline.sh - Kubernetes离线部署脚本(修复版)
# 版本: 4.0
# ===== 配置区域 =====
K8S_VERSION="v1.28.5"
OFFLINE_DIR="/opt/offline_packages"
BIN_DIR="${OFFLINE_DIR}/bin"
IMG_DIR="${OFFLINE_DIR}/images"
LOG_FILE="/var/log/k8s_install_$(date +%Y%m%d%H%M%S).log"
CRI="containerd" # docker 或 containerd
MAX_RETRY=5 # 操作重试次数
# 日志函数
log() {
local level=$1
local message=$2
local timestamp=$(date +'%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() { log "INFO" "$1"; }
log_warn() { log "WARN" "$1"; }
log_error() { log "ERROR" "$1"; }
log_success() { log "SUCCESS" "$1"; }
# ===== 工具函数 =====
retry_command() {
local cmd=$1
local description=$2
local retry=0
while [ $retry -lt $MAX_RETRY ]; do
log_info "尝试 $((retry+1)): $description"
if eval "$cmd"; then
return 0
else
((retry++))
sleep $((retry * 3))
fi
done
log_error "$description 失败 (重试 $MAX_RETRY 次)"
return 1
}
# ===== 安装函数 =====
install_container_runtime() {
log_info "===== [1/6] 安装容器运行时 (${CRI}) ====="
if [ "$CRI" = "docker" ]; then
# 安装Docker
yum remove -y docker* containerd.io || true
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
retry_command \
"yum install -y docker-ce docker-ce-cli containerd.io" \
"安装Docker"
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<EOL
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {"max-size": "100m"},
"storage-driver": "overlay2",
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
EOL
systemctl enable docker
systemctl start docker
elif [ "$CRI" = "containerd" ]; then
# 安装Containerd
yum install -y containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|registry.k8s.io/pause|registry.aliyuncs.com/google_containers/pause|' /etc/containerd/config.toml
systemctl enable containerd
systemctl start containerd
fi
# 加载离线镜像
for img in "${IMG_DIR}"/*.tar; do
[ -f "$img" ] || continue
if [ "$CRI" = "docker" ]; then
retry_command \
"docker load -i '$img'" \
"加载镜像 $(basename "$img")"
else
retry_command \
"ctr -n=k8s.io images import '$img'" \
"加载镜像 $(basename "$img")"
fi
done
log_success "容器运行时安装完成"
}
install_k8s_components() {
log_info "===== [2/6] 安装Kubernetes组件 ====="
# 添加仓库
cat > /etc/yum.repos.d/kubernetes.repo <<EOL
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOL
# 安装基础包
retry_command \
"yum install -y kubelet-${K8S_VERSION} kubeadm-${K8S_VERSION} kubectl-${K8S_VERSION} --disableexcludes=kubernetes" \
"安装Kubernetes组件"
# 使用离线二进制
for bin in kubeadm kubelet kubectl; do
[ -f "${BIN_DIR}/${bin}" ] && install -m 0755 "${BIN_DIR}/${bin}" /usr/bin/
done
systemctl enable --now kubelet
log_success "Kubernetes组件安装完成"
}
init_control_plane() {
log_info "===== [3/6] 初始化控制平面 ====="
local NODE_IP=$(hostname -I | awk '{print $1}')
retry_command \
"kubeadm init \
--apiserver-advertise-address=$NODE_IP \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=Swap \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=$K8S_VERSION" \
"初始化Kubernetes控制平面"
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /root/.bashrc
source /root/.bashrc
log_success "控制平面初始化完成"
}
install_network_addon() {
log_info "===== [4/6] 安装网络插件 (Flannel) ====="
# 应用Flannel配置
retry_command \
"kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml" \
"安装Flannel网络插件"
# 等待网络插件就绪
log_info "等待网络插件启动..."
retry_command \
"kubectl wait --for=condition=ready pod -l app=flannel -n kube-system --timeout=300s" \
"等待Flannel就绪"
log_success "网络插件安装完成"
}
install_metrics_server() {
log_info "===== [5/6] 安装Metrics Server ====="
retry_command \
"kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml" \
"安装Metrics Server"
# 修改配置以支持离线环境
kubectl patch deployment metrics-server -n kube-system --type=json \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'
log_info "等待Metrics Server启动..."
retry_command \
"kubectl wait --for=condition=ready pod -l k8s-app=metrics-server -n kube-system --timeout=180s" \
"等待Metrics Server就绪"
log_success "Metrics Server安装完成"
}
install_dashboard() {
log_info "===== [6/6] 安装Kubernetes Dashboard ====="
retry_command \
"kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml" \
"安装Kubernetes Dashboard"
# 创建管理员用户
cat <<EOL | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOL
# 获取访问令牌
local token=$(kubectl -n kubernetes-dashboard create token admin-user 2>/dev/null)
if [ -n "$token" ]; then
log_info "Dashboard访问令牌: ${token}"
log_info "访问地址: https://$(hostname -I | awk '{print $1}'):30000"
else
log_warn "无法获取Dashboard令牌,请手动获取"
fi
log_success "Kubernetes Dashboard安装完成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始Kubernetes离线安装 ====="
log_info "主机名: $(hostname -f)"
log_info "IP地址: $(hostname -I | awk '{print $1}')"
log_info "Kubernetes版本: ${K8S_VERSION}"
log_info "容器运行时: ${CRI}"
log_info "日志文件: ${LOG_FILE}"
install_container_runtime
install_k8s_components
init_control_plane
install_network_addon
install_metrics_server
install_dashboard
log_success "===== Kubernetes安装成功! ====="
echo "加入节点命令:"
kubeadm token create --print-join-command || echo "请手动生成加入命令: kubeadm token create --print-join-command"
echo "验证集群状态: kubectl get nodes"
} 2>&1 | tee -a "$LOG_FILE"
}
main "$@"
EOF
chmod +x "${OFFLINE_DIR}/install_k8s_offline.sh"
log_success "Kubernetes安装脚本已生成"
}
# ===== 主函数 =====
main() {
{
log_info "===== 开始下载Kubernetes离线资源 ====="
log_info "Kubernetes版本: ${K8S_VERSION}"
log_info "离线包目录: ${OFFLINE_DIR}"
create_dirs
download_k8s_binaries || { log_error "Kubernetes二进制文件下载失败"; exit 1; }
download_k8s_images || log_warn "部分容器镜像下载失败,请在离线环境中手动加载镜像"
download_system_tools
generate_deployment_scripts
# 创建打包脚本
cat > "${OFFLINE_DIR}/package_offline.sh" <<'EOF'
#!/bin/bash
# 打包离线资源
tar -czvf k8s-offline-pkg-$(date +%Y%m%d).tar.gz -C /opt offline_packages
echo "离线包已创建: k8s-offline-pkg-$(date +%Y%m%d).tar.gz"
EOF
chmod +x "${OFFLINE_DIR}/package_offline.sh"
log_success "===== 下载完成! ====="
log_info "1. 打包离线资源: sudo ${OFFLINE_DIR}/package_offline.sh"
log_info "2. 复制离线包到目标服务器"
log_info "3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt"
log_info "4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh"
log_info "5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh"
} 2>&1 | tee -a "$LOG_FILE"
}
main
```
### 关键修复和改进:
1. **Docker服务自动管理**:
- 自动检测并安装Docker
- 确保Docker服务在镜像下载前已启动
- 添加Docker健康检查
2. **下载重试机制**:
- 所有下载操作最多重试3次
- 每次重试间隔时间递增
- 失败后提供清晰错误日志
3. **GitHub镜像支持**:
- 使用 `https://mirror.ghproxy.com/` 作为GitHub镜像
- 解决国内访问GitHub困难问题
4. **镜像下载改进**:
- 分离镜像拉取和保存操作
- 每个镜像单独处理错误
- 失败时跳过当前镜像继续后续操作
5. **部署脚本增强**:
- 所有关键操作添加重试机制
- 更健壮的错误处理
- 自动生成加入节点命令
- 容器运行时安装优化
6. **日志改进**:
- 每个操作步骤清晰标记
- 重试次数明确显示
- 错误信息详细记录
### 使用说明:
#### 1. 执行下载脚本:
```bash
chmod +x download_k8s_offline.sh
sudo ./download_k8s_offline.sh
```
#### 2. 打包离线资源:
```bash
sudo /opt/offline_packages/package_offline.sh
```
#### 3. 传输到目标服务器:
```bash
scp k8s-offline-pkg-*.tar.gz user@target-server:/tmp/
```
#### 4. 在目标服务器上:
```bash
# 解压离线包
sudo tar -xzvf /tmp/k8s-offline-pkg-*.tar.gz -C /opt/
# 系统优化
sudo /opt/offline_packages/optimize_system.sh
# 安装Kubernetes
sudo /opt/offline_packages/install_k8s_offline.sh
```
### 故障处理建议:
1. **镜像下载失败**:
- 手动下载缺失镜像到 `/opt/offline_packages/images/`
- 使用命令 `docker pull <镜像名>` 然后 `docker save -o <文件名>.tar <镜像名>`
2. **工具下载失败**:
- 从其他来源获取工具并放入 `/opt/offline_packages/tools/`
- 系统优化脚本会自动安装可用工具
3. **网络问题**:
- 在下载脚本中替换 `MIRROR_URL` 为可用的GitHub镜像
- 使用代理设置:`export https_proxy=http://proxy-ip:port`
此版本脚本针对原始错误进行了全面加固,能够更好地处理网络问题和服务状态问题,确保离线部署的可靠性。
阅读全文
相关推荐














