SMALL

IT/컨테이너 8

containerd NRI, 사실 내부적으로는 이렇게 돌아간다

containerd 2.0이 나오면서 NRI(Node Resource Interface)가 기본 enable 상태가 됐다. 그동안 "kubelet의 device plugin이나 CDI랑 뭐가 다르냐"는 질문을 꽤 많이 받았는데, 막상 코드를 따라가 보면 NRI는 컨테이너 라이프사이클 hook을 user-space 프로세스로 빼낸 RPC 인터페이스에 가깝다. CPU pinning, NUMA-aware allocation, GPU annotation 같은 걸 runtime을 건드리지 않고 끼워넣을 수 있는 곳. 우리 팀에서도 최근 AI 워크로드 노드에 NRI 기반 토폴로지 플러그인을 깔면서 처음으로 코드를 깊이 봤다. 이 글에서는 NRI가 어디서 호출되고, 플러그인이 어떻게 컨테이너 스펙을 조작하며, 왜 s..

IT/컨테이너 2026.06.11

BuildKit cache mount 제대로 쓰는 법 — Rust/Node CI 빌드 시간을 절반으로

CI에서 컨테이너 빌드가 매번 5분 넘게 걸리면 슬슬 화가 난다. 우리 팀에서도 Rust 서비스 하나 빌드하는 데 평균 5분 40초가 찍히길래, 며칠 시간 내서 BuildKit cache mount를 제대로 정리했다. 결과는 36초. 그래서 오늘은 이 과정을 정리해두려고 한다.이 글은 BuildKit cache mount 자체의 동작 원리부터, CI 환경(특히 GitHub Actions처럼 runner가 ephemeral한 환경)에서 캐시를 살려두는 패턴까지 다룬다. Dockerfile 잘 쓰는 법은 인터넷에 널려 있지만, “CI에서 cache mount가 왜 안 살아남는지”를 한 번에 정리한 글이 의외로 잘 없어서 한번 써본다.cache mount는 layer cache와 뭐가 다른가일반적인 Docke..

IT/컨테이너 2026.06.08

cgroup v2 전환 후 OOMKill 동작이 바뀐 이유

cgroup v2 전환 후 OOMKill 동작이 바뀐 이유올해 초 우리 팀 클러스터를 EKS 1.28에서 1.30으로 올리면서 cgroup v2 노드 비율이 100%가 됐다. 그 직후부터 묘하게 신경 쓰이는 현상이 생겼다. 예전 같으면 사이드카 하나만 OOM으로 죽고 메인 컨테이너는 살아 있던 케이스가, 이제는 컨테이너 안의 모든 프로세스가 한꺼번에 같이 죽고 있었다. 처음에는 "그래, 이게 더 깔끔하긴 한데" 정도로 넘겼는데, 일부 멀티 프로세스 워크로드가 갑자기 불안정해지는 걸 보고 한참을 파봤다. 결론부터 말하면 이건 버그가 아니라 의도된 변경이고, 알고 쓰면 오히려 운영이 단순해진다. 다만 모르고 쓰면 황당한 장애를 만난다.이 글은 그 동작이 왜, 어디서, 어떻게 바뀌었는지를 cgroup, kub..

IT/컨테이너 2026.06.04

Spegel로 in-cluster 이미지 미러 만들기

ECR pull rate limit에 한 번이라도 당해봤다면, 이 글이 도움이 될 거다. Spegel은 클러스터 안에서 노드끼리 이미지를 공유하게 해주는 stateless P2P OCI registry mirror다. 어느 노드 하나가 이미지를 받아두면, 같은 클러스터의 다른 노드들은 그 노드에서 끌어다 쓴다. 외부 레지스트리 호출이 확 줄어든다.최근 3월에 CoreWeave가 자기네 매니지드 쿠버네티스(CKS)에서 Spegel 튜토리얼을 공식 문서로 내놓을 정도로 P2P 이미지 분배는 더 이상 실험 단계가 아니다. K3s, RKE2는 아예 임베디드로 들어가 있고, AKS/EKS에서도 Helm으로 깔아서 잘 굴러간다. 우리 팀에서도 노드 80대 EKS 클러스터에 두 달째 돌리고 있는데, 한번 정리해두면 ..

IT/컨테이너 2026.05.27

Kaniko가 archived된 뒤, 우리는 어떻게 컨테이너 빌드 도구를 골랐나

작년쯤만 해도 우리 팀 CI 파이프라인의 절반은 Kaniko로 굴러갔다. EKS 안에서 in-cluster 빌드를 돌리는 게 너무 깔끔했기 때문에. 근데 2025년 6월 3일에 GoogleContainerTools/kaniko 리포가 read-only로 archived 돼 버렸다. 그 다음 주에 사내 보안팀에서 "유지보수 안 되는 OSS는 점진적으로 걷어내자"는 공지가 떴고, 우리도 슬슬 다른 길을 찾기 시작했다.이 글은 그 과정에서 Buildx, Kaniko(Chainguard fork 포함), ko 세 가지를 다 돌려보고 결정한 이야기다. "이게 정답이다" 같은 결론은 없다. 워크로드에 따라 답이 갈렸다.우리가 쓰던 환경먼저 맥락을 좀 깔자. 우리 팀 빌드 워크로드는 대략 60개의 서비스 이미지인데,..

IT/컨테이너 2026.05.24

containerd image pull 흐름 — snapshotter와 unpack 단계 파헤치기

kubectl describe pod에서 Pulling image "..."가 한참 머물러 있을 때, 그 안에서 무슨 일이 벌어지고 있는지 정확히 설명할 수 있는 사람이 의외로 적다. 나도 그랬다. "registry에서 layer 받아서 디스크에 풀고 mount한다" 정도가 내가 가진 모델의 전부였다. 근데 작년 말부터 ARC runner들이 콜드 스타트에서 한참 깔리는 문제를 디버깅하면서, 이 흐름을 좀 진지하게 들여다봐야겠다는 생각이 들었다. fetch가 느린 건지, unpack이 느린 건지, snapshotter가 느린 건지 분리해서 보지 못하면 튜닝 포인트가 없다.이 글은 containerd 2.x 기준으로 image pull 한 번이 어떤 단계를 거치는지, 각 단계에서 무엇을 디스크에 쓰는지, ..

IT/컨테이너 2026.05.08

Alpine 베이스 이미지를 Wolfi로 갈아치우면서 삽질한 이야기

지난 한 달 반 동안 우리 팀 컨테이너 이미지 베이스를 alpine에서 Wolfi로 거의 다 갈아치웠다. 처음엔 한 주 잡고 시작한 일이었는데, 막상 들어가보니 musl/glibc 차이부터 시작해서 빌드 캐시, CI 시간, 배포 호환성까지 줄줄이 엮여 있어서 결국 6주 가까이 걸렸다. 솔직히 시작할 때 알았으면 일정을 더 넉넉하게 잡았을 거다.이 글은 그 과정에서 마주친 문제들과 해결한 방법, 그리고 아직 풀지 못한 것들에 대한 기록이다.왜 옮겼나원래 우리는 거의 모든 서비스 베이스가 alpine:3.19 였다. 30MB도 안 되는 사이즈가 매력적이었고, 5년 가까이 큰 문제 없이 잘 써왔다. 근데 작년 4분기부터 보안팀이 들고 온 Trivy 리포트가 점점 두꺼워지기 시작했다. 특히 CVE 누적 속도가 ..

IT/컨테이너 2026.05.02

BuildKit cache mount, 이거 모르는 분 꽤 많더라

오늘 PR 리뷰하다가 Dockerfile에서 발견한 게 있어서 짧게 적어둔다. CI 빌드 시간 길다고 투덜대는 동료가 있는데, 정작 Dockerfile에는 RUN apt-get install -y ... 한 줄만 덩그러니 있더라. cache mount를 안 쓰고 있었다.이게 좀 의외였다. Docker 18.09에서 BuildKit 들어온 게 한참 됐고, cache mount도 새 기능이 아닌데, 의외로 실무에서 안 쓰는 사람이 많다. 한번 적용하면 빌드 시간이 절반 이하로 떨어지는 걸 자주 본다.그래서 뭐하는 건데RUN --mount=type=cache,target=... 한 줄을 RUN 명령에 붙이면, BuildKit이 그 디렉토리를 빌드 간에 영속화해준다. 캐시 레이어가 깨져서 RUN을 다시 돌려도,..

IT/컨테이너 2026.04.25
BIG