LabHub

RHEL 계열 관리 · 서비스 유닛 파일 작성 · 실습

systemd 유닛 파일 작성

LabHub 에서 이어서 보기

목표

systemd 유닛 파일을 처음부터 작성하고, 타이머 쌍을 만들고, 유닛 검증 스크립트를 직접 만듭니다.

왜 중요한가

유닛 파일에서 가장 중요한 한 줄은 Type= 입니다. Type=simple 인데 프로세스가 데몬화하면 systemd 는 부모가 죽는 것을 서비스 종료로 보고 실패 처리합니다. 반대로 Type=forking 인데 포그라운드로 돌면 systemd 가 영원히 기다리다 타임아웃으로 죽입니다 — "시작이 30초 멈추다 실패한다" 의 전형적인 원인입니다.

그리고 [Install] 섹션이 없으면 systemctl enable 이 아무것도 하지 않아 부팅 시 자동 시작이 안 됩니다. 이건 재부팅 전까지 아무도 모릅니다.

이 실습은 AlmaLinux 9 가상머신에서 돕니다. systemd 가 PID 1 로 실제로 돌기 때문에, 유닛 파일을 쓴 다음 systemctl enable --now 로 곧바로 띄워 볼 수 있습니다. 파일 한 줄이 어떤 동작으로 이어지는지를 눈으로 확인하면서 배웁니다.\n\n예전에는 파드에서 돌아 systemctl 자체가 없었고, 작성과 검증까지가 전부였습니다. 처음 뜨는 데 30초쯤 걸립니다.

단계

1. /etc/systemd/system/labhub-api.service 를 만들고 [Unit], [Service], [Install] 세 섹션을 넣으세요. /root/unit 작업 디렉터리도 만드세요.
2. [Unit]Description, Documentation, After=network-online.target, Wants=network-online.target 네 줄을 넣으세요.
3. [Service]Type=notify, ExecStart=/usr/local/bin/labhub-api --config /etc/labhub/api.yaml, User=labhub, Group=labhub, WorkingDirectory=/opt/labhub 를 넣으세요. ExecStart 는 절대 경로여야 합니다.\n\n 실습 프로그램이 셸 스크립트이므로 NotifyAccess=all 도 함께 넣습니다. 기본값 mainMainPID 가 보낸 알림만 받는데, systemd-notify 는 스크립트의 자식이라 PID 가 다릅니다. 그러면 systemd 가 준비 신호를 못 받고 기다리다 Job for labhub-api.service failed because a timeout was exceeded 로 끝납니다 — 유닛 파일에는 아무 문제가 없어 보입니다.
4. 재시작 정책을 추가하세요. [Service]Restart=on-failureRestartSec=5 를, [Unit] StartLimitIntervalSec=300StartLimitBurst=5 를 넣습니다. 이 둘은 systemd 230 에서 [Service] 에서 [Unit] 로 옮겨 갔습니다 — [Service] 에 적으면 Unknown key name 만 남기고 조용히 무시되어 속도 제한이 걸리지 않습니다.
5. 보안 지시자를 추가하세요. NoNewPrivileges=true, ProtectSystem=strict, ProtectHome=true, PrivateTmp=true, ReadWritePaths=/var/lib/labhub /var/log/labhub
6. [Install]WantedBy=multi-user.target 을 넣고, systemctl enable 이 만들 심링크를 직접 만드세요. 경로는 /etc/systemd/system/multi-user.target.wants/labhub-api.service 이고 원본 유닛을 가리켜야 합니다.
7. 타이머 쌍을 만드세요. /etc/systemd/system/labhub-backup.service(Type=oneshot, ExecStart 절대 경로)와 /etc/systemd/system/labhub-backup.timer([Timer]OnCalendar=*-*-* 02:30:00, Persistent=true, Unit=labhub-backup.service, [Install]WantedBy=timers.target).
8. /root/unit/lint.sh 를 작성하세요. 첫 번째 인자로 유닛 파일 경로를 받아 다음 세 규칙을 검사하고, 위반이 없으면 종료 코드 0, 있으면 0 이 아닌 값으로 끝나야 합니다.

참고

단계 8개

  1. 세 섹션 골격
  2. [Unit] 섹션 채우기
  3. [Service] 실행 설정
  4. 재시작 정책
  5. 보안 강화
  6. [Install] 과 enable 결과
  7. 타이머 쌍 작성
  8. 유닛 검증 스크립트