CentOS 7 一键部署 K8s 1.23 + Rancher 2.7 完整指南

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

2.2 主脚本(k8s-install.sh

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            │
└─────────────────────────────────────────┘
相关推荐
.ZGR.2 小时前
智能无人机防空平台 V2.0 ——攻击反制
java·开发语言·无人机
江湖有缘2 小时前
基于华为openEuler搭建Coolmonitor监控服务
linux·华为云·openeuler
the sun342 小时前
Linux上位机开发中的串口termios库函数使用
linux·运维·服务器
XerCis2 小时前
Linux内网环境无法访问外网的情况下安装程序
linux·运维·服务器
Predestination王瀞潞2 小时前
SQL 片段的提取与复用机制
java·sql·mybatis
ding_zhikai2 小时前
【Web应用开发笔记】Django笔记8:用户账户相关功能
笔记·后端·python·django
IMPYLH2 小时前
Lua 的 UTF-8 模块
开发语言·笔记·后端·游戏引擎·lua
炸炸鱼.2 小时前
linux系统安全及应用_扫描版
linux·运维·系统安全