Q:在文件管理器使用过程中您是否发现过,在文件管理器中,新增或者删除或者重命名文件,都无法立即显示对应的修改,而必须要先离开当前路径的页面再回来,相当于刷新一下,才能看到对应的删改的问题。
A:这是由于用户使用环境中有其它程序也在监听文件,文件管理器使用inotify时触发系统的监听上限导致的。
遇到凡事不要慌,我们来给您帮忙!
您可以在终端使用命令新建文件
aaa@aaa-PC:sudo vi /etc/sysctl.d/watches.conf
输入以下内容:
fs.inotify.max_user_watches = 10485760
保存成功后注销用户,重新登录就可以正常使用啦。
inotify允许程序监视文件的更改,以便每当用户或程序修改文件时它们都会收到事件。inotify它跟踪的每个文件都需要内核资源(内存和处理器)。因此,Linux 内核限制了每个用户可以注册的文件观察程序的数量。默认设置因主机系统分布而异;在 Ubuntu 20.04 LTS 上,默认限制是每个实例 8,192 个手表。
在 64 位系统上,inotify程序注册的每个 watch 将消耗大约 1 kB 的内核内存,这些内存无法交换到磁盘并且不计入工作区内存限制设置。
如果您遇到本文重点的错误,则表明正在使用的观察者总数正在接近max_user_watches设置。以下部分将向您展示如何验证是否是这种情况。
检查可调设置
有三个与inotify系统相关的内核调优选项:
fs.inotify.max_queued_events: 等待传送到程序的文件通知事件数的上限
fs.inotify.max_user_instances:每个用户的最大inotify实例数(使用的程序inotify通常会创建一个实例,因此此限制不太可能导致问题)
fs.inotify.max_user_watches:程序可以监视更改的最大文件和文件夹数
要查看适用于您的工作区的这些设置的值,请运行:
sysctl fs.inotify.{max_queued_events,max_user_instances,max_user_watches}
您应该会看到类似于以下内容的输出:
fs.inotify.max_queued_events = 16384
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 8192
因为这些设置不支持命名空间,所以无论您是在主机系统上还是在该主机上运行的容器内运行命令,这些值都是相同的。
要识别消耗inotify watches 的程序,您可以使用总结/proc文件系统中可用信息的脚本,例如 inotify-consumers.
运行./inotify-consumers将显示程序名称以及inotify向内核注册的watches数量,如下所示:
$ ./inotify-consumers
INOTIFY
WATCHER
COUNT PID USER COMMAND
--------------------------------------
269 254560 coder /var/tmp/coder/code-server/lib/node /var/tmp/coder/code-server/lib/vscode/out/bootstrap-fork --type=watcherService
5 1722 coder /var/tmp/coder/code-server/lib/node /var/tmp/coder/code-server/lib/vscode/out/vs/server/fork
2 254538 coder /var/tmp/coder/code-server/lib/node /var/tmp/coder/code-server/lib/vscode/out/bootstrap-fork --type=extensionHost
2 1507 coder gpg-agent --homedir /home/coder/.gnupg --use-standard-socket --daemon
278 WATCHERS TOTAL COUNT
要查看工具跟踪更改的特定文件,您可以使用它strace 来监视inotify_add_watch系统调用的调用,例如:
$ strace --follow-forks --trace='inotify_add_watch' inotifywait --quiet test
inotify_add_watch(3, "test", IN_ACCESS|IN_MODIFY|IN_ATTRIB|IN_CLOSE_WRITE|IN_CLOSE_NOWRITE|IN_OPEN|IN_MOVED_FROM|IN_MOVED_TO|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF) = 1
如果遇到文件观察程序限制,您可以执行以下两项操作之一:
减少文件观察者注册的数量
增加最大文件观察者限制
我们建议首先尝试减少文件监视程序注册,因为增加文件监视程序的数量可能会导致处理器利用率高。
许多应用程序包含很少更改的文件(例如,存储在 中的第三方依赖项node_modules)。您的工具可能会监视这些文件和文件夹的更改,从而消耗inotify观察者。这些工具通常提供配置设置以从文件监视中排除特定文件、路径和模式。
例如,Visual Studio Code 并默认code-server应用以下用户工作区设置:
许多应用程序包含很少更改的文件(例如,存储在 中的第三方依赖项node_modules)。您的工具可能会监视这些文件和文件夹的更改,从而消耗inotify观察者。这些工具通常提供配置设置以从文件监视中排除特定文件、路径和模式。
例如,Visual Studio Code 并默认code-server应用以下用户工作区设置:
考虑将其他不经常更改的文件添加到此列表中,这将导致 Visual Studio Code 轮询(或定期检查)对这些文件的更改。
您可以增加内核可调选项以增加 inotify每个用户的最大监视数。这是一个全局设置,适用于共享同一系统/Kubernetes 节点的所有用户。为此,请修改sysctl 配置文件,或将 DaemonSet 应用到 Kubernetes 集群以自动将该更改应用到所有节点。
例如,您可以创建一个名为/etc/sysctl.d/watches.conf并包含以下内容的文件:
fs.inotify.max_user_watches = 10485760
或者,您可以使用以下 DaemonSet kubectl apply:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: more-fs-watchers
namespace: kube-system
labels:
app: more-fs-watchers
k8s-app: more-fs-watchers
spec:
selector:
matchLabels:
k8s-app: more-fs-watchers
template:
metadata:
labels:
name: more-fs-watchers
k8s-app: more-fs-watchers
annotations:
seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
nodeSelector:
kubernetes.io/os: linux
initContainers:
- name: sysctl
image: alpine:3
env:
# Each inotify watch consumes kernel memory, and existing container memory
# limits do not account for this. While you can set an arbitrary limit here,
# note that permitting large numbers of watches may result in performance
# degradation and out-of-memory errors. The required memory per watcher is
# platform-dependent and defined as INOTIFY_WATCH_COST in fs/notify:
# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/notify/inotify/inotify_user.c
#
# The default in this file is 10 million watchers per user.
- name: "USER_WATCHES_MAX"
value: "10485760"
command:
- sysctl
- -w
- fs.inotify.max_user_watches=$(USER_WATCHES_MAX)
resources:
requests:
cpu: 10m
memory: 1Mi
limits:
cpu: 100m
memory: 5Mi
securityContext:
# We need to run as root in a privileged container to modify
# /proc/sys on the host (for sysctl)
runAsUser: 0
privileged: true
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
containers:
- name: pause
image: k8s.gcr.io/pause:3.5
command:
- /pause
resources:
requests:
cpu: 10m
memory: 1Mi
limits:
cpu: 100m
memory: 5Mi
securityContext:
runAsNonRoot: true
runAsUser: 65535
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
terminationGracePeriodSeconds: 5
这个 DaemonSet 将确保相应的 pod在集群中的每个Linux 节点上运行。当新节点加入集群时,例如在自动缩放事件期间,DaemonSet 将确保 pod 也在新节点上运行。
您可以通过运行以下命令删除 DaemonSet:
$ kubectl delete --namespace=kube-system daemonset more-fs-watchers
daemonset.apps "more-fs-watchers" deleted
但是,请注意,该设置将持续存在,直到节点重新启动或其他程序设置该fs.inotify.max_user_watches设置。