原理
kubespray 通过 ansible playbook 编写的自动化任务工具,通过 SSH 协议批量在远程机器执行脚本,完成 K8S 集群搭建。
准备工作
方案1: 物理部署
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
注:指定版本,不要直接拉取master,可能有未知的bug
git clone --depth=1 https://github.com/kubernetes-sigs/kubespray.git -b v2.28.0 cd kubespary apt install python3-pip pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
方案2: Docker部署
git clone --depth=1 https://github.com/kubernetes-sigs/kubespray.git
docker run --rm -it --mount type=bind,source="$(pwd)"/inventory/sample,dst=/inventory \
--mount type=bind,source="${HOME}"/.ssh/id_rsa,dst=/root/.ssh/id_rsa \
quay.io/kubespray/kubespray:v2.28.0 bash
# 容器内执行命令
ansible-playbook -i /inventory/inventory.ini --private-key /root/.ssh/id_rsa cluster.yml
修改配置
复制一份配置文件
cp -rfp inventory/sample inventory/mycluster
需要修改的配置文件列表:
inventory/mycluster/group_vars/all/*.yml
inventory/mycluster/group_vars/k8s-cluster/*.yml
下面介绍一些需要重点关注的配置,根据自己需求进行修改。
修改集群配置
inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
# 选择网络插件,支持 cilium, calico, weave 和 flannel
kube_network_plugin: calico
# 设置 Service 网段
kube_service_addresses: 10.230.0.0/18
# 设置 Pod 网段
kube_pods_subnet: 10.230.64.0/18
# 支持 docker, crio 和 containerd,推荐 containerd.
container_manager: containerd
# 是否开启 kata containers
kata_containers_enabled: false
# 是否开启自动更新证书,推荐开启。默认一年有效期
auto_renew_certificates: true
修改containerd配置
inventory/mycluster/group_vars/all/containerd.yml
# containerd数据目录
containerd_storage_dir: "/data/containerd"
修改etcd配置
inventory/mycluster/group_vars/all/etcd.yml
# etcd数据目录
etcd_data_dir: /data/etcd
打开日志排错
inventory/mycluster/group_vars/all/all.yml
unsafe_show_logs: true
其它相关配置文件:
inventory/mycluster/group_vars/k8s_cluster/k8s-net-*.yml
inventory/mycluster/group_vars/all/containerd.yml
inventory/mycluster/group_vars/all/cri-o.yml
inventory/mycluster/group_vars/all/docker.yml
使用外部负载器
这里使用外部haproxy负载kube-apiserver
例haproxy配置
frontend kubernetes-api
bind *:6443
default_backend kubernetes-apiservers
backend kubernetes-apiservers
balance roundrobin
mode tcp
option ssl-hello-chk
server k8s-master1 192.168.1.81:6443 check inter 2000 rise 2 fall 3
server k8s-master2 192.168.1.82:6443 check inter 2000 rise 2 fall 3
server k8s-master3 192.168.1.83:6443 check inter 2000 rise 2 fall 3
定义了loadbalancer_apiserver
会自动关闭loadbalancer_apiserver_localhost
注:启用apiserver_loadbalancer_domain_name则需要提前解析
inventory/mycluster/group_vars/all/all.yml
apiserver_loadbalancer_domain_name: "apiserver-lb.sundayhk.com"
loadbalancer_apiserver:
address: 192.168.10.220
port: 8443
配置主机列表
https://github.com/kubernetes-sigs/kubespray/blob/master/docs/ansible/inventory.md
inventory/mycluster/inventory.ini
[all]
master1 ansible_host=192.168.10.221
master2 ansible_host=192.168.10.222
master3 ansible_host=192.168.10.223
node1 ansible_host=192.168.10.224
node2 ansible_host=192.168.10.225
node3 ansible_host=192.168.10.226
[kube_control_plane]
master1
master2
master3
[etcd]
master1
master2
master3
[kube_node]
master1
master2
master3
node1
node2
node3
[calico_rr]
[k8s_cluster:children]
kube_control_plane
kube_node
calico_rr
注: 务必使用
ansible_host
标识节点内网 IP,否则可能导致出现类似 这个issue 的问题。
查看集群部署配置
ansible-inventory -i inventory/mycluster/inventory.ini --list
国内环境安装
在国内进行安装时会因GFW影响而安装失败.
- 方案1:参考镜像加速
- 方案2: 通过设置http_proxy和https_proxy` inventory/mycluster/group_vars/all/all.yml
- 方案3: 参考kubespray离线安装配置
部署集群
配置sudo用户及ssh免密码 (所有节点)
echo "sunday ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/sunday ssh-key-gen ssh-copy-id sunday@192.168.10.221
ansible-playbook -i inventory/mycluster/inventory.ini \
--private-key=~/.ssh/id_rsa \
--user=sunday \
-b cluster.yml
# 指定kubernetes版本可以加
# -e kube_version=1.32.7
第一次安装若出错,可以到每个节点执行
kubeadm reset
该步骤仅限部署的新集群操作,生产集群扩容谨慎操作,会重置集群,影响所有服务。
获取 kubeconfig
部署完成后,从 master 节点上的 /root/.kube/config
路径获取到 kubeconfig,这里以 ansible 的 fetch 功能为例,将 kubeconfig 拷贝下来:
cd ~/kubespray/inventory/mycluster
ansible -i inventory.ini -m fetch -a 'src=/root/.kube/config dest=kubeconfig flat=yes' -b --private-key=~/.ssh/id_rsa --user=sunday master1
可以看到 server地址是 haproxy配置,这里可以直接使用
root@ansible23:~/kubespray# cat kubeconfig | grep server
server: https://apiserver-lb.sundayhk.com:3443
root@ansible23:~/kubespray# kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane 21h v1.33.3
master2 Ready control-plane 11h v1.33.3
master3 Ready control-plane 11h v1.33.3
node1 Ready <none> 11h v1.33.3
node2 Ready <none> 11h v1.33.3
node3 Ready <none> 11h v1.33.3
扩容节点
如果要扩容节点,可以准备好节点的内网 IP 列表,并追加到之前的 inventory 文件里,然后再次使用 ansible-playbook
运行一次,有点不同的是: cluster.yml
换成 scale.yml
:
ansible-playbook \
-i inventory/mycluster/inventory.ini \
--private-key=~/.ssh/id_rsa \
--user=sunday -b \
scale.yml
缩容节点
如果有节点不再需要了,我们可以将其移除集群,步骤是:
kubectl cordon NODE
驱逐节点,确保节点上的服务飘到其它节点上去- 停止节点上的一些 k8s 组件 (kubelet, kube-proxy) 等。
kubectl delete NODE
将节点移出集群。- 如果节点是虚拟机,并且不需要了,可以直接销毁掉。
# 标记节点为不可调度 (Cordon),执行后,该节点的状态会变为 `Ready,SchedulingDisabled`
kubectl cordon <node-name>
# 驱逐节点上的所有 Pod (Drain)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 从集群中删除节点(如果永久下线)
kubectl delete node <node-name>
前 3 个步骤,也可以用 kubespray
提供的 remove-node.yml
实现:
ansible-playbook \
-i inventory/mycluster/inventory.ini \
--private-key=~/.ssh/id_rsa \
--user=sunday -b \
--extra-vars "node=node1,node2" \
remove-node.yml
--extra-vars
里写要移出的节点名列表,如果节点已经卡死,无法通过 SSH 登录,可以在--extra-vars
加个reset_nodes=false
的选项,跳过第二个步骤。