시스템 서비스의 여러 인스턴스에 대한 총 메모리 사용량 제한

시스템 서비스의 여러 인스턴스에 대한 총 메모리 사용량 제한

Ubuntu 16.04(곧 18.04 예정)에서 일부 .NET Core 프로세스를 systemd 서비스로 실행하고 있습니다. 다음과 같은 시스템 구성 파일( )이 있습니다./lib/systemd/system/[email protected]

[Unit]
Description=My Service %i

[Service]
Type=simple
User=myservice
EnvironmentFile=/etc/environment
WorkingDirectory=/home/myservice/instances/%i
ExecStart=/opt/dotnet/dotnet My.Service.dll

[Install]
WantedBy=multi-user.target

제한하고 싶다모두RAM 양모두이 서비스의 인스턴스를 사용할 수 있습니다. 단일 인스턴스의 RAM을 그 미만으로 제한하고 싶지 않으므로 MemoryHigh및 같은 설정은 MemoryMax도움이 되지 않습니다.

나는 systemd가 서비스 템플릿에 대한 cgroup을 생성한다는 것을 알고 있으므로 어떻게든 해당 cgroup의 메모리 제한을 변경하고 싶습니다.

Ubuntu 18.04에서는 수동으로 편집할 수 /sys/fs/cgroup/memory/system.slice/system-myservice.slice/memory.limit_in_bytes있으며 이는 기본적으로 내가 원하는 작업을 수행하지만(총 메모리 사용량이 제한을 초과하면 프로세스가 종료됨) 이 접근 방식에는 몇 가지 문제가 있습니다.

  • 이 파일은 서비스가 시작될 때까지 시작 시 항상 존재하지 않습니다.
  • Ubuntu 18.04에서는 systemctl daemon-reload이 파일을 호출할 때마다 덮어씁니다.
  • 파일에 쓰려고 하면 때때로 반환되는 경우가 있습니다.write error: Device or resource busy

(Ubuntu 16.04에서는 서비스가 시작될 때마다 제한이 재설정되는 것 같아서 아무런 효과가 없습니다.)

시스템 자체에서 이 값을 설정하여 싸울 필요가 없도록 하는 방법이 있습니까? 아니면 프로세스 그룹의 총 메모리 사용량을 제한하는 다른 방법이 있습니까? 모두 동일한 사용자로 실행되므로 해당 사용자가 사용하는 RAM이 제한될 수 있습니다.

수동으로 cgroup( cgcreate -t myservice:myservice -g memory:mycgroup)을 생성한 다음 ExecStart서비스 구성을 로 변경하려고 시도했지만 /usr/bin/cgexec -g memory:mycgroup /opt/dotnet/dotnet My.Service.dll다시 작동했지만 신뢰할 수 없었습니다. 내가 작성한 메모리 제한이 memory.limit_in_bytes어느 시점에서 재설정되었기 때문에 언제, 왜 그런지 모르겠습니다.

답변1

드디어 성공했어요! 비결은 나만의 슬라이스를 만들고 이를 서비스 파일에 다음과 같이 설정하는 것이었습니다.

[Service]
# Everything else as in the original question
Slice=my_service_limit.slice

그리고 다음과 같이 슬라이싱 유닛 파일을 생성합니다 /lib/systemd/system/my_service_limit.slice.

[Unit]
Description=Slice that limits memory for all my services

[Slice]
# MemoryHigh works only in "unified" cgroups mode, NOT in "hybrid" mode
MemoryHigh=500M
# MemoryMax works in "hybrid" cgroups mode, too
MemoryMax=600M

노트:-에 설명된 대로 계층 구분 기호 와 마찬가지로 슬라이스 이름을 지정할 때 주의하세요.https://systemd.io/CGROUP_DELEGATION- 이 기능을 구성하려는 모든 사람에게 매우 유용한 페이지입니다. 출력을 보면 서비스가 실제로 구성된 조각을 사용하고 있는지 확인할 수 있습니다. 출력에는 다음이 systemctl status myservice표시되어야 합니다.

  CGroup: /my_service_limit.slice/[email protected]

systemd.unified_cgroup_hierarchy=1(다음에 따라) 설정할 필요가 없습니다 .마츠모토 류타로답변) MemoryMax가 작동하도록 하려면예전에는MemoryHigh에 필요 - "하이브리드" 모드(Ubuntu 18.04의 기본값)에서도 자동으로 무시됩니다.

또한 이는 사용된 물리적 RAM에만 적용된다는 점에 주목할 가치가 있습니다.아니요사용된 스왑 공간을 포함합니다. (MemorySwapMax에는 별도의 설정이 있는 것으로 보이지만 MemorySwapHigh는 없습니다.)

답변2

아래와 같이 "통합 cgroup 계층 구조"를 사용해야 할 수도 있습니다. 통합 및 레거시 제어 그룹 계층 구조 .

이 기능을 활성화하려면 GRUB_CMDLINE_LINUX_DEFAULTin 에 systemd.unified_cgroup_hierarchy=1을 추가하고 를 /etc/default/grub실행한 update-grub다음 Linux를 다시 시작합니다.

systemd.unified_cgroup_hierarchy다음과 같이 해석됩니다.systemd unified cgroup hierarchy.

[Service]그런 다음 유닛 파일의 systemd 섹션에 다음 줄을 추가하고 다음을 실행합니다 systemctl daemon-reload.

Delegate=memory
MemoryHigh=8G (if you choose 8 gigabytes as the limit)

"MemoryHigh"에 대한 설명은 다음 위치에 있습니다. systemd.resource-control.

관련 정보