Kubernetes 1.11已经发布一个多月了。我们线上的版本都是按照比官方最新版本低一个版本的节奏。 因此可以开始考虑将团队线上环境的Kubernetes集群从1.9升级到1.10了。 本文记录了在测试环境中的演练过程。
1.准备
当前Kubernetes 1.10的小版本是1.10.6。 在升级之前一定要多读几遍官方的升级须知Kubernetes 1.10 - Action Required Before Upgrading。
其中针对我们对Kubernetes的使用情况,有几个需要我们注意的地方:
--pod-infra-container-imagePod的pause镜像由3.0升级到了3.1,即k8s.gcr.io/pause-amd64:3.1,这个需要提前准备- 通过kubelet的配置文件
--config指定的参数和原来kubelet命令行参数的有很多有不同的默认值,在切换到--config时一定要注意这一点 - kubelet的cadvisor端口被废弃了,它的默认值在Kubernetes 1.12将变成0,在1.13将会被彻底移除
Kubernetes 1.10所需的外部依赖和一些组件的版本:
- etcd 3.1.12
- 以下docker版本在Kubernetes 1.10上进行过验证:docker 1.11.2, 1.13.1, 17.03.x (支持的最小docker版本是1.11)
- CNI 0.6.0和Kubernetes 1.9依赖的版本相同
- CSI更新到了0.2.0
- dashboard 1.8.3
- heapster 1.5.0
- kube-dns 1.14.8
- flannel 0.10.0
- kube-state-metrics 1.3.1
2.使用ansible升级Kubernetes
2.1 master节点
我们的集群有3个master节点,在使用ansible升级master节点(kube-apiserver, kube-scheduler, kube-controller-manager)时,通过修改ansible role的inventory文件,只先升级第一个master节点,当测试没有问题后再升级剩余两个master节点。master节点的升级十分顺利,对ansible role的修改也不大。
2.2 node节点
同样也是先选择一个node节点升级做测试,如果这个节点上有业务Pod正在运行,可以先将这个节点排干(drain),将业务容器转移到其他的node节点上。 测试环境中的升级十分顺利,算上下载二进制文件,半个小时就完成了集群的升级,各个核心组件成功升级到了1.10.6。
注意提前准备
--pod-infra-container-image到k8s.gcr.io/pause-amd64:3.1
2.3 Kubelet动态配置
Kubelet动态配置(Dynamic Kubelet Configuration beta)特性,在Kubernetes 1.10进入Beta阶段,可以在Node不下线的情况下改变Kubelet的配置。从Kubernetes 1.11开始kubelet的绝大多数命令行flag参数都被标记为DEPRECATED,而官方推荐我们使用--config指定配置文件,并在配置文件中指定原来这些flag所配置的内容。
因此,我们决定在这次将Kubernetes升级到1.10的过程中为kubelet启用--config指定配置文件,需要在我们的ansible role中加入相关的配置task。
config.yaml:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: {{ k8s_node_address }}
authentication:
anonymous:
enabled: true
authorization:
mode: AlwaysAllow
cgroupDriver: cgroupfs
cgroupsPerQOS: true
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: false
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: {{ kube_pod_manifest_dir }}
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s