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在宿主上禁用会比较好。

总结

  1. 学习到了使用 journalctl _PID=<PID> 来输出 systemd 管理下的进程日志;
  2. 对 kubelet 的启动限制有了进一步的了解;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343