소개
이전 실습에서는 로그와 이벤트에 대해 다루었습니다. 로그와 이벤트는 문제 해결의 첫 번째 신호이지만, 때로는 실행 중인 컨테이너 내부를 직접 확인하거나 터미널에서 서비스에 일시적으로 접근해야 할 필요가 있습니다. 쿠버네티스는 이를 위해 kubectl exec와 kubectl port-forward라는 두 가지 유용한 도구를 제공합니다.
이번 실습에서는 소규모 웹 애플리케이션을 배포하고, kubectl exec를 사용하여 Pod 내부의 파일과 프로세스를 확인하며, kubectl port-forward를 사용하여 서비스에 대한 임시 로컬 연결을 생성해 보겠습니다. 실습 과정은 애플리케이션의 복잡성보다는 디버깅 기술 자체에 집중할 수 있도록 간결하게 구성되었습니다.
디버깅을 위한 네임스페이스 준비
이 단계에서는 exec 및 포트 포워딩 실습을 위한 깨끗한 네임스페이스를 준비합니다.
먼저 /home/labex/project 디렉토리에서 시작합니다. 애플리케이션 매니페스트는 이 디렉토리에 유지합니다.
mkdir -p /home/labex/project
cd /home/labex/project
쿠버네티스 API 서버에 접근 가능한지 확인합니다. 가상 머신이 막 시작되어 노드가 아직 준비되지 않았다면, 잠시 기다린 후 명령어를 다시 실행하세요.
kubectl get nodes --request-timeout=5s
예상 출력은 다음과 같습니다:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
클러스터 네트워킹 Pod 가 준비될 때까지 기다립니다. 포트 포워딩은 API 서버 연결을 사용하지만, 애플리케이션이 정상적으로 작동하려면 Pod 와 서비스가 모두 정상 상태여야 합니다.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
예상 출력:
pod/calico-node-... condition met
ckad-prep-debug라는 이름의 네임스페이스를 생성하고 현재 네임스페이스로 설정합니다:
kubectl create namespace ckad-prep-debug
kubectl config set-context --current --namespace=ckad-prep-debug
현재 네임스페이스를 확인합니다:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
예상 출력:
ckad-prep-debug
소규모 웹 애플리케이션 배포
이 단계에서는 검사하고 접근할 간단한 애플리케이션을 배포합니다.
이 Pod 는 index.html 파일을 생성하고 8080 포트에서 BusyBox httpd를 실행합니다. debug-web이라는 서비스는 클러스터 내부의 Pod 를 80 포트로 노출합니다. kubectl port-forward는 Pod 뿐만 아니라 서비스도 대상으로 지정할 수 있기 때문에 서비스를 포함했습니다.
debug-web.yaml 파일을 생성합니다:
cat > debug-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: debug-web
spec:
replicas: 2
selector:
matchLabels:
app: debug-web
template:
metadata:
labels:
app: debug-web
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
mkdir -p /www
echo "debug-web-ready" > /www/index.html
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: debug-web
spec:
selector:
app: debug-web
ports:
- port: 80
targetPort: 8080
EOF
매니페스트를 적용하고 배포가 완료될 때까지 기다립니다:
kubectl apply -f debug-web.yaml
kubectl rollout status deployment/debug-web --timeout=120s
예상 출력은 다음과 같습니다:
deployment.apps/debug-web created
service/debug-web created
deployment "debug-web" successfully rolled out
Pod 와 서비스를 확인합니다:
kubectl get pods -l app=debug-web
kubectl get service debug-web
두 개의 실행 중인 Pod 와 ClusterIP 서비스가 확인되어야 합니다:
debug-web-... 1/1 Running
debug-web ClusterIP
exec 를 사용하여 실행 중인 컨테이너 검사
이 단계에서는 kubectl exec를 사용하여 애플리케이션 Pod 내부에서 명령어를 실행합니다.
kubectl exec는 Pod 가 실행 중이지만 컨테이너 내부의 상태를 확인해야 할 때 유용합니다. 이는 로그를 대체하는 도구가 아니며, 정상적인 배포 과정에서 임의로 수정하는 용도로 사용해서는 안 됩니다. 디버깅 워크플로우에서는 컨테이너 내부에서 파일, 프로세스, 환경 변수 및 로컬 네트워크 동작을 확인하는 데 도움을 줍니다.
Pod 이름 하나를 셸 변수에 저장합니다:
POD_NAME="$(kubectl get pods -l app=debug-web -o jsonpath='{.items[0].metadata.name}')"
echo "$POD_NAME"
예상 출력은 Pod 이름 하나입니다:
debug-web-...
컨테이너 내부에서 hostname을 실행합니다. 쿠버네티스는 Pod 이름을 기반으로 컨테이너의 호스트 이름을 설정하므로, 출력값은 Pod 이름과 일치해야 합니다.
kubectl exec "$POD_NAME" -- hostname
예상 출력:
debug-web-...
컨테이너 내부에서 실행 중인 프로세스 목록을 확인합니다:
kubectl exec "$POD_NAME" -- ps
예상 출력에는 httpd 프로세스가 포함되어야 합니다:
PID USER TIME COMMAND
... root ... httpd -f -p 8080 -h /www
웹 서버가 제공하는 파일을 읽어봅니다:
kubectl exec "$POD_NAME" -- cat /www/index.html
예상 출력:
debug-web-ready
마지막으로, 동일한 컨테이너 내부에서 웹 서버를 테스트합니다:
kubectl exec "$POD_NAME" -- wget -qO- http://127.0.0.1:8080
예상 출력:
debug-web-ready
포트 포워딩을 이용한 서비스 테스트
이 단계에서는 kubectl port-forward를 사용하여 터미널에서 서비스에 접근합니다.
포트 포워딩은 로컬 포트에서 클러스터 내의 Pod 나 서비스로 임시 터널을 생성합니다. 서비스 타입을 변경하거나, Ingress 를 생성하거나, 외부 접근을 허용할 필요 없이 빠르게 디버깅할 수 있어 유용합니다. kubectl port-forward 명령어는 중단할 때까지 계속 실행되므로, 이번 실습에서는 백그라운드에서 실행하고 테스트한 뒤 종료하겠습니다.
로컬 포트 18080에서 서비스 포트 80으로 포트 포워딩을 시작합니다. 터미널을 계속 사용할 수 있도록 출력은 /tmp/debug-web-port-forward.log 파일로 리다이렉트합니다.
kubectl port-forward service/debug-web 18080:80 > /tmp/debug-web-port-forward.log 2>&1 &
PF_PID=$!
sleep 3
cat /tmp/debug-web-port-forward.log
예상 출력은 다음과 같습니다:
Forwarding from 127.0.0.1:18080 -> 8080
로컬 포워딩 포트를 통해 요청을 보냅니다:
wget -qO- http://127.0.0.1:18080
예상 출력:
debug-web-ready
백그라운드 포트 포워딩 프로세스를 중단합니다. 로컬 포트가 계속 점유되지 않도록 정리하는 과정이 중요합니다.
kill "$PF_PID"
wait "$PF_PID" 2>/dev/null || true
포트 포워딩 로그에 연결 기록이 남았는지 확인합니다:
cat /tmp/debug-web-port-forward.log
예상 출력에는 다음 내용이 포함되어야 합니다:
Handling connection for 18080
요약
두 가지 실용적인 디버깅 도구를 실습했습니다. kubectl exec를 사용하여 실행 중인 컨테이너의 호스트 이름, 프로세스, 파일 및 로컬호스트 HTTP 응답을 확인했습니다. 또한 kubectl port-forward를 사용하여 ClusterIP 서비스에 대한 임시 로컬 연결을 생성하고, 터미널에서 테스트한 뒤 백그라운드 포워딩 프로세스를 깔끔하게 종료했습니다.


