📚 系统准备(所有节点)
以下步骤需要在您的虚拟机上执行,为K8s安装做好准备。
-
关闭防火墙 K8s 需要特定的端口进行通信,为避免冲突,建议关闭防火墙。
shsystemctl stop firewalld systemctl disable firewalld -
关闭 SELinux 将 SELinux 设置为 permissive 模式,这是容器访问主机文件系统所必需的。
shsetenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config -
关闭 Swap Kubelet 在 Kubernetes 1.8+ 版本中不支持 Swap,必须关闭。
shswapoff -a sed -i '/ swap / s/^(.*)$/#\1/g' /etc/fstab -
配置网络参数 使桥接的 IPv4 流量传递到 iptables 的链,这是网络插件正常工作所必需的。
shcat <<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 -
设置主机名与 hosts(可选但建议) 设置一个易于识别的主机名,并确保在
/etc/hosts中正确解析。shhostnamectl set-hostname k8s-master echo "$(hostname -I | awk '{print $1}') k8s-master" >> /etc/hosts
📦 安装Kubernetes组件
-
配置 Docker(如已安装请检查) K8s 对 Docker 版本有要求,建议使用Docker 18.09.x或19.03.x等已验证的版本。同时,需要将 Docker 的 Cgroup 驱动改为
systemd以与 Kubelet 保持一致。shsudo 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 -
添加 Kubernetes 的阿里云 YUM 源
shcat <<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 -
安装 kubeadm, kubelet 和 kubectl 建议指定版本安装,以避免版本不兼容问题。这里以
1.19.0为例(请选择稳定版本)。shsudo yum install -y kubelet-1.19.0 kubeadm-1.19.0 kubectl-1.19.0 --disableexcludes=kubernetes sudo systemctl enable --now kubelet
🚀 初始化Master节点(控制平面)
-
如果初始化时遇到镜像拉取问题,可以手动拉取:
shimages=( 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 -
使用 kubeadm init 初始化集群 使用
--image-repository参数指定阿里云镜像仓库,这是解决国外镜像无法下载的关键。shsudo 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 网络设置)。
-
配置 kubectl 认证文件 初始化成功后,按照屏幕提示执行以下命令,使当前用户能够使用 kubectl。
shmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config -
安装 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启动完成。
-
查看节点状态
shkubectl get nodes如果一切正常,你应该看到
k8s-master节点的状态为Ready。 -
查看所有 Pod 状态
shkubectl 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"
🔧 脚本使用说明
-
保存脚本 :将内容分别保存为
k8s-start.sh和k8s-stop.sh -
赋予执行权限:
bashchmod +x k8s-start.sh k8s-stop.sh -
使用脚本:
bash# 启动集群 ./k8s-start.sh # 停止集群 ./k8s-stop.sh