CentOS 7 一键部署 K8s 1.23 + Rancher 2.7 完整指南
一、环境规划
| 节点 |
IP |
角色 |
配置 |
| master |
192.168.1.102 |
控制平面 |
2C4G+ |
| worker1 |
192.168.1.130 |
工作节点 |
2C4G+ |
| worker2 |
192.168.1.133 |
工作节点 |
2C4G+ |
软件版本:
- OS: CentOS 7.9 (3.10.0-1160)
- K8s: 1.23.17
- CRI: containerd 1.6+
- CNI: Flannel 0.24
- Rancher: 2.7.9
二、一键安装脚本
2.1 前置清理(如重装)
bash
复制代码
systemctl stop kubelet 2>/dev/null
kubeadm reset -f 2>/dev/null
rm -rf /etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/ ~/.kube/ /etc/cni/net.d/
yum remove -y kubelet kubeadm kubectl 2>/dev/null
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
bash
复制代码
#!/bin/bash
set -e
# ==================== 配置区 ====================
declare -A NODES=(
["192.168.1.102"]="master"
["192.168.1.130"]="worker1"
["192.168.1.133"]="worker2"
)
K8S_VERSION="1.23.17"
POD_CIDR="10.244.0.0/16"
SERVICE_CIDR="10.96.0.0/12"
IMAGE_REPO="registry.aliyuncs.com/google_containers"
PRIVATE_REGISTRY="your-mirror.registry.com" # 替换为你的镜像仓库
# ==================== 函数区 ====================
log() { echo -e "\033[32m[INFO]\033[0m $1"; }
err() { echo -e "\033[31m[ERROR]\033[0m $1"; exit 1; }
get_ip() {
ip -4 route get 1.1.1.1 2>/dev/null | grep -oP 'src \K\S+' || hostname -I | awk '{print $1}'
}
pre_setup() {
local ip=$(get_ip)
[[ ${NODES[$ip]} ]] || err "IP $ip 不在节点列表中"
# 主机名
hostnamectl set-hostname ${NODES[$ip]}
# hosts
for k in "${!NODES[@]}"; do echo "$k ${NODES[$k]}" >> /etc/hosts; done
# 系统配置
swapoff -a && sed -i '/swap/d' /etc/fstab
setenforce 0 2>/dev/null; sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
systemctl stop firewalld 2>/dev/null; systemctl disable firewalld 2>/dev/null
# 内核模块
cat > /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
overlay
EOF
modprobe br_netfilter overlay 2>/dev/null || true
# 网络参数
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system >/dev/null
}
install_containerd() {
log "安装 containerd..."
yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y containerd.io
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|config_path = ""|config_path = "/etc/containerd/certs.d"|' /etc/containerd/config.toml
# 镜像加速配置
for reg in docker.io registry.k8s.io k8s.gcr.io quay.io ghcr.io; do
mkdir -p /etc/containerd/certs.d/$reg
cat > /etc/containerd/certs.d/$reg/hosts.toml <<EOF
server = "https://$reg"
[host."https://${PRIVATE_REGISTRY}"]
capabilities = ["pull", "resolve"]
[host."https://${reg%.*}.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
done
systemctl restart containerd && systemctl enable containerd
# crictl 配置
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
EOF
}
install_k8s() {
log "安装 K8s ${K8S_VERSION}..."
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF
yum install -y kubelet-${K8S_VERSION} kubeadm-${K8S_VERSION} kubectl-${K8S_VERSION}
# 配置 kubelet 使用国内 pause 镜像
mkdir -p /var/lib/kubelet
echo "KUBELET_KUBEADM_ARGS=\"--pod-infra-container-image=${IMAGE_REPO}/pause:3.6\"" > /var/lib/kubelet/kubeadm-flags.env
systemctl enable kubelet
}
setup_master() {
local ip=$(get_ip)
log "初始化 Master ($ip)..."
cat > /tmp/kubeadm.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: ${ip}
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v${K8S_VERSION}
imageRepository: ${IMAGE_REPO}
networking:
podSubnet: ${POD_CIDR}
serviceSubnet: ${SERVICE_CIDR}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF
kubeadm config images pull --config /tmp/kubeadm.yaml
kubeadm init --config /tmp/kubeadm.yaml --upload-certs
# kubectl 配置
mkdir -p ~/.kube
cp /etc/kubernetes/admin.conf ~/.kube/config
# 保存 join 命令
kubeadm token create --print-join-command > /root/join.sh 2>/dev/null || true
chmod +x /root/join.sh
# 安装 Flannel
install_flannel
log "Master 初始化完成"
echo "========================================"
echo "Join 命令已保存至: /root/join.sh"
cat /root/join.sh
echo "========================================"
}
install_flannel() {
log "安装 Flannel..."
# 预拉取镜像
crictl pull ${PRIVATE_REGISTRY}/flannel/flannel:v0.24.3 2>/dev/null || true
crictl pull ${PRIVATE_REGISTRY}/flannel/flannel-cni-plugin:v1.2.0 2>/dev/null || true
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.24.3/Documentation/kube-flannel.yml 2>/dev/null || \
kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Namespace
metadata:
name: kube-flannel
---
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
data:
cni-conf.json: |
{"name":"cbr0","cniVersion":"0.3.1","plugins":[{"type":"flannel","delegate":{"hairpinMode":true,"isDefaultGateway":true}},{"type":"portmap","capabilities":{"portMappings":true}}]}
net-conf.json: |
{"Network":"${POD_CIDR}","Backend":{"Type":"vxlan"}}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
app: flannel
spec:
hostNetwork: true
tolerations:
- operator: Exists
effect: NoSchedule
containers:
- name: kube-flannel
image: ${PRIVATE_REGISTRY}/flannel/flannel:v0.24.3
command: ["/opt/bin/flanneld","--ip-masq","--kube-subnet-mgr"]
securityContext:
capabilities:
add: ["NET_ADMIN","NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: flannel-cfg
mountPath: /etc/kube-flannel/
volumes:
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
EOF
kubectl wait --for=condition=Ready node/$(hostname) --timeout=300s 2>/dev/null || true
}
setup_worker() {
log "加入 Worker 节点..."
[[ -f /root/join.sh ]] || { echo "请将 Master 的 /root/join.sh 复制到本机"; exit 1; }
bash /root/join.sh
}
# ==================== 主逻辑 ====================
main() {
[[ $EUID -eq 0 ]] || err "请使用 root 执行"
pre_setup
case "$1" in
--reset)
kubeadm reset -f 2>/dev/null || true
rm -rf /etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/ ~/.kube/
log "已重置"
exit 0
;;
esac
install_containerd
install_k8s
local role=${NODES[$(get_ip)]}
[[ "$role" == "master" ]] && setup_master || setup_worker
log "节点 $(hostname) 部署完成"
kubectl get nodes 2>/dev/null || true
}
main "$@"
2.3 执行部署
bash
复制代码
# 1. 所有节点下载脚本并修改 PRIVATE_REGISTRY
chmod +x k8s-install.sh
# 2. Master 节点执行
./k8s-install.sh
# 3. 复制 join 命令到 Worker 节点
scp /root/join.sh root@192.168.1.130:/root/
scp /root/join.sh root@192.168.1.133:/root/
# 4. Worker 节点执行
./k8s-install.sh
# 5. Master 验证
kubectl get nodes -o wide
# 预期输出:3 节点 Ready 状态
三、Rancher 安装与集群导入
3.1 Docker 部署 Rancher
bash
复制代码
docker run -d --restart=unless-stopped \
-p 28080:80 -p 28443:443 \
-v /opt/rancher:/var/lib/rancher \
--privileged \
--name rancher \
rancher/rancher:v2.7.9
3.2 初始化配置
bash
复制代码
# 查看初始密码
docker logs rancher 2>&1 | grep "Bootstrap Password:"
# 访问 https://<服务器IP>:28443
# 首次登录需设置新密码
3.3 导入 K8s 集群
| 步骤 |
操作 |
| 1 |
点击 "导入已有集群" → 选择 "通用" |
| 2 |
填写集群名称 → 点击 "创建" |
| 3 |
复制 "如果 Rancher Server 的 CA 证书不被信任" 下方的命令 |
| 4 |
在 Master 节点执行该命令(绕过证书验证) |
导入命令示例:
bash
复制代码
curl --insecure -sfL https://<rancher-host>:28443/v3/import/<token>.yaml | kubectl apply -f -
3.4 验证状态
bash
复制代码
# Rancher UI 中查看集群状态
# 预期:Active(约 1-2 分钟)
四、关键检查项
| 检查项 |
命令 |
预期结果 |
| 节点状态 |
kubectl get nodes |
全部 Ready |
| Pod 状态 |
kubectl get pods -A |
无 CrashLoopBackOff |
| CNI 状态 |
kubectl get pods -n kube-flannel |
Running |
| 网络连通 |
kubectl run test --image=busybox --rm -it -- ping 10.244.0.1 |
通 |
| Rancher 代理 |
kubectl get cattle-system |
代理 Pod Running |
五、常见问题
| 现象 |
原因 |
解决 |
kubectl get nodes 显示 NotReady |
CNI 未启动/镜像拉取失败 |
检查 Flannel Pod 日志,确认镜像仓库可访问 |
| Worker join 失败 |
token 过期/网络不通 |
Master 执行 kubeadm token create --print-join-command 重新生成 |
| Rancher 导入 Pending |
防火墙/证书问题 |
开放 28443 端口,或使用 --insecure 命令 |
| containerd 镜像拉取慢 |
镜像加速未生效 |
检查 /etc/containerd/certs.d/ 配置,重启 containerd |
六、架构示意
复制代码
┌─────────────────────────────────────────┐
│ Rancher 2.7.9 │
│ (Web UI / 集群管理) │
│ HTTPS :28443 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Kubernetes 1.23.17 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Master │ │ Worker1 │ │ Worker2 │ │
│ │ 1.102 │ │ 1.130 │ │ 1.133 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ CNI: Flannel │
│ CRI: containerd │
└─────────────────────────────────────────┘