Systemd

如何辨識使用 systemd 啟動的服務的所有已配置記憶體限制?

  • November 8, 2018

我正在追逐一個錯誤,試圖將新曲調應用於 postgres。

確切的錯誤是:

2018-11-07 22:14:49 EST [7099]: [1-1] FATAL:  could not map anonymous shared memory: Cannot allocate memory
2018-11-07 22:14:49 EST [7099]: [2-1] HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 35301089280 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

我熟悉這個錯誤。調整各種 postgres 實例是與我一起工作的工程師的每月任務。解決方案是要麼撤回我們的 postgres 調整,要麼管理諸如shmall和之類的設置ulimit

在這種情況下,我們正在調整一個由其他人創建的 postgres 安裝,並且在幾年的執行時和升級中存在一些問題。此安裝開始於 CentOS 5 安裝,現在安裝在 CentOS 7 上。CentOS 5 上的舊 SysV 安裝應用了幾個記憶體限制控制,包括:

  • /etc/sysconfig/postgresql.d/ulimit.sh
  • /etc/sysconfig/postgresql.d/memory-cap
  • 非常保守的設置shmmaxshmall
  • 來自其他供應商或系統管理員的腳本,通過更改配置文件故意強制某些值
  • /etc/sysctl.conf

自從從 CentOS 5 升級到 CentOS 7 以來,現在似乎對記憶體限制進行了額外的控制,這些控制是在將其從 SysV 更改為 SystemD 時應用的。

例如systemctl cat postgresql.service顯示:

# /usr/lib/systemd/system/postgresql.service
[Unit]
Description=PostgreSQL database server
After=network.target

[Service]
Type=forking
User=postgres
Group=postgres
Environment=PGPORT=5432
Environment=PGDATA=/opt/pgsql/data
OOMScoreAdjust=-1000
LimitSTACK=16384
ExecStart=/opt/pgsql/bin/pg_ctl start -D ${PGDATA} -s -o "-p ${PGPORT}" -w -l ${PGDATA}/serverlog
ExecStop=/opt/pgsql/bin/pg_ctl stop -D ${PGDATA} -s -m fast
ExecReload=/opt/pgsql/bin/pg_ctl reload -D ${PGDATA} -s
TimeoutSec=300

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/postgresql.service.d/memory-cap.conf
#
# THIS FILE IS AUTO-GENERATED by /opt/pgsql/bin/tune.sh
# DO NOT MODIFY, it will be overwritten on next postgres startup.
# If you need to make a change, then disable the tuner:
#
# ln -s /dev/null /etc/systemd/system/postgresql.service.d/tune.conf
#

[Service]
LimitAS=12884901888
# /etc/systemd/system/postgresql.service.d/tune.conf
# /usr/lib/systemd/system/postgresql.service.d/use-system-timezone.conf
# Disable automatically setting the timezone by masking this drop-in file:
# ln -s /dev/null /etc/systemd/system/postgresql.service.d/use-system-timezone.conf
# Then you need to:
# systemctl daemon-reload
[Service]
ExecStartPre=/opt/pgsql/bin/use-system-timezone.sh

現在回到我的實際問題:顯然有幾層核心設置、每使用者限制和服務配置,它們都可以對shmmaxshmallulimit和相關設置施加限制。如何從配置或執行時確定 SystemD 服務在啟動時實際應用的限制?

如果我能確定執行時的限制是什麼,我就可以開始grep配置文件和腳本來查找它們的設置位置。一旦我能找到那些我可以設置他們需要的值。我希望我可以設置一個標誌來讓 SystemD 或我的 postgres 程序在它作為服務啟動時註銷其明顯的設置。

我對這些值應該設置什麼感到滿意,有太多層可能會強製或覆蓋這些值。我想了解我需要觸摸哪些配置位置。

我的看法是,我可能會遇到像 SystemDLimitFOO設置這樣的情況,它的sysctl -w kernel.shmfoo值不同於/etc/someconfig/serviceuser/limit.foo. 我需要確定實際使用或應用了哪些限制,以便我可以正確更改和設置這些限制以調整我正在執行的服務。

正如您在問題中指出的那樣,有幾個限制:

  1. System V IPC 的,例如shmall,shmmax等。
  2. RLIMIT(通常由 shell 中的命令設置和檢查,ulimit因此您可能通過該名稱知道它們。)
  3. cgroup 限制(特別是記憶體 cgroup,在您的情況下),這是一種將限制應用於現代核心中的程序組的新方法。

systemd 管理後兩者,特別是使用 cgroups 作為限制和記帳的主要機制。它確實對 System V IPC 有一些小的有限支持,但並不是真正的限制。

讓我們分解這三個獨立的概念,並研究如何檢查和調整每個與 systemd 相關的限制。

系統 V IPC

systemd 對 System V IPC 有一些小的支持(例如,在服務停止時清理 IPC在其自己的 IPC 命名空間中執行服務為單個服務安裝私有 tmpfs(由 shm 支持)/tmp),但大多數情況下它不會進一步管理 System V IPC 限制,也不會對其進行任何核算。

因此 System V IPC 的限制由 獨家管理sysctl,因此您可以通過以下方式檢查這些限制:

$ sysctl kernel.shmmax kernel.shmall kernel.shmmni
kernel.shmmax = 18446744073692774399
kernel.shmall = 18446744073692774399
kernel.shmmni = 4096

並用sysctl -w.

systemd 只參與設置這些限制,因為它包括systemd-sysctl.service,它負責設置來自/etc/sysctl.conf/etc/sysctl.d/*.conf. 但除此之外,它還sysctl直接為您提供有關這些限制的核心資訊。

RLIMITs (ulimit)

這些限制是按程序設置的,並由子程序繼承(因此通常它們在程序樹中是相同的,但不一定。)

systemd 允許為每個服務設置這些限制,以便在服務啟動時將限制設置為配置。

這些是由您在問題中已經提到的指令配置的,例如LimitSTACK=,等。您可以在 systemd 的手冊頁中查看LimitAS=RLIMIT 的完整列表,其中還將這些列表與熟悉的命令相關聯。ulimit

您可以使用命令檢查正在執行的單元的目前限制,該systemctl show命令從 systemd 轉儲單元的內部狀態。

例如:

$ systemctl show postgresql.service | grep ^Limit
LimitSTACK=16384
LimitSTACKSoft=16384
LimitAS=12884901888
LimitASSoft=12884901888
... (other RLIMITs omitted for terseness) ...

您還可以通過查看來檢查核心認為的限制是什麼/proc/$pid/limits(請記住,這些是每個程序的,因此您需要查看各個 PID。)

例如:

$ cat /proc/12345/limits 
Limit                     Soft Limit           Hard Limit           Units     
Max stack size            16384                16384                bytes     
Max address space         12884901888          12884901888          bytes     
... (other RLIMITs omitted for terseness) ...

cgroups(記憶體 cgroup)

最後,cgroups 是 systemd 管理服務、提供限制和記帳的主要機制。

systemd 有許多可用和支持的 cgroup(如 CPU、記憶體、IO、任務等),但在本次討論中,讓我們關注記憶體 cgroup(因為這些是您的問題中涉及的限制,我們查看了SysV IPC 和 RLIMIT 也有相應的記憶體限制。)

與 RLIMIT 一樣,您也可以systemctl show使用 cgroups 查看 systemd 提供的記憶體記帳:

$ systemctl show postgresql.service | grep ^Memory
MemoryCurrent=631328768
MemoryAccounting=yes
MemoryLow=0
MemoryHigh=infinity
MemoryMax=infinity
MemorySwapMax=infinity
MemoryLimit=infinity
MemoryDenyWriteExecute=yes

您會看到啟用了記憶體記帳 ( MemoryAccounting=yes) 但沒有設置任何限制(全部設置為inifinity。)限制列表可能會因您的 systemd 和核心版本而異,這是核心 4.20-rc0 上的 systemd 239,具有“低”、“高”、“最大”、“限制”和專門用於交換的單獨限制。

MemoryCurrent=您可能會發現有趣的另一點是,您將能夠通過該值來判斷該服務正在使用多少記憶體。這是從核心 cgroup 資訊中獲取的,它是該服務對記憶體使用情況的新測量。

當您systemctl status在服務上使用時,您還可以看到該資訊:

$ systemctl status postgresql.service
● postgresql.service - PostgreSQL database server
  Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor preset: disabled)
Main PID: 12345 (postgresql)
   Tasks: 10 (limit: 4321)
  Memory: 602M
  CGroup: /system.slice/postgresql.service
          └─12345 /usr/lib/postgresql/postgresql

如您所見,systemd 正在報告記憶體使用情況 ( Memory: 602M),它來自 cgroup 資訊。您還可以看到啟用了任務記帳(通過相應的 cgroup),並且它報告目前正在使用 10 個任務,而該服務的最大任務數為 4321。

狀態輸出還包括有關底層 cgroup 的資訊,以服務命名(每個服務都在其自己的 cgroup 中執行),然後您可以使用這些資訊直接從核心檢查 cgroup 限制和記帳資訊。

例如:

$ cd /sys/fs/cgroup/memory/system.slice/postgresql.service/
$ cat memory.limit_in_bytes 
9223372036854771712
$ cat memory.usage_in_bytes 
631328768

(數字 9223372036854771712 是2^63 - 4096,在這種情況下表示infinity在 64 位計數器內。)

您可以查看記憶體 cgroup 的核心文件以獲取有關這些限制和計數器的更多詳細資訊。核心中有兩個版本的 cgroup(cgroup-v1 和 cgroup-v2),因此如果使用 cgroup-v2 代替,您可能會發現系統中存在一些顯著差異。systemd 支持兩者(以及同時使用兩者的混合模型),因此systemctl無論核心上啟用了哪個版本的 cgroup,使用查詢限制和計數器都應該為您提供一致的視圖。

引用自:https://unix.stackexchange.com/questions/480574