느린 웹 서비스, 명확한 메시지 없이 종료된 작업자 또는 스왑이 발생한 서버는 반드시 기계의 RAM을 모두 소진한 것은 아닙니다. systemd와 함께 유닛에 설정된 제한이 증상을 설명하는 데 충분할 수 있습니다.
cgroups는 리눅스 커널이 프로세스 그룹의 리소스를 집계하고 제한하며 우선 순위를 정할 수 있도록 합니다. 메모리를 추가하거나 무작위로 재시작하기 전에 영향을 받는 서비스에 대해 systemd가 적용하는 내용을 확인하세요.

서비스의 cgroup 보기
최근 배포판에서는 systemd가 각 서비스를 고유한 cgroup에 배치합니다. Nginx, PostgreSQL 또는 응용 프로그램 작업자와 같은 전통적인 유닛을 진단하기 위해 PID를 손으로 이동할 필요가 없습니다.
서비스 상태와 리소스 관련 속성을 읽는 것부터 시작하세요. nginx.service를 실제 유닛 이름으로 교체하십시오.
systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec
ControlGroup은 systemd에 의해 관리되는 경로를 제공합니다. MemoryCurrent는 읽을 때 유닛에 대해 집계된 메모리를 표시합니다. 만약 MemoryMax가 infinity라면, systemd가 이 서비스에 대해 하드 메모리 한계를 설정하지 않았음을 의미합니다.
PID에서 시작하는 경우 /proc에서 해당 cgroup을 다시 읽으세요. cgroup v2에서는 0::/system.slice/nginx.service와 같은 라인을 자주 볼 수 있습니다.
pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup
만약 MainPID가 0라면, 서비스에 활성화된 주요 프로세스가 없습니다. 빈 PID를 바탕으로 결론을 내리기보다는 systemctl status 및 journalctl로 돌아가세요.
메모리 및 CPU 한계 읽기
MemoryMax는 하드 한계입니다. 만약 cgroup이 이 상한에 도달하고 커널이 충분한 메모리를 회수하지 못하면, 그룹의 프로세스 중 하나가 OOM 킬러에 의해 종료될 수 있습니다.
MemoryHigh는 덜 가혹합니다. 커널은 할당을 제어하고 cgroup이 이 임계치를 초과할 때 메모리를 회수하려고 시도합니다. 서비스를 첫 번째 피크에서 중단시키지 않고 수용하기 위해, 이는 종종 MemoryMax보다 더 나은 첫 번째 설정입니다.
CPUQuota는 서비스에 제공되는 CPU 시간을 제한합니다. CPUQuota=25%는 논리적 코어의 1/4에 해당합니다. 다수의 코어가 있는 기계에서는 CPUQuota=200%가 최대 두 개의 CPU 시간 코어를 허용합니다.
systemctl show nginx.service
-p MemoryCurrent -p MemoryMax -p MemoryHigh
-p CPUUsageNSec -p CPUQuotaPerSecUSec
쿼터와 우선 순위를 혼동하지 마세요. 쿼터는 서비스가 CPU 양을 초과하지 못하게 방지합니다. 우선 순위는 nice나 CPUWeight로 처리되며, 주로 여러 작업이 동시에 CPU를 요구할 때 경쟁을 조정합니다.
한계의 원인 찾기
한계는 패키지에서 제공하는 파일, systemd의 드롭인 또는 로컬에서 생성된 오버라이드에서 올 수 있습니다. 서비스를 수정하기 전에 전체 구성을 읽어보십시오.
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
/etc/systemd/system/nginx.service.d/ 아래의 파일은 일반적으로 패키지에서 제공하는 유닛보다 우선합니다. /usr/lib/systemd/system/ 또는 /lib/systemd/system/의 파일을 직접 수정하는 것은 피하십시오, 왜냐하면 업데이트로 인해 덮어씌워질 수 있기 때문입니다.
그런 다음 증상을 확인하세요. 느린 서비스는 또한 느린 SQL 요청, 포화된 디스크, 가득 찬 대기열 또는 응용 프로그램 오류로 인해 발생할 수 있습니다.
journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'
한계가 infinity로 남아 있고 커널 저널에 메모리 이벤트가 나타나지 않으면 cgroups를 건드리기 전에 다른 곳을 찾아보십시오: 응용 프로그램 로그, 디스크 메트릭, 네트워크 지연 또는 프로세스의 실제 소비.
서비스에 손대지 않고 테스트하기
구문을 검증하거나 한계의 효과를 측정하기 위해 systemd-run을 사용하여 임시 유닛을 시작하세요. 테스트는 Nginx, PostgreSQL 또는 귀하의 비즈니스 서비스를 수정하지 않습니다.
sudo systemd-run --unit=essai-limite-memoire
--property=MemoryMax=256M
--property=CPUQuota=25%
/usr/bin/bash -c 'sleep 300'
그런 다음 적용된 속성을 다시 읽으세요. CPUQuota=25%에서 systemd는 초당 250ms에 해당하는 값을 보여줄 수 있습니다.
systemctl show essai-limite-memoire.service
-p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat essai-limite-memoire.service
테스트 유닛을 완료하면 즉시 중지하십시오. sleep로 인해 잊는 것은 큰 문제가 아니지만, 이 반응은 실제 명령이 실행되어 예상치 못한 상황을 피하는 데 도움이 됩니다.
sudo systemctl stop essai-limite-memoire.service
systemd 오버라이드 적용하기
로그와 측정이 한계가 의미가 있다고 확인되면 systemd 오버라이드를 통해 진행하세요. 아래 예는 800MB의 높은 한계와 1GB의 하드 한계, CPU 코어에 상응하는 서비스 한계를 설정합니다.
sudo systemctl edit mon-service.service
필요한 지시문만 추가하세요. 정상적인 소비와 피크를 관찰한 후 해당 값을 프로덕션 서비스에 복사하지 마십시오.
[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%
systemd를 다시 로드한 후 서비스 중단이 허용 가능한 경우에만 서비스를 다시 시작하십시오. 원격에서 중요한 구성 요소를 수정할 때는 SSH 세션을 하나 더 열어 두세요.
sudo systemctl daemon-reload
sudo systemctl restart mon-service.service
systemctl status mon-service.service --no-pager
systemctl show mon-service.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
만약 서비스가 더 이상 시작되지 않거나 너무 느려지면 주의 깊게 오버라이드를 제거하세요. sudo systemctl revert mon-service.service는 유닛의 로컬 오버라이드를 삭제합니다. 동일한 디렉터리에 유지할 다른 설정이 있는 경우에는 사용하지 마십시오.
변경 후 점검
systemctl is-active mon-service.service로 상태를 확인하십시오.- 재시작 후
MemoryCurrent,MemoryHigh,MemoryMax및CPUQuotaPerSecUSec를 다시 읽으세요. - 문제가 있었던 부하 피크 동안
journalctl -u mon-service.service -b및 커널 저널을 모니터링하십시오. - 응용 프로그램 측에서의 효과를 측정하세요: 응답 시간, 지연 작업, 대기열, 사용자 오류.
- 조정 이유, 날짜, 유지된 값 및 수정된 증상을 운영 절차에 기록하세요.
cgroups는 기계의 나머지를 보호하고 한계를 가시화합니다. 메모리 누수, 비용이 많이 드는 요청 또는 잘못 설정된 작업자를 수정하지는 않습니다. 한계에 도달하면 로그, 관찰된 부하 및 설정된 값을 사용하여 한계를 조정할지 응용 프로그램을 수정할지를 선택하세요.
더 알아보려면 systemd.resource-control(5) 페이지를 참조하세요. 리눅스에서의 Nice 가이드는 엄격한 한계가 적합하지 않을 때 CPU 우선 순위를 선택하는 데 도움을 줍니다.