Kubernetes 单节点集群搭建

Kubernetes 单节点集群搭建教程

本人尝试基于Ubuntu搭建一个单节点K8S集群,其中遇到各种问题,最大的问题就是网络,各种镜像源下载不下来,特此记录!注意:文中使用了几个镜像,将看来可能失效导致安装失败,但安装的逻辑不变可以自行寻找可以用的镜像。文末附上一个无脑脚本,保存为 xx.sh 直接bash 执行即可。

前置条件

  1. 操作系统:Ubuntu 20.04 或更高版本。
  2. 硬件要求
    • 至少 2 核 CPU 和 10GB 内存。
  3. 网络环境:确保服务器可以访问互联网。
  4. 权限 :以 root 用户或使用 sudo 运行以下命令。

步骤 1:更新系统并安装必要工具

bash 复制代码
# 更新系统包
apt-get update && apt-get upgrade -y

# 安装必要的工具
apt-get install -y curl apt-transport-https ca-certificates software-properties-common

步骤 2:安装和配置 containerd

bash 复制代码
apt-get install -y containerd
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd

步骤 3:安装 crictl 工具

bash 复制代码
CRITCL_VERSION="v1.28.0"
curl -L https://github.moeyy.xyz/https://github.com/kubernetes-sigs/cri-tools/releases/download/$CRITCL_VERSION/crictl-${CRITCL_VERSION}-linux-amd64.tar.gz --output crictl-${CRITCL_VERSION}-linux-amd64.tar.gz
tar -xzvf crictl-${CRITCL_VERSION}-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-${CRITCL_VERSION}-linux-amd64.tar.gz
cat <<EOF | tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

步骤 4:配置 containerd 使用阿里云沙箱镜像

bash 复制代码
if ! grep -q "sandbox_image = \"registry.aliyuncs.com/google_containers/pause:3.9\"" /etc/containerd/config.toml; then
    sed -i 's|sandbox_image = .*|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml
fi
systemctl restart containerd

步骤 5:清理现有 Kubernetes 集群(如果存在)

bash 复制代码
systemctl stop kubelet || true
systemctl disable kubelet || true
kubeadm reset -f
rm -rf /etc/kubernetes/* /var/lib/kubelet/* /etc/cni/net.d/*
crictl ps -q | xargs -r crictl rm -f || true
crictl images -q | xargs -r crictl rmi -f || true

步骤 6:加载内核模块并启用 IP 转发

bash 复制代码
modprobe br_netfilter
echo "br_netfilter" | tee -a /etc/modules-load.d/modules.conf
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward=1" | tee -a /etc/sysctl.conf
sysctl -p

步骤 7:添加 Kubernetes 国内镜像源并安装组件

bash 复制代码
cat <<EOF | tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
apt-get update
apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
apt-mark hold kubelet kubeadm kubectl

步骤 8:关闭 swap 分区

复制代码
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

步骤 9:初始化 Kubernetes 集群

bash 复制代码
kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

步骤 10:安装 Flannel 网络插件

bash 复制代码
MIRROR_SOURCE="ghcr.monlor.com"
crictl pull ${MIRROR_SOURCE}/flannel-io/flannel:v0.26.4
ctr -n k8s.io images tag ${MIRROR_SOURCE}/flannel-io/flannel:v0.26.4 ghcr.io/flannel-io/flannel:v0.26.4
crictl pull ${MIRROR_SOURCE}/flannel-io/flannel-cni-plugin:v1.6.2-flannel1
ctr -n k8s.io images tag ${MIRROR_SOURCE}/flannel-io/flannel-cni-plugin:v1.6.2-flannel1 ghcr.io/flannel-io/flannel-cni-plugin:v1.6.2-flannel1
FLANNEL_YAML="https://github.moeyy.xyz/https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml"
curl -L $FLANNEL_YAML | kubectl apply -f -

步骤 11:验证集群状态

复制代码
kubectl get nodes
kubectl get pods --all-namespaces

大功告成!

单节点调度需去除污点

bash 复制代码
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

无脑脚本

bash 复制代码
#!/bin/bash

# 设置脚本退出条件:任何命令失败则退出
set -e

# 定义颜色变量,方便输出日志
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# 打印信息函数
log_info() {
    echo -e "${GREEN}[INFO] $1${NC}"
}

log_warn() {
    echo -e "${YELLOW}[WARN] $1${NC}"
}

log_error() {
    echo -e "${RED}[ERROR] $1${NC}"
    exit 1
}

# 检查是否以 root 用户运行
if [ "$EUID" -ne 0 ]; then
    log_error "请以 root 用户或使用 sudo 运行此脚本。"
fi

# 更新系统包(仅在未更新时执行)
if ! grep -q "Last update" /var/log/apt/history.log 2>/dev/null || [ $(($(date +%s) - $(stat -c %Y /var/log/apt/history.log))) -gt 86400 ]; then
    log_info "更新系统包..."
    apt-get update && apt-get upgrade -y
else
    log_warn "系统包已更新,跳过此步骤。"
fi

# 安装必要的工具(仅在未安装时执行)
if ! dpkg -l | grep -q "curl"; then
    log_info "安装必要的工具(curl、apt-transport-https等)..."
    apt-get install -y curl apt-transport-https ca-certificates software-properties-common
else
    log_warn "必要的工具已安装,跳过此步骤。"
fi

# 安装 containerd(仅在未安装时执行)
if ! dpkg -l | grep -q "containerd"; then
    log_info "安装 containerd..."
    apt-get install -y containerd
else
    log_warn "containerd 已安装,跳过此步骤。"
fi

# 配置 containerd(仅在未配置时执行)
if [ ! -f /etc/containerd/config.toml ]; then
    log_info "配置 containerd..."
    mkdir -p /etc/containerd
    containerd config default > /etc/containerd/config.toml
    sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
    systemctl restart containerd
else
    log_warn "containerd 已配置,跳过此步骤。"
fi

# 定义 crictl 下载 URL
CRITCL_VERSION="v1.28.0"
ACCELERATED_CRITCL_URL="https://github.moeyy.xyz/https://github.com/kubernetes-sigs/cri-tools/releases/download/$CRITCL_VERSION/crictl-${CRITCL_VERSION}-linux-amd64.tar.gz"

# 安装 crictl 工具(仅在未安装时执行)
if ! command -v crictl &> /dev/null; then
    log_info "安装 crictl 工具..."
    
    # 尝试从加速镜像源下载
    if ! curl -L $ACCELERATED_CRITCL_URL --output crictl-${CRITCL_VERSION}-linux-amd64.tar.gz; then
        log_error "无法从加速镜像源下载 crictl,请检查网络或手动下载并安装。"
    fi

    # 解压并安装 crictl
    tar -xzvf crictl-${CRITCL_VERSION}-linux-amd64.tar.gz -C /usr/local/bin
    rm -f crictl-${CRITCL_VERSION}-linux-amd64.tar.gz
else
    log_warn "crictl 已安装,跳过此步骤。"
fi

# 配置 crictl(仅在未配置时执行)
if [ ! -f /etc/crictl.yaml ]; then
    log_info "配置 crictl..."
    cat <<EOF | tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
else
    log_warn "crictl 已配置,跳过此步骤。"
fi

# 配置 containerd 使用阿里云的沙箱镜像
log_info "配置 containerd 使用阿里云的沙箱镜像..."

# 修改 containerd 配置文件
if ! grep -q "sandbox_image = \"registry.aliyuncs.com/google_containers/pause:3.9\"" /etc/containerd/config.toml; then
    # 备份原始配置文件
    cp /etc/containerd/config.toml /etc/containerd/config.toml.bak

    # 修改配置文件,设置 sandbox_image
    sed -i 's|sandbox_image = .*|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml

    # 如果配置文件中不存在 sandbox_image,则直接添加
    if ! grep -q "sandbox_image" /etc/containerd/config.toml; then
        echo 'sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"' >> /etc/containerd/config.toml
    fi

    log_info "已配置 containerd 使用阿里云的沙箱镜像。"
else
    log_warn "containerd 已配置为使用阿里云的沙箱镜像,跳过此步骤。"
fi

# 重启 containerd 服务以应用更改
systemctl restart containerd

## 检测是否需要清理现有集群
if [ -f /etc/kubernetes/admin.conf ] || systemctl is-active --quiet kubelet; then
    log_info "检测到已存在的 Kubernetes 集群,开始清理..."

    # 停止并禁用 kubelet 服务
    log_info "停止并禁用 kubelet 服务..."
    systemctl stop kubelet || true
    systemctl disable kubelet || true

    # 重置 kubeadm 集群
    log_info "重置 kubeadm 集群..."
    kubeadm reset -f

    # 清理所有 Kubernetes 相关进程
    log_info "清理所有 Kubernetes 相关进程..."
    pkill -f kube-apiserver || true
    pkill -f kube-controller-manager || true
    pkill -f kube-scheduler || true
    pkill -f etcd || true
    pkill -f kubelet || true

    # 删除 /etc/kubernetes 目录
    log_info "删除 /etc/kubernetes 目录..."
    rm -rf /etc/kubernetes/*

    # 删除 /var/lib/kubelet 目录
    log_info "删除 /var/lib/kubelet 目录..."
    rm -rf /var/lib/kubelet/*

    # 清理 CNI 配置文件
    log_info "清理 CNI 配置文件..."
    rm -rf /etc/cni/net.d/*

    # 清理 containerd 中的残留容器和镜像
    log_info "清理所有容器..."
    crictl ps -q | xargs -r crictl rm -f || true

    log_info "清理所有镜像..."
    crictl images -q | xargs -r crictl rmi -f || true

    log_info "Kubernetes 集群清理完成,准备重新初始化。"
else
    log_warn "未检测到已存在的 Kubernetes 集群,无需清理。"
fi

# 加载 br_netfilter 内核模块并启用 IP 转发
log_info "加载 br_netfilter 内核模块并启用 IP 转发..."

# 加载 br_netfilter 模块
if ! lsmod | grep -q "br_netfilter"; then
    modprobe br_netfilter
    log_info "已加载 br_netfilter 模块。"
else
    log_warn "br_netfilter 模块已加载,跳过此步骤。"
fi

# 确保 br_netfilter 模块在系统启动时自动加载
if ! grep -q "br_netfilter" /etc/modules-load.d/modules.conf; then
    echo "br_netfilter" | tee -a /etc/modules-load.d/modules.conf
    log_info "已配置 br_netfilter 模块开机自动加载。"
else
    log_warn "br_netfilter 模块已配置为开机自动加载,跳过此步骤。"
fi

# 启用 IPv4 转发
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != "1" ]; then
    echo "1" > /proc/sys/net/ipv4/ip_forward
    log_info "已启用 IPv4 转发。"
else
    log_warn "IPv4 转发已启用,跳过此步骤。"
fi

# 确保 IPv4 转发配置在系统重启后仍然生效
if ! grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf; then
    echo "net.ipv4.ip_forward=1" | tee -a /etc/sysctl.conf
    log_info "已配置 IPv4 转发开机生效。"
else
    log_warn "IPv4 转发已配置为开机生效,跳过此步骤。"
fi

# 应用 sysctl 配置
sysctl -p

# 添加 Kubernetes 国内镜像源(仅在未添加时执行)
if [ ! -f /etc/apt/sources.list.d/kubernetes.list ]; then
    log_info "添加 Kubernetes 阿里云镜像源..."
    cat <<EOF | tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
    curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
    apt-get update
else
    log_warn "Kubernetes 镜像源已添加,跳过此步骤。"
fi

# 安装 kubeadm、kubelet 和 kubectl(仅在未安装时执行)
if ! dpkg -l | grep -q "kubeadm"; then
    log_info "安装 Kubernetes 1.28..."
    apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
    apt-mark hold kubelet kubeadm kubectl
else
    log_warn "Kubernetes 组件已安装,跳过此步骤。"
fi

# 关闭 swap 分区(仅在未关闭时执行)
if swapon --show | grep -q "/dev/"; then
    log_info "关闭 swap 分区..."
    swapoff -a
    sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
else
    log_warn "swap 分区已关闭,跳过此步骤。"
fi

# 配置 kubelet 使用国内镜像源(仅在未配置时执行)
if ! grep -q "registry.aliyuncs.com/google_containers" /etc/systemd/system/kubelet.service.d/20-aliyun.conf 2>/dev/null; then
    log_info "配置 kubelet 使用国内镜像源..."
    cat <<EOF | tee /etc/systemd/system/kubelet.service.d/20-aliyun.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--cgroup-driver=systemd --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9"
EOF
    systemctl daemon-reload
    systemctl restart kubelet
else
    log_warn "kubelet 已配置为使用国内镜像源,跳过此步骤。"
fi

# 初始化 Kubernetes 集群(仅在未初始化时执行)
if ! kubectl get nodes 2>/dev/null | grep -q "Ready"; then
    log_info "初始化 Kubernetes 集群..."

    # 清理现有集群
    log_info "清理现有 Kubernetes 集群..."
    kubeadm reset -f
    rm -rf /etc/kubernetes/*
    rm -rf /var/lib/kubelet/*
    rm -rf /etc/cni/net.d/*
    crictl ps -q | xargs -r crictl rm -f || true
    crictl images -q | xargs -r crictl rmi -f || true

    # 删除用户的 kubeconfig 文件
    if [ -f $HOME/.kube/config ]; then
        log_info "删除用户的 kubeconfig 文件..."
        rm -f $HOME/.kube/config
    fi

    kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers

    # 配置 kubectl
    log_info "配置 kubectl..."
    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
else
    log_warn "Kubernetes 集群已初始化,跳过此步骤。"
fi

# 设置镜像源变量
MIRROR_SOURCE="ghcr.monlor.com"

# 提前拉取并标记 Flannel 镜像
log_info "提前拉取并标记 Flannel 镜像..."

# 拉取 Flannel 主镜像
if ! crictl images | grep -q "${MIRROR_SOURCE}/flannel-io/flannel"; then
    log_info "拉取 Flannel 主镜像..."
    crictl pull ${MIRROR_SOURCE}/flannel-io/flannel:v0.26.4
else
    log_warn "Flannel 主镜像已存在,跳过此步骤。"
fi

# 重新标记 Flannel 主镜像
if ! ctr -n k8s.io images list | grep -q "ghcr.io/flannel-io/flannel:v0.26.4"; then
    log_info "重新标记 Flannel 主镜像..."
    ctr -n k8s.io images tag ${MIRROR_SOURCE}/flannel-io/flannel:v0.26.4 ghcr.io/flannel-io/flannel:v0.26.4
else
    log_warn "Flannel 主镜像已标记,跳过此步骤。"
fi

# 拉取 Flannel CNI 插件镜像
if ! crictl images | grep -q "${MIRROR_SOURCE}/flannel-io/flannel-cni-plugin"; then
    log_info "拉取 Flannel CNI 插件镜像..."
    crictl pull ${MIRROR_SOURCE}/flannel-io/flannel-cni-plugin:v1.6.2-flannel1
else
    log_warn "Flannel CNI 插件镜像已存在,跳过此步骤。"
fi

# 重新标记 Flannel CNI 插件镜像
if ! ctr -n k8s.io images list | grep -q "ghcr.io/flannel-io/flannel-cni-plugin:v1.6.2-flannel1"; then
    log_info "重新标记 Flannel CNI 插件镜像..."
    ctr -n k8s.io images tag ${MIRROR_SOURCE}/flannel-io/flannel-cni-plugin:v1.6.2-flannel1 ghcr.io/flannel-io/flannel-cni-plugin:v1.6.2-flannel1
else
    log_warn "Flannel CNI 插件镜像已标记,跳过此步骤。"
fi

# 安装 Flannel 网络插件(仅在未安装时执行)
if ! kubectl get pods -n kube-system | grep -q "kube-flannel"; then
    log_info "安装 Flannel 网络插件..."

    # 使用原始地址下载 Flannel 配置文件
    FLANNEL_YAML="https://github.moeyy.xyz/https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml"
    
    # 下载并应用配置文件
    curl -L $FLANNEL_YAML | kubectl apply -f -
else
    log_warn "Flannel 网络插件已安装,跳过此步骤。"
fi

# 等待所有系统 Pod 启动
log_info "等待所有系统 Pod 启动..."
sleep 10

# 检查节点状态
log_info "检查节点状态..."
kubectl get nodes

# 检查 Pod 状态
log_info "检查 Pod 状态..."
kubectl get pods --all-namespaces

log_info "Kubernetes 单节点集群已成功搭建!"
相关推荐
烟雨书信2 分钟前
Docker文件操作、数据卷、挂载
运维·docker·容器
IT成长日记5 分钟前
【Docker基础】Docker数据卷管理:docker volume prune及其参数详解
运维·docker·容器·volume·prune
这儿有一堆花11 分钟前
Docker编译环境搭建与开发实战指南
运维·docker·容器
LuckyLay11 分钟前
Compose 高级用法详解——AI教你学Docker
运维·docker·容器
Uluoyu20 分钟前
redisSearch docker安装
运维·redis·docker·容器
IT成长日记4 小时前
【Docker基础】Docker数据持久化与卷(Volume)介绍
运维·docker·容器·数据持久化·volume·
疯子的模样9 小时前
Docker 安装 Neo4j 保姆级教程
docker·容器·neo4j
虚伪的空想家9 小时前
rook-ceph配置dashboard代理无法访问
ceph·云原生·k8s·存储·rook
庸子12 小时前
基于Jenkins和Kubernetes构建DevOps自动化运维管理平台
运维·kubernetes·jenkins
Lpy256912 小时前
Docker Desktop 安装到D盘(包括镜像下载等)+ 汉化
运维·docker·容器