11 min read

Kubernetes 사용 방법

쿠버네티스 란?

쿠버네티스(Kubernetes)는 컨테이너 오케스트레이션 엔진이며 구글내부에서 사용하던 오케스트레이션 솔루션이였습니다.
구글은 이를 Linux Foundation의 CNCF프로젝트로 편입하여
오케스트레이션은 컴퓨터 시스템과 소프트웨어의 자동화된 구성, 조율, 관리를 뜻하며 쿠버네티스는 컨테이너에 이러한 개념을 적용했다고 보시면됩니다.
쿠버네티스는 쉽고 자동화된 배포, 업데이트(롤링 업데이트)를 수행하고 다운타임이 거의 없이 앱과 서비스를 관리함으로써 개발 프로세스의 속도를 높일 수 있습니다.
기본 Docker 지식을 사용하여 애플리케이션을 패키징하고 쿠버네티스에 배포할 수 있습니다.

쿠버네티스 구성요소

쿠버네티스는 클러스터 형태로 배포되며 클러스터를 컨트롤하는 컨트롤 플레인(Master Node) 컴포넌트와 노드(Worker Node) 컴포넌트로 이루어져있습니다.

컨트롤 플레인(Control Plane)

컨트롤 플레인은 클러스터의 상태 및 구성에 대한 데이터와 함께 클러스터를 제어하며 노드 컴포넌트와 지속적으로 접촉하여 구성 및 상태확인 작업을 수행합니다.

아래는 컨트롤 플레인의 각각의 컴포넌트를 설명합니다.

1. kube-apiserver

쿠버네티스 API 서버는 클러스터의 모든 구성요소를 엑세스하는 서버이며 API 객체에 대한 데이터를 검증하고 구성하는 역할을 담당합니다.
kube-apiserver는 REST API로 구현되어있으며 http 또는 https 프로토콜을 사용하여 오브젝트를 관리할 수 있으며, 일반적으로는 kubectl을 사용하여 kube-apiserver로 API 요청을 합니다.

2. etcd

클러스터에서 액세스해야 하는 데이터를 안정적으로 저장하는 방법을 제공하는 강력하게 일관된 분산 키-값 저장소입니다.
kube-apiserver에 API요청이 발생하면 모든 데이터를 저장하게됩니다.
예를들어 kube-apiserver에서 Pod(쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위)를 생성하는 요청을 받으면 해당 매니페스트(리소스를 정의한 정보) 파일을 키-값 형태로 etcd에 저장합니다.

3. kube-scheduler

노드를 할당하지 않은 Pod를 감시하고 실행할 노드를 선택하는 역할을 합니다.
Pod를 배포할 때 kube-scheduler는 Node를 지정하지않은 Pod에 대해서 최적의 노드를 선택하여 해당 노드에 Pod를 배치합니다.
kube-scheduler는 kube-apiserver를 통해 Pod 정보를 모니터링하며 새로운 Pod(노드를 할당하지 않은 Pod)를 Pod가 실행가능한 노드로 배치하고 kube-apiserver를 통해 etcd에 Pod 정보를 추가하여 저장(또는 업데이트)합니다.

4. kube-controller-manager

클러스터의 상태를 조절하는 구성 요소인 다양한 유형의 컨트롤러 실행 및 관리를 담당합니다.
Namespace 컨트롤러, ServiceAccount 컨트롤러 등 다양한 컨트롤러를 관리합니다.
kube-controller-manager는 원하는 클러스터 상태를 유지하는데 중요한 역할을 합니다.

노드(Worker Node)

1. kubelet

클러스터의 각 노드에서 실행되며 해당 노드의 컨테이너 관리를 담당하는 역할을 담당합니다.
kubelet은 kube-apiserver와 통신하여 노드의 컨테이너가 올바르게 실행되고 있는지 확인하고 컨테이너의 현재 상태를 kube-apiserver에 보고합니다.

2. kube-proxy

클러스터 내의 노드들 사이의 네트워크 트래픽을 제어하는 역할을 담당합니다.
동일한 노드의 Pod와 클러스터의 다른 노드에 있는 Pod 간의 네트워크 통신을 허용하는 네트워크 규칙을 구현하는 일을 담당합니다.
트래픽에 대한 라우팅 외에도 서비스에 대한 로드 밸런싱도 제공하는 역할을 합니다.

3. Container Runtime

노드에서 컨테이너 레지스트리에서 컨테이너 이미지를 가져오고, 이미지 압축을 풀어 컨테이너 실행을 담당하는 역할을 담당합니다.
컨테이너 런타임은 일반적으로 Docker로 많이 알려져있으며 CRI-O 및 containerd와 같은 컨테이너 런타임이 있습니다.
컨테이너 런타임은 Control Plane에 의해 자동으로 관리됩니다.

작업 수행 명령어

아래 부터 설명드릴 명령어에 리소스가 여러가지 나오지만 추후에 별도로 설명 드릴예정이며(작성예정) 자세한 내용은 아직 모르셔도 됩니다.
기본적인 명령어를 통해 클러스터의 리소스를 컨트롤 하는 방법에 대해 학습합니다.

쿠버네티스의 대부분의 작업은 kubectl을 사용하여 리소스를 배포합니다.
kubectl 커맨드 라인 툴은 클러스터에서 리소스를 생성, 업데이트 및 삭제하는데 사용할 수 있는 광범위한 명령을 제공합니다.
리소스를 생성, 배포, 삭제등 대부분의 리소스는 파일 형태로 제작되며, Yaml 또는 Json 파일로 리소스를 작성하여 사용할 수 있습니다. (극히 일부를 제외하고는 Yaml 형태를 가장 많이 선호하고 사용합니다.)

1. 리소스 생성(create)

kubectl create
해당 명령어를 사용하여 클러스터의 새 리소스를 생성할 수 있습니다.
kubectl create deployment my-deployment --image=nginx
이 명령은 nginx 이미지를 실행하는 my-deployment라는 deployment를 생성하는 명령어 입니다.
--namespace 플래그를 사용하여 다른 네임 스페이스를 지정하지 않는 한 배포는 기본 네임스페이스를 지정합니다.
deployment 종류 뿐만이 아니라 다양한 클러스터 리소스를 생성할 수 있습니다.

2. 리소스 생성(apply)

kubectl apply
해당 명령어는 kubectl create 명령어와 유사하지만 생성 외에 기존 리소스를 업데이트하는 역할을 합니다.
kubectl apply -f deployment.yaml
이 명령은 파일에 지정된 새 구성으로 deployment.yaml 파일에 지정된 배포를 업데이트를 합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-deployment
  template:
    metadata:
      labels:
        app: my-deployment
    spec:
      containers:
        - name: nginx
          image: nginx
코드는 위 deployments.yaml 파일의 내용입니다.
위 create 명령어와 동일하게 deployment를 생성합니다.

3. 리소스 삭제

kubectl delete
해당 명령어를 사용하여 클러스터의 리소스를 삭제하는데 사용됩니다.
kubectl delete deployment my-deployment
이 명령은 deployment중 “my-deployment”를 삭제하는 명령어입니다.
-n(--namespace) 플래그를 사용하여 다른 네임 스페이스를 지정하지 않는 한 배포는 기본 네임스페이스를 지정합니다.
deployment 종류 뿐만이 아니라 다양한 클러스터 리소스를 삭제할 수 있습니다.

4. 리소스 수정

kubectl edit
해당 명령어를 사용하여 클러스터의 리소스를 편집하는데 사용됩니다.
kubectl edit deployment my-deployment
이 명령은 deployment중 “my-deployment” 구성을 변경하는 작업을 수행합니다.
변경(수정)은 Linux 텍스트 편집기를 통하여 yaml 파일 내용을 수정합니다.
수정이 되면 내용이 즉시 적용되며 실수로 변경하기 쉬워 해당 명령어는 주의해서 사용해야합니다.

5. 컨테이너 접속

kubectl exec
해당 명령어를 사용하여 실행중인 컨테이너에 접속할 수 있습니다.
kubectl exec -it my-pod -- /bin/bash
이 명령어는 my-pod의 컨테이너에 bash 쉘로 접근하는 작업을 수행합니다.
-it 플래그를 사용하여 일반적인 터미널 명령처럼 작동하도록 합니다.
중간의 “--”는 입력을 하지않아도 정상적으로 명령을 수행하지만 kubectl에 대한 인수를 명확하게 하기 위해 사용합니다.

작업 조회 명령어

클러스터의 리소스에 대한 정보를 보고 쿼리하기 위한 명령도 존재합니다.
이러한 명령은 클러스터의 현재 상태를 검사하고, 문제를 해결하고, 클러스터에서 실행 중인 애플리케이션의 상태와 성능을 모니터링 하는 데 유용할 수 있습니다.

1. 리소스 나열

kubectl get <resource-type> <resource>
해당 명령을 사용하여 리소스에 정의된 이름, 레이블 및 상태 등 현재 상태를 볼 수 있는 명령을 수행합니다.
리소스 타입만 입력하면 전체 리소스를 모두 나열합니다.
kubectl get deployments -o yaml
해당 명령어를 사용하여 deployments를 조회하는 명령입니다.
-n(--namespace)플래그를 사용하면 특정 namespace를 참고할 수 있고, 사용하지않으면 “default” namespace를 참조합니다. (대부분의 모든 kubectl 명령어에서는 -n 옵션을 사용합니다.)
-o 플래그는 특정 출력 형식을 지정합니다. (보통은 -o wide 또는 -o yaml을 많이 사용합니다.)

2. 리소스 세부정보 표시

kubectl describe <resource-type> <resource>
해당 명령어를 사용하여 리소스에 대한 자세한 정보를 표시하는데 사용되는 명령입니다.
get 명령어와 마찬가지로 리소스 타입만 입력하면 전체 리소스의 세부정보를 모두 표시합니다.
kubectl describe deployment my-deployment
이 명령은 메타데이터, 레이블, 상태 및 기타 정보를 포함하여 my-deployment 라는 deployment 리소스에 대한 자세한 정보를 표시합니다.
명령 실행시 아래와 같은 결과가 출력됩니다.
Name:                   my-deployment
Namespace:              default
CreationTimestamp:      Mon, 12 Dec 2022 17:13:10 +0900
Labels:                 app=my-deployment
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=my-deployment
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=my-deployment
  Containers:
   nginx:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   my-deployment-67b5d4bf57 (1/1 replicas created)
Events:          <none>

3. 컨테이너 로그 조회

kubectl logs <pod-name> <container-name>
클러스터에 있는 컨테이너의 로그를 보는데 사용되는 명령어입니다.
Pod에 컨테이너가 2개 이상일 때 container-name을 입력하여 컨테이너를 선택합니다.
apiVersion: v1
kind: Pod
metadata:
  name: pod
  namespace: edu
  labels:
    app: pod-test
spec:
  containers:
  - name: nginx
    image: nginx:1.22.1
    env:
    - name: TEST_ENV
      value: "its-env"
    command: ["/bin/sh"]
    args: ["-c", "echo $TEST_ENV && sleep 1d"]
    ports:
    - containerPort: 80
  - name: busybox
    image: busybox
    command: ["/bin/sh", "-c", "echo 'hello world' && sleep 1d"]
해당 코드는 Pod의 Yaml 파일 내용이며 container가 2개를 배포하는 것을 확인할 수 있습니다.
해당 Pod를 배포하고 log를 확인하면 아래와 같이 출력됩니다.
> k logs -n edu pod
Defaulted container "nginx" out of: nginx, busybox
its-env
을 입력하지 않아 기본 컨테이너인 nginx의 로그를 보여줍니다.
> k logs -n edu pod busybox
hello world
을 정상적으로 입력하니 busybox의 로그가 확인됩니다.