cgroup v1 경로 하드코딩 — v2에서 조용히 죽은 격리 로직
사용자가 환경을 만들 때마다 서버에서 컨테이너가 하나씩 뜹니다. 만들고 지우는 일이 하루 종일 도는 서버입니다.
보안 인증 요건 때문에 쓰던 곳(AWS)이 아닌 다른 클라우드에 이 환경을 새로 구축하면서 OS 를 Ubuntu 22.04 로, Docker 도 최신으로 올렸는데, 코드는 하나도 안 바꿨는데도 컨테이너 생성 요청이 몰릴 때 간헐적으로 실패하기 시작했습니다. 뜸할 땐 멀쩡하다가 동시에 여러 개가 들어오면 랜덤하게 깨집니다.
왜 갑자기 — cgroup v1에서 v2로
간헐 실패 자체는 동시성 레이스였지만, “왜 예전엔 없던 게 지금 생겼나” 가 진짜 질문이었습니다. 파고들다 보니, 오래전부터 있던 격리 로직 하나가 새 환경에서 조용히 죽어 있는 걸 발견했습니다.
이 서비스는 컨테이너를 만들 때마다 보조 프로세스를 하나씩 띄웁니다. 그리고 그
보조 프로세스를 자기(서비스) cgroup 밖으로 빼내는 코드가 있었습니다. 이유가
있습니다 — systemd 서비스는 기본이 KillMode=control-group 이라, 서비스가
재시작되면 그 cgroup 안의 자식 프로세스가 전부 같이 죽습니다. 보조
프로세스가 그 참사에 휩쓸리지 않게 미리 빼두려던 겁니다.
그런데 그 코드가 이런 경로를 하드코딩하고 있었습니다.
/sys/fs/cgroup/systemd/system.slice/<서비스>.service/cgroup.procs
/sys/fs/cgroup/systemd/... 는 cgroup v1 전용 경로입니다. 새로 올린 OS 는
cgroup v2(unified)라 이 경로가 아예 없습니다.
$ stat -fc %T /sys/fs/cgroup/
cgroup2fs ← 이 시스템은 순수 cgroup v2
$ ls /sys/fs/cgroup/systemd/
No such file or directory ← v1 호환 경로가 없음
그래서 이 함수는 파일 읽기에 실패하고 매번 조용히 빈 값으로 끝나고
있었습니다. 에러를 리턴·전파하지 않고 println 으로만 찍어서, 아무도 이게 죽어
있다는 걸 몰랐습니다.
조용한 no-op이 만든 증상
빼내기가 계속 실패했다는 건, 컨테이너를 만들 때마다 붙는 보조 프로세스가 전부 서비스 cgroup 안에 그대로 쌓여 왔다는 뜻입니다. 서비스가 한 번 재시작되면 그것들이 같이 죽고, 평소엔 프로세스가 늘어나며 동시 생성이 몰릴 때 문제가 터지는 타이밍 창을 넓혔습니다. 겉으로는 “가끔 컨테이너 생성이 실패한다” 로만 보였습니다.
해결 — cgroup 버전을 판별해서 분기
cgroup v1/v2 를 런타임에 판별해서 경로를 각각에 맞게 나눴습니다. 판별은
/sys/fs/cgroup/cgroup.controllers 파일 존재 여부로 합니다(v2 에만 있습니다).
func IsCgroupV2() bool {
_, err := os.Stat("/sys/fs/cgroup/cgroup.controllers")
return err == nil
}
// 읽는 경로도, "빼낼" 대상 경로도 v1/v2로 분기
path := "/sys/fs/cgroup/systemd/system.slice/<svc>.service/cgroup.procs"
if IsCgroupV2() {
path = "/sys/fs/cgroup/system.slice/<svc>.service/cgroup.procs"
}
cgroup v2 전환과 무시된 에러
코드가 하나도 안 바뀌어도, 실행 환경의 세대가 바뀌면 그 코드의 전제가 깨집니다. cgroup v1 경로를 하드코딩한 로직은 v2 로 넘어가는 순간 소리 없이 아무 일도 안 하게 됐습니다. OS 를 올릴 때 겉으로는 커널·패키지 버전만 바뀐 것 같지만, 그 밑에서 cgroup 이 v1 에서 v2 로 넘어가는 게 이런 코드에는 훨씬 큰 변화입니다.
무엇보다, 에러를 무시하면 이런 no-op 은 드러나지 않습니다. 파일 읽기가 실패했을 때 그냥 빈 값으로 넘어가고 로그만 남기면, 몇 달이 지나 “왜 요즘 간헐적으로 실패하지?” 하는 증상으로 뒤늦게 돌아옵니다. 조용히 넘어가도 되는 실패는 없습니다.
댓글 0