Core concepts - 총 정리

2025. 12. 29. 10:14·CKA

이 글은 “쿠버네티스가 실제로 어떻게 돌아가는지”를 컴포넌트 흐름(데이터/제어) 관점으로 정리한 Chapter 1입니다.


1) Docker 이야기부터 시작하는 이유: “Docker = 런타임”이 아니라 “Docker 안에 런타임이 포함”이었기 때문

강의에서 “쿠버네티스가 Docker 지원을 중단했다”라는 말이 초보자를 혼란스럽게 만드는 이유는, Docker가 한 덩어리로 보이기 때문입니다.

Docker는 여러 구성요소의 묶음(bundle)이다

  • Docker CLI / Docker API: 개발자가 쓰는 도구
  • 이미지 빌드(빌더), 레지스트리 연동, 인증, 볼륨 등 부가 기능
  • 그리고 내부에 컨테이너 런타임(runc 등) 과 이를 관리하는 데몬

쿠버네티스 입장에서는 “도커라는 브랜드”가 필요한 게 아니라, 컨테이너를 실제로 실행하는 런타임이 필요합니다.

CRI(Container Runtime Interface): 쿠버네티스가 런타임과 대화하는 표준 인터페이스

  • 쿠버네티스는 CRI를 통해 런타임에 “이미지 풀”, “컨테이너 생성/시작/중지” 같은 작업을 요청합니다.
  • containerd 같은 런타임은 CRI 호환이라 쿠버네티스와 직접 붙을 수 있습니다.
  • 그래서 “Docker 전체”를 쿠버네티스 런타임으로 쓰지 않아도 되었고, 결과적으로 “Docker 지원 중단” 같은 표현이 생겼습니다.

“도커 설치 안 돼도 이미지 pull 가능한가?”

가능합니다. 노드에 Docker가 아니라 containerd 같은 CRI 런타임이 있으면 kubelet이 그 런타임을 통해 이미지를 pull하고 컨테이너를 실행합니다.

“containerd는 pull은 되는데 build는 안 되나?”

정확히는:

  • containerd는 “컨테이너 실행/이미지 관리” 쪽에 초점이 있고,
  • “이미지 빌드(build)”는 보통 Docker build, BuildKit, kaniko, buildah 같은 별도 빌더 계열 도구를 씁니다.
    즉, 빌드는 런타임의 주업무가 아닙니다.

ctr vs nerdctl vs crictl

  • ctr: containerd 기본 제공 / containerd 전용 / 디버깅용 / 사용자 친화적 아님
  • nerdctl: containerd 커뮤니티 / containerd 전용 / 일반 사용(Docker 대체) / Docker와 유사
  • crictl: Kubernetes 커뮤니티 / CRI 전체 지원 / 디버깅용 / kubelet 관점과 맞춰 사용
  • 일반적으로 kubectl에 문제가 생겨서 안될 경우 대부분 crictl로 처리가 되며, crictl도 안될 경우 nerdctl 사용하면 됨

2) 쿠버네티스 아키텍처: 요청 한 번이 클러스터를 바꾸는 실제 흐름

쿠버네티스를 “오브젝트 시스템”으로 이해하면 핵심이 빨리 잡힙니다.
오브젝트는 결국 etcd에 저장되고, 그 상태를 맞추려고 컴포넌트들이 움직입니다.

(1) etcd: 클러스터의 “진실의 원천(Source of Truth)”

  • etcd는 분산 Key-Value 저장소입니다.
  • 쿠버네티스에서 저장되는 것: 노드, 파드, 설정(ConfigMap), 시크릿, 계정/권한(Role/Binding) 등 “클러스터 상태” 전부.
  • kubectl get ... 로 보이는 대부분의 정보는 결국 etcd에 저장된 오브젝트를 기반으로 합니다.

(2) kube-apiserver: 클러스터의 “관문”이자 “유일한 etcd 직접 접근자”

강의에서 강조된 문장 그대로가 핵심입니다.

  • kubectl은 사실상 API 서버를 호출하는 클라이언트입니다.
  • API 서버는 요청을
    1. 인증(Authentication)
    2. 인가(Authorization)
    3. 유효성 검증(Validation)
    4. etcd 읽기/쓰기
      순으로 처리합니다.
  • etcd와 직접 상호작용하는 유일한 컴포넌트가 kube-apiserver입니다.
    • 스케줄러, 컨트롤러 매니저, kubelet 등은 모두 “API 서버를 통해” 클러스터를 바꿉니다.

(3) “Pod 생성 요청이 오면 실제로 뭐가 생기는가?”

강의 흐름을 그대로 정리하면:

  1. 사용자가 Pod 생성 요청(예: kubectl apply -f pod.yaml)
  2. API 서버가 Pod 오브젝트를 생성하고 etcd에 저장
    • 이 단계에서 Pod는 “오브젝트로서 존재”합니다.
  3. 스케줄러가 “nodeName이 없는 Pod”를 감지하고 노드 선택
  4. API 서버가 스케줄링 결과(바인딩)를 반영(역시 etcd 업데이트)
  5. 해당 노드의 kubelet이 “내 노드에 배정된 Pod”를 보고 컨테이너 런타임에 실행 요청
  6. kubelet이 상태를 API 서버에 보고 → etcd 업데이트

“노드가 할당되지 않은 새 Pod”는 Pod가 없다는 뜻인가?

아닙니다.

  • “오브젝트로서의 Pod”는 이미 API 서버/etcd에 존재합니다.
  • 다만 아직 어느 노드에서 실행할지 결정되지 않았고, 실제 컨테이너도 안 떠서 “Pending”일 수 있습니다.
    즉 “오브젝트는 생겼고, 실행은 아직” 상태입니다.

3) 컨트롤러는 왜 “쿠버네티스의 두뇌”인가: 원하는 상태(Desired State)를 맞추는 자동화 프로세스

컨트롤러의 정체

  • 컨트롤러는 “헬스체크를 직접 때리는 녀석”이라기보다,
  • API 서버를 통해 오브젝트 상태를 계속 관찰하고,
    “원하는 상태와 다르면 필요한 조치(새로 만들기/지우기 등)를 수행”하는 프로세스입니다.

“레플리케이션 컨트롤러가 Pod 상태를 어떻게 아나?”

핵심은 이 구조입니다.

  • kubelet이 노드에서 Pod/컨테이너 상태를 관찰
  • 그 상태를 API 서버에 보고
  • API 서버는 etcd를 업데이트
  • 컨트롤러는 API 서버를 통해 “현재 상태”를 보고 판단

즉, 보통 컨트롤러가 Pod에 직접 헬스체크를 쏘는 구조로 이해하기보다, 클러스터 상태 데이터(오브젝트 상태)를 보고 조치한다고 이해하는 게 맞습니다.


4) 스케줄러 vs 컨트롤러 매니저: 둘 다 “감시”하지만 역할이 다르다

둘 다 API 서버(정확히는 그 뒤의 상태 변화)를 “감시”하는 것처럼 보이지만, 책임이 다릅니다.

kube-scheduler

  • 책임: Pod를 어느 노드에 배치할지 결정
  • 실제로 노드에 Pod를 “만드는 작업”은 하지 않음 (그건 kubelet)

스케줄러는 보통 다음과 같은 로직을 수행합니다.

  1. 필터링: 조건에 안 맞는 노드 제거(리소스 부족 등)
  2. 스코어링: 남은 노드를 점수화해 최적 노드 선택

kube-controller-manager

  • 책임: 노드, 레플리카, 엔드포인트 등 다양한 컨트롤러를 묶어서 실행
  • 예: 노드 컨트롤러는 노드 상태를 보고 장애 시 조치, 레플리카 관련 컨트롤러는 “개수 유지” 조치 등

5) kubelet: “노드의 선장”이 실제 실행을 담당한다

kubelet은 워커 노드에서 다음을 수행합니다.

  • 노드를 클러스터에 등록
  • API 서버와 통신하는 워커 노드의 대표 에이전트
  • “내 노드에 배정된 Pod”를 보고 컨테이너 런타임에 실행 요청
  • 상태를 주기적으로 보고

중요 포인트:

  • kubeadm으로 클러스터를 올려도 kubelet은 “워커 노드에 설치/구동”이 전제인 경우가 많고(환경에 따라 자동화 정도는 다름),
  • 실행 주체는 kubelet입니다. 스케줄러는 결정만 합니다.
  • kubelet도 전반적인 운영을 담당하고 pod를 띄어라 등은 cri호출을 통해 containerd에게 명령

6) kube-proxy와 Service: “서비스는 가상 오브젝트지만, 트래픽은 실제로 흘러야 한다”

서비스는 “실체가 없는 가상 컴포넌트”

  • Pod처럼 컨테이너가 떠서 listen 하는 프로세스가 아닙니다.
  • “클러스터 메모리/오브젝트로 존재하는 추상”에 가깝습니다.

그런데 왜 서비스 IP로 접속이 되나?

여기서 kube-proxy가 등장합니다.

  • kube-proxy는 각 노드에서 실행되는 프로세스
  • 새 서비스가 생기면 iptables 같은 규칙을 만들어
    • 서비스 IP로 들어오는 트래픽을
    • 실제 백엔드 Pod IP로 전달하게 합니다.

즉, 서비스는 추상이고, kube-proxy가 노드 단의 네트워크 규칙으로 “추상을 현실로 만드는 역할”을 합니다.


7) Pod

“2개 이상 컨테이너가 절대 없다고 가정”하면 Pod의 장점이 줄어드는 건 맞습니다.
하지만 그럼에도 쿠버네티스가 Pod를 최소 단위로 삼은 이유는 다음 “샌드박스 단위” 때문입니다.

Pod = 컨테이너를 담는 “실행 샌드박스”

  • Pod는 애플리케이션의 단일 인스턴스다.
  • Pod는 Kubernetes에서 생성할 수 있는 가장 작은 배포 단위(오브젝트) 다.

스케일링은 “컨테이너 추가”가 아니라 “Pod 추가”로 한다

  • 보통 컨테이너와 Pod는 1:1 관계
  • 스케일 업: Pod를 새로 만든다
  • 스케일 다운: 기존 Pod를 삭제한다
  • 애플리케이션 확장을 위해 기존 Pod에 컨테이너를 추가하지 않는다

Pod에 여러 컨테이너?

Pod는 일반적으로 컨테이너와 1:1로 쓰이지만, 한 Pod 안에 여러 컨테이너를 넣을 수도 있다.
단, 중요한 전제가 있다.

  • “같은 종류의 컨테이너를 여러 개 넣어서 스케일링”하려는 목적이라면 → 잘못된 접근
    스케일링은 여전히 Pod를 늘리는 방식이다.
  • 멀티 컨테이너 Pod는 보통 서로 다른 역할의 컨테이너를 ‘붙여서’ 배치하는 경우에 쓴다.

특징

  • 두 컨테이너는 함께 생성되고 함께 종료된다(“같은 운명”)
  • 같은 네트워크 공간을 공유하므로 서로를 localhost로 호출하며 통신 가능
  • 같은 스토리지(볼륨)를 쉽게 공유할 수 있음

멀티 컨테이너 Pod를 Docker만으로 직접 운영하면 생기는 문제

  • “어떤 앱 컨테이너 ↔ 어떤 헬퍼 컨테이너”가 짝인지 맵을 유지
  • 링크/커스텀 네트워크로 컨테이너 간 통신을 직접 구성
  • 컨테이너 간 공유 볼륨을 만들고, 그 관계도 따로 관리
  • 앱 컨테이너가 죽으면 헬퍼도 필요 없어지니 헬퍼 컨테이너를 수동으로 종료
  • 새 앱 인스턴스를 띄울 때마다 헬퍼도 함께 띄우는 운영 작업이 추가됨

8) YAML로 Pod 만들기: 쿠버네티스 정의 파일의 공통 골격

쿠버네티스 오브젝트 YAML은 대부분 공통 구조를 가집니다.

최상위 4대 필드

  1. apiVersion
  2. kind
  3. metadata
  4. spec

apiVersion은 v1만 있나?

리소스마다 다릅니다.

  • Pod/Service 같은 핵심 리소스는 흔히 v1
  • ReplicaSet/Deployment 같은 건 보통 apps/v1
    즉 “v2/v3가 있냐”는 질문은 “리소스 그룹/버전에 따라 다르다”가 정확합니다.

kind는 왜 대문자로 쓰나?

  • Kubernetes API가 정의한 “리소스 타입 이름”이기 때문입니다. (Pod, Service, Deployment 등)
  • YAML 파서는 대소문자에 관대하지 않습니다. 정확히 써야 합니다.

metadata의 name과 labels는 무엇인가?

  • metadata.name: 오브젝트의 고유 이름
    • 같은 네임스페이스 내에서 동일 kind는 보통 이름이 유니크해야 합니다.
    • kubectl get pods nginx처럼 참조하는 기준이 됩니다.
  • metadata.labels: 검색/그룹핑/선택을 위한 태그(Key-Value)
    • “이 Pod는 어떤 역할인가?”를 기계가 찾기 쉽게 붙이는 표식입니다.
    • Service/ReplicaSet/Deployment가 Pod를 “선택”할 때 핵심이 됩니다.

중요한 뉘앙스:

  • “Pod들을 그룹화한다”는 말은
    • 레이블 자체가 태그를 붙이는 행위이고,
    • Service/ReplicaSet은 selector로 그 레이블을 기준 삼아 ‘논리적 그룹’을 만든다
      로 이해하면 정확합니다.
      즉, 그룹의 기준 데이터는 레이블이고, “그 레이블 집합을 서비스/레플리카셋이 채택해서 엔드포인트/대상 집합을 구성한다”가 전체 그림입니다.

9) Pod YAML 실습 예시 (이론 + CLI 생성 템플릿)

(1) 가장 기본 Pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx

(2) CLI로 YAML 템플릿 뽑기 (시험/실습에서 시간 절약)

  • --dry-run=client: 실제 생성하지 않고 “가능 여부만” 확인
  • -o yaml: YAML로 출력
kubectl run nginx --image=nginx --dry-run=client -o yaml

-o의 의미

--output 옵션의 축약입니다. 즉 -o yaml은 “출력 형식을 yaml로 해라” 입니다.


10) ReplicaController vs ReplicaSet vs Deployment: “상태 유지”의 계층 구조

10.1 ReplicationController(구형)와 ReplicaSet(신형)

둘 다 목적은 같습니다.

  • “지정한 개수만큼 Pod가 항상 살아있게 유지”

차이를 한 문장으로 요약하면:

  • ReplicaSet은 selector가 필수이고, 더 유연한 매칭을 지원합니다.
  • ReplicationController는 구형이고, 현대 쿠버네티스에서는 ReplicaSet을 권장합니다.

“차이가 단순 selector뿐인가?”

학습 관점에서 가장 큰 차이를 그렇게 잡아도 됩니다.
특히 강의 맥락에서도 “ReplicaSet은 selector를 반드시 정의해야 한다”가 핵심 포인트였습니다.

10.2 selector에 걸리는 Pod가 이미 존재하면?

ReplicaSet은 “선택된 Pod 수”를 보고 desired replicas를 맞춥니다.

  • replicas: 3
  • selector로 잡히는 기존 Pod: 3개
    → 새로 만들지 않습니다. 이미 충족했기 때문입니다.
  • replicas: 3
  • selector로 잡히는 기존 Pod: 4개
    → 줄여야(desired=3) 하므로 보통 하나를 종료시키는 방향으로 수렴합니다.
    (어떤 Pod가 정리될지는 상황/컨트롤러 판단에 따라 달라질 수 있지만 “개수 맞추기”가 목표입니다.)

10.3 Deployment: 운영에서 필요한 “롤링 업데이트/롤백/일시정지”의 주체

Deployment는 ReplicaSet의 상위 오브젝트입니다.

  • Deployment를 만들면 내부적으로 ReplicaSet이 생성되고
  • ReplicaSet이 Pod를 생성합니다.

Deployment가 제공하는 운영 기능:

  • 롤링 업데이트(한 번에 다 바꾸지 않고 순차 교체)
  • 롤백(업데이트 취소)
  • 일시정지/재개(변경을 모아 한 번에 롤아웃)

11) Service 3종: NodePort / ClusterIP / LoadBalancer

11.1 NodePort: 외부에서 노드 IP:포트로 접근

  • 노드의 특정 포트(기본 범위 30000~32767)를 열고
  • 그 트래픽을 Pod로 전달

핵심 포트 3개:

  • targetPort: Pod(컨테이너)가 실제로 여는 포트 (예: 80)
  • port: 서비스가 내부적으로 노출하는 포트 (보통 80)
  • nodePort: 노드에서 외부 접근을 받는 포트 (예: 30080)

11.2 ClusterIP: 클러스터 내부 통신의 표준

  • 서비스에 클러스터 내부 가상 IP + DNS 이름이 생김
  • 프론트엔드 → 백엔드, 백엔드 → DB/Redis 같은 내부 계층 통신에 사용

11.3 LoadBalancer: 클라우드에서 “진짜 외부 LB”를 붙여줌

  • AWS/GCP/Azure 같은 지원 클라우드에서 동작
  • 로컬/미지원 환경에서는 NodePort처럼만 보일 수 있음

11.4 생성 명령어

  • kubectl expose deployment web --type=NodePort --port=80 --target-port=8080
  • 이런식으로 service를 생성할 수 있는데 이는 web이라는 이름을 갖는 Deployment를 찾아서 그것의 label을 가져와 selector로 맵핑시킴

12) kubectl expose vs create service: “같은 Service인데 왜 명령이 다르지?”

쿠버네티스에서 서비스를 만드는 CLI 경로가 여러 개라서 그렇습니다.

kubectl expose

  • “기존 리소스(Pod/Deployment 등)를 노출(expose)한다”는 관점
  • 장점: 대상 리소스의 labels를 자동으로 selector로 사용하는 경우가 많음
  • 단점: NodePort 값 같은 것을 CLI에서 원하는 형태로 딱 지정 못하는 케이스가 생김(상황에 따라)

예:

kubectl expose pod redis --port=6379 --name=redis-service --dry-run=client -o yaml

이 명령은 파일을 자동 생성하지 않습니다.
표준 출력으로 YAML을 “찍어주는 것”이라서, 파일이 필요하면 리다이렉션이 필요합니다.

kubectl expose pod redis --port=6379 --name=redis-service --dry-run=client -o yaml > redis-service.yaml

kubectl create service ...

  • “서비스 오브젝트를 직접 생성한다”는 관점
  • 단점: 셀렉터가 자동으로 대상 Pod 레이블을 정확히 따라가지 않는 경우가 있어, 생성된 YAML을 수정해야 할 때가 있음

결론(시험/실전 팁):

  • 빠르게 만들 땐 expose가 편한 경우가 많고,
  • 옵션 한계가 있으면 --dry-run -o yaml로 뽑아서 YAML 수정 후 apply/create가 안정적입니다.

13) 네임스페이스: “이름/정책/리소스”의 경계

네임스페이스는 한 클러스터 안에서 리소스를 분리하는 가장 기본 단위입니다.

기본적으로 존재하는 것들:

  • default: 우리가 아무 생각 없이 작업하면 들어가는 곳
  • kube-system: 쿠버네티스 내부 컴포넌트용 (사용자 실수로 건드리면 위험)
  • kube-public: 모든 사용자가 볼 수 있어야 하는 일부 리소스용

왜 쓰나?

  • dev/prod 분리 (같은 클러스터를 쓰되 실수 방지)
  • 정책(RBAC) 분리
  • 리소스 할당량(ResourceQuota)로 과다 사용 제한

네임스페이스 간 서비스 접근 DNS 형태

  • 같은 네임스페이스면 db-service 같은 이름만으로 접근
  • 다른 네임스페이스면 보통:
    • 서비스이름.네임스페이스.svc.cluster.local

14) kubectl config set-context --current --namespace=dev 상세 해부

kubectl config set-context --current --namespace=dev
  • kubectl config: kubeconfig(클러스터 접속 설정) 조작
  • set-context: 컨텍스트(클러스터/유저/네임스페이스 묶음) 설정 변경
  • --current: 현재 사용 중인 컨텍스트를 대상으로
  • --namespace=dev: 기본 네임스페이스를 dev로 바꾸기

효과:

  • 이후 kubectl get pods는 기본으로 dev 네임스페이스를 조회
  • 다른 네임스페이스 보려면 -n default 같은 옵션을 명시해야 함

15) Imperative vs Declarative: 시험/실무에서 둘 다 써야 하는 이유

Imperative(명령형)

  • “이걸 만들어라 / 이걸 바꿔라”를 명령으로 즉시 수행
  • 빠르지만, 실행 자체가 기록/공유에 취약
  • 복잡한 요구사항은 커맨드가 길고 실수 확률이 늘어남

예:

  • kubectl run ...
  • kubectl create deployment ...
  • kubectl expose ...
  • kubectl scale ...
  • kubectl edit ...

Declarative(선언형)

  • YAML로 “원하는 상태”를 선언하고
  • kubectl apply로 클러스터가 그 상태로 수렴하게 함
  • GitOps/리뷰/재현성에 강함

16) apply의 내부 동작: Local vs Live vs Last-Applied

kubectl apply는 “그냥 덮어쓰기”가 아닙니다.
강의의 핵심은 세 가지를 비교한다는 점입니다.

  1. Local configuration (내 YAML)
  2. Live object configuration (클러스터에 실제 존재하는 오브젝트)
  3. Last-applied configuration (마지막 apply 때 저장한 스냅샷)

Last-applied는 어디에 저장되나?

  • 오브젝트의 annotation(주석)으로 저장됩니다.
  • 그래서 apply로 만든 리소스는 “마지막 apply 값”을 기억할 수 있습니다.
  • create/replace는 이 정보를 남기지 않는 흐름이므로 혼용에 주의가 필요합니다.

“local vs live만 비교하면 되지 않나?”가 헷갈리는 이유

헷갈리는 포인트를 정리하면 이렇습니다.

  • Live는 현재 상태라서, 다른 시스템/사람이 imperative로 바꾼 값이 섞일 수 있습니다.
  • Local에는 “내가 의도한 값”이 들어있고,
  • Last-applied는 “내가 이전에 apply로 의도했던 값”이 남아있습니다.

apply가 Last-applied를 쓰는 결정적 이유:

  • 필드 삭제 판단 때문입니다.
    • Local에서 어떤 필드를 지웠을 때,
    • 그게 “원래 없던 것”인지 “예전에 내가 넣었다가 지금 지운 것”인지
    • live만 보고는 판단이 애매해질 수 있습니다.
    • Last-applied를 보면 “이 필드는 과거에 내가 apply로 넣었는데, 지금 local에서 사라졌네 → 삭제 의도”라고 판단할 수 있습니다.

imperative로 live만 변경한 뒤 apply하면?

  • apply는 3-way merge로 “내가 관리하는 영역(Last-applied 기준)”을 중심으로 반영합니다.
  • 즉, “내가 apply로 관리하던 필드”는 local로 되돌릴 수 있고,
  • “내가 건드린 적 없는 필드(Last-applied에도 없고 local에도 없는 필드)”는 보존될 가능성이 큽니다.
    이게 단순 덮어쓰기와 다른 점입니다.

헷갈리는 점 정리

  • Live object configuration과 Last-applied configuration는 사실상 같은 것 아닌가?
    • Live는 현재 오브젝트에 실제로 적용된 애용
    • Last-applied는 내가 마지막으로 apply -f 적용했던 내용
    • Live는 Imperative 혹은 다른 시스템에서 건드리는 내용이 추가적으로 들어갈 수 있음
  • apply시 그냥 그러면 local로 덮으면 되는 것 아닌가?
    • Imperative 같은 것은 덮으면 되지만 다른 시스템에서 건드리던 내용은 건드리면 안됨
    • 다른 시스템에서 건드린 내용은 Last-applied와 Local 둘 다에도 없는 것으로 판별 가능

17) kubectl 생산성 도구: api-resources / explain

kubectl api-resources

  • “리소스 이름, 약칭, API 버전, 네임스페이스 범위” 등을 한 번에 확인
  • 시험에서 리소스 약칭/대소문자/버전이 기억 안 날 때 매우 유용

kubectl explain

  • 터미널에서 바로 스키마/필드 확인
  • kubectl explain pod
  • kubectl explain pod.spec
  • kubectl explain pod.spec --recursive (전체 필드 덤프)

이 흐름이 중요한 이유:

  • 문서 검색 없이도 “이 리소스에 어떤 필드가 있지?”를 확인 가능
  • YAML을 처음부터 만들기보다 필드를 빠르게 맞출 수 있음

18) 자주 나오는 CLI 실수 케이스 (이번 세션에서 나온 질문 기반)

1) “yml 자동 생성 아닌가?” → 출력만 하고 파일은 리다이렉션 필요

  • --dry-run=client -o yaml은 화면 출력입니다.
  • 파일로 저장하려면 >가 필요합니다.

2) kubectl create redis --image=redis -n finance가 왜 틀리나?

  • create는 리소스 타입을 정확히 요구합니다.
    • kubectl create deployment ...
    • kubectl create service ...
    • kubectl create namespace ...
  • 단순히 “redis라는 이름으로 이미지 실행”이면 보통 kubectl run을 씁니다.

3) kubectl run redis --image=redis:alpine --tier=db가 왜 틀리나?

  • kubectl run은 임의의 --tier 같은 플래그를 “레이블”로 해석하지 않습니다.
  • 레이블을 주려면 보통 --labels 형태를 사용합니다(버전/명령 체계에 따라 차이가 있어, 시험에서는 --dry-run -o yaml로 확인 후 확정하는 방식이 안전합니다).

4) kubectl expose pods httpd --port=80 --dry-run=client -o yaml 결과에 status:가 왜 있나?

  • kubectl이 출력하는 YAML 템플릿에 따라 status가 포함되어 보일 수 있습니다.
  • 실제로 매니페스트로 적용할 때는 보통 status는 쿠버네티스가 관리하는 영역이라, 필요 시 제거하는 것이 일반적입니다.
  • 가장 안전한 루틴은:
    1. 템플릿 생성
    2. 필요한 필드만 남기고 정리
    3. apply/create

19) Chapter 1 정리: “쿠버네티스는 결국 상태(etcd) + 관문(API 서버) + 수렴(컨트롤러/스케줄러/kubelet) + 연결(Service/kube-proxy)”

이 챕터의 핵심 문장들을 한 번에 요약하면 아래와 같습니다.

  • 클러스터의 상태는 etcd에 저장된다.
  • etcd와 직접 대화하는 건 kube-apiserver뿐이다.
  • 스케줄러는 “어디에 둘지” 결정하고, kubelet이 “실제로 실행”한다.
  • 컨트롤러는 “원하는 상태로 유지”되도록 계속 수렴시킨다.
  • 서비스는 가상 오브젝트지만 kube-proxy 규칙으로 트래픽이 흐르게 된다.
  • 네임스페이스는 이름/정책/리소스를 나누는 경계다.
  • 시험/실무 모두에서 --dry-run=client -o yaml, explain, api-resources, apply를 활용하면 속도와 정확도가 올라간다.

 

19) 헷갈리는 내용 간단한 추가 정리

  • NodePort Service도 내부 통신은 ClusterIP 방식으로 동작한다. NodePort는 “노드IP:nodePort”라는 추가 진입점만 붙는 것이고, 클러스터 내부에서는 보통 서비스 DNS/ClusterIP로 접근한다.
  • Service 생성에 도움되는 명령
    • 생성: kubectl expose deploy/<name> ..., kubectl create service ..., --dry-run=client -o yaml로 YAML 뽑기
    • 확인/디버깅: kubectl get svc -o wide, kubectl describe svc, kubectl get endpoints, kubectl get endpointslices, kubectl get pods -l ...
  • 왜 deployment를 쓰나?
    Service는 라우팅(주소/로드밸런싱)만 하고, Pod를 유지/복구/스케일/롤링업데이트/롤백하는 건 Deployment(ReplicaSet)가 담당한다. Pod만 띄우고 Service 붙이는 건 가능하지만 운영엔 취약하다.
  • kubectl expose web --port=...는 보통 안 됨
    expose는 대상 리소스 타입이 필요해서 보통 kubectl expose deploy/web ... 또는 kubectl expose pod/webpod ...처럼 타입을 명시하는 게 안전하다.
  • kubectl expose pod webpod ...가 selector를 만드는 방식
    Pod “이름”을 selector로 쓰는 게 아니라, Pod의 labels를 읽어서 Service spec.selector로 복사한다. 그래서 같은 라벨을 가진 Pod가 여러 개면 전부 선택된다.
  • Service 이름과 라벨은 별개
    Service 이름은 기본적으로 expose한 리소스 이름을 따라간다(원하면 --name으로 변경 가능). 라벨은 selector(대상 선택) 용도다.
  • Service DNS 접근 규칙(같은 클러스터)
    • 같은 네임스페이스: http://svc-name
    • 다른 네임스페이스: http://svc-name.namespace (또는 svc-name.namespace.svc)
    • 완전한 FQDN: svc-name.namespace.svc.cluster.local (도메인은 클러스터 설정에 따라 다를 수 있음)
  • 다른 클러스터는 FQDN을 길게 쓴다고 접근되지 않음
    클러스터 간 접근은 별도 연결/노출(LoadBalancer/Ingress/Gateway, VPC 연결+DNS, 멀티클러스터/서비스메시 등)이 필요하다.
  • 노드마다 /etc/resolv.conf는 다를 수 있지만, 중요한 건 Pod의 /etc/resolv.conf
    일반 Pod는 dnsPolicy: ClusterFirst로 kubelet이 클러스터 DNS(CoreDNS)와 search domain을 Pod에 주입하므로, 어느 노드에 떠도 Pod 기준으로 일관되게 서비스 이름 해석이 된다(예외: dnsPolicy: Default, hostNetwork 조합 등).
 

'CKA' 카테고리의 다른 글

Scheduling- Label & Selector  (0) 2025.12.29
Scheduling- 수동 스케줄링  (0) 2025.12.29
Core Concepts - apply 커맨드 실행시 발생하는 비교 로직  (0) 2025.12.28
Core Concepts - 명령어 정리  (0) 2025.12.28
Core Concepts - Imperative vs Declarative  (0) 2025.12.28
'CKA' 카테고리의 다른 글
  • Scheduling- Label & Selector
  • Scheduling- 수동 스케줄링
  • Core Concepts - apply 커맨드 실행시 발생하는 비교 로직
  • Core Concepts - 명령어 정리
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      jdk 동적 프록시
      WAS
      cglib
      프록시 팩토리
      gesingleresult
      빈 후처리기
      @within
      락
      Thread
      조회 성능 최적화
      버퍼
      페치 조인
      @discriminatorcolumn
      Target
      단방향 맵핑
      프록시
      @discriminatorvalue
      hibernate5module
      typequery
      JPQL
      reentarantlock
      양방향 맵핑
      log trace
      고급
      자바
      jpq
      스레드
      requset scope
      김영한
      @args
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Core concepts - 총 정리
    상단으로

    티스토리툴바