Docker & Kubernetes 면접 질문
Docker 및 Kubernetes 인터뷰는 애플리케이션을 컨테이너화하고 대규모로 오케스트레이션하는 능력을 테스트합니다. 이러한 질문은 DevOps, SRE 및 플랫폼 엔지니어링 역할에서 일반적으로 묻습니다. 이미지와 컨테이너와 같은 기본 개념부터 YAML 매니페스트 작성 및 클러스터 디버깅과 같은 실용적인 기술을 다룹니다. 개념 설명, 실습 작업 및 문제 해결 시나리오가 혼합되어 나옵니다.
Docker & Kubernetes 면접에서 다루는 내용
컨테이너 기본
Docker 아키텍처, 이미지, 컨테이너, 볼륨 및 네트워크에 대한 질문. Dockerfile 작성 및 멀티 스테이지 빌드 이해가 필요할 수 있습니다.
Kubernetes 아키텍처
컨트롤 플레인 구성 요소, 노드, 파드, 디플로이먼트, 서비스, 인그레스에 초점. 스케줄러, kubelet, API 서버에 대한 질문 예상.
네트워킹 및 스토리지
파드 네트워킹, 서비스 유형, 네트워크 정책, 퍼시스턴트 볼륨, 스토리지 클래스. 컨테이너가 클러스터 내부 및 외부에서 통신하는 방법 이해.
CI/CD 및 모니터링
Docker 및 Kubernetes를 CI/CD 파이프라인에 통합, Helm 사용, Prometheus로 모니터링, Fluentd 또는 유사 도구로 로깅에 대한 질문.
샘플 Docker & Kubernetes 면접 질문
- Docker 이미지와 컨테이너의 차이점은 무엇인가요?좋은 답변이 다루는 것
- Docker 이미지는 읽기 전용 템플릿으로, 애플리케이션과 의존성을 포함합니다.
- 컨테이너는 이미지를 실행한 인스턴스로, 읽기-쓰기 가능한 레이어가 추가됩니다.
- 이미지는 불변이며, 여러 컨테이너가 동일한 이미지를 공유할 수 있습니다.
- 이미지는 Dockerfile로 빌드되거나 레지스트리에서 가져오고, 컨테이너는 생성, 시작, 중지, 삭제가 가능합니다.
샘플 답변 보기
Docker 이미지는 애플리케이션과 그 실행에 필요한 모든 의존성(라이브러리, 환경 변수, 설정 파일 등)을 포함하는 읽기 전용 템플릿입니다. 이미지는 여러 레이어로 구성되어 있으며, 각 레이어는 Dockerfile의 명령어에 의해 생성됩니다. 반면, 컨테이너는 이미지를 기반으로 생성된 실행 가능한 인스턴스입니다. 컨테이너는 이미지의 읽기 전용 레이어 위에 읽기-쓰기 가능한 얇은 레이어(container layer)를 추가하여, 파일 시스템 변경을 추적합니다. 이미지는 불변이므로 수정할 수 없지만, 컨테이너는 상태를 가지며 시작, 중지, 삭제가 가능합니다. 하나의 이미지로 여러 컨테이너를 생성할 수 있으며, 각 컨테이너는 격리된 환경에서 실행됩니다. 따라서 이미지는 소스 코드의 '클래스'에, 컨테이너는 '인스턴스'에 비유할 수 있습니다.
- CrashLoopBackOff 상태에 빠진 파드를 어떻게 디버깅하겠습니까?좋은 답변이 다루는 것
- kubectl logs 명령어로 컨테이너 로그를 확인합니다.
- kubectl describe pod로 이벤트와 상태를 살펴봅니다.
- kubectl get events로 클러스터 레벨 이벤트를 확인합니다.
- 리소스 제한(CPU/메모리)이 원인인지 검토합니다.
- Liveness/Readiness 프로브 설정이 올바른지 확인합니다.
샘플 답변 보기
CrashLoopBackOff는 파드 내 컨테이너가 계속 충돌하여 재시작될 때 발생하는 상태입니다. 먼저 kubectl logs <pod-name> -c <container-name> 명령어로 컨테이너의 표준 출력 및 오류 로그를 확인하여 구체적인 오류 메시지를 찾습니다. 로그가 없거나 이전 크래시 로그를 보려면 --previous 플래그를 사용합니다. 다음으로 kubectl describe pod <pod-name>을 실행하여 파드의 상세 정보를 확인합니다. 여기서 'Last State'의 종료 코드와 이유, 그리고 'Events' 섹션에서 스케줄링, 이미지 풀, 컨테이너 시작 관련 이벤트를 분석합니다. 또한 kubectl get events --sort-by=.metadata.creationTimestamp로 최근 클러스터 이벤트를 확인합니다. 리소스 부족으로 인한 OOM(Out Of Memory) 종료인지 확인하기 위해 파드의 리소스 요청과 제한을 점검합니다. Liveness 또는 Readiness 프로브가 잘못 설정되어 컨테이너가 정상적으로 시작되기 전에 프로브가 실패하는 경우도 원인이 될 수 있으므로 프로브 설정을 검토합니다. 마지막으로 동일한 이미지를 로컬에서 직접 실행하여 이미지 자체의 문제인지 확인합니다.
- 포트 3000에서 실행되는 Node.js 애플리케이션을 위한 Dockerfile을 작성하세요.좋은 답변이 다루는 것
- FROM node:18-alpine으로 경량 베이스 이미지 선택
- WORKDIR /usr/src/app으로 작업 디렉토리 설정
- package.json 먼저 복사하여 레이어 캐싱 활용
- npm ci --only=production으로 프로덕션 의존성만 설치
- EXPOSE 3000으로 포트 문서화
- CMD ["node", "app.js"]로 애플리케이션 실행
샘플 답변 보기
위의 Dockerfile은 Node.js 애플리케이션을 컨테이너화하기 위한 표준적인 방법을 보여줍니다. 베이스 이미지로 node:18-alpine을 사용하여 이미지 크기를 최소화하고 보안을 강화했습니다. package.json과 package-lock.json을 먼저 복사하여 의존성 설치 단계에서 Docker 레이어 캐싱을 극대화합니다. npm ci 명령어는 package-lock.json을 기반으로 정확한 의존성을 설치하며, --only=production 옵션으로 devDependencies를 제외하여 프로덕션 이미지의 크기를 줄입니다. 소스 코드는 모든 파일을 복사하지만, .dockerignore 파일을 추가하여 node_modules와 같은 불필요한 파일을 제외하는 것이 좋습니다. EXPOSE 3000는 문서화 목적이며, 실제 포트 매핑은 컨테이너 실행 시 -p 옵션으로 지정합니다. CMD는 배열 형태로 작성하여 쉘을 거치지 않고 직접 실행하도록 합니다.
참고 코드dockerfile # Node.js 애플리케이션을 위한 Dockerfile # 공식 Node.js 18 알파인 이미지 사용 (경량) FROM node:18-alpine # 작업 디렉토리 설정 WORKDIR /usr/src/app # package.json과 package-lock.json을 먼저 복사하여 의존성 캐싱 활용 COPY package*.json ./ # 의존성 설치 (프로덕션 의존성만 설치하여 이미지 크기 최소화) RUN npm ci --only=production # 애플리케이션 소스 코드 복사 COPY . . # 애플리케이션이 사용할 포트 3000 노출 EXPOSE 3000 # 컨테이너 시작 시 실행할 명령어 CMD ["node", "app.js"] - Kubernetes 서비스가 어떻게 작동하며 로드 밸런싱을 어떻게 활성화하는지 설명하세요.좋은 답변이 다루는 것
- Kubernetes Service는 레이블 셀렉터를 사용하여 파드 그룹을 식별합니다.
- Service는 안정적인 ClusterIP와 DNS 이름을 제공합니다.
- kube-proxy는 iptables 또는 IPVS를 사용하여 트래픽을 파드로 전달합니다.
- 로드 밸런싱은 기본적으로 무작위 또는 라운드 로빈 방식으로 동작합니다.
- 서비스 타입(ClusterIP, NodePort, LoadBalancer)에 따라 외부 접근 방식이 달라집니다.
샘플 답변 보기
Kubernetes Service는 셀렉터와 일치하는 레이블을 가진 파드 집합에 대한 논리적 네트워크 엔드포인트를 제공합니다. Service는 클러스터 내부에서 고정된 IP 주소(ClusterIP)와 DNS 이름을 할당받아, 파드가 동적으로 변경되어도 안정적으로 접근할 수 있게 합니다. 트래픽은 kube-proxy에 의해 각 워커 노드에서 iptables 또는 IPVS 규칙으로 로드 밸런싱되어 파드로 전달됩니다. 기본적으로 kube-proxy는 무작위 또는 라운드 로빈 방식으로 패킷을 분산합니다. 서비스 타입에 따라 외부 접근이 가능합니다: ClusterIP는 클러스터 내부에서만 접근 가능, NodePort는 각 노드의 특정 포트로 서비스를 노출, LoadBalancer는 클라우드 제공자의 로드 밸런서를 생성하여 외부 트래픽을 받습니다. 로드 밸런싱 동작은 sessionAffinity 필드를 통해 클라이언트 IP 기반의 고정 세션을 설정할 수도 있습니다.
- 무중단 업데이트를 롤아웃하는 디플로이먼트를 생성하세요.좋은 답변이 다루는 것
- strategy.type을 RollingUpdate로 설정하여 무중단 업데이트 지원
- rollingUpdate.maxSurge와 maxUnavailable을 25%로 설정하여 롤링 업데이트 속도 조절
- readinessProbe를 설정하여 새 파드가 트래픽을 받을 준비가 되었는지 확인
- livenessProbe로 컨테이너가 정상 동작하는지 주기적으로 확인
- initialDelaySeconds로 프로브 시작 지연 시간 설정
샘플 답변 보기
위의 Deployment YAML은 무중단 업데이트를 위한 RollingUpdate 전략을 정의합니다. replicas는 3으로 설정되어 최소 3개의 파드가 실행됩니다. strategy.type: RollingUpdate는 새 파드를 하나씩 생성하고 이전 파드를 제거하여 다운타임 없이 업데이트를 진행합니다. maxSurge: 25%는 업데이트 중에 추가로 생성될 수 있는 파드의 최대 수 (25% of 3 = 약 1개)를 의미하며, maxUnavailable: 25%는 업데이트 중에 사용 불가능한 파드의 최대 수를 의미합니다. readinessProbe는 HTTP GET 요청을 /healthz 엔드포인트로 보내 파드가 트래픽을 처리할 준비가 되었는지 확인하며, 통과해야 Service의 엔드포인트에 포함됩니다. livenessProbe는 주기적으로 컨테이너의 상태를 확인하고, 실패 시 컨테이너를 재시작합니다. 이러한 프로브는 무중단 업데이트 중에도 새 파드가 정상적으로 서비스될 수 있도록 보장합니다.
참고 코드yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: my-app:latest ports: - containerPort: 8080 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 15 periodSeconds: 20 strategy: type: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 25% - Kubernetes에서 시크릿을 어떻게 관리하나요?좋은 답변이 다루는 것
- Secret 리소스를 사용하여 base64 인코딩된 데이터 저장
- 환경 변수 또는 볼륨 마운트를 통해 파드에 주입
- 외부 시크릿 관리 도구(SealedSecrets, External Secrets Operator, Vault) 활용
- etcd 암호화 및 RBAC를 통한 접근 제어
- 시크릿을 일반 텍스트로 버전 관리하지 않도록 주의
샘플 답변 보기
Kubernetes에서 시크릿은 Secret 오브젝트를 통해 관리됩니다. Secret은 민감한 데이터를 base64로 인코딩하여 저장하며, Opaque, tls, dockerconfigjson 등의 타입이 있습니다. 시크릿은 kubectl create secret generic 명령어나 YAML 파일로 생성할 수 있습니다. 파드에서는 env.valueFrom.secretKeyRef를 통해 환경 변수로 주입하거나, volumes.secret으로 볼륨에 마운트하여 사용합니다. 보안을 강화하기 위해 etcd 데이터 암호화(encryption at rest)를 활성화하고, RBAC를 설정하여 시크릿에 대한 접근을 최소 권한 원칙으로 제한해야 합니다. 또한 GitOps 워크플로에서는 SealedSecrets를 사용하여 시크릿을 암호화된 상태로 저장하거나, External Secrets Operator를 통해 AWS Secrets Manager나 GCP Secret Manager와 같은 외부 서비스에서 시크릿을 동기화할 수 있습니다. HashiCorp Vault와 같은 툴도 CSI 드라이버를 통해 시크릿을 동적으로 제공할 수 있습니다. 중요한 점은 시크릿을 평문으로 소스 코드 저장소에 커밋하지 말아야 한다는 것입니다.
- 파드의 생성부터 삭제까지의 생명 주기를 설명하세요.좋은 답변이 다루는 것
- 파드 생성 → Pending 상태에서 스케줄링 대기
- 스케줄링 완료 후 ContainerCreating → Running 상태
- 컨테이너 내부 상태: Waiting, Running, Terminated
- 파드 종료 시 graceful shutdown 후 Terminating → Succeeded/Failed
- CrashLoopBackOff는 반복적인 충돌 시 적용되는 백오프 상태
샘플 답변 보기
파드의 생명 주기는 크게 Pending, Running, Succeeded/Failed 세 가지 단계로 나뉩니다. 파드가 생성되면 먼저 Pending 상태가 되며, 이때 스케줄러가 적절한 노드를 선택할 때까지 대기합니다. 스케줄링이 완료되면 노드에서 컨테이너 이미지를 다운로드하고 시작하는 동안 ContainerCreating 상태를 거쳐 Running 상태로 전환됩니다. 각 컨테이너는 내부 상태를 가지며: Waiting (초기화 또는 대기), Running (실행 중), Terminated (종료)가 있습니다. 파드가 정상적으로 종료되면 컨테이너가 모두 종료되어 Succeeded 상태가 되고, 비정상 종료 시 Failed 상태가 됩니다. 파드 삭제 명령이 내려지면 Terminating 상태가 되며, preStop 훅과 terminationGracePeriodSeconds에 따라 정리 시간을 갖습니다. 만약 컨테이너가 계속 충돌하면 CrashLoopBackOff 상태로 진입하여 재시작 간격이 지수적으로 증가합니다.
- HorizontalPodAutoscaler를 사용하여 CPU 사용량에 따라 디플로이먼트를 어떻게 확장하겠습니까?좋은 답변이 다루는 것
- metrics-server가 클러스터에 설치되어 있어야 함
- scaleTargetRef로 대상 Deployment 지정
- minReplicas와 maxReplicas로 스케일 범위 설정
- metrics에서 CPU averageUtilization 목표치 설정 (여기서는 50%)
- HPA는 주기적으로 CPU 사용률을 계산하여 레플리카 수 조정
샘플 답변 보기
HorizontalPodAutoscaler(HPA)는 CPU 사용량과 같은 메트릭을 기반으로 파드의 레플리카 수를 자동으로 조정합니다. 위의 YAML은 my-app Deployment를 대상으로 CPU 사용률을 50%로 유지하도록 설정합니다. minReplicas와 maxReplicas는 각각 최소 1, 최대 10개의 레플리카를 유지합니다. HPA는 metrics-server에서 수집한 CPU 사용률 데이터를 주기적으로 확인하며, desiredReplicas = ceil(currentMetricValue / targetMetricValue) * currentReplicas 공식을 사용하여 목표 레플리카 수를 계산합니다. 예를 들어 현재 CPU 사용률이 80%이고 목표가 50%라면, desiredReplicas = ceil(80/50) * 1 = 2가 되어 레플리카를 2개로 늘립니다. 스케일 다운은 반대로 동작하며, 급격한 변화를 방지하기 위해 안정화 시간( stabilizationWindowSeconds)이 적용될 수 있습니다. HPA는 autoscaling/v2 API를 사용하여 CPU, 메모리, 커스텀 메트릭 등 다양한 메트릭을 지원합니다.
참고 코드yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-app-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-app minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50
준비 방법
- 도구에 의존하지 않고 손으로 Dockerfile과 Kubernetes YAML 매니페스트를 작성하는 연습을 하세요.
- Minikube나 kind를 사용하여 로컬 클러스터를 설정하고 실제 디플로이먼트와 서비스를 실험해보세요.
- kubectl 명령줄을 철저히 이해하세요. 디버깅 명령어(예: kubectl describe, kubectl logs, kubectl exec)를 포함합니다.
- 컨테이너 네트워킹의 핵심 개념과 Kubernetes가 CNI 플러그인으로 네트워킹을 구현하는 방법을 배우세요.
- 롤링 업데이트, 카나리 디플로이먼트, 파드 리소스 제한과 같은 일반적인 인터뷰 시나리오를 공부하세요.
자주 묻는 질문
인터뷰를 위해 Docker와 Kubernetes를 모두 알아야 하나요?
네, 대부분의 인터뷰는 두 가지를 모두 다룹니다. Docker는 종종 전제 조건이며, Kubernetes 질문은 컨테이너 기본에 대한 편안함을 가정합니다.
실습 문제를 준비하는 가장 좋은 방법은 무엇인가요?
로컬 클러스터(Minikube/kind)를 설정하고 앱 배포, 처음부터 YAML 작성, 문제 디버깅을 연습하세요.
YAML 매니페스트 작성 기술이 얼마나 중요한가요?
매우 중요합니다. 많은 인터뷰에서 디플로이먼트, 서비스, 컨피그맵에 대한 YAML 파일 작성 또는 디버깅을 포함합니다.
Docker에 더 집중해야 할까요, Kubernetes에 더 집중해야 할까요?
Kubernetes가 일반적으로 더 비중이 높지만, Docker 기본(이미지, Dockerfile, compose)도 테스트됩니다.
알아야 할 특정 도구가 있나요?
kubectl, Helm, docker logs 및 exec를 이용한 기본 디버깅을 알아야 합니다. Prometheus와 Grafana에 대한 친숙함은 플러스입니다.
즉각적인 AI 피드백으로 Docker & Kubernetes 질문 연습하기
이력서를 업로드하고 맞춤형 모의 면접을 받아 무엇을 개선해야 할지 정확히 확인하세요 — 무료로 시작하세요.