关于本文
工作中想验证下VerticalPodAutoscaler功能,但是其中的admission-controller组件必须依赖与1.9以上版本的mutatingadmissioncontroller功能,平时用的开发环境还一直是很早之前用kubeadmin部署的1.8.×,本来用kubeadmin升级很简单,差不多一条命令就可以了,但考虑到生产环境没有外网连接只能手工升级,另外还沒最终决定何时升级,在升级之前的一些开发和功能验证还是要基于旧版本进行,所以尝试手动升级并备份旧有集群可以随时切换。主要记录一下升级过程中碰到的问题,不会描述每一个详细步骤,网上应该已经有很多了。
集群备份
etcd数据
k8s的最重要数据比如namespace,deployment,job,账号之类的信息都在etcd,所以这个一定要事先做备份,可以用快照,backup或者直接拷贝数据目录(缺省/var/lib/etcd)
配置文件
master节点的/etc/kubernetes/,下面包含静态pod manifests 文件,kebeconfig文件,如果是本地化部署相应的配置文件在systemd目录下,各个节点上的kubelet配置文件也要备份,因为很多参数选项变化太大
集群升级
具体升级其实不负杂,下载相应的镜像文件和二进制文件并放到对应目录,
修改kubelet的配置参数
修改manifests文件里的镜像版本号以及命令参数
这里记录升级中值得的问题
calico网络插件
开始一直有问题,没有仔细分析,可能也是和MutatingAdmssionController相關,應爲從生成的pod配置中插入了Calico相關的一些注解信息,直接删掉重新安装新版本后就好了
kube-proxy
新版本的k8s中ipvs功能已经GA,在集群中服务数比较多时很有必要启用该功能,首先要在所有节点上启用ip_vs内核模块,modprobe ip_vs ip_vs_rr nf_conntrack_ipv4…,为了节点重启时可以保持配置,把这些模块添加到/etc/modules文体中。
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4
另一碰到的问题就是开始日志中始终显示加载模块失败,尽管我已经确认加载成功了,其实原因是我的kube-proxy是以容器方式部署的,而1.8旧版本中是用的iptables模式,所以在yaml文件中没有挂载hostpath volume。
volumeMounts:
- mountPath: /lib/modules
name: lib-modules
readOnly: true
volumes:
- hostPath:
path: /lib/modules
type: ""
name: lib-modules
namespace删除失败
升级好后一切功能看起来正常,但很快发现删除namespace一直处于Terminating状态,就算是刚建的新namespace也是一样
查了一通没有什么突破,没有办法只能手动到etcd里把该namespace相关的资源全部删除
etcdctl get / --prefix --keys-only | grep <NS>
etcdctl del <KEY>
但这终究不是个办法,仔细检查日志发现aggregate apiservice字样,原来新版本里加了功能删除namespace时apiserver会调用所有注册的apiservice并让它们也删除与这个namespace相关的资源,只有都返回后才能最终删除namespace,而我原先在集群上创建过两个apiservice,后端extension-apiserver已经删除了,但apiservice还在,这导致上述流程无法顺利完成,只要删除相应的apiservice就好了。
kubectl get apiservice
kubectl delete apiserver <unhealthy services>
coredns
新版本中dns缺省使用coredns替換原來的kube-dns組件, 要相應修改配置文件
device-plugin升级
nvidia gpu-device-plugin一直处于alpha,beta阶段,1.12版本后升级为beta版本,api有变动支持一个pod里多个容器申请不同的device,所以升级k8s后一定要升级device-plugin,否则GPU申请失败
相应的fuse-device-plugin代码也要升级否则s3fs挂载失败
其他的一些变动
新版本中kubelet的很多配置参数变了,比如缺省启用deviceplugin了,另外启动时看多日志里有很多warning,原来很多命令行选项建议放到配置文件里,新增加了一个kubeletconfig的资源类型,而且支持版本回溯,我觉得也是一个不错的功能
kubectl proxy
export NODE_NAME="vm2"
curl -sSL "http://localhost:8001/api/v1/nodes/${NODE_NAME}/proxy/configz" | jq '.kubeletconfig|.kind="KubeletConfiguration"|.apiVersion="kubelet.config.k8s.io/v1beta1"' > kubelet_configz_${NODE_NAME}
kubectl -n kube-system create configmap ${NODE_NAME}-config --from-file=kubelet=kubelet_configz_${NODE_NAME} --append-hash -o yaml
kubectl patch node ${NODE_NAME} -p "{\"spec\":{\"configSource\":{\"configMap\":{\"name\":\"${CONFIG_MAP_NAME}\",\"namespace\":\"kube-system\",\"kubeletConfigKey\":\"kubelet\"}}}}"
restart kubelet with --dynamic-config-dir=<DIR>
总的印象
新旧版本总的架构没有变化,但是新增了不少功能,整个系统还在不停的快速演进,使用者应该紧跟步伐升级,否则后面有什么要用的功能对版本有强依赖(比如istio也依赖1.9以上版本)再考虑升级会比较局促,本文只尝试了但master的情况,生产上ha的配置下理论上不会有什么事情,还有如果用flannel插件会不会也要有什么依赖,这些都要实际验证了才放心。