使用Docker-Desktop for Windows,如何配置sysctl参数以在重启后保留设置?

21
在Win10 [WSL2] Docker桌面上运行elasticsearch需要通过sysctl -w vm.max_map_count=262144来增加mmap计数到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

回答这个问题Elastic的文档中建议相应地更新/etc/sysctl.conf中的vm.max_map_count,以使该值永久生效,即在重启后仍然有效。
请注意下面的输出,显示有效的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

考虑到在etc/中更改了错误的sysctl.conf,我尝试在<hostname>:/tmp/docker-desktop-root/etc#中更改sysctl.conf。 由于这是一个只读文件系统,所以不允许这样做。
如果可以的话,是否应该将其参数化到.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

值得注意的是,上述sysctl.conf文件中的标题引用了一个/boot/sysctl.conf-。考虑到在启动时可能需要定义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

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

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

有人可以验证这是否是参数化sysctl.conf无法有效实现目标的原因吗?

系统

主机:
操作系统:Microsoft Windows 10 Enterprise
版本:10.0.18363 Build 18363 \

Docker
客户端:
版本: 20.10.8
API 版本: 1.41
Go 版本: go1.16.6
Git 提交: 3967b7d
构建时间: Fri Jul 30 19:54:02 2021
操作系统/架构: linux/amd64
插件:
compose: Docker Compose (Docker Inc., v2.0.0-rc.2)
scan: 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
操作系统/架构:linux/amd64
containerd:
版本:1.4.9
Git 提交:e25210fe30a0a703442421b0f60afac609f950a3
runc:
版本:1.0.1
Git 提交:v1.0.1-0-g4144b63
docker-init:
版本:0.19.0
Git 提交:de40ad0
内核版本:5.10.16.3-microsoft-standard-WSL2
操作系统:Docker Desktop
操作系统类型:linux
架构:x86_64
CPU 数量:4
总内存:12.39GiB
名称:docker-desktop
2个回答

55

简短回答:

在你的Windows %userprofile% 目录(通常是 C:\Users\<username>)中创建或编辑文件.wslconfig,并添加以下内容:

[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"

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

> sysctl vm.max_map_count
vm.max_map_count = 262144

更新后的简短回答:

现在WSL支持Systemd,需要进行一些额外配置。如果您选择在WSL上启用Systemd,则可以使用“正常”的方法将vm.max_map_count(和其他参数)持久化到/etc/sysctl.conf中。请参阅此社区Wiki答案我的原始版本以了解先决条件和如何启用。


更多细节:

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

  • (主要是)如何最好地保留此设置

  • 是否可以通过 .wslconfig 完成?

    如果可以/应该在 .wslconfig 中将其参数化,如何操作?

  • 为什么 /etc/sysctl.conf 无法持久化它?

    /etc/sysctl.conf 设置此值为永久性,即使重启后仍然生效....为什么不行呢?

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

由于更改相对较新,因此这并不容易找到。答案请见 this answer

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

只要您升级了 WSL 内核(这是我在两个系统中没有做的,因为 wsl --update 直到21H1才被发布),您就可以设置如上所述的 %userprofile%\.wslconfig


/etc/sysctl.conf

在撰写此问题时,这是WSL2的一个已知问题。根本问题在于,尽管sysctl和Systemd/systemctl是两个完全不同的东西,但正如Microsoft WSL团队的therealkenc指出的那样,某些内容必须读取并处理/etc/sysctl.conf。在大多数Linux发行版中,这是Systemd或SysVInit脚本的工作。当时的WSL不支持Systemd,因此……启动时没有任何内容读取和处理/etc/sysctl.conf

本答案的剩余部分包括一些与systcl.conf有关的解决方法,但我们可以使用.wslconfig来完成此操作,因此这些内容并非必需。为了以防万一,我们仍然保留这些内容。

有几种解决方法可供选择。所有解决方法都需要找到一种自动运行sysctl -w vm.max_map_count=262144(以root身份)的方式:

  • First the latest versions of WSL have a new feature to simplify this. Simply create/edit /etc/wsl.conf (via sudo) with:

    [boot]
    command="sysctl -w vm.max_map_count=262144"
    

    This will run at root each time the WSL instance starts. As far as I know, this will also work from within the docker-desktop instance, but I have not been able to test that.


如果设置了Docker Desktop在登录时运行,则可以通过Windows任务计划程序添加一个定期任务,以便在登录时也运行。这将是一个:
  • "基本任务"
  • 将"Program"设置为wsl.exe
  • 并将参数设置为-d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"
请注意,如果docker-desktop WSL实例在任何时候终止,则更改将在下次重新启动之前丢失。但是,由于Docker Desktop在启动/登录时正在运行,因此该实例应该保持运行,并且该更改应该得到保留。
  • Depending on your workflow, this may or may not fit. If you are using a separate WSL instance (e.g. Ubuntu) for development purposes, you can have that instance modify the docker-desktop instance when you start up.

    So that you don't have to type the sudo password each time you start up, use the following line in your .bashrc (or equivalent):

    wsl.exe -d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"
    

1
绝对是我在找的Dr01d^^ 非常感谢您的专注回答。 - ToOolzZz
谢谢@NotTheDr01ds。 在您的回答中,能否加上一个关于sysctl参数是否可以在.wslconfig中定义的声明? - ToOolzZz
@ToOolzZz 你知道吗,我完全忘记在整个“sysctl”兔子洞中跟进“.wslconfig”部分了。结果发现找到答案并不容易。但好消息是——可以通过“.wslconfig”实现。我即将开始编辑答案,将其作为主要解决方案。 - NotTheDr01ds
在Build 18363上运行,.wslconfig可能不适用于我,尽管尚未进行顽固测试。我会尝试这样做,并且我还将测试该页面上描述的特定于发行版的wsl.conf是否可以作为替代方案,当按照您在.wslconf答案中建议的语法进行更改时。 - ToOolzZz
1
是的,我谨慎地表述了我的测试结果,不完全反对在我的评论中提供的链接下文档中有关最小Windows版本构建的声明。我有一种印象,.wslconfig比19041版本更旧,因为其中显然存在“kernelCommandLine”键。但也许,他们指的是至少另一个.wslconfig键,在较旧的版本中将无法使用。 - ToOolzZz
显示剩余10条评论

2

我在Windows 10 上安装了Docker Desktop和Git。遵循@NotTheDr01ds提供的说明,我打开了一个Git bash控制台:

$ wsl -d docker-desktop sh -c "sysctl -w vm.max_map_count=262144"
vm.max_map_count = 262144

在那个更改之后,SonarQube的ElasticSearch无错误地启动了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接