Systemd 종속성 이해: 유닛 충돌 방지 및 해결

안정적인 서비스 시작을 보장하고 부팅 실패를 방지하기 위해 systemd 종속성 관리를 마스터하세요. 이 가이드는 필수적인 종속성 지시문(`Requires=`, `After=`, `Wants=`)을 자세히 설명하고, 순서 문제 진단을 위한 `systemctl list-dependencies`와 같은 실용적인 명령어를 제공하며, Linux 시스템 서비스에서 일반적인 유닛 충돌을 해결하기 위한 실행 가능한 단계를 제시합니다.

33 조회수

Systemd 종속성 이해: 단위 충돌 방지 및 해결

Systemd는 대부분의 주요 Linux 배포판에서 사용되는 최신 시스템 및 서비스 관리자입니다. 강력한 설계는 서비스, 마운트, 소켓 및 기타 시스템 구성 요소를 정의하기 위해 단위 파일에 크게 의존합니다. 이러한 구성 요소를 관리하는 중요한 측면은 종속성 해석입니다. 종속성이 잘못 구성되면 서비스가 시작되지 않거나, 잘못된 순서로 시작되거나, 서로 충돌하여 서비스 불안정 또는 부팅 실패를 초래할 수 있습니다.

이 가이드는 systemd의 종속성 메커니즘을 깊이 탐구합니다. 서비스 관계를 설정하는 데 사용되는 핵심 지시문, 종속성 관련 시작 문제 진단 기술, 일반적인 단위 충돌을 해결하여 안정적이고 예측 가능한 시스템 부팅 시퀀스를 보장하는 실용적인 방법을 살펴보겠습니다.

기반: Systemd 단위 종속성 지시문

Systemd는 단위 파일(일반적으로 /etc/systemd/system/ 또는 /lib/systemd/system/에 위치) 내의 특정 지시문을 사용하여 한 단위가 다른 단위보다 언제 시작, 중지 또는 대기해야 하는지를 지시합니다. 이러한 지시문을 이해하는 것이 종속성을 올바르게 관리하는 첫 번째 단계입니다.

핵심 순서 지정 지시문

이러한 지시문은 다른 단위와 관련하여 단위가 처리되는 순서를 제어합니다.

  • Requires=:
    • 강력한 종속성을 설정합니다. 요구되는 단위가 시작되지 않으면 현재 단위도 실패합니다.
    • PartOf=를 암묵적으로 의미합니다.
  • Wants=:
    • 약한 종속성입니다. 원하는 단위가 실패하더라도 현재 단위는 계속 시작을 시도합니다. 이는 선택적 종속성에 사용됩니다.
  • BindsTo=:
    • Requires=와 유사하지만 중지 측면에서 더 강력합니다. 바인딩된 단위가 (어떤 이유로든) 중지되면 현재 단위도 중지됩니다.
  • PartOf=:
    • 현재 단위가 다른 단위의 하위 부분임을 나타냅니다(예: 기본 서비스와 관련된 특정 소켓 활성화). 상위 단위가 중지되면 하위 단위도 중지됩니다.

핵심 시작 동기화 지시문

이러한 지시문은 요구되는 단위에 상대적으로 종속 단위가 언제 시작되어야 하는지를 지시합니다.

  • After=:
    • 현재 단위는 나열된 단위가 성공적으로 시작된 후(또는 지정된 상태, 일반적으로 active에 도달한 후)에만 시작되어야 함을 지정합니다.
  • Before=:
    • 현재 단위는 나열된 단위보다 먼저 시작되어야 함을 지정합니다.

모범 사례: 일반적인 서비스 시작 순서의 경우, Wants=After=의 조합이 가장 일반적이고 안전한 패턴입니다. Requires=는 종속성의 실패가 종속된 서비스의 실패를 반드시 유발해야 하는 종속성에 대해서만 예약되어야 합니다.

예시: 서비스 파일에 종속성 정의

PostgreSQL(postgresql.service)이 관리하는 데이터베이스와 통신해야 하는 사용자 지정 애플리케이션 서비스인 myapp.service를 고려해 보겠습니다.

# /etc/systemd/system/myapp.service
[Unit]
Description=My Custom Application

# me를 시작하기 전에 PostgreSQL이 실행 중인지 확인
Requires=postgresql.service
After=postgresql.service

[Service]
ExecStart=/usr/bin/myapp

[Install]
WantedBy=multi-user.target

종속성 문제 진단

서비스가 시작되지 않으면 systemd는 일반적으로 로그에 충분한 정보를 제공하지만, 종속성 체인이 근본 원인을 가릴 수 있습니다. 다음은 문제 해결을 위한 필수 도구 및 명령입니다.

1. 단위 상태 및 로그 확인

근본적인 시작 지점은 서비스 상태를 확인하고 실패한 시작 시도 직후 해당 로그를 검토하는 것입니다.

# 종속성 실패를 자주 언급하는 전반적인 상태 확인
systemctl status myapp.service

# 단위와 관련된 자세한 로그 보기
journalctl -u myapp.service --since "5 minutes ago"

2. 종속성 트리 분석

Systemd는 무엇이 무엇을 기다리고 있는지 정확히 확인하기 위한 강력한 시각화 도구를 제공합니다.

systemctl list-dependencies

이 명령은 지정된 단위를 통해 전체 종속성 체인을 탐색하며, 해당 단위에 의해 요구되거나 원하는 단위를 보여줍니다.

myapp.service가 시작하기 위해 필요한 것을 보려면 다음을 수행하십시오.

# 순방향 종속성 (나보다 먼저 시작해야 하는 것)
systemctl list-dependencies --after myapp.service

# 역방향 종속성 (나에게 의존하는 것)
systemctl list-dependencies --before myapp.service

systemctl graphical-view (사용 가능/구성된 경우)

종종 시각화 그래프(예: SVG 또는 DOT 형식 출력)에 사용되지만, 구조를 이해하면 순환 종속성을 추적하는 데 도움이 됩니다.

3. 충돌 및 순서 지정 문제 감지

종속성 충돌은 서비스가 너무 일찍 시작되거나 예기치 않게 중지되어 실패하는 방식으로 자주 나타납니다.

순환 종속성: 이는 단위 A가 B를 요구하고 단위 B가 A를 요구하는 가장 위험한 충돌입니다. Systemd는 이를 해결하려고 시도하지만 종종 하나 또는 두 단위 모두가 무기한 failed 또는 activating 상태로 유지됩니다.

시스템 전체에 걸친 잠재적인 문제를 찾으려면 순서 지정과 관련된 특정 실패 메시지에 대해 로그를 검색할 수 있습니다.

journalctl -b | grep -E "failed|refused to start|dependency was not satisfied"

일반적인 종속성 문제 해결

문제가 식별되면 관련 단위 파일의 지시문을 조정하여 종속성 문제를 해결할 수 있습니다.

시나리오 1: 서비스가 필수 조건이 준비되기 전에 시작됨

증상: 애플리케이션 로그에 데이터베이스 연결 오류가 표시되지만 systemctl status에서 postgresql.serviceactive로 표시됩니다.

진단: 서비스가 After=를 사용하고 있지만 충분히 강력한 순서 지정 메커니즘이 없거나, 필수 서비스가 초기화 시퀀스 시작을 완료했지만 소켓/포트가 아직 수신 대기 중이 아닐 수 있습니다.

해결 방법: 서비스가 네트워크 소켓이나 장치가 완전히 사용 가능하도록 의존하는 경우 소켓 기반 활성화를 사용하거나, 그것이 불가능한 경우 Requires=After=를 사용하고 있는지 확인하거나, 사용 가능한 경우 필수 서비스가 'active'로 보고된 후 특정 조건을 확인하십시오.

시나리오 2: 시작/중지 순서 충돌

증상: 시스템을 중지할 때 중요한 프로세스가 멈추거나 갑자기 실패합니다.

진단: 이는 종종 BindsTo=의 오용이나 형제 서비스에서 Before=After= 지시문 간의 복잡한 상호 작용을 나타냅니다.

해결 방법: 형제 서비스(예: 동일한 대상으로 시작되는 서비스)인 서비스를 검토합니다. 서비스 A가 서비스 B가 실행되는 동안 실행되어야 하는 경우 BindsTo= 또는 Requires=를 사용하고 있는지 확인합니다. 서비스 A가 정리 작업을 시작하기 전에 작업을 완료해야 하는 경우 After= 순서가 올바른지 확인합니다.

시나리오 3: 불필요한 종속성 제거

증상: 불필요한 서비스가 시작 체인으로 끌어와져 시스템 부팅이 느려집니다.

진단: 선택적 연결만 필요했을 때 Requires=를 사용했을 수 있습니다.

해결 방법: Requires=Wants=로 변경합니다. 서비스가 기능하는 데 종속성이 절대적으로 필요하지 않은 경우 Wants=를 사용하면 종속성이 실패하거나 마스크되어도 시스템이 계속 진행될 수 있습니다.

# 이전 (너무 엄격함)
Requires=optional_logging.service

# 이후 (더 나음)
Wants=optional_logging.service
After=optional_logging.service

변경 사항 적용 및 다시 로드

단위 파일을 수정할 때마다 변경 사항을 테스트하기 전에 systemd에 구성을 다시 로드하도록 지시해야 합니다.

# 1. systemd 관리자 구성 다시 로드
sudo systemctl daemon-reload

# 2. 영향을 받는 서비스 다시 시작
sudo systemctl restart myapp.service

# 3. 상태 확인
systemctl status myapp.service

요약 및 다음 단계

Systemd 종속성 관리는 안정적인 서비스 오케스트레이션의 기반입니다. Requires/Wants(포함용)와 After/Before(순서 지정용)의 상호 작용을 숙달함으로써 관리자는 부팅 프로세스를 정확하게 제어할 수 있습니다. 문제 해결 시에는 항상 systemctl status로 시작하고 systemctl list-dependencies를 사용하여 실패를 유발하는 체인을 시각화하십시오. 일관되고 잘 정의된 단위 파일은 예측 가능한 시스템 동작으로 이어져 부팅 또는 런타임 중 예기치 않은 서비스 중단을 최소화합니다.