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-image Pod的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-imagek8s.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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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