infra
Platform

모듈 맵

[Kubernetes] get, describe, logs, exec 필수 kubectl 명령어 10선

0 / 29 완료

펼치기
0 / 29 완료0%

Kubernetes · 03 / 29

[Kubernetes] get, describe, logs, exec 필수 kubectl 명령어 10선

get, describe, logs, exec, apply, delete — 실무에서 매일 쓰는 kubectl 명령어를 체계적으로 마스터합니다

🚨INCIDENT ALERT
HIGH

운영 배포 직후 파드가 CrashLoopBackOff가 되었지만 팀원이 kubectl get, describe, logs의 차이를 몰라 같은 명령만 반복하고 있습니다. Kubernetes 장애 대응의 첫 5분은 대부분 kubectl 출력 읽기에서 결정됩니다. 기본 명령을 손에 익혀야 다음 단계의 진단이 가능합니다.

kubectl 기본 명령어

팀에 합류한 첫 날, 선임이 말했다. "Pod가 자꾸 죽는데, 로그 좀 봐줄 수 있어?" kubectl을 처음 본 신입은 화면을 뚫어져라 쳐다봤다. 명령어를 모르니 아무것도 할 수 없었다. Kubernetes는 아무리 강력한 플랫폼이어도, kubectl을 다루지 못하면 블랙박스일 뿐이다. kubectl은 Kubernetes를 조종하는 유일한 손이다. get으로 상태를 확인하고, describe로 원인을 찾고, logs로 앱 내부를 들여다보고, exec로 컨테이너 안으로 들어간다. 이 네 개 명령어만 능숙해도, 대부분의 Pod 장애는 10분 안에 원인을 찾을 수 있다.


이번 챕터에서 배울 것

매일 쓰는 kubectl 명령어를 체계적으로 익히고, 각 명령어가 장애 진단의 어느 단계에서 쓰이는지 파악합니다.

  • 1kubectl get — 리소스 목록 조회와 출력 형식 조정 (-o wide, -o yaml, -o json)
  • 2kubectl describe — 이벤트와 상세 정보로 장애 원인 파악
  • 3kubectl logs — 컨테이너 로그 조회 (-f, --previous, --since)
  • 4kubectl exec — 실행 중인 컨테이너 내부 접속
  • 5kubectl apply/delete — 선언적 리소스 관리
  • 6--dry-run=client -o yaml 패턴으로 YAML 템플릿 생성
실습 환경 준비

minikube 사용 시: minikube start로 클러스터를 시작하세요. kubectl이 설치되어 있고 클러스터에 연결되어 있으면 바로 시작할 수 있습니다.

kubectl 설치 확인
kubectl version --client
클러스터 연결 확인
kubectl cluster-info
현재 컨텍스트 확인
kubectl config current-context
기본 네임스페이스 리소스 확인
kubectl get all
💡개념

kubectl get — 상태 확인의 시작점

장애 대응 첫 5분, 아무것도 모르는 상황에서 가장 먼저 해야 할 일은 현재 상태를 파악하는 것입니다. 파드가 Running인지, 몇 개가 Ready인지, 어느 노드에 배치됐는지를 빠르게 확인해야 다음 단계로 진단을 좁힐 수 있습니다. kubectl get은 클러스터의 리소스 목록과 기본 상태를 한눈에 보여주는 가장 자주 쓰이는 명령어입니다. -o wide, -o yaml, -l 플래그를 조합하면 IP, 노드, 레이블까지 원하는 정보를 골라 볼 수 있습니다. 이 CB에서는 일상적인 상태 확인부터 장애 시 빠른 파악까지 kubectl get의 핵심 사용 패턴을 다룹니다.

kubectl get — 상태 확인의 시작점

기본 사용법

Kubernetes
# Pod 목록
kubectl get pods
# NAME          READY   STATUS    RESTARTS   AGE
# nginx-xxx     1/1     Running   0          5m
# broken-xxx    0/1     Error     3          2m

# 모든 네임스페이스
kubectl get pods -A  # 또는 --all-namespaces
# NAMESPACE     NAME                    READY   STATUS    RESTARTS
# kube-system   coredns-xxx             1/1     Running   0
# default       nginx-xxx               1/1     Running   0

# 특정 네임스페이스
kubectl get pods -n kube-system

# 여러 리소스 동시 조회
kubectl get pods,services,deployments

# 모든 리소스 타입 조회
kubectl get all
🔍실행 후 확인할 것
  • NAME조회 대상 리소스 이름이 예상한 대상과 일치하는지 확인합니다.
  • STATUS/READYRunning, Ready, Available처럼 정상 상태를 나타내는 필드가 있는지 봅니다.
  • RESTARTS/EVENTS재시작 횟수나 Warning 이벤트가 증가하지 않는지 확인합니다.

출력 형식 조정

Kubernetes
# 넓은 형식 (노드 IP 포함)
kubectl get pods -o wide
# NAME       READY   STATUS    IP           NODE
# nginx-xxx  1/1     Running   10.244.0.5   minikube

# YAML 형식 (전체 스펙 확인)
kubectl get pod nginx-xxx -o yaml

# JSON 형식 (스크립트에서 파싱 시)
kubectl get pods -o json

# 특정 필드만 추출
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# nginx-xxx broken-xxx

# 테이블 커스텀 컬럼
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName
# NAME       STATUS    NODE
# nginx-xxx  Running   minikube

라벨 필터링

Kubernetes
# 라벨로 필터
kubectl get pods -l app=nginx
kubectl get pods -l app=nginx,env=prod

# 라벨 표시
kubectl get pods --show-labels

# 실시간 감시 (상태 변화 추적)
kubectl get pods -w  # watch
💡개념

kubectl describe — 장애 원인의 보물창고

파드가 Pending인데 kubectl get만 보면 이유를 알 수 없습니다. 노드 자원 부족인지, 이미지 pull 실패인지, Affinity 조건 미충족인지 구분이 되지 않아 엉뚱한 방향으로 디버깅을 시작하게 됩니다. kubectl describe의 Events 섹션은 스케줄러와 kubelet이 파드에 무슨 일을 했는지 타임라인으로 기록합니다. "왜 그 상태인가"를 알려주는 핵심 도구입니다. 이 CB에서는 kubectl describe의 출력 구조와, Events 섹션에서 장애 원인을 빠르게 읽어내는 방법을 다룹니다. 특히 Events 섹션이 핵심입니다.

기본 사용법

Kubernetes
kubectl describe pod <pod-name>
kubectl describe node <node-name>
kubectl describe deployment <deployment-name>
kubectl describe service <service-name>

describe 출력 구조 이해

Kubernetes
kubectl describe pod nginx-xxx
# Name:         nginx-xxx
# Namespace:    default
# Priority:     0
# Node:         minikube/192.168.49.2    ← 어느 노드에서 실행 중인지
# Start Time:   ...
# Labels:       app=nginx
# Status:       Running
# IP:           10.244.0.5
#
# Containers:
#   nginx:
#     Image:          nginx:alpine
#     Port:           80/TCP
#     State:          Running
#     Ready:          True
#     Restart Count:  0           ← 재시작 횟수 (높으면 문제)
#     Limits:         ...
#     Requests:       ...
#     Liveness:       http-get ... ← 헬스체크 설정
#
# Conditions:
#   Type              Status
#   Initialized       True
#   Ready             True        ← Ready가 False면 문제
#   ContainersReady   True
#   PodScheduled      True
#
# Events:                         ← 여기가 핵심!
#   Type    Reason     Age    Message
#   Normal  Scheduled  5m     Successfully assigned default/nginx-xxx to minikube
#   Normal  Pulling    5m     Pulling image "nginx:alpine"
#   Normal  Pulled     4m     Successfully pulled image
#   Normal  Created    4m     Created container nginx
#   Normal  Started    4m     Started container nginx

이벤트로 장애 진단

Kubernetes
# 이미지 pull 실패 예시
# Events:
#   Warning  Failed   2m   Failed to pull image "nginx:nonexistent": ...
#             ImagePullBackOff

# 리소스 부족으로 스케줄 실패
# Events:
#   Warning  FailedScheduling  ... 0/1 nodes available: 1 Insufficient memory.

# 네임스페이스 전체 이벤트 확인 (장애 시 빠른 파악)
kubectl get events --sort-by='.lastTimestamp'
kubectl get events --field-selector type=Warning  # 경고만
💡개념

kubectl logs, exec — 컨테이너 내부 들여다보기

파드가 Running인데 API가 500을 반환합니다. kubectl getkubectl describe에는 이상이 없고, 문제는 컨테이너 안에서 돌고 있는 애플리케이션에 있습니다. 이때 필요한 것이 kubectl logskubectl exec입니다. logs는 앱이 stdout/stderr에 출력한 내용을 보여주고, exec는 컨테이너 내부로 직접 들어가 환경변수, 파일, 네트워크 연결을 확인합니다. CrashLoopBackOff 상황에서는 --previous 플래그로 죽기 직전 로그를 볼 수 있습니다. 이 CB에서는 로그 조회와 컨테이너 내부 접속의 핵심 패턴을 다룹니다.

kubectl logs — 앱 로그 확인

Kubernetes
# 기본 로그 조회
kubectl logs <pod-name>

# 실시간 스트리밍
kubectl logs -f <pod-name>

# 마지막 N줄
kubectl logs --tail=100 <pod-name>

# 특정 시간 이후 로그
kubectl logs --since=1h <pod-name>
kubectl logs --since-time="2024-01-15T10:00:00Z" <pod-name>

# 이전 컨테이너 로그 (CrashLoopBackOff 시 필수)
kubectl logs --previous <pod-name>
# ← 현재 컨테이너가 죽기 전 로그를 봄

# 멀티 컨테이너 Pod에서 특정 컨테이너 로그
kubectl logs <pod-name> -c <container-name>

# 라벨 셀렉터로 여러 Pod 로그 동시
kubectl logs -l app=nginx --tail=50

kubectl exec — 컨테이너 내부 접속

Kubernetes
# 인터랙티브 셸 접속
kubectl exec -it <pod-name> -- bash
kubectl exec -it <pod-name> -- sh  # bash 없을 때

# 단일 명령어 실행 (셸 없이)
kubectl exec <pod-name> -- ls /app
kubectl exec <pod-name> -- cat /etc/nginx/nginx.conf
kubectl exec <pod-name> -- env | grep DB

# 멀티 컨테이너 Pod에서 특정 컨테이너
kubectl exec -it <pod-name> -c <container-name> -- bash

# 환경변수 확인 (설정 디버깅 시)
kubectl exec <pod-name> -- env

# 네트워크 확인 (내부에서 다른 서비스 접근 테스트)
kubectl exec -it <pod-name> -- curl http://other-service:8080/health
kubectl exec -it <pod-name> -- nslookup other-service

실습: 핵심 명령어 마스터하기

실습 1: 기본 CRUD 패턴

로컬 터미널
# 실습용 리소스 생성
cat <<EOF > /tmp/practice-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: practice-nginx
  labels:
    app: practice
    env: dev
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    env:
    - name: MY_ENV
      value: "hello-k8s"
EOF

# 적용
kubectl apply -f /tmp/practice-pod.yaml
# pod/practice-nginx created

# 상태 확인
kubectl get pod practice-nginx -o wide

# 상세 확인
kubectl describe pod practice-nginx

# 라벨 필터링
kubectl get pods -l app=practice

실습 2: 로그와 exec 실습

Kubernetes
# nginx 로그 확인
kubectl logs practice-nginx

# 실시간 로그 (다른 터미널에서 curl을 날리면서 확인)
kubectl logs -f practice-nginx

# 컨테이너 내부 접속
kubectl exec -it practice-nginx -- sh

# 내부에서 실행할 명령어들:
# ls /usr/share/nginx/html
# cat /etc/nginx/nginx.conf | head -20
# env | grep MY_ENV  # MY_ENV=hello-k8s 확인
# exit

실습 3: --dry-run과 -o yaml 패턴

Kubernetes
# 실제 생성 없이 YAML 생성 (템플릿 작성 시 유용)
kubectl run my-app --image=nginx:alpine --dry-run=client -o yaml
# apiVersion: v1
# kind: Pod
# metadata:
#   creationTimestamp: null
#   labels:
#     run: my-app
#   name: my-app
# spec:
#   containers:
#   - image: nginx:alpine
#     name: my-app
#     resources: {}
# ...

# 파일로 저장해서 수정 후 사용
kubectl run my-app --image=nginx:alpine --dry-run=client -o yaml > /tmp/my-app.yaml

# 기존 리소스의 YAML 추출 (현재 설정 확인)
kubectl get pod practice-nginx -o yaml > /tmp/practice-nginx-export.yaml

# 정리
kubectl delete pod practice-nginx

실습 4: kubectl apply vs create 비교

로컬 터미널
cat <<EOF > /tmp/test-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
data:
  key: "value1"
EOF

# apply: 없으면 생성, 있으면 업데이트
kubectl apply -f /tmp/test-cm.yaml
# configmap/test-config created

kubectl apply -f /tmp/test-cm.yaml
# configmap/test-config unchanged  ← 이미 동일하면 변경 없음

# 내용 변경 후 재apply
sed -i 's/value1/value2/' /tmp/test-cm.yaml
kubectl apply -f /tmp/test-cm.yaml
# configmap/test-config configured  ← 변경됨

# create는 이미 존재하면 에러
kubectl create -f /tmp/test-cm.yaml
# Error from server (AlreadyExists): configmaps "test-config" already exists

# 정리
kubectl delete configmap test-config

상황

Kubernetes
kubectl logs my-pod
# Error from server (NotFound): pods "my-pod" not found

kubectl describe pod my-pod
# Error from server (NotFound): pods "my-pod" not found

분명히 배포했는데 Pod를 찾을 수 없다는 에러입니다.

진단: 네임스페이스 확인

Kubernetes
# 1. 현재 컨텍스트의 네임스페이스 확인
kubectl config get-contexts
# CURRENT   NAME       CLUSTER    AUTHINFO   NAMESPACE
# *         minikube   minikube   minikube   (비어있으면 default)

# 2. 모든 네임스페이스에서 검색
kubectl get pods -A | grep my-pod
# production   my-pod   1/1   Running   0   5m
# ↑ 'production' 네임스페이스에 있었음!

# 3. 네임스페이스를 명시해서 명령 실행
kubectl logs my-pod -n production
kubectl describe pod my-pod -n production

원인과 해결

원인해결
다른 네임스페이스에 배포됨-n <namespace> 플래그 추가
Pod가 실제로 없음 (배포 실패)kubectl get events로 배포 오류 확인
이름 오타kubectl get pods -A | grep <partial-name>
이미 종료되어 삭제됨Job/CronJob이면 정상 (--previous 로그 확인)

기본 네임스페이스 변경 (자주 쓰는 네임스페이스가 있을 때)

Kubernetes
# 현재 컨텍스트의 기본 네임스페이스 변경
kubectl config set-context --current --namespace=production

# 이후 -n 생략 가능
kubectl get pods  # production 네임스페이스가 기본

# 다시 default로
kubectl config set-context --current --namespace=default

핵심 교훈: NotFound 에러의 80%는 네임스페이스 문제입니다. 항상 -A 플래그로 모든 네임스페이스를 먼저 확인하세요.

💼
실무 맥락
현업 패턴

실무 시나리오: kubectl 장애 대응 플로우

팀장: "API 서버에서 500 에러가 납니다."

1단계: 빠른 상태 파악 (30초)

Kubernetes
kubectl get pods -n production
# NAME           READY   STATUS             RESTARTS   AGE
# api-server-xxx 0/1     CrashLoopBackOff   5          10m

2단계: 이벤트로 원인 파악 (1분)

Kubernetes
kubectl describe pod api-server-xxx -n production | grep -A20 Events
# Events:
#   Warning  BackOff  ... Back-off restarting failed container

3단계: 로그로 앱 오류 확인 (2분)

Kubernetes
# 현재 컨테이너 로그
kubectl logs api-server-xxx -n production --tail=50
# Error: Cannot connect to database at postgres:5432

# 이전 컨테이너 로그 (죽기 직전)
kubectl logs api-server-xxx -n production --previous | tail-20

4단계: 내부 진단 (필요시)

Kubernetes
# DB 연결 확인
kubectl exec -it api-server-xxx -n production -- nc -zv postgres 5432
# postgres (5432:) open  ← 연결 가능
# postgres (5432:) refused  ← DB 다운

# 환경변수 확인
kubectl exec api-server-xxx -n production -- env | grep DB

총 소요 시간: 5분 이내에 "DB 연결 문제" 파악 완료.

kubectl get → describe → logs → exec 이 4단계 흐름이 K8s 장애 진단의 표준 패턴입니다.


다음 모듈 pod-lifecycle에서는 Pod가 Pending → Running → Succeeded/Failed로 전환되는 상태 머신을 이해하고, CrashLoopBackOff와 ImagePullBackOff 같은 실무에서 자주 만나는 에러를 체계적으로 진단합니다.

지식 확인

퀴즈 — 4문제

Q1

`kubectl get pods`와 `kubectl describe pod <name>`의 가장 큰 차이점은?

Q2

`kubectl apply -f`와 `kubectl create -f`의 차이점은?

Q3

실행 중인 Pod의 컨테이너 내부에서 셸 명령을 실행하려면?

Q4

`kubectl get pods -o yaml`에서 `-o yaml` 플래그의 주요 활용 용도는?

0 / 4 답변

🧪 실습으로 확인하기

K8s 기초 — Pod/Deployment/Service 생성

초급

kubectl로 nginx Pod를 생성하고 Deployment와 Service를 차례로 만들어 클러스터 외부에서 접근 가능한 상태까지 구성한다. K8s 3대 리소스의 역할과 관계를 직접 손으로 익힌다.

40📋 5단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

kubernetes입문 · 60
[Kubernetes] Deployment를 이용한 안정적인 서비스 배포와 롤백 전략
Kubernetes 트랙 계속
docker입문 · 30
[Docker] 백엔드 개발자에게 Docker와 컨테이너 가상화가 필수인 이유
Docker 트랙 시작점