CentOS7.6 单机部署 K8S 集群

📚 系统准备(所有节点)

以下步骤需要在您的虚拟机上执行,为K8s安装做好准备。

  1. 关闭防火墙 K8s 需要特定的端口进行通信,为避免冲突,建议关闭防火墙。

    sh 复制代码
    systemctl stop firewalld
    systemctl disable firewalld
  2. 关闭 SELinux 将 SELinux 设置为 permissive 模式,这是容器访问主机文件系统所必需的。

    sh 复制代码
    setenforce 0
    sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
  3. 关闭 Swap Kubelet 在 Kubernetes 1.8+ 版本中不支持 Swap,必须关闭。

    sh 复制代码
    swapoff -a
    sed -i '/ swap / s/^(.*)$/#\1/g' /etc/fstab
  4. 配置网络参数 使桥接的 IPv4 流量传递到 iptables 的链,这是网络插件正常工作所必需的。

    sh 复制代码
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
    EOF
    sudo sysctl --system
  5. 设置主机名与 hosts(可选但建议) 设置一个易于识别的主机名,并确保在/etc/hosts中正确解析。

    sh 复制代码
    hostnamectl set-hostname k8s-master
    echo "$(hostname -I | awk '{print $1}') k8s-master" >> /etc/hosts

📦 安装Kubernetes组件

  1. 配置 Docker(如已安装请检查) K8s 对 Docker 版本有要求,建议使用Docker 18.09.x或19.03.x等已验证的版本。同时,需要将 Docker 的 Cgroup 驱动改为 systemd 以与 Kubelet 保持一致。

    sh 复制代码
    sudo cat > /etc/docker/daemon.json <<-'EOF'
    {
      "exec-opts": ["native.cgroupdriver=systemd"],
      "registry-mirrors": ["https://8aklptao.mirror.aliyuncs.com"]
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker
  2. 添加 Kubernetes 的阿里云 YUM 源

    sh 复制代码
    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
    enabled=1
    gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
  3. 安装 kubeadm, kubelet 和 kubectl 建议指定版本安装,以避免版本不兼容问题。这里以 1.19.0 为例(请选择稳定版本)。

    sh 复制代码
    sudo yum install -y kubelet-1.19.0 kubeadm-1.19.0 kubectl-1.19.0 --disableexcludes=kubernetes
    sudo systemctl enable --now kubelet

🚀 初始化Master节点(控制平面)

  1. 如果初始化时遇到镜像拉取问题,可以手动拉取:

    sh 复制代码
    images=(
        kube-apiserver:v1.19.0
        kube-controller-manager:v1.19.0
        kube-scheduler:v1.19.0
        kube-proxy:v1.19.0
        pause:3.2
        etcd:3.4.13-0
        coredns:1.7.0
    )
    
    for image in ${images[@]}; do
        docker pull registry.aliyuncs.com/google_containers/$image
        docker tag registry.aliyuncs.com/google_containers/$image k8s.gcr.io/$image
    done
  2. 使用 kubeadm init 初始化集群 使用 --image-repository 参数指定阿里云镜像仓库,这是解决国外镜像无法下载的关键。

    sh 复制代码
    sudo kubeadm init \
      --apiserver-advertise-address=$(hostname -I | awk '{print $1}') \
      --image-repository=registry.aliyuncs.com/google_containers \
      --kubernetes-version=v1.19.0 \
      --service-cidr=10.96.0.0/12 \
      --pod-network-cidr=10.244.0.0/16 \
      --ignore-preflight-errors=Swap

    参数说明:

    • --apiserver-advertise-address: 指定 API Server 公布的 IP 地址,通常是本机 IP。
    • --image-repository: 指定从阿里云拉取控制平面镜像。
    • --pod-network-cidr: 指定 Pod 网络 IP 范围,必须与后续安装的网络插件匹配(此处为 Flannel 网络设置)。
  3. 配置 kubectl 认证文件 初始化成功后,按照屏幕提示执行以下命令,使当前用户能够使用 kubectl。

    sh 复制代码
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  4. 安装 Pod 网络插件(CNI) 网络插件是集群内 Pod 之间通信的基础。这里使用 Flannel。由于其原始 YAML 文件地址可能被墙,可以先下载到本地或直接应用。

    sh 复制代码
    # 直接应用(如果网络通畅)
    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    
    # 如果无法下载,可尝试先获取文件内容(例如通过其他途径下载),然后使用本地的yml文件
    # kubectl apply -f kube-flannel.yml

✅ 验证集群状态

等待几分钟,让所有Pod启动完成。

  1. 查看节点状态

    sh 复制代码
    kubectl get nodes

    如果一切正常,你应该看到k8s-master节点的状态为 Ready

  2. 查看所有 Pod 状态

    sh 复制代码
    kubectl get pods -n kube-system -o wide

    检查所有核心组件(如 coredns, flannel 等)是否都处于 Running 状态。

🔍 检查节点当前污点

首先,我们需要确认你的节点上当前设置的污点到底是什么。不同版本的 Kubernetes 或不同的安装方式可能会使用不同的污点键名。

请执行以下命令来查看节点的详细污点信息:

sh 复制代码
kubectl describe node k8s-master | grep Taints

或者使用这个更清晰的查看方式:

sh 复制代码
kubectl get nodes -o=custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

🛠️ 可能的原因与解决方案

根据上述命令的输出,你可以参考下表判断具体情况并采取相应操作:

情况说明 可能的原因 解决方案
输出 Taints: <none> 节点上确实已无污点,Pod 应可正常调度。 无需任何操作,你的集群已经允许在 Master 节点上调度 Pod。
输出包含 node-role.kubernetes.io/master:NoSchedule 在稍早版本的 Kubernetes(约 1.24 之前)中,控制平面节点的污点键名是 master 而非 control-plane 使用对应的污点键名进行移除: kubectl taint nodes --all node-role.kubernetes.io/master:NoSchedule-
输出包含其他键名的污点 可能存在其他自定义或特定环境设置的污点。 根据 kubectl describe node 输出中显示的完整污点信息,使用 kubectl taint nodes <node-name> <taint-key>- 命令移除。

💎 验证结果

无论采用哪种方案,执行成功后,再次运行 kubectl describe node k8s-master | grep Taints,应该会看到 Taints: <none>。之后,你再部署 Pod 就不会被节点污点所阻挡了 。

💡 理解污点与容忍度

简单来说,污点(Taint) 是打在节点上的一个"标记",用于拒绝不能"忍受"此标记的 Pod 调度上来。容忍度(Toleration) 则是 Pod 的"承受能力",声明自己能容忍哪些污点,从而可以被调度到对应节点 。默认情况下,控制平面节点会被打上污点,以防止用户的工作负载在可能资源紧张的控制平面上运行,确保集群管理组件自身稳定。对于单节点集群,我们通常需要移除这个限制。

📥 集群启停脚本

k8s-start.sh (集群启动脚本)

bash 复制代码
#!/bin/bash
set -e

echo "正在启动K8s集群..."

# 1. 启动Docker服务
echo "启动Docker服务..."
systemctl start docker
systemctl enable docker

# 2. 启动kubelet服务
echo "启动kubelet服务..."
systemctl enable kubelet
systemctl start kubelet

# 3. 检查并初始化Master节点
if [ ! -f /etc/kubernetes/admin.conf ]; then
    echo "正在初始化Kubernetes Master节点..."
    kubeadm init \
        --apiserver-advertise-address=$(hostname -I | awk '{print $1}') \
        --image-repository registry.aliyuncs.com/google_containers \
        --pod-network-cidr=10.244.0.0/16
    

    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
else
    echo "Master节点已存在,跳过初始化。"
fi

# 4. 安装Flannel网络插件
if ! kubectl get pods -n kube-system | grep -q flannel; then
    echo "正在安装Flannel网络插件..."
    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
else
    echo "Flannel网络插件已安装。"
fi

# 5. 改进的污点移除逻辑:自动检测并移除污点
echo "正在检查并移除Master节点污点(单节点集群)..."

# 检查当前污点
TAINTS=$(kubectl describe node $(hostname) | grep -i taints | awk '{print $2}')
echo "当前污点状态: $TAINTS"

if [ "$TAINTS" != "<none>" ]; then
    # 尝试移除可能存在的两种污点键名
    kubectl taint nodes --all node-role.kubernetes.io/master:NoSchedule- 2>/dev/null || true
    kubectl taint nodes --all node-role.kubernetes.io/control-plane:NoSchedule- 2>/dev/null || true
    echo "污点移除命令执行完成。"
    
    # 验证污点是否已移除
    sleep 5
    NEW_TAINTS=$(kubectl describe node $(hostname) | grep -i taints | awk '{print $2}')
    if [ "$NEW_TAINTS" = "<none>" ]; then
        echo "✅ Master节点污点已成功移除。"
    else
        echo "⚠️  污点可能仍存在,当前状态: $NEW_TAINTS"
        echo "如需手动移除,请执行: kubectl taint nodes --all node-role.kubernetes.io/master:NoSchedule-"
    fi
else
    echo "✅ Master节点无污点,无需处理。"
fi

echo ""
echo "K8s集群启动完成!"
echo "节点状态:"
kubectl get nodes
echo ""
echo "系统Pod状态:"
kubectl get pods -n kube-system

k8s-stop.sh (集群停止脚本)

bash 复制代码
#!/bin/bash
set -e

echo "正在停止K8s集群..."

# 1. 获取节点名称
NODE_NAME=$(hostname)
echo "正在处理节点: $NODE_NAME"

# 2. 排空当前节点(优雅终止Pod)
echo "正在排空节点..."
kubectl drain $NODE_NAME --delete-emptydir-data --ignore-daemonsets --timeout=300s --force || {
    echo "⚠️  排空节点过程中可能出现警告,继续执行停止操作..."
}

# 3. 停止kubelet服务
echo "停止kubelet服务..."
systemctl stop kubelet

# 4. 停止Docker服务
echo "停止Docker服务..."
systemctl stop docker

echo "K8s集群已停止。"
echo "如需重新启动,请运行: ./k8s-start.sh"

🔧 脚本使用说明

  1. 保存脚本 :将内容分别保存为 k8s-start.shk8s-stop.sh

  2. 赋予执行权限

    bash 复制代码
    chmod +x k8s-start.sh k8s-stop.sh
  3. 使用脚本

    bash 复制代码
    # 启动集群
    ./k8s-start.sh
    
    # 停止集群
    ./k8s-stop.sh
相关推荐
爱勇宝3 小时前
第 1 章:别把“需求文档”当成真正的需求
前端·后端·程序员
IT_陈寒7 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码9 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo9 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志9 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..9 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects10 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰10 小时前
一些基础和问题解决
后端
陈随易10 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN10 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp