分享kubernetes集群搭建之前的节点内核优化.
1. 写在前面
这是宝贵的一线生产经验(涉及到一点关于特定云厂商的内容),如果对大家有帮助请不吝打赏,谢谢支持。
网络参数,分别套用到node和pod,其中pod级通过发布的时候注入init-container生效,node级通过运维初始化机器脚本生效到内存。主要涵盖以下内容优化:
- 加强tcp握手队列能力,timewait相关优化
- 调大了conntrack表,保证操作效率
- ulimit优化
技巧
为提高性能,可以根据设备资源情况,设置各 linux
用户的最大线程数和文件打开数
2. Node 相关调参汇总
ulimit
是一种 linux
系统的内键功能,它具有一套参数集,用于为由它生成的 shell 进程及其子进程的资源使用设置限制。为了让系统能够支持更大的并发,优化linux内核也是重中之重
2.1 最大线程数和文件打开数
编辑 /etc/security/limits.conf
1
2
3
4
5
6
7
8
|
root soft nofile 655350
root hard nofile 655350
root soft nproc 655350
root hard nproc 655350
* soft nofile 655350
* hard nofile 655350
* soft nproc 655350
* hard nproc 655350
|
2.2 nf_conntrack 优化
编辑 /etc/sysctl.conf
1
2
3
4
5
6
7
|
# 容器环境下,优化这些参数可以避免 NAT 过的 TCP 连接 带宽上不去。
net.netfilter.nf_conntrack_tcp_be_liberal = 1
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_max = 3200000
net.netfilter.nf_conntrack_buckets = 1600512
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
|
2.3 tcp 握手队列相关优化
1
2
3
4
5
6
7
8
9
10
11
12
|
net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
# 端口范围
net.ipv4.ip_local_port_range = "1024 65000"
# k8s节点还需要排除nodeport端口范围,不然高版本1.23以上会经常出现kubelet使用这个范围的端口去做健康检测,导致健康检测一直出现超时失败的情况:context deadline exceeded (Client.Timeout exceeded while awaiting headers)
net.ipv4.ip_local_reserved_ports = 30000-32767
# timewait相关优化
net.ipv4.tcp_max_tw_buckets = 50000
net.ipv4.tcp_fin_timeout = 30
|
2.4 优化 arp 缓存的 gc 阀值
1
2
3
4
|
# 以下三个参数是 arp 缓存的 gc 阀值,相比默认值提高了,避免在某些场景下arp缓存溢出导致网络超时,参考:https://k8s.imroc.io/troubleshooting/cases/arp-cache-overflow-causes-healthcheck-failed
net.ipv4.neigh.default.gc_thresh1="2048"
net.ipv4.neigh.default.gc_thresh2="4096"
net.ipv4.neigh.default.gc_thresh3="8192"
|
2.5 开启 ipv4 转发
1
2
3
4
5
6
7
|
net.ipv4.tcp_max_orphans="32768"
vm.max_map_count="262144"
kernel.threads-max="30058"
net.ipv4.ip_forward="1"
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 0
|
2.6 转发磁盘 IO 优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 磁盘 IO 优化: https://www.cnblogs.com/276815076/p/5687814.html
# vm.dirty_background_bytes和vm.dirty_bytes是另一种指定这些参数的方法。如果设置_bytes版本,则_ratio版本将变为0,反之亦然。
# 可以通过下面方式看内存中有多少脏数据:cat /proc/vmstat | egrep "dirty|writeback", nr_dirty 值表示多少页
# vm.dirty_background_bytes = 0
# vm.dirty_bytes = 0
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 300
vm.dirty_ratio = 10
vm.dirty_writeback_centisecs = 50
vm.dirtytime_expire_seconds = 43200
# fd优化
fs.file-max=655360
fs.inotify.max_user_instances="8192"
fs.inotify.max_user_watches="524288"
# 最大线程数量
kernel.pid_max = 655350
|
3. Pod 相关调参汇总
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
|
# socket buffer优化
net.ipv4.tcp_wmem = 4096 16384 4194304
net.ipv4.tcp_rmem = 4096 87380 6291456
net.ipv4.tcp_mem = 381462 508616 762924
net.core.rmem_default = 8388608
# 读写 buffer 调到 25M 避免大流量时导致 buffer 满而丢包 "netstat -s" 可以看到 receive buffer errors 或 send buffer errors
net.core.rmem_max = 26214400
net.core.wmem_max = 26214400
# timewait相关优化
# 这个优化意义不大
net.ipv4.tcp_max_tw_buckets = 131072
# 通常默认本身是开启的
net.ipv4.tcp_timestamps = 1
# 仅对客户端有效果,对于高并发客户端,可以复用TIME_WAIT连接端口,避免源端口耗尽建连失败
net.ipv4.tcp_tw_reuse = 1
# 对于高并发客户端,加大源端口范围,避免源端口耗尽建连失败(确保容器内不会监听源端口范围的端口)
net.ipv4.ip_local_port_range="1024 65535"
# 缩短TIME_WAIT时间,加速端口回收
net.ipv4.tcp_fin_timeout=30
# 握手队列相关优化
# 没有启用syncookies的情况下,syn queue(半连接队列)大小除了受somaxconn限制外,也受这个参数的限制,默认1024,优化到8096,避免在高并发场景下丢包
net.ipv4.tcp_max_syn_backlog = 10240
# 表示socket监听(listen)的backlog上限,也就是就是socket的监听队列(accept queue),当一个tcp连接尚未被处理或建立时(半连接状态),会保存在这个监听队列,默认为 128,在高并发场景下偏小,优化到 32768。参考 https://imroc.io/posts/kubernetes-overflow-and-drop/
net.core.somaxconn = 65535
net.ipv4.tcp_syncookies = 1
# fd优化
# 提升文件句柄上限,像 nginx 这种代理,每个连接实际分别会对 downstream 和 upstream 占用一个句柄,连接量大的情况下句柄消耗就大。
fs.file-max=1048576
# 表示同一用户同时最大可以拥有的 inotify 实例 (每个实例可以有很多 watch)
fs.inotify.max_user_instances="8192"
# 表示同一用户同时可以添加的watch数目(watch一般是针对目录,决定了同时同一用户可以监控的目录数量) 默认值 8192 在容器场景下偏小,在某些情况下可能会导致 inotify watch 数量耗尽,使得创建 Pod 不成功或者 kubelet 无法启动成功,将其优化到 524288
fs.inotify.max_user_watches="524288"
|
技巧
Pod
瓶颈是 TCP
协议栈。
需要注意的是,如果内核版本过低(<3.12), 有些参数是无法修改的,升级内核解决问题。