k8s_kubelet启动时必须关闭swap_转

转自:Kubernetes 设计分析: 为什么 kubelet 运行时不能打开 swap?

问题背景

在我自己的测试环境里,使用 kubeadm 来创建 k8s 集群,而我们知道 kubeadm 运行机制首先要求控制节点(简称 kmaster)上的 kubelet 需要先启动。

测试环境使用 systemd 对进程进行管理。

测试环境重启后,发现 kubelet 无法正常启动,表现如下:

root@kmaster135:~# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: activating (auto-restart) (Result: exit-code) since Sun 2019-04-07 22:06:29 PDT; 295ms ago
     Docs: https://kubernetes.io/docs/home/
  Process: 19593 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_
 Main PID: 19593 (code=exited, status=255)

Apr 07 22:06:29 kmaster135 systemd[1]: kubelet.service: Main process exited, code=exited, status=255/n/a
Apr 07 22:06:29 kmaster135 systemd[1]: kubelet.service: Unit entered failed state.
Apr 07 22:06:29 kmaster135 systemd[1]: kubelet.service: Failed with result 'exit-code'.

过程记录

kubelet 拉起实验

可以看到启动命令失败,而失败的具体原因,我们需要查看对应的进程日志,参考: 如何使用Journalctl查看并操作Systemd日志
,学习到可以使用journalctl _PID=<PID> 来查看对应进程的日志,在上面可以看到 kubelet 在最近一次重启失败的主进程 PID 是 19593。

root@kmaster135:~# journalctl _PID=19593 | vim -

-- Logs begin at Sun 2019-04-07 20:03:02 PDT, end at Sun 2019-04-07 22:08:53 PDT. --
Apr 07 22:06:29 kmaster135 kubelet[19593]: Flag --cgroup-driver has been deprecated, This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.
Apr 07 22:06:29 kmaster135 kubelet[19593]: Flag --cgroup-driver has been deprecated, This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.
Apr 07 22:06:29 kmaster135 kubelet[19593]: I0407 22:06:29.445241   19593 server.go:408] Version: v1.12.3
Apr 07 22:06:29 kmaster135 kubelet[19593]: I0407 22:06:29.445739   19593 plugins.go:99] No cloud provider specified.
Apr 07 22:06:29 kmaster135 kubelet[19593]: I0407 22:06:29.449904   19593 certificate_store.go:131] Loading cert/key pair from "/var/lib/kubelet/pki/kubelet-client-current.pem".
Apr 07 22:06:29 kmaster135 kubelet[19593]: I0407 22:06:29.502617   19593 server.go:667] --cgroups-per-qos enabled, but --cgroup-root was not specified.  defaulting to /
Apr 07 22:06:29 kmaster135 kubelet[19593]: F0407 22:06:29.503369   19593 server.go:262] failed to run Kubelet: Running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false. /proc/swaps contained: [Filename                                Type                Size        Used        Priority /dev/sda5                               partition        998396        0        -1]

重定向标准输出到 vim 是为了避免屏幕显示时被截断,没有自动换行,不是关键点。

根据 Fatal 级别的日志

Apr 07 22:06:29 kmaster135 kubelet[19593]: F0407 22:06:29.503369 19593 server.go:262] failed to run Kubelet: Running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false.

可以看出来是因为开启了 swap,而 kubelet 在 1.8 版本以后强制要求 swap 必须关闭。

我之前是通过 swapoff -a命令来关闭 swap 的,看来没有被固化。

root@kmaster135:~# free
              total        used        free      shared  buff/cache   available
Mem:         997616       97500      519460       10784      380656      713456
Swap:        998396           0      998396

先来测试一下,关闭 swap 后能否正常,再来考虑固化的问题。

root@kmaster135:~# swapoff -a
root@kmaster135:~# free
              total        used        free      shared  buff/cache   available
Mem:         997616       97180      519904       10784      380532      713992
Swap:             0           0           0

看起来没有直接退出了:

root@kmaster135:~# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since Sun 2019-04-07 22:14:10 PDT; 46s ago
     Docs: https://kubernetes.io/docs/home/
 Main PID: 20719 (kubelet)
    Tasks: 16
   Memory: 50.6M
      CPU: 3.764s
   CGroup: /system.slice/kubelet.service
           └─20719 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubecon

Apr 07 22:14:43 kmaster135 kubelet[20719]: W0407 22:14:43.334707   20719 cni.go:293] CNI failed to retrieve
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.695545   20719 cni.go:310] Error adding network:
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.696050   20719 cni.go:278] Error while adding to
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.827405   20719 remote_runtime.go:96] RunPodSandbo
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.827475   20719 kuberuntime_sandbox.go:65] CreateP
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.827498   20719 kuberuntime_manager.go:657] create
Apr 07 22:14:43 kmaster135 kubelet[20719]: E0407 22:14:43.827576   20719 pod_workers.go:186] Error syncing
Apr 07 22:14:44 kmaster135 kubelet[20719]: W0407 22:14:44.342386   20719 docker_sandbox.go:375] failed to r
Apr 07 22:14:44 kmaster135 kubelet[20719]: W0407 22:14:44.351209   20719 pod_container_deletor.go:75] Conta
Apr 07 22:14:44 kmaster135 kubelet[20719]: W0407 22:14:44.354070   20719 cni.go:293] CNI failed to retrieve

虽然还是有一些报错,按照上面的逻辑进一步排查可以发现是初始化阶段的报错,集群很快恢复了正常。

root@kmaster135:~# kubectl get cs
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}
root@kmaster135:~# kubectl get nodes
NAME         STATUS   ROLES    AGE   VERSION
dnode136     Ready    <none>   12d   v1.12.3
dnode137     Ready    <none>   12d   v1.12.3
kmaster135   Ready    master   12d   v1.12.3
root@kmaster135:~# kubectl get pods
NAME                          READY   STATUS             RESTARTS   AGE
hello-world-6897d55fb-2crbf   1/1     Running            1          12d
hello-world-6897d55fb-ssc28   1/1     Running            1          12d
hello-world-6897d55fb-txg5j   1/1     Running            1          12d

swapoff 固化

kubelet 问题看起来解决了,接下来要解决 swap 设置如何固化的问题,参考 How do I disable swap?, 配置 /etc/fstab

root@kmaster135:~# cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=aac6ee1b-f945-473b-8222-4be8c11e4822 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=d36ffe9b-676a-419a-b6fb-b95dc12d93ac none            swap    sw              0       0
...

注释掉最下面的UUID=d36ffe9b-676a-419a-b6fb-b95dc12d93ac这一行就可以了。

swap & kubelet

进一步了解一下,为什么 swap 打开对 kubelet 来说会是一个需要直接退出进程的错误呢??

参考 Why disable swap on kubernetesKubelet needs to allow configuration of container memory-swap #7294, 得出基本的知识总结:

  1. 一开始大家在讨论的是,如果容许 Pod 使用 Swap,应该怎么去衡量默认的 Swap 设置,以及调度器应该如何根据 Swap 来进行调度?
  2. 讨论了一段时间后,发现支持 Swap 很复杂。。。总之就是很复杂。一位大佬站出来说,真的有需要用到 Swap 的场景么?
  3. 然后大家就开始批判起 Swap 来了,Swap 带来各种性能上的不确定性啦,而且也找不到哪些场景一定要用 Swap 啦,经过大家高兴地一致决定,Swap 这个东西真的是有害而无利,而且要用起来还复杂,就是不用它好了(K8S 1.5版本)。
  4. 然后如果有人想用?一开始还是支持通过参数配置使用的,后来发现一个不推荐的用法,有人非得用,代码上各种坑,还不如大家一起坚决不用好了。
  5. 然后到了1.8后就是默认不用了,除非你强制打开,官方强烈不推荐,踩坑自己负责。

看 Issue 主要是觉得这个过程实在是一个很典型的,功能要不要的讨论,说来说去,没有明确的用户场景,就不要把一个事情搞复杂的哲学很重要。

更新--fail-swap-on flag含义

这个flag表示为:Makes the Kubelet fail to start if swap is enabled on the node.

也就是说如果为true(默认值)就要求必须要关闭swap,false是表示即使宿主开启了swap,kubelet也是可以成功启动,但是pod是允许使用swap了,这部分代码因为经常出问题,所以直接swap在宿主上禁用会比较好。

原文地址:https://www.cnblogs.com/embedded-linux/p/12388586.html