k8s 심화

Jeonghyeon Park·2025년 4월 23일

SKALA

목록 보기
13/13
post-thumbnail

Docker 네트워크 에러: TCP 포트 충돌

컨테이너 실행 중 다음과 같은 오류 메시지를 만난 적이 있다:

docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint ...: failed to listen on TCP socket: address already in use

이 에러는 호스트의 포트가 이미 사용 중일 때 발생한다. 특히 Docker는 -p <host_port>:<container_port> 방식으로 포트를 바인딩하므로, 이미 바인딩된 포트를 또 사용하려 하면 위와 같은 오류가 난다.

해결 방법

  1. 현재 사용 중인 포트를 확인:

    lsof -i -P -n | grep LISTEN

    또는:

    sudo lsof -iTCP -sTCP:LISTEN -n -P
  2. 필요 시 해당 프로세스 종료:

    kill -9 <PID>
  3. 문제가 되는 컨테이너 정리:

    docker ps -a
    docker rm -f <container_id>
  4. Docker 네트워크 설정 리셋 (macOS 기준):

    # Docker Desktop 환경에서는 아래 명령은 직접 실행 불가
    # 대신 Docker 재시작 또는 재설치를 통해 처리

쿠버네티스 리소스 상태 확인

kubectl get pod -n skala-practice
  • 현재 skala-practice 네임스페이스에 속한 파드들의 상태를 확인할 수 있다.
  • 이 명령은 현재 컨텍스트에 상관없이, 특정 네임스페이스의 리소스를 확인할 수 있게 해준다.
kubectl get ns
  • 전체 네임스페이스 리스트를 조회할 수 있다.
  • 단, 모든 네임스페이스를 조회하려면 해당 권한이 필요하다. RBAC 설정에 따라 제한될 수 있다.

쿠버네티스의 인증 구성 요소

sa.crt 파일

  • 클러스터 내부의 서비스 계정이 API 서버에 접근하기 위한 인증서 파일이다.
  • /var/run/secrets/kubernetes.io/serviceaccount/sa.crt 경로에 존재하며, Pod 내부에서 자동 마운트된다.
  • 함께 사용되는 토큰(token)과 네임스페이스 정보(namespace)와 함께 API 인증에 사용된다.

etcd란?

  • 쿠버네티스 클러스터의 모든 상태 정보를 저장하는 key-value 저장소.
  • 클러스터 상태, 네임스페이스, 파드 정보, 컨피그맵, 시크릿 등 모든 리소스의 메타데이터가 저장된다.
  • Control Plane 구성 요소 중 하나이며, 단일 장애 지점을 방지하기 위해 HA 구성이 권장된다.

kubelet과 kube-proxy

kubelet

  • 각 워커 노드에서 실행되는 에이전트.
  • API 서버와 통신하여 파드를 실행하고, 상태를 주기적으로 보고한다.
  • PodSpec에 따라 컨테이너를 실제로 생성하고 관리한다.

kube-proxy

  • 클러스터 내부에서 서비스 간 네트워크 라우팅을 담당하는 컴포넌트.
  • iptables 또는 IPVS 기반으로 서비스 IP에 대한 트래픽을 올바른 파드로 전달한다.
  • kube-proxy가 없다면, 클러스터 DNS 및 서비스 디스커버리가 동작하지 않는다.

Namespace란?

  • 쿠버네티스 리소스를 논리적으로 격리하기 위한 가상 클러스터 단위.
  • 리소스 이름 충돌을 방지하고, 리소스 관리/권한 제어/할당량 설정 등에 사용된다.
  • 예: dev, staging, production 등 환경별 분리 가능.

kubectl get ns vs kubectl get pod

명령어설명
kubectl get ns클러스터 전체의 네임스페이스 목록 확인
kubectl get pod현재 컨텍스트 또는 지정한 네임스페이스 내의 파드 목록 확인

네임스페이스를 지정하지 않으면 기본(default) 네임스페이스를 기준으로 조회된다.

다른 네임스페이스의 존재 확인 가능 여부

  • 가능은 하지만, 권한이 필요하다.
  • kubectl get ns 자체는 리소스 리스트 요청이므로, list namespaces 권한이 필요하다.
  • 제한된 사용자라면, 자신이 속한 네임스페이스 외에는 보이지 않을 수 있다.

API Group이란?

쿠버네티스 API는 리소스들을 그룹으로 나눠 관리한다. 각 그룹은 특정 범위의 리소스를 제공한다.

주요 API Group

  • core (빈 그룹): Pod, Service, ConfigMap, Secret 등 기본 리소스
  • apps: Deployment, StatefulSet, DaemonSet 등
  • batch: Job, CronJob 등
  • rbac.authorization.k8s.io: Role, RoleBinding 등
  • apiextensions.k8s.io: CRD
  • metrics.k8s.io: 리소스 사용량 정보 제공 (Metrics Server)

확인은 다음과 같이 가능:

kubectl api-resources --api-group=<group>

/metrics 엔드포인트

kubectl get --raw /metrics
  • API 서버 자체의 Prometheus 포맷 메트릭 정보를 출력한다.
  • 이 정보를 Prometheus가 수집해서 Grafana 같은 대시보드에서 시각화할 수 있다.
  • 일반적으로 인증이 필요한 엔드포인트이며, 보안상 외부로는 노출하지 않는 것이 좋다.

kubectl get task는 무엇인가?

task는 쿠버네티스 기본 리소스가 아니며, 보통 Custom Resource Definition (CRD)을 통해 생성된 리소스다.

대표적인 예: Tekton Pipelines

  • Task: 하나의 CI/CD 작업 단위
  • Pipeline: Task들을 묶은 실행 흐름
kubectl get task

이 명령이 동작한다면, 클러스터에 task라는 CRD가 등록되어 있다는 의미다.

확인 방법:

kubectl get crd | grep task

리소스 사용량 확인 명령어 정리

Pod별 사용량

kubectl top pod -n <namespace>

노드별 사용량

kubectl top node

Pod 리소스 요청/제한 확인

kubectl get pod <name> -o=jsonpath="{.spec.containers[*].resources}"

모든 네임스페이스에서 파드 리소스 보기

kubectl top pod --all-namespaces

좋아, 아래는 지금까지 네가 질문한 내용들을 기반으로 기술 블로그 스타일로 정리한 마크다운 문서야. 이건 스터디용으로도 좋고, 바로 블로그에 올려도 어울릴 만큼 깊이 있고 체계적으로 작성했어.


Init Container 동작 원리 및 종료 후 상태

Kubernetes에서 initContainer는 Pod의 메인 컨테이너가 시작되기 전에 일회성 작업을 수행하기 위한 컨테이너이다. Init Container는 모두 순차적으로 실행되며, 하나라도 실패하면 Pod 자체가 대기 상태에 머물게 된다.

성공적으로 실행된 Init Container는 종료되며, kubectl exec로는 접근이 불가능하다. 예를 들어, 다음과 같이 작성된 Init Container는 특정 파일(/root/active.enabled)이 생성될 때까지 대기하다가 종료된다:

initContainers:
  - name: check-active-enabled
    image: busybox
    command:
      - sh
      - -c
      - |
        timeout 300 sh -c "
        while [ ! -f /root/active.enabled ]; do
          echo 'Waiting for active.enabled file...'
          sleep 5
        done
        echo 'File active.enabled found. Initialization complete.'
        "
    volumeMounts:
      - name: root-volume
        mountPath: /root

timeout으로 타임 리미트를 설정해 무한 대기를 방지하며, 파일이 존재하면 성공적으로 종료된다. 이 상태는 kubectl describe pod에서 State: TerminatedExit Code: 0으로 확인 가능하다.


Init Container와 메인 컨테이너 간 볼륨 공유 문제

Init Container에서 생성한 파일이 메인 컨테이너에서 보이지 않는 경우가 있는데, 이는 볼륨 공유 설정이 되어 있지 않아서 발생하는 문제이다.

Init Container가 /root에 볼륨을 마운트했지만 메인 컨테이너가 동일한 볼륨을 마운트하지 않았다면, 파일 시스템이 완전히 분리된다.

문제 발생 예시:

initContainers:
  - name: check-active-enabled
    ...
    volumeMounts:
      - name: root-volume
        mountPath: /root

containers:
  - name: init-container-test
    ...
    # volumeMounts 없음 → /root는 다른 공간

해결 방법:

containers:
  - name: init-container-test
    ...
    volumeMounts:
      - name: root-volume
        mountPath: /root

Init Container와 App Container 모두 동일한 볼륨(root-volume)을 /root 경로에 마운트해야 동일한 파일 시스템을 사용할 수 있다.


kubectl get pod -w 명령어의 활용

kubectl get pod -wkubectl get pod 명령어에 --watch 옵션을 준 형태로, Pod의 상태 변화를 실시간으로 모니터링할 수 있다.

kubectl get pod -w

이 명령은 배포, 초기화, 재시작, CrashLoop 등 다양한 상태 변화를 실시간으로 보여주기 때문에 디버깅 시 매우 유용하다. 종료하려면 Ctrl + C를 누르면 된다.


Service Mesh와 Envoy Proxy 개요

Service Mesh란?

Service Mesh는 마이크로서비스 간의 통신을 제어하고, 보안, 트래픽 제어, 관측 기능 등을 담당하는 인프라 계층이다. 일반적으로 프록시를 사이드카로 각 서비스에 붙여 트래픽을 관리한다.

이러한 구조를 통해 다음과 같은 문제를 코드 수정 없이 해결할 수 있다:

  • 요청 리트라이, 타임아웃
  • mTLS 보안 통신
  • 레이트 리밋
  • 서킷 브레이커
  • 트래픽 분산 (A/B 테스트, 카나리 배포)
  • 모니터링 및 분산 추적

Envoy Proxy란?

Envoy는 Lyft에서 개발한 고성능 L7 프록시로, 현재는 Service Mesh 솔루션에서 거의 표준처럼 사용된다. Istio를 포함한 대부분의 서비스 메시에서 사이드카 프록시로 Envoy를 사용한다.

Envoy는 다음 기능들을 제공한다:

  • HTTP/gRPC 기반 라우팅
  • mTLS 기반의 암호화된 통신
  • 장애 대응을 위한 서킷 브레이커
  • Prometheus, Zipkin, Jaeger와의 통합
  • 로드 밸런싱 및 헬스 체크
  • 다양한 플러그인 및 필터 체인

대표적인 Service Mesh 솔루션

이름특징
Istio가장 기능이 풍부하고 복잡함. Envoy 기반
Linkerd경량 서비스 메시. Rust 기반 proxy 사용
ConsulHashiCorp 제공. Consul KV와 통합
Kuma / OSMCNCF 기반, 간단하고 가벼움

마무리

k8s 어려운데 재밌다. 아닌가, 이용우 교수님이 잘 가르쳐주시는건가?

profile
안녕하세요

0개의 댓글