쿠버네티스란?
쿠버네티스에 대해 알아보자


쿠버네티스란?
컨테이너화된 애플리케이션의 배포, 확장 및 관리를 자동화하는 오픈소스 컨테이너 오케스트레이션 플랫폼이다.
그래서 왜 쓰는데??
쿠버네티스를 사용하는 핵심 이유는 자동화와 안정성이다.
- 자동 복구 (Self-healing): 특정 컨테이너에 문제가 생기면, 쿠버네티스는 이를 감지하고 자동으로 재시작하거나 새로운 컨테이너로 교체하여 서비스 중단을 최소화한다.
- 자동 확장 (Auto-scaling): 사용량이 급증하면 자동으로 컨테이너 수를 늘려 트래픽을 감당하고, 반대로 사용량이 줄면 컨테이너 수를 줄여 자원을 효율적으로 사용한다.
- 배포 및 롤백 자동화: 새로운 버전의 애플리케이션을 배포할 때, 순차적으로 컨테이너를 업데이트(롤링 업데이트)하여 무중단 배포를 가능하게 한다. 만약 배포 후 문제가 발생하면 이전 버전으로 쉽게 되돌릴(롤백) 수 있다.
- 서비스 디스커버리 및 로드 밸런싱: 여러 컨테이너에 걸쳐 있는 애플리케이션에 대해, 쿠버네티스는 자체 DNS나 IP 주소를 통해 쉽게 접근할 수 있도록 하고, 들어오는 네트워크 트래픽을 여러 컨테이너에 자동으로 분산시켜 과부하를 방지한다.
Docker 와 차이?
그냥 도커 쓰면 안되나??
라는 생각이 들기도 한다.
기본적으로 도커는 컨테이너를 Build, Run 하는 기술에 중점을 두고 어플리케이션을 컨테이너라는 표준화된 규격으로 포장하는 역할이다.
그리고 쿠버네티스는 이런 수많은 컨테이너들을 클러스터 환경에서 효율적으로 관리 조율 즉 오케스레이션하는데 중점을 둔다.
따라서 소규묘 어플리케이션을 운영할때는 도커만으로도 충분히 운영이 가능하지만
컨테이너가 여러 서버에 걸쳐서 수십, 수백 개로 확장된다면 쿠버네티스와 같은 오케스트레이션 기능이 필수적이게 된다.
쿠버네티스 구성요소
핵심 컴포넌트
기본적으로 쿠버네티스 클러스터는 컨트롤 플레인, 워커 노드로 구성된다.
컨트롤 플레인
- API 서버 (kube-apiserver): 클러스터의 모든 요청과 명령은 해당 서버를 통해서만 전달된다.
- etcd: 클러스터의 모든 상태 정보를 저장한다. '어떤 애플리케이션이 실행 중인지', '각각 몇 개씩 실행해야 하는지' 등 모든 설정과 상태가 여기에 기록된다.
- 스케줄러 (kube-scheduler): 새로운 컨테이너(파드)를 어느 워커 노드에 배치할지 결정한다. 각 워커 노드의 자원 상태(CPU, 메모리 등)를 보고 가장 적절한 곳에 컨테이너를 할당한다.
- 컨트롤러 매니저 (kube-controller-manager): 클러스터의 상태를 지속적으로 확인하고 원하는 상태를 유지한다.
워커 노드
- 큐블릿 (Kubelet): 각 노드에서 컨트롤 플레인의 API 서버로부터 명령을 받아 컨테이너가 제대로 실행되고 있는지 감시하고, 컨테이너의 상태를 컨트롤 플레인에 보고한다.
- 큐브 프록시 (Kube-proxy): 노드의 네트워크를 담당한다. 컨테이너들이 서로 통신하고, 외부에서 컨테이너에 접근할 수 있도록 네트워크 규칙을 관리하고 연결을 담당한다.
- 컨테이너 런타임 (Container Runtime): 컨테이너를 실제로 실행하는 엔진이다. 가장 대표적인 것이 도커(Docker)이며, 이 외에도
containerd
,CRI-O
등이 있다.
파드(Pod)
파드(Pod) 는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위이다.
파드는 하나 이상의 컨테이너의 그룹이다.
이 그룹은 스토리지 및 네트워크를 공유하고, 구동 방식에 대한 명세를 갖는다.
실제 사용?
일반적으로는 파드를 직접 만들 필요는 없다.
대신 Deployment, Job 같은 워크로드 리소스를 사용하여 생성한다.
상태 추적이 필요한 경우엔 StatefulSet 리소스를 사용한다.
실제 거의 모든 쿠버네티스 환경에서 '파드 하나당 핵심 컨테이너 하나' (1 Pod = 1 Container) 원칙이 모범 사례(Best Practice)이다.
여러 컨테이너를 사용하는 경우는
사이트카 패턴을 사용할 때로
메인 컨테이너의 기능을 보조, 확장하는 헬퍼 컨테이너를 함께 띄우는 경우이다.
파드와 컨트롤러
다음은 하나 이상의 파드를 관리하는 워크로드 리소스의 몇 가지 예시이다.
- 디플로이먼트
- 스테이트풀셋
- 데몬셋(DaemonSet)
파드 템플릿
워크로드 리소스에 대한 컨트롤러는 파드 템플릿 에서 파드를 생성하고 사용자 대신 해당 파드를 관리한다.
파드템플릿(PodTemplate)은 파드를 생성하기 위한 명세이며 워크로드 리소스에 포함된다.
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 여기서부터 파드 템플릿이다
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# 여기까지 파드 템플릿이다
파드 갱신 및 교체 그리고 라이프사이클
워크로드 리소스의 파드 템플릿이 바뀌면, 컨트롤러는 기존의 파드를 갱신하거나 패치하는 대신 갱신된 템플릿을 기반으로 신규 파드를 생성한다.
파드는 정의된 라이프사이클을 따른다.
Pending 단계에서 시작해서, 기본 컨테이너 중 적어도 하나 이상이 OK로 시작하면 Running 단계를 통과하고, 그런 다음 파드의 컨테이너가 실패로 종료되었는지 여부에 따라 Succeeded 또는 Failed 단계로 이동한다.
stateDiagram-v2
[*] --> Pending
Pending --> Running: 하나 이상의 컨테이너 시작
Running --> Succeeded: 모든 컨테이너 성공적으로 종료
Running --> Failed: 컨테이너가 실패로 종료
Succeeded --> [*]
Failed --> [*]
간단하게 테스트해보기
Mac Apple Silicon기준
brew install kubectl
brew를 사용해서 설치
brew install --cask docker
Docker Desktop 실행 및 쿠버네티스 활성화를 해준다.
- 설치가 끝나면
응용 프로그램
폴더에서 Docker 앱을 실행 - 실행 후, 메뉴 막대의 Docker 아이콘을 클릭하고
Settings
(설정) 클릭 Kubernetes
탭으로 이동해서Enable Kubernetes
체크박스를 선택
$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
docker-desktop Ready control-plane 58s v1.32.2
요렇게 나오면 쿠버네티스 세팅 완료이다.
E1005 17:01:25.151652 51212 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp [::1]:8080: connect: connection refused"
요런 식으로 에러 뜬다면 도커 데스크탑앱에서 쿠버네티스가 정상적으로 활성화 되었는지 확인
다음은 간단하게 Nginx를 띄워보자
$ kubectl create deployment my-nginx --image=nginx
deployment.apps/my-nginx created
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
my-nginx 0/1 1 0 7s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-nginx-5b584c864b-cllht 0/1 ContainerCreating 0 13s
$ kubectl expose deployment my-nginx --type=LoadBalancer --port=80
service/my-nginx exposed
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 100s
my-nginx LoadBalancer 10.100.112.99 localhost 80:32212/TCP 5s
http://localhost/ 로 접속해보면
정상적으로 노출되는것을 확인할 수 있다~
지금은 간단하게 Nginx를 띄웠지만
yaml 로 설정을 추가해서 띄우면 복잡한 어플리케이션도 띄울 수 있다~
띄운 k8s 정리
$ kubectl delete service my-nginx
$ kubectl delete deployment my-nginx
다음 포스트에서는 EKS 사용법에 대해서 작성해 볼 예정~