Skip to content

Kubespray 部署

Kubespray 用 Ansible 部署 Kubernetes,适合多节点、参数较多、需要批量扩容升级的自建集群。kubeadm 更适合理解组件关系和手工搭建,Kubespray 更像一套自动化交付方案——把集群安装变成可重复执行的 playbook。

Kubespray 适合什么

场景说明
多节点裸机 / 虚拟机统一初始化系统、安装运行时和 K8s 组件
多控制平面inventory 里声明 control plane、etcd、worker 三种角色
离线或半离线环境可以提前准备镜像和二进制包
后续扩容升级通过 Ansible playbook 重复执行,参数在 group_vars 里管理

学习组件关系还是 kubeadm 清楚;真正要在一批机器上反复交付集群时,Kubespray 的可重复性更好。

目录和 inventory

bash
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray

# 用虚拟环境安装依赖,不污染系统 Python
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

cp -rfp inventory/sample inventory/mycluster

inventory 主机文件写成 YAML,角色清晰:

yaml
# inventory/mycluster/hosts.yaml
all:
  hosts:
    k8s-master01:
      ansible_host: 192.168.10.11
      ip: 192.168.10.11
      access_ip: 192.168.10.11
    k8s-master02:
      ansible_host: 192.168.10.12
      ip: 192.168.10.12
      access_ip: 192.168.10.12
    k8s-master03:
      ansible_host: 192.168.10.13
      ip: 192.168.10.13
      access_ip: 192.168.10.13
    k8s-node01:
      ansible_host: 192.168.10.21
      ip: 192.168.10.21
      access_ip: 192.168.10.21
  children:
    kube_control_plane:
      hosts:
        k8s-master01:
        k8s-master02:
        k8s-master03:
    etcd:
      hosts:
        k8s-master01:
        k8s-master02:
        k8s-master03:
    kube_node:
      hosts:
        k8s-node01:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
    calico_rr:
      hosts: {}

kube_control_plane 表示控制平面节点,etcd 表示 etcd 成员,kube_node 表示工作节点。三种角色可以重叠(stacked etcd),也可以拆开(external etcd)。

关键 group_vars

集群级配置在:

text
inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
inventory/mycluster/group_vars/k8s_cluster/k8s-net-calico.yml
inventory/mycluster/group_vars/all/containerd.yml
yaml
# k8s-cluster.yml
kube_version: v1.36.0
container_manager: containerd
kube_network_plugin: calico

kube_service_addresses: 10.96.0.0/12 # Service CIDR
kube_pods_subnet: 10.244.0.0/16      # Pod CIDR

dns_mode: coredns
helm_enabled: true
metrics_server_enabled: true

控制平面入口:

yaml
# all.yml
apiserver_loadbalancer_domain_name: "k8s-api.example.local"
loadbalancer_apiserver:
  address: 192.168.10.100
  port: 6443

如果外部已经有 HAProxy/Keepalived 或云负载均衡,就把地址写成 VIP。

安装前检查

安装前最容易漏的是:节点时间不同步、DNS 解析不一致、系统源不可用、镜像仓库不可达、机器里残留旧 kubelet/containerd 配置。

bash
ansible -i inventory/mycluster/hosts.yaml all -m ping
ansible -i inventory/mycluster/hosts.yaml all -m shell -a 'hostname; date; df -h /'
ansible -i inventory/mycluster/hosts.yaml all -m shell -a 'ip route; ping -c 2 192.168.10.11'

执行安装

bash
ansible-playbook -i inventory/mycluster/hosts.yaml \
  --become --become-user=root \
  cluster.yml
参数说明
--become提权执行系统级操作
-b--become 简写
--limit限制执行主机,扩容或修复时常用
-vvv输出更详细日志

安装完成后取 kubeconfig:

bash
scp root@192.168.10.11:/etc/kubernetes/admin.conf ./kubeconfig
export KUBECONFIG=$PWD/kubeconfig
kubectl get nodes -o wide
kubectl get pods -A -o wide

离线环境和镜像

国内或内网环境要重点处理镜像。思路是把默认镜像仓库改成内部 registry:

yaml
# k8s-cluster.yml
registry_host: "registry.example.local"

实际项目中还需要同步 kube-apiserver、etcd、pause、CoreDNS、Calico、metrics-server、Helm 组件的镜像。离线环境先在一台联网机器上生成镜像清单,再同步到 Harbor,比安装现场临时拉外网镜像可靠得多。

扩容节点

新增工作节点时,先在 inventory 加主机并加入 kube_node,然后执行:

bash
ansible-playbook -i inventory/mycluster/hosts.yaml \
  --become --become-user=root \
  scale.yml \
  --limit k8s-node02

扩容前要确认新节点的内核、系统源、DNS、镜像仓库、时间同步和已有节点一致。节点差异太多,后面排查会很难判断是 Kubernetes 问题还是系统问题。

升级

升级一般先改 kube_version,再执行:

bash
ansible-playbook -i inventory/mycluster/hosts.yaml \
  --become --become-user=root \
  upgrade-cluster.yml

升级前固定检查:

bash
kubectl get nodes
kubectl get pods -A
kubectl -n kube-system get pods

升级不是只升 Kubernetes 版本,还要看 containerd、CNI、CSI、Ingress/Gateway、Prometheus Operator、metrics-server 和业务组件兼容性。Kubespray 能执行升级动作,不能替代版本兼容性判断。

常见问题

现象常见原因处理方向
Ansible ping 失败SSH、sudo、Python 环境先跑 ansible all -m ping
任务卡在拉镜像外网慢、仓库认证失败配内部 registry,提前同步镜像
节点 Join 失败Token、证书、API 入口不可达看 kubelet 日志和 API Server 入口
CNI Pod 不正常Pod CIDR、镜像、内核模块看 Calico/Cilium 日志
重跑失败节点残留旧配置按 Kubespray reset 流程清理

Kubespray 的优势是可重复,但前提是 inventory 和 group_vars 也被当成代码管理。手工改一堆节点再跑 playbook,最后会失去自动化的意义。