채용공고 요구사항 6개 중 자신 있게 답할 수 있는 게 절반도 안 됐다
DevOps 채용공고를 기준으로 내 경험의 빈틈을 세어보고, 실무에서 만든 위성 MSA 플랫폼을 단순한 도메인으로 다시 처음부터 재현하며 채우기로 한 학습 로드맵. 목표 아키텍처부터 8개 시리즈 계획, 우선순위 규칙, ISMS-P 매핑표까지.
DevOps 엔지니어 채용공고 하나를 붙잡고 요구사항을 하나씩 짚어봤다. 여섯 가지였다.
- 온프레미스·클라우드 하이브리드 인프라 구축·운영
- CI/CD 파이프라인 설계·자동화
- Kubernetes 기반 컨테이너 플랫폼 운영
- IaC 구현
- 모니터링 체계 구축 및 장애 대응
- ISMS-P 인프라 영역 인증(심사) 대응
위성 변화탐지 플랫폼을 MSA로 쪼개고, RabbitMQ로 비동기 파이프라인을 만들고, Kubernetes 위에 Envoy Gateway·Keycloak·Cilium까지 올린 건 실무에서 이미 한 일이다. 다만 온프레미스 클러스터를 kubeadm으로 처음부터 세우는 것, IaC로 Day-0부터 전부 재현 가능하게 만드는 것, ISMS-P 심사 대응, 자체 인증 구현부터 게이트웨이 마이그레이션까지의 전체 과정 - 이 네 가지는 실무에서 다룬 방식과 결이 달라서 직접 채워보기로 했다.
시작하기 전에 - 인프라란 무엇인가
"인프라(Infrastructure)"는 앱 코드 자체가 아니라, 그 코드가 실제로 돌아가게 만드는 모든 것을 말한다. 앱이 "가게에서 파는 상품"이라면, 인프라는 그 가게가 서 있는 건물·전기·수도·물류망에 가깝다 - 상품(코드)이 아무리 좋아도 건물이 없으면 팔 수 없고, 전기가 끊기면 가게 문을 못 연다.
이 프로젝트에서 인프라는 크게 네 겹으로 쌓인다.
[서버/가상머신] ← 물리적으로 컴퓨터가 존재해야 한다 (온프레미스 VM, 클라우드 인스턴스)
↓
[Kubernetes 클러스터] ← 그 컴퓨터들을 하나의 자원 풀처럼 묶어서, 컨테이너를 어디서 실행할지 관리
↓
[서비스들] ← 클러스터 위에서 실제로 도는 컨테이너 (api-server, RabbitMQ, inference-worker...)
↓
[운영 도구] ← 서비스들을 배포(CI/CD)하고, 지켜보고(관측), 지키는(보안) 도구들
요청 하나가 처리되는 흐름도 아주 단순화하면 이렇다 - 이 로드맵의 모든 시리즈는 결국 이 한 줄짜리 흐름의 어느 한 단계를 다룬다.
사용자 요청
→ [게이트웨이] 누가 보낸 요청인지 확인하고 알맞은 서비스로 안내
→ [서비스] 요청을 받아 처리 (바로 끝나면 응답, 오래 걸리면 아래로)
→ [큐] "오래 걸리는 작업"을 일단 접수만 해두고 순서대로 처리
→ [워커] 큐에서 작업을 꺼내 실제로 처리 (AI 추론 등)
→ [DB] 결과를 저장
→ 사용자에게 응답 또는 조회 가능한 상태로 남김
이 흐름 자체는 몇 줄이면 그릴 수 있지만, "이 흐름이 24시간 안 죽고, 늘어나는 트래픽을 견디고, 배포 중에도 끊기지 않고, 침해당하지 않게" 만드는 일 전체가 인프라 엔지니어링이다. 아래 시리즈들은 전부 이 문장 하나를 실제로 만족시키기 위한 작업이라고 보면 된다.
목표: 위성 도메인 대신 단순 도메인으로, 처음부터 다시
간극을 메우는 방법으로 두 가지를 놓고 고민했다 - 이론 공부로 채우거나, 작게라도 직접 만들어보거나. 이론만으로는 "클러스터가 죽었을 때 실제로 뭐가 어떻게 망가지는지"를 알 수 없다는 게 문제였다. 그래서 실무에서 다뤘던 위성 변화탐지 MSA 아키텍처를 훨씬 단순한 도메인으로 축소해서 처음부터 다시 만들기로 했다.
위성 대신 단순한 흐름 하나만 남긴다 - "이미지 업로드 → 비동기 AI 추론(오래 걸리는 작업) → 결과 저장/조회".
[클라이언트]
↓
Envoy Gateway ─ Keycloak OIDC (SecurityPolicy, TLS, SealedSecret)
↓
┌─ api-server (FastAPI) ── CRUD · 작업 등록 · 헬스체크/메트릭 표준화
│ ↓ publish
├─ RabbitMQ ── ack/nack + DLQ (3회 실패 시 격리)
│ ↓ consume
├─ inference-worker (Python + ONNX 또는 더미 sleep 모델) ── 수 분짜리 작업 시뮬레이션
│ ↓
└─ PostgreSQL (CloudNativePG 오퍼레이터로 운영)
실무 프로젝트와 패턴은 같지만(게이트웨이 인증, 비동기 큐, ack/nack) 도메인은 가볍다 - 추론 모델도 처음엔 몇 분간 sleep하는 더미로 시작해서, 인프라와 파이프라인 자체가 먼저 제대로 도는지부터 검증한다.
실행 기반은 이렇게 잡았다.
| 영역 | 선택 |
|---|---|
| 클러스터 | 직접 구축한 온프레미스 K8s(kubeadm) + 클라우드 1개, 가능하면 하이브리드 연동 |
| 배포 | Jenkins(CI) + ArgoCD(GitOps, CD) |
| IaC | Terraform(클라우드) + Ansible(온프레미스 노드) |
| 관측 | Prometheus + Grafana + Alertmanager + Loki(로그 보존) |
| 인증 | 자체 JWT 구현 → 한계 체험 → Keycloak+게이트웨이로 마이그레이션 (순서 고정) |
인증 쪽은 순서를 일부러 고정했다. Keycloak을 바로 붙이면 "왜 이게 필요한지"를 체감하지 못한 채 정답만 베끼는 셈이 된다. 자체 JWT를 먼저 구현하고, alg:none 공격이나 폐기 불가 문제 같은 한계를 직접 겪은 다음에 Keycloak으로 넘어가는 순서를 지킨다.
우선순위 규칙: 코어 6개 + 확장 항목
시리즈가 8개까지 늘어나면서 전부 같은 무게로 취급하면 안 된다는 판단이 들었다. 그래서 코어와 확장을 나눴다.
- 코어 (시리즈 1~6): 채용공고 요구사항 6개와 1:1로 대응한다. 이 여섯 개를 끝내는 게 이 프로젝트의 최소 성공 기준이다.
- 확장: 코어를 실무 수준에 더 가깝게 만드는 항목들이다. 없어도 로드맵은 완결되지만, 있으면 실제 NIPA 프로젝트에서 쓴 것과 더 가까워진다.
| 구분 | 항목 | 위치 |
|---|---|---|
| 확장 | kube-vip 컨트롤플레인 HA | 시리즈 1 |
| 확장 | Calico → Cilium 마이그레이션 | 시리즈 1 |
| 필수 추가 | Harbor 사설 레지스트리 + Trivy 스캔 | 시리즈 2 |
| 확장 | CloudNativePG로 PostgreSQL 운영 | 시리즈 2 |
| 확장 | OpenTelemetry 분산 트레이싱 | 시리즈 4 |
| 확장 | SealedSecret → OpenBao + ESO 마이그레이션 | 시리즈 6 |
| 확장(시리즈 자체) | 폐쇄망(에어갭) 시뮬레이션 | 시리즈 8 |
Harbor+Trivy만 "필수 추가"로 분류했다 - CI가 이미지를 어딘가에 푸시해야 하는데, 사설 레지스트리 없이는 시리즈 2 자체가 완결되지 않기 때문이다. 나머지는 전부 순수 확장이다.
진행 규칙: 코어가 끝나기 전에 확장 항목에 먼저 손을 대는 것 자체는 막지 않는다. 다만 그 시점에 "코어 6개 중 몇 개가 아직 안 끝났는지"를 짚어주기로 한다 - 막지는 않되, 지금 뭘 미루고 있는지는 스스로 알고 있어야 한다는 뜻이다.
시간이 부족할 때 줄이는 순서
전부 다 할 시간이 없다면 아래 순서대로 줄인다 - 뒤쪽일수록 먼저 포기해도 코어 요구사항 대응에 지장이 적다.
- 확장 항목(kube-vip·Cilium·OpenBao·OpenTelemetry) 보류
- 시리즈 8(폐쇄망 시뮬레이션) 생략
- 시리즈 7(AI 워크로드) 생략
- 시리즈 3(IaC)을 Terraform 또는 Ansible 한쪽으로 축소
- 시리즈 1의 클라우드 하이브리드 연동 생략 (온프레미스 단독으로 유지)
계획: 8개 시리즈
각 단계의 완료 조건은 동일하다 - 동작 확인 + 블로그 글 1편 이상 + 진행 기록 갱신. 순서는 원칙적으로 아래를 따르되, 막히면 다음 단계를 먼저 진행해도 된다.
| 시리즈 | 구분 | 분량 | 핵심 내용 | 상태 |
|---|---|---|---|---|
| 1. 온프레미스 클러스터 맨땅 구축 | 코어 | 4~5편 | kubeadm 클러스터, CNI(Calico), MetalLB, 스토리지, 파괴 후 재구축 (+ 선택: kube-vip, Cilium) | 절차 정리됨 |
| 2. 서비스 골격 + CI/CD | 코어 | 3~4편 | api-server/inference-worker, RabbitMQ ack/nack+DLQ, Jenkins→ArgoCD 전환, Harbor+Trivy (+ 선택: CloudNativePG) | 절차 정리됨 |
| 3. IaC | 코어 | 2~3편 | Terraform(클라우드), Ansible(온프레미스), Day-0 재구축 검증 | 절차 정리됨 |
| 4. 관측과 장애 대응 | 코어 | 3~4편 | Prometheus/Grafana/Alertmanager/Loki, 장애 주입 3종, 포스트모템 (+ 선택: OpenTelemetry) | 절차 정리됨 |
| 5. 인증: 자체 JWT → Keycloak → ISMS-P | 코어 | 4편 (순서 고정) | JWT 취약점 체험, 검증 로직 분산의 고통, Keycloak+Envoy 마이그레이션, ISMS-P 관점 회고 | 절차 정리됨 |
| 6. ISMS-P 인프라 영역 심사 대응 시뮬레이션 | 코어 | 2~3편 | 인증기준 매핑표, 접근통제/암호화/로그 증적, 모의 심사 (+ 선택: OpenBao+ESO) | 절차 정리됨 |
| 7. AI 워크로드 | 확장 | - | 더미 워커 → 실제 ONNX 추론 교체, GPU 스케줄링 | 절차 정리됨 |
| 8. 폐쇄망(에어갭) 시뮬레이션 | 확장 | 2~3편 | Harbor/Nexus 미러, egress 차단, 미러만으로 배포 검증, Day-0 재구축(심화) | 절차 정리됨 |
"절차 정리됨"은 실제로 손으로 실행하고 검증하기 전, 각 시리즈에서 무엇을 어떤 순서·명령어로 만들지 정리해둔 상태를 뜻한다. 실제 구축·실험·수치는 아직 없다 - 이 로드맵을 따라 직접 진행한 뒤에 결과와 트러블슈팅을 별도로 기록한다.
시리즈 14는 "일단 만들고 굴려본다"에 가깝고, 시리즈 56이 이 로드맵에서 가장 공고 요구사항과 직접 맞닿아 있다 - 특히 6번은 지금까지 한 번도 해본 적 없는 영역이라 가장 기대되면서도 가장 막막하다.
원리 체크리스트
시리즈를 마쳤다고 표시하기 전에, 아래 각 항목을 남에게 설명할 수 있는지 스스로 확인한다. 명령어를 따라 쳐서 화면에 결과가 떴다는 것과, 왜 그렇게 동작하는지 아는 것은 다른 문제다.
| 시리즈 | 스스로 설명할 수 있어야 하는 것 |
|---|---|
| 1 | 컨트롤플레인과 워커의 역할 차이, CNI가 왜 필요한지(kube-proxy가 안 하는 일), MetalLB가 온프레미스에서 LoadBalancer를 흉내내는 원리 |
| 2 | 헬스체크 3종의 차이, 메시지 큐가 동기 호출보다 나은 지점과 대가, ack/nack이 "처리 완료"를 어떻게 보장하는지, CI가 CD와 왜 분리돼야 하는지 |
| 3 | 선언적(Terraform) vs 절차적(Ansible) 도구가 왜 나뉘는지, state 파일이 하는 역할, 멱등성이 없는 스크립트의 위험 |
| 4 | 메트릭·로그·트레이스가 서로 다른 질문에 답한다는 것, 알림 지연이 어디서 생기는지, 카오스 실험이 "장애를 만드는 것"이 아니라 "탐지 공백을 재는 것"이라는 것 |
| 5 | JWT가 왜 검증 없이는 위험한지(alg:none), 대칭키/비대칭키가 검증 주체 배포 문제에 미치는 영향, 게이트웨이 레벨 인증이 "신뢰 경계"를 어디로 옮기는지 |
| 6 | "인증(authentication)"과 "인증(certification)"이 이 문서에서 다른 뜻이라는 것, 구현과 증적이 왜 별개인지, NetworkPolicy의 default-deny가 왜 기본이어야 하는지 |
| 7 (확장) | ONNX가 프레임워크 종속성을 어떻게 없애는지, GPU 리소스가 CPU와 다르게 스케줄링되는 이유 |
| 8 (확장) | 이미지 pull 경로(클라이언트 → 레지스트리 → containerd), apt/pip 미러가 실제로 대체하는 것, egress 차단(방화벽)과 NetworkPolicy가 서로 다른 계층이라는 것 |
ISMS-P 매핑표 뼈대
시리즈 6을 위해 미리 뼈대만 잡아뒀다. 표의 항목 번호·명칭은 KISA 안내서 원문을 확인하며 정정할 것 - 지금은 뼈대일 뿐이다.
| 인증기준 영역 | 이 프로젝트에서의 구현 | 증적(심사원에게 보여줄 것) | 상태 |
|---|---|---|---|
| 2.5 인증 및 권한관리 | Keycloak (정책·MFA·RBAC) | Realm 정책 화면, 클라이언트별 Role | 미착수 |
| 2.6 접근통제 | Envoy SecurityPolicy, NetworkPolicy, (확장) egress 차단 정책 | HTTPRoute/Policy 정의, 통신 매트릭스, 폐쇄망 시뮬레이션 결과 | 미착수 |
| 2.7 암호화 적용 | TLS, SealedSecret, (확장) OpenBao+ESO | 인증서 체계, 시크릿 관리 흐름, 시크릿 접근 감사 로그 | 미착수 |
| 2.9 시스템·서비스 운영관리 | Loki 로그 보존, 백업 | 보존 정책 설정, 로그 접근 통제 | 미착수 |
| 2.10 시스템·서비스 보안관리 | Harbor+Trivy 이미지 스캔, 패치 이력 | CI 스캔 결과, 취약 이미지 배포 차단 정책, 업그레이드 기록 | 미착수 |
기록 원칙
이 프로젝트의 목적은 결과물이 아니라 배우는 것이다. 그래서 두 가지를 규칙으로 못박아둔다.
- 핵심 개념이 걸린 부분은 완성본부터 베끼지 않는다. JWT 검증 로직, ack/nack, NetworkPolicy, Terraform 리소스처럼 이해가 목적인 부분은 개념 → 뼈대 → 직접 채우기 → 리뷰 순서로 간다.
- 에러와 실패는 삭제하지 않고 기록한다. 클러스터를 부수고 다시 세우다 막힌 지점, kubeadm 트러블슈팅, 왜 장애 알림이 늦게 왔는지 - 이런 삽질이 결국 이 로드맵의 진짜 글감이다. 결과가 깔끔하게 나온 것보다, 막혔다가 뚫은 지점을 남기는 쪽이 이 시리즈의 기록 원칙에 더 가깝다.
지금은 각 시리즈에서 무엇을, 어떤 순서로, 어떤 명령어로 만들지까지만 정리해둔 상태다(위 표의 링크). 실제로 손을 움직여 클러스터를 세우고, 장애를 주입해보고, 막히는 지점을 기록하는 게 다음 단계다 - 그 결과는 이 로드맵과 별도로 진행 상황에 따라 채워나간다.