零基础部署K8s单节点集群:一键脚本实现快速落地

前言

Kubernetes(简称K8s)作为容器编排领域的事实标准,是云原生技术栈的核心组件。对于初学者而言,手动部署K8s集群往往涉及大量配置项和依赖处理,容易踩坑。本文分享一套经过优化的K8s单节点集群一键部署脚本,涵盖Containerd运行时配置、K8s组件安装、Calico网络部署等全流程,帮助大家快速搭建可用于学习和测试的单节点K8s环境。

环境说明

  • 操作系统:Ubuntu(Debian系发行版均可适配)
  • 架构:amd64(x86_64)
  • 核心版本
    • Kubernetes:1.33.6
    • Containerd:1.7.30
    • Calico网络插件:v3.29.0
  • 前提条件
    1. 服务器关闭Swap(脚本已自动处理)
    2. 服务器有外网访问能力(或配置好内网代理)
    3. 服务器IP:192.168.56.111(需根据实际环境修改)

脚本核心功能

该脚本实现了从环境清理到集群初始化的全自动化,核心流程包括:

  1. 系统基础配置(时区、依赖包、Swap关闭)
  2. 旧K8s/Containerd环境清理
  3. Containerd运行时部署与配置
  4. K8s核心组件(kubeadm/kubelet/kubectl)安装
  5. K8s集群初始化
  6. Calico网络插件部署
  7. 临时文件清理

完整部署脚本

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

# 核心配置(根据实际环境修改以下参数)
PROXY_ADDR="http://192.168.56.103:8080"  # 代理地址(无代理可注释相关curl --proxy参数)
HARBOR_REGISTRY="192.168.56.103"        # Harbor私有仓库地址
HARBOR_FULL_ADDR="http://${HARBOR_REGISTRY}"
HARBOR_USER="admin"                     # Harbor用户名
HARBOR_PASS="Harbor12345"               # Harbor密码
K8S_VERSION="1.33.6"                    # K8s版本
NODE_IP="192.168.56.111"                # 节点IP(必填,需修改为自身服务器IP)
ARCH="amd64"                            # 架构
DOWNLOAD_DIR="/tmp/k8s-bin"
CALICO_VERSION="v3.29.0"                # Calico版本
SOURCE_REGISTRY="registry.k8s.io"
TARGET_REGISTRY="${HARBOR_REGISTRY}/library"
PAUSE_VERSION="3.8"
PAUSE_TARGET_VERSION="3.10"

# 1. 系统基础配置
timedatectl set-timezone Asia/Shanghai
apt update -y
apt upgrade -y
# 安装必要依赖包
apt install -y curl wget iptables apt-transport-https ca-certificates gnupg2 software-properties-common net-tools

# 2. 清理旧环境(避免残留配置干扰)
systemctl stop kubelet containerd || true
pkill -9 containerd || true
pkill -9 kubelet || true
mount | grep /run/containerd | awk '{print $3}' | xargs -r umount -l
rm -rf /run/containerd /var/lib/containerd /etc/containerd /etc/kubernetes /var/lib/kubelet /var/lib/cni /opt/cni/bin /run/kubelet/*
rm -f /usr/bin/kubeadm /usr/bin/kubelet /usr/bin/kubectl /usr/local/bin/crictl
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
ip link delete cni0 || true
ip link delete cali* || true
systemctl daemon-reload

# 3. 部署Containerd运行时
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab  # 永久关闭Swap
# 加载内核模块
cat <<EOF | tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# 配置内核参数
cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system

# 安装containerd、runc、CNI插件
curl -L --proxy ${PROXY_ADDR} --insecure -s https://github.com/containerd/containerd/releases/download/v1.7.30/containerd-1.7.30-linux-${ARCH}.tar.gz -o /tmp/containerd.tar.gz
tar Cxzvf /usr/local /tmp/containerd.tar.gz
curl -L --proxy ${PROXY_ADDR} --insecure -s https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.${ARCH} -o /tmp/runc
install -m 755 /tmp/runc /usr/local/sbin/runc
CNI_VERSION="1.4.0"
curl -L --proxy ${PROXY_ADDR} --insecure -s https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-${ARCH}-v${CNI_VERSION}.tgz -o /tmp/cni-plugins.tgz
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin /tmp/cni-plugins.tgz

# 配置containerd
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/' /etc/containerd/config.toml  # 启用SystemdCgroup
sed -i 's/config_path = ""/config_path = "\/etc\/containerd\/certs.d"/' /etc/containerd/config.toml
sed -i 's/^\(\s*\)tls_verify = true/\1tls_verify = false/' /etc/containerd/config.toml

# 配置Harbor私有仓库认证
mkdir -p /etc/containerd/certs.d/${HARBOR_REGISTRY}
cat > /etc/containerd/certs.d/${HARBOR_REGISTRY}/hosts.toml << EOF
server = "${HARBOR_FULL_ADDR}"
[host."${HARBOR_FULL_ADDR}"]
  capabilities = ["pull", "resolve", "push"]
  skip_verify = true
  allow_insecure = true
  [host."${HARBOR_FULL_ADDR}".auth]
    username = "${HARBOR_USER}"
    password = "${HARBOR_PASS}"
EOF

# 启动containerd
cat <<EOF | tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Restart=always
RestartSec=5
LimitNOFILE=infinity
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now containerd

# 4. 安装crictl(容器运行时命令行工具)
CRICTL_VERSION="v1.30.0"
curl -L --proxy ${PROXY_ADDR} --insecure -s https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz | tar zxvf - -C /usr/local/bin
cat > /etc/crictl.yaml << EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

# 配置pause镜像(K8s基础容器镜像)
crictl pull ${TARGET_REGISTRY}/pause:${PAUSE_TARGET_VERSION}
ctr -n k8s.io images tag ${TARGET_REGISTRY}/pause:${PAUSE_TARGET_VERSION} ${SOURCE_REGISTRY}/pause:${PAUSE_VERSION}

# 5. 安装K8s核心组件
mkdir -p ${DOWNLOAD_DIR} && cd ${DOWNLOAD_DIR}
for bin in kubeadm kubelet kubectl; do
  curl -L --proxy ${PROXY_ADDR} --insecure -s https://dl.k8s.io/v${K8S_VERSION}/bin/linux/${ARCH}/${bin} -o ${bin}
  chmod +x ${bin} && mv ${bin} /usr/bin/
done

# 配置kubelet
cat <<EOF | tee /etc/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
After=network-online.target
[Service]
ExecStart=/usr/bin/kubelet
Restart=always
RestartSec=10
LimitNOFILE=infinity
[Install]
WantedBy=multi-user.target
EOF

mkdir -p /etc/systemd/system/kubelet.service.d
cat <<EOF | tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
ExecStart=
ExecStart=/usr/bin/kubelet \$KUBELET_KUBECONFIG_ARGS \$KUBELET_CONFIG_ARGS \$KUBELET_KUBEADM_ARGS --container-runtime-endpoint=unix:///run/containerd/containerd.sock
EOF

cat <<EOF | tee /etc/default/kubelet
KUBELET_EXTRA_ARGS="--pod-infra-container-image=${TARGET_REGISTRY}/pause:${PAUSE_TARGET_VERSION}"
EOF
systemctl daemon-reload
systemctl enable --now kubelet

# 6. 初始化K8s集群
cat > /root/kubeadm-config.yaml << EOF
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.33.6
imageRepository: ${TARGET_REGISTRY}
networking:
  podSubnet: 192.168.32.0/24  # Calico网络子网,需与Calico配置一致
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
podSandboxImage: "${TARGET_REGISTRY}/pause:${PAUSE_TARGET_VERSION}"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: ${NODE_IP}
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock
EOF

kubeadm init --config /root/kubeadm-config.yaml --ignore-preflight-errors all --v=5
# 配置kubectl认证
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# 7. 部署Calico网络插件
curl -L --proxy ${PROXY_ADDR} --insecure -s https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/calico.yaml -o /tmp/calico.yaml
sed -i "s|docker.io/calico|${TARGET_REGISTRY}/calico|g" /tmp/calico.yaml  # 替换镜像仓库为Harbor
kubectl apply -f /tmp/calico.yaml
# 移除控制平面污点(单节点集群允许Pod调度到控制平面)
kubectl taint nodes --all node-role.kubernetes.io/control-plane- || true

# 8. 清理临时文件
rm -rf ${DOWNLOAD_DIR} /tmp/containerd.tar.gz /tmp/runc /tmp/cni-plugins.tgz /tmp/calico.yaml /root/kubeadm-config.yaml

echo "K8s单节点集群部署完成!"
echo "验证集群状态:kubectl get nodes"
echo "验证网络插件:kubectl get pods -n kube-system -l k8s-app=calico-node"

脚本使用步骤

1. 前置修改

  • 必改项:NODE_IP 修改为服务器实际IP;
  • 可选项:若无Harbor私有仓库,需注释/删除相关Harbor配置段落;若无代理,删除curl命令中的--proxy ${PROXY_ADDR}参数;

2. 执行脚本

bash 复制代码
# 赋予脚本执行权限
chmod +x k8s-single-node.sh
# 执行脚本(建议使用root用户)
./k8s-single-node.sh

3. 验证部署结果

bash 复制代码
# 查看节点状态(Ready即为正常)
kubectl get nodes

# 查看系统组件Pod状态(所有Pod Running即为正常)
kubectl get pods -n kube-system

关键配置说明

1. Containerd配置

  • 启用SystemdCgroup:适配Systemd系统的cgroup管理,避免容器资源管理异常;
  • 私有仓库配置:通过certs.d目录配置Harbor认证,解决私有仓库拉取镜像权限问题;

2. K8s初始化配置

  • podSubnet: 192.168.32.0/24:Calico网络子网,需与Calico插件配置一致;
  • ignore-preflight-errors all:忽略预检查错误(适合学习环境,生产环境需谨慎);
  • 移除控制平面污点:单节点集群中,允许业务Pod调度到控制平面节点;

3. Calico网络插件

Calico是K8s主流的网络插件,支持网络策略、高性能网络转发,脚本中替换了镜像仓库地址为私有Harbor,解决官方镜像拉取慢的问题。

常见问题排查

  1. Containerd启动失败 :检查内核模块overlaybr_netfilter是否加载成功(lsmod | grep overlay);
  2. kubelet启动失败 :查看日志journalctl -u kubelet -f,常见原因是Swap未关闭、镜像拉取失败;
  3. Calico Pod未Running :检查Pod子网与podSubnet配置是否一致,或节点网络是否互通;
  4. 镜像拉取失败:确认Harbor仓库可访问,或替换为公有镜像仓库(如阿里云镜像);

总结

本文提供的一键部署脚本封装了K8s单节点集群的全流程,适合初学者快速上手。实际生产环境中,需根据需求调整配置(如高可用、安全认证、镜像仓库等),但该脚本可作为基础模板,帮助理解K8s部署的核心流程。建议大家在测试环境中反复调试,熟悉每个配置项的作用,逐步掌握K8s部署的底层逻辑。

相关推荐
hrhcode1 小时前
【云原生】四.Kubernetes核心对象(下):Deployment、Service与Namespace
云原生·k8s
zhu62019761 小时前
Postgres数据库docker快速安装
数据库·docker·容器
数据知道2 小时前
PostgreSQL:如何在容器中部署 Crunchy Data Operator(Kubernetes 运维)
运维·postgresql·kubernetes
王德印2 小时前
工作踩坑之导入数据库报错:Got a packet bigger than ‘max_allowed_packet‘ bytes
java·数据库·后端·mysql·云原生·运维开发
AI_56782 小时前
ableau可视化进阶:颜色与交互设计让数据会说话
数据库·云原生·excel
only_Klein2 小时前
Jenkinsfile流水线设计解析
kubernetes·jenkins·argocd·cicd
leblancAndSherry3 小时前
阿里云轻量/ECS 实战:K3s + Helm + cert-manager + 云效 Codeup 全链路 CI/CD 落地(记录自用)
linux·运维·阿里云·ci/cd·kubernetes·云计算
认真的薛薛3 小时前
5.k8s的deploy-ds-nfs-loadbalancer
云原生·容器·kubernetes
RK_Dangerous3 小时前
第一次使用Docker(Ubuntu)
ubuntu·docker·容器