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 单节点集群已成功搭建!"
相关推荐
LCY1331 小时前
k8s系统学习路径
学习·容器·kubernetes
云上艺旅2 小时前
K8S学习之基础二十七:k8s中daemonset控制器
云原生·容器·kubernetes·jenkins
4dm1n2 小时前
kube-proxy有什么作用☆
kubernetes
fenglllle3 小时前
K8S下nodelocaldns crash问题导致域名请求响应缓慢
docker·容器·kubernetes
小马爱打代码3 小时前
描述K8S创建pod的全过程
云原生·容器·kubernetes
小白学安全hhhh3 小时前
VPC4-通达oa-docker逃逸-shiro反序列化-hash传递-CrackMapExec喷射-历史ptt攻击-进程注入
运维·安全·网络安全·docker·容器·网络攻击模型·安全架构
一个处女座的程序猿O(∩_∩)O5 小时前
使用 Docker 部署前端项目全攻略
前端·docker·容器
爪哇哇哇哇6 小时前
docker部署jenkins,安装使用一条龙教程
docker·容器·jenkins
小李的便利店6 小时前
软件环境安装-通过Docker安装Elasticsearch和Kibana【保姆级教程、内含图解】
elasticsearch·docker·容器·kibana