쿠버네티스란?

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

쿠버네티스란?

쿠버네티스란?

컨테이너화된 애플리케이션의 배포, 확장 및 관리를 자동화하는 오픈소스 컨테이너 오케스트레이션 플랫폼이다.

그래서 왜 쓰는데??

쿠버네티스를 사용하는 핵심 이유는 자동화와 안정성이다.

  • 자동 복구 (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 사용법에 대해서 작성해 볼 예정~