71일차는 파일이 날라감 이슈로 인해 작성하지 못했습니다
오늘부터 쿠버네티스를 배우기 시작했다. 도커가 단일 컨테이너를 다루는 도구라면, 쿠버네티스는 여러 컨테이너를 관리하는 컨테이너 오케스트레이션 툴이다.
실습은 con_tem VM을 복제해서 총 3개의 노드를 구성하는 방식으로 진행했다.
| 역할 | IP | 호스트네임 |
|---|---|---|
| master | 211.183.3.100/24 | master |
| worker1 | 211.183.3.110/24 | worker1 |
| worker2 | 211.183.3.120/24 | worker2 |
VM 복제 후 IP와 호스트네임을 직접 수정해줘야 한다.
여기서 Docker는 이미지 빌드 전용 도구다. 쿠버네티스의 컨테이너 런타임과는 무관하다. 마스터 노드에서 docker build를 할 예정이라 스크립트 실행 권한을 먼저 줬다.
root@master:~# chmod +x check_ip_and_restart_docker.sh
yaml 파일을 편하게 수정하기 위해 vimrc를 설정해준다.
vi ~/.vimrc
쿠버네티스 클러스터는 크게 마스터 노드(Control Plane) 와 워커 노드로 나뉜다.
마스터 노드에만 존재하는 컴포넌트들이다. 클러스터 전체를 관리하고 제어하는 역할을 한다.
클러스터의 모든 요청이 통과하는 관문이다. kubectl 명령어를 치면 결국 이 apiserver에 요청이 간다. 클러스터 내 모든 컴포넌트들도 apiserver를 통해 통신한다.
새로 생성된 Pod를 어느 노드에 배치할지 결정하는 컴포넌트다. 노드의 리소스 상태, 제약 조건 등을 고려해서 최적의 노드를 선택한다.
클러스터의 상태를 원하는 상태(Desired State)로 유지시켜주는 컴포넌트다. 예를 들어 Pod가 3개 있어야 하는데 1개가 죽으면, 자동으로 새 Pod를 띄워서 3개를 맞춰준다.
클러스터의 모든 상태 데이터를 저장하는 key-value 저장소다. 클러스터의 두뇌 같은 존재로, etcd가 죽으면 클러스터 전체가 마비된다. 그래서 실무에서는 etcd를 별도로 이중화해서 운영하는 경우가 많다.
마스터, 워커 구분 없이 모든 노드에 공통으로 존재하는 컴포넌트들이다.
쿠버네티스의 기본 실행 단위다. Pod도 결국 컨테이너로 구성되어 있으며, 이 컨테이너를 실행하고 삭제하기 위해 Docker, containerd, CRI-O 같은 CRI(컨테이너 런타임) 가 필요하다.
Pod 하나에 컨테이너가 여러 개 들어갈 수도 있는데, 같은 Pod 안의 컨테이너들은 네트워크와 스토리지를 공유한다.
# Pod 생성 (run 방식 - 간단하게 테스트할 때)
root@master:~# kubectl run test-pod --image=public.ecr.aws/docker/library/nginx:alpine
# Pod 목록 확인
root@master:~# kubectl get pod
# Pod 상세 정보 확인 (트러블슈팅할 때 유용)
root@master:~# kubectl describe pod test-pod
# 각 리소스 관련 이벤트들을 확인 가능하다.
# 실시간 모니터링
root@master:~# watch kubectl get pod
# Pod 삭제
root@master:~# kubectl delete pod test-pod
Pod가 잘 안 뜨거나 이상하면
kubectl describe pod <pod명>으로 이벤트 로그를 확인하는 게 트러블슈팅의 기본이다.
kubectl run은 간단하게 Pod를 띄울 때 쓰고, 실제로는 매니페스트 파일을 작성해서 apply하는 방식을 더 많이 쓴다.
root@master:~# vi test-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- image: public.ecr.aws/docker/library/httpd:latest
name: test-con
root@master:~# kubectl apply -f test-pod.yml
kubectl apply -f는 도커의 docker compose up, docker stack deploy와 비슷한 개념이다.
내가 원하는 상태(Desired State)를 매니페스트 파일에 미리 정의해두고 apply해서 반영하는 방식이다. run에 비해 업데이트가 훨씬 수월한데, 매니페스트 수정 후 다시 apply하면 변경사항이 바로 반영된다.
yml 파일 작성 시 반드시 들어가야 하는 항목들이 있다. 이게 빠지면 apply 자체가 안 된다.
| 항목 | 설명 |
|---|---|
apiVersion | 사용할 Kubernetes API 버전 (예: v1, apps/v1) |
kind | 리소스 종류 (Pod, Deployment, Service 등) |
metadata | 이름, 네임스페이스, 레이블 등 메타 정보 |
spec | 실제 리소스 스펙 정의 (컨테이너 이미지, 포트 등) |
클러스터에서 문제가 생겼을 때 주로 쓰는 명령어들이다.
# Pod 상태 확인
kubectl get pod
kubectl get pod -o wide # 어느 노드에 배치됐는지도 같이 확인
# 상세 이벤트 확인 (가장 많이 쓰는 트러블슈팅 명령어)
kubectl describe pod <pod명>
# Pod 로그 확인
kubectl logs <pod명>
# 모든 리소스 확인
kubectl get all
기본적으로 kubectl은 마스터 노드에서만 동작한다. worker1 노드에서도 kubectl로 마스터 노드의 apiserver에 요청할 수 있는 상태를 만드는 실습을 진행했다.
마스터 노드의 kubeconfig 파일(~/.kube/config)을 worker 노드에 복사해주면 된다.
# 마스터 노드에서
scp ~/.kube/config root@worker1:~/.kube/config
# worker1에서 확인
kubectl get nodes
label은 쿠버네티스에서 정말 중요한 개념이다. 리소스에 key-value 형태로 붙이는 태그인데, 단순한 태그처럼 보이지만 쿠버네티스의 핵심 동작 원리와 연결된다.
metadata:
name: my-pod
labels:
app: web
env: production
label을 잘못 설정하면 Service가 Pod를 못 찾거나, Deployment가 엉뚱한 Pod를 관리하는 문제가 생긴다. 나중에 배울 Service, Deployment와 연결되는 개념이라 지금부터 잘 이해해두는 게 중요하다.
오늘은 Pod 위주로 배웠지만, 쿠버네티스에는 다양한 리소스들이 있다. 앞으로 배울 내용들이다.
| 리소스 | 설명 |
|---|---|
| Pod | 기본 실행 단위 |
| Deployment | Pod를 선언적으로 관리, 롤링 업데이트 지원 |
| Service | Pod에 안정적인 네트워크 엔드포인트 제공 |
| ConfigMap | 설정 데이터를 Pod에 주입 |
| Secret | 민감한 데이터(비밀번호 등)를 안전하게 관리 |
| Namespace | 클러스터를 논리적으로 분리 |
오늘은 쿠버네티스의 기본 개념과 클러스터 구성, Pod 생성 방법까지 배웠다. 도커랑 비교하면서 배우니까 이해가 훨씬 잘 됐다. 특히 kubectl run vs kubectl apply -f의 차이, Desired State 개념, 그리고 label이 핵심인 것 같다. label은 나중에 Service, Deployment랑 연결되면서 더 중요해질 것 같으니 잘 기억해둬야겠다.
이번 velog는 AWS Kiro를 통해 작성하였다. 배운 내용을 Notion에 정리하고 Kiro를 통해 검토받아 작성하였다.