附加组件是 group_vars 里的开关,打开后要确认它在工作
目标
在安装之前,通过 group_vars 打开 metrics-server、local-path-provisioner 和 Helm,并在安装之后确认它们各自是否真的在工作。
同时观察 -e 把布尔值当作字符串传递的陷阱,以及默认网络插件 calico 是以哪种封装方式运行的。
为什么重要
在 kubespray 中,附加组件就是一个变量。所以打开很容易,而“已经打开”和“正在工作”这两件事也很容易被混为一谈。即使 metrics-server 在运行, 如果 APIService 不是 Available,HPA 就会停止;即使有存储类,如果 PVC 没有绑定到节点磁盘,有状态的应用就起不来。 网络插件是安装之后最难更换的选择,所以必须了解默认值是什么、这个默认值要求什么样的网络条件,然后再去选择。
步骤
- 在
/root/ks/inventory/lab/group_vars/k8s_cluster/addons.yml中,把metrics_server_enabled、local_path_provisioner_enabled、helm_enabled全部改为true。用ansible-inventory --host node1解析时,这三个值必须是布尔值 true,而不是字符串。 - 在
/opt/ks/kubespray中,分别运行ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml -e helm_enabled=true和-e '{"helm_enabled": true}'。在/root/ks/addons/string-trap.json中写入kv_failed_task(第一条命令失败的任务名称,不带 role 前缀)、kv_type(第一条命令中 helm_enabled 成为的类型:"str"或"bool")、json_passed(第二条命令是否以 failed=0 结束,布尔值)。 - 在
/opt/ks/kubespray中运行ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml,把完整输出保存到/root/ks/logs/cluster-1.log(约 8 分钟)。PLAY RECAP 中的 node1 必须是failed=0。 - 等到
kubectl top node能显示 node1 的 CPU 和内存之后,在/root/ks/addons/metrics.json中写入apiservice_available(APIServicev1beta1.metrics.k8s.io的 Available 条件的 status)、image(metrics-server Deployment 的容器镜像)、insecure_tls(metrics-server 是否以--kubelet-insecure-tls参数运行,布尔值)。 - 在 default 命名空间中创建 PVC
data(storageClassNamelocal-path,64Mi,ReadWriteOnce),以及把它挂载到/data的 Podwriter(镜像busybox:latest,命令sh -c 'echo kubespray > /data/hello.txt && sleep 3600')。PVC 必须变为 Bound,并且在节点的 local-path 存储路径下,该卷的目录中要有内容为kubespray的hello.txt。 - 用
helm create /root/ks/addons/demo创建 Chart,并用helm install demo /root/ks/addons/demo -n demo --create-namespace --wait安装。releasedemo必须是 deployed,Pod 必须是 Ready。在/root/ks/addons/helm.json中写入helm_version(helm version --template '{{.Version}}')、kubespray_helm_version(这个 kubespray 版本的默认 helm_version,前面加上 v)。 - 在
/root/ks/addons/cni.json中写入plugin(inventory 解析出的 kube_network_plugin)、calico_version(calico-node DaemonSet 中 calico-node 容器的镜像标签)、vxlan_mode、ipip_mode(calicoctl.sh get ippool default-pool -o json的 spec 值)、pool_cidr(该 IP 池的 cidr)。
参考
- kubespray v2.32.0 位于
/opt/ks/kubespray,inventory 位于/root/ks/inventory/lab/inventory.ini(kube_version 1.35.8),均已准备好。安装在第 3 步亲自进行。 - 附加组件的镜像从 registry.k8s.io 和 docker.io 下载。这台 VM 可以通过公网 80/443 端口访问外部。
- 常见错误:像
"true"这样在 addons.yml 中加上引号。有些变量会被 validate_inventory 拦下,有些变量则在条件表达式中被悄悄地解析成不同的结果。 - 常见错误:看到 kubectl top 最初几十秒失败,就重新安装 metrics-server。请等待第一个采集周期。
- 文档:Kubespray — CNI 选择(k8s-cluster.yml) · Kubespray — Calico · Kubernetes — Resource metrics pipeline
附加组件要在安装前选好
在 /root/ks/inventory/lab/group_vars/k8s_cluster/addons.yml 中,把 metrics_server_enabled、local_path_provisioner_enabled、helm_enabled 全部改为 true。用 ansible-inventory --host node1 解析时,这三个值必须是布尔值 true,而不是字符串。
示例的 addons.yml 中这三行写的是 false。在 YAML 中,不带引号的 true 是布尔值,而 "true" 是字符串。在 ansible-inventory 的 JSON 输出中,两者分别显示为 true 和 "true"。
-e 传递的是字符串
在 /opt/ks/kubespray 中,分别运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml -e helm_enabled=true 和 -e '{"helm_enabled": true}'。在 /root/ks/addons/string-trap.json 中写入 kv_failed_task(第一条命令失败的任务名称,不带 role 前缀)、kv_type(第一条命令中 helm_enabled 成为的类型:"str" 或 "bool")、json_passed(第二条命令是否以 failed=0 结束,布尔值)。
从 ansible-core 2.19 起,条件表达式必须是布尔值,而 -e key=value 传递的始终是字符串。kubespray 在 validate_inventory 中按类型检查几个已知的布尔值。类型可以用 ansible -i ... node1 -m debug -a 'msg={{{{ helm_enabled | type_debug }}}}' -e helm_enabled=true 查看。
连同附加组件一起搭建
在 /opt/ks/kubespray 中运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml,把完整输出保存到 /root/ks/logs/cluster-1.log(约 8 分钟)。PLAY RECAP 中的 node1 必须是 failed=0。
附加组件是在 cluster.yml 的最后一个 play(Install Kubernetes apps)中安装的。如果是已经搭建好的集群,修改 group_vars 之后,也可以用 --tags apps 或附加组件的标签(metrics_server 等)只重新运行那一部分,但这里要从一开始就打开它们并搭建。请用 systemd-run 或 tmux 启动,使它即使控制台断开也能继续运行。
metrics-server 真的能给出数值吗
等到 kubectl top node 能显示 node1 的 CPU 和内存之后,在 /root/ks/addons/metrics.json 中写入 apiservice_available(APIService v1beta1.metrics.k8s.io 的 Available 条件的 status)、image(metrics-server Deployment 的容器镜像)、insecure_tls(metrics-server 是否以 --kubelet-insecure-tls 参数运行,布尔值)。
metrics-server 通过 aggregation layer 接入 API 服务器。如果 APIService 不是 Available,kubectl top 会以 “Metrics API not available” 失败。要过几十秒才会出现第一个数值。kubespray 的默认值(metrics_server_kubelet_insecure_tls: true)意味着不验证 kubelet 的服务证书,所以在生产中应该考虑正确签发 kubelet 服务证书。
PVC 绑定到节点磁盘
在 default 命名空间中创建 PVC data(storageClassName local-path,64Mi,ReadWriteOnce),以及把它挂载到 /data 的 Pod writer(镜像 busybox:latest,命令 sh -c 'echo kubespray > /data/hello.txt && sleep 3600')。PVC 必须变为 Bound,并且在节点的 local-path 存储路径下,该卷的目录中要有内容为 kubespray 的 hello.txt。
local-path-provisioner 会在使用 PVC 的 Pod 被调度时(WaitForFirstConsumer),在节点磁盘上创建目录并作为 PV 提供。PV 的 spec.hostPath.path 或 spec.local.path 就是那个目录。busybox 是 local-path 使用的辅助镜像,kubespray 已经提前下载好了。
用 kubespray 安装的 Helm 创建一个 release
用 helm create /root/ks/addons/demo 创建 Chart,并用 helm install demo /root/ks/addons/demo -n demo --create-namespace --wait 安装。release demo 必须是 deployed,Pod 必须是 Ready。在 /root/ks/addons/helm.json 中写入 helm_version(helm version --template '{{.Version}}')、kubespray_helm_version(这个 kubespray 版本的默认 helm_version,前面加上 v)。
kubespray 的 Helm,是从 get.helm.sh 下载以校验和固定的版本,放在 /usr/local/bin/helm。默认版本是 roles/kubespray_defaults/vars/main/checksums.yml 中 helm_archive_checksums 的第一个键。helm create 创建的 Chart 使用 docker.io 的 nginx 镜像。
calico 是怎样运行的
在 /root/ks/addons/cni.json 中写入 plugin(inventory 解析出的 kube_network_plugin)、calico_version(calico-node DaemonSet 中 calico-node 容器的镜像标签)、vxlan_mode、ipip_mode(calicoctl.sh get ippool default-pool -o json 的 spec 值)、pool_cidr(该 IP 池的 cidr)。
kubespray 把 calicoctl 包装为 /usr/local/bin/calicoctl.sh。默认 IP 池由 kube_pods_subnet 创建,封装方式由 calico_vxlan_mode 和 calico_ipip_mode 这两个变量决定。VXLAN 只需要节点之间 L3 互通,IPIP 则必须放行 IP 协议 4——云防火墙正是决定选择的关键点。