使用适用于 Windows 的 Docker-Desktop,如何配置 sysctl 参数以在重新启动后继续存在?

ToO*_*zZz 22 opensuse elasticsearch docker wsl-2

在 win10 [wsl2] docker-desktop 中运行 elasticsearch 需要通过以下方式将 mmap 计数增加到 262144sysctl -w vm.max_map_count=262144

C:\Users\<username>>wsl -d docker-desktop
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># sysctl -w vm.max_map_count=262144
Run Code Online (Sandbox Code Playgroud)

在对此问题和弹性文档的回答中,建议相应地更新以将该值设置为永久,即使其在重新启动后仍然存在。vm.max_map_count/etc/sysctl.conf

请注意下面的输出,显示在我尝试遵循此建议并重新启动后,有效 mmap 计数未适应 sysctl.conf 中定义的值。

为什么没有呢?

PS C:\Users\<username>> wsl -d docker-desktop
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># sysctl vm.max_map_count
vm.max_map_count = 65530
<hostname>:/tmp/docker-desktop-root/mnt/host/c/Users/<username># cd /etc
<hostname>:/etc# cat sysctl.conf
# content of this file will override /etc/sysctl.d/*
vm.max_map_count=262144
Run Code Online (Sandbox Code Playgroud)

考虑到更改了错误的 sysctl.conf,etc/我尝试更改 中的 sysctl.conf <hostname>:/tmp/docker-desktop-root/etc#。这是不允许的,因为这是一个Read-only file system.

可以/应该在 .wslconfig 中对其进行参数化吗?如果可以,如何?

使用 openSUSE Leap 15.2 代替 Win10 的 PowerShell 并没有改变结果。

<username@hostname>:~> sysctl vm.max_map_count
vm.max_map_count = 65530
<username@hostname>:~> cat /etc/sysctl.conf
####
#
# /etc/sysctl.conf is meant for local sysctl settings
#
# sysctl reads settings from the following locations:
#   /boot/sysctl.conf-<kernelversion>
#   /lib/sysctl.d/*.conf
#   /usr/lib/sysctl.d/*.conf
#   /usr/local/lib/sysctl.d/*.conf
#   /etc/sysctl.d/*.conf
#   /run/sysctl.d/*.conf
#   /etc/sysctl.conf
#
# To disable or override a distribution provided file just place a
# file with the same name in /etc/sysctl.d/
#
# See sysctl.conf(5), sysctl.d(5) and sysctl(8) for more information
#
####
vm.max_map_count=262144
Run Code Online (Sandbox Code Playgroud)

值得注意的是,上述 sysctl.conf 文件中的标头引用了/boot/sysctl.conf-<kernelversion>. 考虑到,mmap 计数可能需要在此文件中定义,以便在启动时考虑,我尝试在那里设置所需的参数,但没有权限这样做。

<username@hostname>:/boot> sudo echo 'vm.max_map_count=262144' >> sysctl.conf-5.10.16.3-microsoft-standard-WSL2
-bash: sysctl.conf-5.10.16.3-microsoft-standard-WSL2: Permission denied
Run Code Online (Sandbox Code Playgroud)

openSUSE:WSL - openSUSE Wiki中报告的已知问题和限制之一是

WSL 中的系统实际上并不启动,也不使用 systemd。专有的 Microsoft /init 二进制文件初始化系统。因此,服务管理不像在虚拟机中那样工作。它的行为就像一个交互式容器。

任何人都可以验证这就是为什么参数化 sysctl.conf 不能成为实现当前目的的有效方法的原因吗?

系统

主机
操作系统:Microsoft Windows 10 企业
版:10.0.18363 Build 18363 \

Docker
客户端:
版本:20.10.8
API 版本:1.41
Go 版本:go1.16.6
Git 提交:3967b7d
构建:2021 年 7 月 30 日星期五 19:54:02
操作系统/Arch:linux/amd64
插件:
compose:Docker Compose (Docker Inc. ,v2.0.0-rc.2)
扫描:Docker Scan(Docker Inc.,v0.8.0)

服务器:
引擎:
版本:20.10.8
API版本:1.41(最低版本1.12)
Go版本:go1.16.6
Git提交:75249d8
构建:2021年7月30日星期五19:52:10
操作系统/Arch:linux/amd64
容器:
版本: 1.4.9
GitCommit:e25210fe30a0a703442421b0f60afac609f950a3
runc:
版本:1.0.1
GitCommit:v1.0.1-0-g4144b63
docker-init:
版本:0.19.0
GitCommit:de40ad0 \

内核版本:5.10.16.3-microsoft-standard-WSL2
操作系统:Docker Desktop
操作系统类型:linux
架构:x86_64
CPU:4
总内存:12.39GiB
名称:docker-desktop

Not*_*1ds 57

简短回答:

在您的 Windows%userprofile%目录(通常)中使用以下内容C:\Users\<username>创建或编辑文件:.wslconfig

[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"
Run Code Online (Sandbox Code Playgroud)

然后退出任何 WSL 实例,wsl --shutdown然后重新启动。

> sysctl vm.max_map_count
vm.max_map_count = 262144
Run Code Online (Sandbox Code Playgroud)

替代(更新)简短答案:

WSL 现在通过一些附加配置支持 Systemd。vm.max_map_count如果您选择在 WSL 上启用 Systemd,则用于保存(和其他参数)的“正常”方法/etc/sysctl.conf将起作用。请参阅此社区 Wiki 答案我的原始版本,了解先决条件以及如何启用。


更多详情:

您确实有三个(密切相关的)问题:

  • (主要)如何最好地持久化这个设置

  • 可以通过 来完成吗.wslconfig

    可以/应该在 .wslconfig 中对其进行参数化吗?如果可以,如何?

  • 为什么不努力/etc/sysctl.conf坚持呢?

    /etc/sysctl.conf 将此值永久设置,即使其在重新启动后继续存在......为什么不呢?

我们将结合前两者,因为答案是:“是的,您可以通过 来完成.wslconfig。”

这并不容易找到,因为更改是最近才发生的。感谢这个答案

从内核版本 5.8 开始,您可以使用值的前缀sysctl在内核命令行上设置值。sysctl.*

因此,只要您升级了 WSL 内核(我的两个系统上都没有wsl --update升级,因为最近才在 21H1 发布),您就可以%userprofile%\.wslconfig按照上面的方式进行设置。


/etc/sysctl.conf

/etc/sysctl.conf 将此值永久设置,即使其在重新启动后继续存在......为什么不呢?

在撰写此问题时,这是WSL2 的一个已知问题。根本问题在于,虽然sysctlSystemd/ 和 Systemd/systemctl是两个完全不同的东西,但正如 realalkenc(Microsoft WSL 团队)指出的那样,某些东西必须读取和处理/etc/sysctl.conf。在大多数 Linux 发行版中,这是 Systemd 或 SysVInit 脚本。

WSL 当时不支持 Systemd,因此....../etc/sysctl.conf启动时不会读取任何内容并执行任何操作。


该答案的其余部分包括一些systcl.conf不需要的解决方法,因为我们可以使用.wslconfig. 留下这个是为了以防万一有人因为某种原因发现它有用。

有一些解决方法。所有这些都将涉及找到一种sysctl -w vm.max_map_count=262144自动运行(以 root 身份)的方法:

  • 首先,最新版本的 WSL 有一个新功能来简化这一过程。只需使用以下命令创建/编辑/etc/wsl.conf(通过sudo):

    [boot]
    command="sysctl -w vm.max_map_count=262144"
    
    Run Code Online (Sandbox Code Playgroud)

    每次 WSL 实例启动时,这都会在 root 下运行。据我所知,这也适用于docker-desktop实例内部,但我无法对此进行测试。


  • 如果 Docker Desktop 设置为在登录时运行,那么您可以添加计划任务(通过 Windows 任务计划程序)以在登录时运行。这将是:

    • 《基本任务》
    • 将“程序”设置为wsl.exe
    • 参数设置为-d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"

    请注意,如果 docker-desktop WSL 实例在任何时候终止,则更改将丢失,直到下次重新启动。但是,由于 Docker Desktop 在启动/登录时运行,因此实例保持此更改不变。


  • 根据您的工作流程,这可能适合也可能不适合。如果您使用单独的 WSL 实例(例如 Ubuntu)进行开发,则可以让docker-desktop实例在启动时修改该实例。

    这样您就不必sudo在每次启动时输入密码,请在您的.bashrc(或等效内容)中使用以下行:

    wsl.exe -d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"
    
    Run Code Online (Sandbox Code Playgroud)