본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 29. · 14 Views
Pod 완전 정복
Kubernetes의 가장 작은 배포 단위인 Pod에 대해 알아봅니다. Pod의 개념부터 매니페스트 작성, 멀티 컨테이너 패턴, 생명주기, 리소스 관리, 디버깅까지 실무에서 필요한 모든 것을 다룹니다.
목차
1. Pod란 무엇인가
어느 날 김개발 씨는 Docker를 열심히 공부한 뒤 의기양양하게 Kubernetes 세계에 발을 들였습니다. 그런데 첫 번째 관문에서부터 막혔습니다.
"컨테이너는 알겠는데, Pod는 대체 뭐지?"
Pod는 Kubernetes에서 생성하고 관리할 수 있는 가장 작은 배포 단위입니다. 마치 콩깍지 속에 여러 개의 콩이 함께 들어있듯이, 하나의 Pod 안에는 하나 이상의 컨테이너가 함께 담겨 있습니다.
같은 Pod 내의 컨테이너들은 네트워크와 스토리지를 공유하며, 마치 한 집에 사는 가족처럼 긴밀하게 협력합니다.
다음 코드를 살펴봅시다.
# 가장 단순한 Pod 정의
apiVersion: v1
kind: Pod
metadata:
name: my-first-pod
labels:
app: hello-world
spec:
containers:
- name: nginx-container
image: nginx:1.24
ports:
- containerPort: 80
김개발 씨는 입사 6개월 차 백엔드 개발자입니다. Docker로 컨테이너를 만들고 실행하는 것은 이제 어느 정도 익숙해졌습니다.
그런데 팀에서 Kubernetes를 도입하기로 했고, 김개발 씨에게도 공부가 필요해졌습니다. 처음 Kubernetes 문서를 펼친 김개발 씨는 곧바로 혼란에 빠졌습니다.
분명 Docker에서는 컨테이너 단위로 모든 것을 관리했는데, Kubernetes에서는 왜 Pod라는 새로운 개념이 등장하는 걸까요? 선배 개발자 박시니어 씨가 다가와 설명을 시작했습니다.
"Pod를 이해하려면 먼저 비유를 들어볼게요. 콩깍지를 상상해보세요." 콩깍지 하나를 열어보면 그 안에 여러 개의 콩이 나란히 들어있습니다.
각각의 콩은 독립적인 존재이지만, 같은 깍지 안에서 영양분을 공유하고 함께 자랍니다. Pod도 마찬가지입니다.
하나의 Pod 안에는 하나 이상의 컨테이너가 들어갈 수 있고, 이 컨테이너들은 서로 긴밀하게 협력합니다. 그렇다면 왜 Kubernetes는 컨테이너를 직접 관리하지 않고 Pod라는 계층을 하나 더 만들었을까요?
현실 세계의 애플리케이션을 생각해봅시다. 웹 서버 하나만 덩그러니 있는 경우는 드뭅니다.
보통은 로그를 수집하는 사이드카 컨테이너, 설정을 주입하는 초기화 컨테이너 등 여러 컨테이너가 함께 동작해야 합니다. 이런 컨테이너들을 개별적으로 관리하면 어떻게 될까요?
네트워크 설정을 각각 해줘야 하고, 스토리지 공유도 복잡해지며, 스케줄링도 따로 이루어집니다. 같은 노드에 배치되리라는 보장도 없습니다.
이런 문제를 해결하기 위해 Pod가 등장했습니다. 같은 Pod 내의 컨테이너들은 동일한 네트워크 네임스페이스를 공유합니다.
이 말은 localhost로 서로 통신할 수 있다는 뜻입니다. 또한 스토리지 볼륨도 공유할 수 있어서, 한 컨테이너가 파일을 쓰면 다른 컨테이너가 읽을 수 있습니다.
위의 코드를 살펴보겠습니다. apiVersion은 이 리소스가 어떤 API 그룹에 속하는지를 나타냅니다.
Pod는 핵심 API에 속하므로 v1입니다. kind는 리소스 종류를 나타내고, metadata에는 이름과 라벨 같은 메타 정보가 들어갑니다.
spec 부분이 핵심입니다. containers 배열 안에 실행할 컨테이너들을 정의합니다.
각 컨테이너에는 이름, 이미지, 포트 등을 지정할 수 있습니다. 이 예제에서는 nginx 이미지를 사용하는 컨테이너 하나를 정의했습니다.
실무에서 Pod를 직접 만드는 경우는 많지 않습니다. 보통은 Deployment나 StatefulSet 같은 상위 컨트롤러를 통해 Pod를 관리합니다.
하지만 Pod의 구조를 이해하는 것은 Kubernetes를 다루는 데 있어 가장 기본이 됩니다. 박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다.
"아, 그래서 Pod가 필요했군요! 관련 있는 컨테이너들을 하나로 묶어서 관리하려는 거네요."
실전 팁
💡 - Pod는 일시적인 존재입니다. 언제든 삭제되고 재생성될 수 있으므로, 중요한 데이터는 외부 스토리지에 저장하세요.
- 대부분의 경우 Pod 하나에 컨테이너 하나를 넣는 것이 권장됩니다. 멀티 컨테이너는 정말 필요한 경우에만 사용하세요.
2. Pod 매니페스트 작성
김개발 씨는 이제 Pod가 무엇인지 이해했습니다. 그런데 막상 YAML 파일을 작성하려니 막막합니다.
"이 많은 필드 중에 뭘 써야 하는 거지?" 매니페스트 작성법을 제대로 배워야 할 때가 왔습니다.
Pod 매니페스트는 원하는 Pod의 상태를 선언적으로 기술한 YAML 파일입니다. Kubernetes는 이 매니페스트를 읽고 실제 Pod를 생성합니다.
마치 건축 설계도처럼, 매니페스트에 적힌 대로 Pod가 만들어집니다. 필수 필드와 선택 필드를 구분해서 알아두면 효율적으로 작성할 수 있습니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Pod
metadata:
name: web-server
namespace: production
labels:
app: web
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.24
ports:
- containerPort: 80
protocol: TCP
env:
- name: NODE_ENV
value: "production"
다음 날, 김개발 씨는 본격적으로 Pod 매니페스트 작성에 도전했습니다. 인터넷에서 예제를 찾아보니 수십 줄짜리 복잡한 YAML 파일들이 넘쳐났습니다.
어디서부터 시작해야 할까요? 박시니어 씨가 조언을 건넵니다.
"처음부터 모든 필드를 외우려고 하지 마세요. 핵심 구조만 먼저 이해하면 됩니다." 모든 Kubernetes 리소스는 공통된 구조를 가집니다.
마치 공문서에 정해진 양식이 있는 것처럼, Kubernetes 매니페스트도 정해진 형식을 따릅니다. 크게 네 부분으로 나눌 수 있습니다.
첫 번째는 apiVersion입니다. 이 리소스가 어떤 API 버전을 사용하는지 명시합니다.
Pod는 Kubernetes의 핵심 리소스이므로 v1을 사용합니다. 만약 Deployment라면 apps/v1을 사용하겠죠.
두 번째는 kind입니다. 어떤 종류의 리소스를 만들 것인지를 나타냅니다.
Pod, Service, Deployment 등이 여기에 들어갑니다. 대소문자를 정확히 지켜야 합니다.
세 번째는 metadata입니다. 리소스를 식별하기 위한 정보가 들어갑니다.
name은 필수이고, namespace와 labels는 선택입니다. labels는 특히 중요한데, 나중에 Service나 Deployment가 Pod를 찾을 때 이 라벨을 사용합니다.
네 번째는 spec입니다. 이 부분이 실제로 Pod의 동작을 정의하는 핵심입니다.
어떤 컨테이너를 실행할지, 어떤 포트를 열지, 환경 변수는 무엇인지 등을 여기에 기술합니다. 위의 코드에서 containers 배열을 살펴봅시다.
각 컨테이너에는 name과 image가 필수입니다. name은 Pod 내에서 컨테이너를 구분하는 용도로 쓰이고, image는 Docker Hub나 프라이빗 레지스트리에서 가져올 이미지를 지정합니다.
ports는 컨테이너가 노출할 포트를 정의합니다. containerPort는 컨테이너 내부 포트이고, protocol은 TCP 또는 UDP를 지정합니다.
기본값이 TCP이므로 생략해도 됩니다. env는 환경 변수를 설정합니다.
위 예제에서는 NODE_ENV를 production으로 설정했습니다. 민감한 정보는 직접 값을 넣지 말고 Secret을 참조하는 방식을 사용해야 합니다.
매니페스트를 작성했다면 kubectl apply 명령으로 클러스터에 적용합니다. kubectl apply -f pod.yaml을 실행하면 Kubernetes가 매니페스트를 읽고 Pod를 생성합니다.
김개발 씨는 직접 매니페스트를 작성해보며 감을 잡아갔습니다. "처음에는 복잡해 보였는데, 구조를 알고 나니 그렇게 어렵지 않네요."
실전 팁
💡 - kubectl explain pod.spec.containers 명령으로 각 필드의 설명을 확인할 수 있습니다.
- YAML 들여쓰기는 탭이 아닌 스페이스 2칸을 사용하세요. 탭을 쓰면 오류가 발생합니다.
3. 멀티 컨테이너 Pod 패턴
김개발 씨의 서비스가 점점 복잡해지고 있습니다. 메인 애플리케이션 외에 로그 수집기와 프록시도 함께 실행해야 합니다.
"이걸 다 따로 만들어야 하나?" 박시니어 씨가 멀티 컨테이너 패턴을 알려줄 차례입니다.
멀티 컨테이너 Pod는 하나의 Pod 안에 여러 컨테이너를 배치하는 패턴입니다. 대표적으로 사이드카, 앰배서더, 어댑터 세 가지 패턴이 있습니다.
각 패턴은 메인 컨테이너를 보조하는 역할을 하며, 마치 주연 배우를 돕는 조연처럼 뒤에서 중요한 일을 담당합니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Pod
metadata:
name: web-with-sidecar
spec:
containers:
- name: web-app
image: my-web-app:1.0
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/input
volumes:
- name: shared-logs
emptyDir: {}
김개발 씨의 웹 애플리케이션이 운영 환경에 배포되었습니다. 그런데 문제가 생겼습니다.
로그를 중앙 로그 시스템으로 보내야 하는데, 애플리케이션 코드를 수정하기는 부담스럽습니다. 박시니어 씨가 해결책을 제시했습니다.
"사이드카 패턴을 써보세요. 애플리케이션 코드는 건드리지 않고도 로그 수집이 가능해요." 사이드카 패턴은 오토바이에 달린 사이드카에서 이름을 따왔습니다.
메인 컨테이너 옆에 보조 컨테이너가 붙어서 함께 달리는 모습입니다. 로그 수집, 모니터링 에이전트, 설정 동기화 등에 주로 사용됩니다.
위 코드를 보면 web-app과 log-collector 두 개의 컨테이너가 있습니다. 둘은 shared-logs라는 볼륨을 공유합니다.
web-app은 /var/log/app에 로그를 쓰고, log-collector는 같은 파일을 /var/log/input에서 읽습니다. emptyDir 볼륨은 Pod가 생성될 때 빈 디렉토리로 시작하는 임시 스토리지입니다.
Pod가 삭제되면 함께 사라지지만, 같은 Pod 내 컨테이너 간 데이터 공유에는 안성맞춤입니다. 두 번째 패턴은 앰배서더 패턴입니다.
외교 대사가 나라를 대표하듯, 앰배서더 컨테이너는 외부 세계와의 통신을 대리합니다. 예를 들어 데이터베이스 연결 풀링이나 샤딩 로직을 앰배서더가 담당하면, 메인 애플리케이션은 단순히 localhost의 고정 포트에 연결하면 됩니다.
세 번째는 어댑터 패턴입니다. 서로 다른 형식의 데이터를 변환하는 역할을 합니다.
예를 들어 레거시 애플리케이션이 특수한 형식으로 메트릭을 내보내면, 어댑터 컨테이너가 이를 Prometheus 형식으로 변환해줍니다. 멀티 컨테이너 Pod에서 중요한 점은 컨테이너 간 통신입니다.
같은 Pod 내 컨테이너들은 localhost로 서로 접근할 수 있습니다. 네트워크 네임스페이스를 공유하기 때문입니다.
포트만 다르면 충돌 없이 통신할 수 있습니다. 하지만 주의할 점도 있습니다.
멀티 컨테이너 Pod는 모든 컨테이너가 같은 노드에 배치됩니다. 리소스를 많이 사용하는 컨테이너들을 무작정 한 Pod에 넣으면 특정 노드에 부하가 집중될 수 있습니다.
김개발 씨는 사이드카 패턴을 적용해 로그 수집 문제를 해결했습니다. "코드 한 줄 안 고치고 해결했네요.
이래서 패턴을 아는 게 중요하구나."
실전 팁
💡 - 컨테이너 간 의존성이 강할 때만 멀티 컨테이너를 사용하세요. 약한 의존성이라면 별도 Pod로 분리하는 것이 좋습니다.
- 사이드카 컨테이너가 메인 컨테이너보다 먼저 종료되면 문제가 생길 수 있으니 종료 순서를 고려하세요.
4. Pod 생명주기 이해
어느 날 김개발 씨가 kubectl get pods를 실행했더니 STATUS 컬럼에 Pending, Running, Failed 등 다양한 상태가 보였습니다. "이게 다 무슨 뜻이지?" Pod의 생명주기를 이해해야 할 때가 왔습니다.
Pod는 생성부터 종료까지 여러 **단계(Phase)**를 거칩니다. Pending, Running, Succeeded, Failed, Unknown 다섯 가지 상태가 있습니다.
마치 사람의 일생처럼, Pod도 태어나고 활동하다가 결국 사라집니다. 각 단계를 이해하면 Pod의 현재 상황을 정확히 파악하고 문제를 해결할 수 있습니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
initContainers:
- name: init-service
image: busybox:1.36
command: ['sh', '-c', 'echo Initializing... && sleep 5']
containers:
- name: main-app
image: nginx:1.24
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Started > /tmp/started"]
preStop:
exec:
command: ["/bin/sh", "-c", "nginx -s quit"]
김개발 씨는 배포 후 Pod 상태를 모니터링하는 습관이 생겼습니다. 그런데 어떤 Pod는 몇 분째 Pending 상태에 머물러 있고, 어떤 Pod는 금방 Running이 됩니다.
무슨 차이일까요? 박시니어 씨가 화이트보드에 그림을 그리며 설명을 시작했습니다.
"Pod의 생명주기를 알면 왜 그런지 이해할 수 있어요." Pending은 Pod가 생성되었지만 아직 실행되지 않은 상태입니다. 이 단계에서는 여러 일이 벌어집니다.
스케줄러가 적합한 노드를 찾고, 컨테이너 이미지를 다운로드합니다. 노드 리소스가 부족하거나 이미지를 찾을 수 없으면 Pending에서 멈춰 있게 됩니다.
Running은 Pod가 노드에 바인딩되고 모든 컨테이너가 생성된 상태입니다. 적어도 하나의 컨테이너가 실행 중이거나 시작 또는 재시작 중입니다.
정상적으로 서비스 중인 Pod는 이 상태입니다. Succeeded는 Pod 내 모든 컨테이너가 성공적으로 종료된 상태입니다.
주로 Job이나 CronJob에서 사용하는 일회성 Pod가 이 상태가 됩니다. 재시작되지 않습니다.
Failed는 모든 컨테이너가 종료되었는데 하나 이상이 실패한 경우입니다. 0이 아닌 종료 코드를 반환하거나 시스템에 의해 종료된 경우입니다.
Unknown은 Pod 상태를 알 수 없는 경우입니다. 보통 노드와의 통신에 문제가 있을 때 나타납니다.
위 코드에서 initContainers를 주목해보세요. 초기화 컨테이너는 메인 컨테이너가 시작되기 전에 실행되고 완료되어야 합니다.
데이터베이스 마이그레이션이나 설정 파일 준비 같은 사전 작업에 유용합니다. lifecycle 섹션에는 postStart와 preStop 훅이 있습니다.
postStart는 컨테이너가 생성된 직후 실행됩니다. 컨테이너 ENTRYPOINT와 비동기로 실행되므로 순서가 보장되지 않습니다.
preStop은 컨테이너가 종료되기 전에 실행됩니다. 위 예제에서는 nginx에 정상 종료 신호를 보내는 명령을 실행합니다.
이렇게 하면 진행 중인 요청을 마무리한 후 깔끔하게 종료할 수 있습니다. Pod가 삭제될 때는 graceful shutdown 과정을 거칩니다.
기본적으로 30초의 유예 기간이 주어지고, 이 시간 동안 preStop 훅이 실행되고 SIGTERM 신호가 전달됩니다. 시간이 지나면 SIGKILL로 강제 종료됩니다.
김개발 씨는 Pending 상태의 Pod를 kubectl describe pod로 확인해봤습니다. Events 섹션에 이미지를 찾을 수 없다는 메시지가 있었습니다.
"아, 이미지 태그를 잘못 적었구나!"
실전 팁
💡 - kubectl describe pod 명령의 Events 섹션을 확인하면 Pod가 왜 특정 상태에 있는지 알 수 있습니다.
- terminationGracePeriodSeconds를 조정해 종료 유예 시간을 변경할 수 있습니다.
5. 리소스 요청과 제한
김개발 씨가 배포한 Pod가 갑자기 죽었습니다. kubectl describe를 해보니 OOMKilled라고 적혀 있습니다.
"메모리가 부족했다고?" 리소스 관리의 중요성을 깨달은 순간입니다.
Pod의 **리소스 요청(requests)**과 **제한(limits)**은 컨테이너가 사용할 CPU와 메모리를 정의합니다. requests는 스케줄링에 사용되는 최소 보장 리소스이고, limits는 절대 넘을 수 없는 상한선입니다.
마치 휴대폰 요금제처럼, 기본 제공량과 최대 사용량을 정해두는 것과 같습니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: app
image: my-app:1.0
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
김개발 씨의 서비스에 갑자기 트래픽이 몰렸습니다. 그런데 Pod들이 하나둘씩 OOMKilled 상태로 죽어나가기 시작했습니다.
무슨 일이 벌어진 걸까요? 박시니어 씨가 상황을 파악하고 말했습니다.
"리소스 제한을 안 걸어뒀네요. 컨테이너가 메모리를 무한정 사용하다가 노드 전체에 영향을 준 거예요." Kubernetes에서 리소스 관리는 두 가지 축으로 이루어집니다.
requests와 limits입니다. requests는 컨테이너에 보장되는 최소 리소스입니다.
스케줄러는 이 값을 보고 어느 노드에 Pod를 배치할지 결정합니다. 노드의 남은 리소스가 requests보다 적으면 그 노드에는 배치되지 않습니다.
limits는 컨테이너가 사용할 수 있는 최대 리소스입니다. 이 값을 넘으면 시스템이 개입합니다.
메모리의 경우 limits를 초과하면 컨테이너가 OOMKilled 됩니다. CPU의 경우는 조금 다릅니다.
강제 종료가 아니라 스로틀링이 걸립니다. 속도가 느려지는 거죠.
CPU 단위를 보면 250m이라고 적혀 있습니다. m은 밀리코어를 뜻합니다.
1000m이 1 CPU 코어입니다. 250m은 코어 하나의 25%를 의미합니다.
소수점으로 0.25라고 적어도 됩니다. 메모리 단위의 Mi는 메비바이트입니다.
1Mi는 1024 x 1024 바이트입니다. Gi는 기비바이트로 1024Mi입니다.
익숙한 MB, GB와 거의 같지만 정확히는 조금 다릅니다. requests와 limits를 어떻게 설정해야 할까요?
경험칙으로, requests는 평소 사용량을, limits는 피크 사용량을 기준으로 설정합니다. 모니터링 도구로 실제 사용량을 측정한 후 조정하는 것이 좋습니다.
requests 없이 limits만 설정하면 어떻게 될까요? Kubernetes는 requests를 limits와 같은 값으로 자동 설정합니다.
반대로 limits 없이 requests만 설정하면, 상한 없이 리소스를 사용할 수 있습니다. QoS 클래스도 알아둘 필요가 있습니다.
requests와 limits를 어떻게 설정하느냐에 따라 Pod는 Guaranteed, Burstable, BestEffort 중 하나로 분류됩니다. 리소스가 부족할 때 BestEffort가 가장 먼저 퇴거됩니다.
김개발 씨는 모든 Pod에 적절한 리소스 설정을 추가했습니다. "이제 트래픽이 몰려도 안정적으로 버틸 수 있겠네요."
실전 팁
💡 - 처음에는 넉넉하게 설정하고, 모니터링 데이터를 보면서 점차 최적화하세요.
- LimitRange와 ResourceQuota를 사용하면 네임스페이스 수준에서 리소스를 제한할 수 있습니다.
6. Pod 로그 확인 및 디버깅
배포한 Pod가 정상 동작하지 않습니다. 에러 메시지도 안 보이고, 뭐가 문제인지 감이 안 잡힙니다.
김개발 씨는 한숨을 쉽니다. "도대체 어디서부터 봐야 하지?" 디버깅 기술이 필요한 순간입니다.
Pod 디버깅은 kubectl logs, kubectl describe, kubectl exec 세 가지 명령이 핵심입니다. 로그로 애플리케이션 출력을 확인하고, describe로 이벤트와 상태를 파악하며, exec로 컨테이너 내부에 직접 접속합니다.
마치 의사가 환자를 진찰하듯, 여러 도구를 조합해 문제의 원인을 찾아갑니다.
다음 코드를 살펴봅시다.
# Pod 로그 확인
kubectl logs my-pod
# 이전 컨테이너 로그 확인 (재시작된 경우)
kubectl logs my-pod --previous
# 멀티 컨테이너 Pod에서 특정 컨테이너 로그
kubectl logs my-pod -c sidecar
# 실시간 로그 스트리밍
kubectl logs -f my-pod
# Pod 상세 정보 확인
kubectl describe pod my-pod
# 컨테이너 내부 접속
kubectl exec -it my-pod -- /bin/sh
금요일 오후, 김개발 씨가 배포한 서비스에서 500 에러가 발생하기 시작했습니다. 사용자 불만이 쏟아지고 있습니다.
빨리 원인을 찾아야 합니다. 박시니어 씨가 다가와 침착하게 말합니다.
"당황하지 말고, 하나씩 확인해봐요. 디버깅에는 순서가 있어요." 첫 번째 단계는 kubectl logs입니다.
컨테이너의 표준 출력과 표준 에러를 확인할 수 있습니다. 애플리케이션이 남긴 로그가 여기에 출력됩니다.
kubectl logs my-pod 명령을 실행하면 로그가 쭉 나옵니다. 너무 길다면 --tail=100 옵션으로 마지막 100줄만 볼 수 있습니다.
-f 옵션을 붙이면 실시간으로 로그가 스트리밍됩니다. 문제 상황을 재현하면서 로그를 지켜볼 때 유용합니다.
Pod가 재시작된 경우에는 --previous 옵션이 필요합니다. 현재 컨테이너가 아닌 이전 컨테이너의 로그를 보여줍니다.
왜 죽었는지 파악하는 데 결정적인 단서가 되기도 합니다. 멀티 컨테이너 Pod에서는 -c 컨테이너이름으로 특정 컨테이너를 지정해야 합니다.
지정하지 않으면 첫 번째 컨테이너의 로그만 보입니다. 두 번째 단계는 kubectl describe pod입니다.
Pod의 상세 정보와 이벤트 기록을 보여줍니다. 특히 하단의 Events 섹션이 중요합니다.
이미지 풀 실패, 리소스 부족, 헬스 체크 실패 등의 정보가 여기에 기록됩니다. 세 번째 단계는 kubectl exec입니다.
컨테이너 내부에 직접 접속해서 상태를 확인합니다. kubectl exec -it my-pod -- /bin/sh를 실행하면 셸에 접속됩니다.
파일 시스템, 환경 변수, 네트워크 연결 등을 직접 확인할 수 있습니다. -it 옵션은 인터랙티브 모드와 TTY를 의미합니다.
셸을 사용하려면 반드시 필요합니다. 단순히 명령 하나만 실행할 때는 kubectl exec my-pod -- ls /app처럼 사용합니다.
네트워크 문제를 의심한다면 컨테이너 안에서 curl이나 ping을 실행해볼 수 있습니다. 다만 최소 이미지에는 이런 도구가 없을 수 있습니다.
그럴 때는 kubectl debug로 디버그 컨테이너를 붙이는 방법도 있습니다. 김개발 씨는 describe를 실행해 Events를 확인했습니다.
Liveness probe failed라는 메시지가 보였습니다. 헬스 체크 엔드포인트가 잘못 설정되어 있었던 것입니다.
문제를 수정하고 재배포하자 서비스가 정상화되었습니다. "후, 다행이다.
이제 디버깅 순서가 손에 익었어요." 김개발 씨는 안도의 한숨을 내쉬었습니다.
실전 팁
💡 - kubectl get events --sort-by='.lastTimestamp' 명령으로 클러스터 전체 이벤트를 시간순으로 볼 수 있습니다.
- 로그가 너무 방대하다면 --since=1h 옵션으로 최근 1시간 로그만 필터링하세요.
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Istio 보안 완벽 가이드
마이크로서비스 환경에서 필수적인 Istio 보안 기능을 실무 중심으로 설명합니다. mTLS부터 인증, 인가까지 단계별로 학습하여 안전한 서비스 메시를 구축할 수 있습니다.
Istio 트래픽 관리 완벽 가이드
Istio의 트래픽 관리 기능을 마스터하는 완벽 가이드입니다. VirtualService와 DestinationRule을 활용한 라우팅부터 트래픽 분할, 헤더 기반 라우팅까지 실무에 필요한 모든 내용을 다룹니다.
Istio 설치와 구성 완벽 가이드
Kubernetes 환경에서 Istio 서비스 메시를 설치하고 구성하는 방법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 가이드입니다. istioctl 설치부터 사이드카 주입까지 단계별로 학습합니다.
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.