前言
这几天给线上搭建 k8s 集群,文件和 systemd
参数大多是从 kubeadm 的 staticPod 的 yml 里扣出来的,起初是除了 flanneld 全部是 systemd 管理二进制。脚本问题导致 kube-proxy
的 kubeocnfig 少执行了 use-context
所以显示的是匿名用户无法 list node 信息,kube-proxy 是在运行但是无法维持 svc 的网络,flanneld 因为是 pod 要 watch 节点是通过 kubernetes 这个 svc 走的连接导致不通,然后 pod 状态变成退出,而 kubelet
在不手动清理掉退出状态的 flannel 容器就不会创建新的 flannel 的 pod,而改退出状态容器的 gc 时间又是全局这样不好,遂萌生了之前一个未完成的坑: flanneld扣成二进制跑
尝试
不要在 etcd 写 flannel 配置了
国内和看到的一些个人博客的 flanneld
全部都是通过 etcdctl v2
去写 pod 子网(而且不用 cni plugins
还去改 docker0 的段就不说了..),新版本 k8s 都是 v3 的 api 存储,而且 v2 和 v3 共存会导致无法恢复备份,并且 etcd 官方打算后期废除掉 v2 的存储。感觉市面上还 etcdctl v2 去 set 网络贼 low,这几天查了下资料成功搞出来了,记录下过程。
尝试和源码相关
先说下之前的尝试:之前就把 kube-flannel.yml
文件和参数照搬写成 systemd 脚本启动,yml 里的 clusterrole 和 sa 啥的都创建好然后用 sa 的 token 生成了 kubeconfig 给 flannel 用。但是运行不起来,报错env variables POD_NAME and POD_NAMESPACE must be set
今天刚开始谷歌搜关键字搜到了这个 issue https://github.com/coreos/flannel/issues/932 ,说手动添加上面两个变量来欺骗集群。但是开发者给出答案说只需要设置下每个 node 环境变量 NODE_NAME
为名字就行了,issue 里还贴了源码对应的逻辑判断
https://github.com/coreos/flannel/blob/master/subnet/kube/kube.go#L94
1 | nodeName := os.Getenv("NODE_NAME") |
找了个flannel的pod默认情况下的环境变量
1 | "Env": [ |
发现根本没环境变量NODE_NAME
但是有变量POD_NAME
和POD_NAMESPACE
,也就是进入到代码if里,但是systemd跑下三个环境变量都没有,也就抛出错误退出。如果我们设置了环境变量NODE_NAME
应该就会像开发者回复那样运行。
从kube-flannel.yml
思考了下逻辑:
net-conf.json
包含所有flanneld
的CIDR
信息文件挂载在目录/etc/kube-flannel/
,手动创建目录和存放文件。当然可以看到源码 https://github.com/coreos/flannel/blob/master/subnet/kube/kube.go#L54 是固定文件名的cni-conf.json
文件同样挂载在目录/etc/kube-flannel/
,但是initContainer
逻辑复制到目录/etc/cni/net.d/10-flannel.conflist
了,systemd脚本里可以写prestart exec啥的模仿,这里我偷懒直接改名放进去- flanneld的pod会在宿主机目录
/run/flannel
生成自己分配到的 cidr 和 mtu 信息文件,文件是连接 apiserver 后生成的,所以我们只需要创建目录 - 把
kube-flannel.yml
里的 clusterrole 和 sa 啥的都创建好然后用 sa 的 token 生成了 kubeconfig 给 flannel 使用 - 准备二进制文件然后就是 systemd 脚本,明确 bind 哪张网卡,然后 ip ,还有健康检查 bind 的 ip 和 port 来用于监控。吐槽下 flannel 从 prometheus 的爸爸 coreos 出生居然到现在还没有
metrics
指标功能
1 | cat<<EOF>/usr/lib/systemd/system/flanneld.service |
上面部署已集成在我写的ansible部署里 https://github.com/zhangguanzhang/Kubernetes-ansible