'Kubernetes'에 해당하는 글 29건



Master


위 그림은 쿠버네티스 클러스터의 아키텍처이다. 좌측의 마스터 컴포넌트는 클러스터의 제어영역(control plane) 을 제공하여, 클러스터에 관한 전반적인 결정을 수행하고 클러스터 이벤트를 감지하고 반응한다. 마스터 컴포넌트는 클러스터 내에 어떤 노드에서든 동작할 수 있지만, 일반적으로 클러스터와 동일한 노드 상에서 구동시킨다. 아래는 마스터 내에서 동작하는 바이너리 컴포넌트들이며 쿠버네티스 초기화시 자동 설치된다.


kube-apiserver

쿠버네티스 API 로, 외부/내부에서 관리자의 원격 명령을 받을 수 있는 컴포넌트이다.


etcd

모든 클러스터 데이터를 저장하는 고가용성 키-값 저장소로, etcd 데이터에 대한 백업 계획은 필수이다.


kube-scheduler

생성된 파드를 노드에 할당해 주는 컴포넌트이다. 이것을 스케줄링이라 하며, 리소스/하드웨어/소프트웨어/정책/워크로드 등을 모두 참고하여 가장 최적화된 노드에 파드를 배치하게 될 것이다.


kube-controller-manager

아래의 컨트롤러들을 구동하는 컴포넌트이다.

- Node Controller : 노드가 다운되었을 때 알림와 대응에 관한 역할을 한다.

- Replication Controller : 지정된 수의 파드들을 유지시켜 주는 역할을 한다.

- Endpoints Controller: 서비스와 파드를 연결시켜 엔드포인트 오브젝트를 만든다.

- Service Account & Token Controllers: 새로운 네임스페이스에 대한 기본 계정과 API 접근 토큰을 생성한다.



Node


우측 하단의 노드 컴포넌트(Minions) 는 마스터 컴포넌트에 의해 관리되며 VM 이나 물리 장치가 될 수 있다. 동작중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공한다. 아래는 노드 내에서 동작하는 바이너리 컴포넌트들이며 노드 오브젝트 생성시 자동 설치된다.


kubelet

클러스터의 각 노드에서 실행되는 에이전트로, 컨테이너들이 파드에서 실행 중인지, 이상이 없는지 확인한다.


kube-proxy

호스트 상의 네트워크 규칙으로 커넥션 포워딩을 수행함으로서 쿠버네티스 Service 가 가능하도록 한다.


Container Runtime

컨테이너 런타임은 컨테이너의 동작을 책임지며, 쿠버네티스에서 지원하는 컨테이너 런타임은 다음과 같다. 

Docker, containerd, cri-o, rktlet, Kubernetes CRI (Container Runtime Interface) 구현체.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

쿠버네티스에서는 배포 방법으로 블루/그린 배포, 카나리 배포, 롤링 업데이트 등을 사용할 수 있다. 롤링 업데이트 방식은 운영중인 어플리케이션의 파드 수를 하나씩 줄이고, 새로운 어플리케이션의 파드 수를 하나씩 늘려가며 변경하는 방법이다. 쿠버네티스는 어플리케이션 이미지를 업데이트 하면 롤링 업데이트 방식으로 배포를 진행할 것이다. 쿠버네티스에서 배포 업데이트는 버전으로 관리되고, 이전의 안정적인 버전으로도 복구가 가능하다.


다음 테스트는 kubernetes-bootcamp:v1 이미지를 사용 중인 서비스 환경에서 v2 이미지로 교체하였을 때 어플리케이션의 배포 진행을 파악하고, 다시 v1 이미지로 복원하는 시나리오 이다.


4개의 파드에 kubernetes-bootcamp:v1 이미지를 구동하여, 이미 서비스로 운영중임을 확인.


$ kubectl get deployment -o wide
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS            IMAGES                                         SELECTOR
kubernetes-bootcamp   4/4     4            4           11m   kubernetes-bootcamp   gcr.io/google-samples/kubernetes-bootcamp:v1   run=kubernetes-bootcamp
cs


해당 deployment 에 어플리케이션 이미지를 교체할 때,  kubectl edit deployment  명령을 사용하거나  kubectl set image  명령을 사용할 수 있다.


$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
cs


위 명령은 deployment 에 다른 이미지를 사용하도록 변경하고, 롤링 업데이트를 시작하도록 한다. 업데이트 확인.


$ kubectl get deployment -o wide
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS            IMAGES                             SELECTOR
kubernetes-bootcamp   4/4     4            4           26m   kubernetes-bootcamp   jocatalin/kubernetes-bootcamp:v2   run=kubernetes-bootcamp
cs


잠시 후에 서비스 ip 로 접근해 보면, 다음과 같이 새로운 v2 버전의 파드에 로드 밸런싱 되는 것을 확인할 수 있다.


$ curl service_ip
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-nqlrr | v=2
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-tjdrs | v=2
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-b6sdv | v=2
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-sr2aw | v=2
cs


그렇다면 업데이트 과정을 살펴보자.


$ kubectl describe deployment
Scaled up replica set kubernetes-bootcamp-6bf84cb898 to 4
Scaled up replica set kubernetes-bootcamp-5bf4d5689b to 1
Scaled down replica set kubernetes-bootcamp-6bf84cb898 to 3
Scaled up replica set kubernetes-bootcamp-5bf4d5689b to 2
Scaled down replica set kubernetes-bootcamp-6bf84cb898 to 2
Scaled up replica set kubernetes-bootcamp-5bf4d5689b to 3
Scaled down replica set kubernetes-bootcamp-6bf84cb898 to 1
Scaled up replica set kubernetes-bootcamp-5bf4d5689b to 4
Scaled down replica set kubernetes-bootcamp-6bf84cb898 to 0
cs


새로 생성된 ReplicaSet(5bf4d5689b) 의 파드 수가 하나씩 늘어나고, 동시에 ReplicaSet(6bf84cb898) 의 파드 수가 줄어들며 롤링 업데이트가 진행되는 것을 확인할 수 있다. 




만약에 경우에 이전 버전의 업데이트로 돌아가려면  rollout undo  명령으로 가능하다.


$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.extensions/kubernetes-bootcamp rolled back
 
$ curl service_ip
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-nqlrr | v=1
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-tjdrs | v=1
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-b6sdv | v=1
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5bf4d5689b-sr2aw | v=1
cs


여기서 또 다시 rollout undo 명령을 실행하면 v1 버전보다 더 예전의 업데이트가 아닌 바로 전인 v2 버전으로 다시 돌아가는 것에 주의하자.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

파드에서 어플리케이션이 비정상 작동을 할 경우에 대비하여 Liveness/Readiness Probe 를 설정할 수 있다. Liveness Probe 는 컨테이너가 정상적으로 구동 중 인지를 체크할 수 있다. 결과가 정상이 아니면 컨테이너를 재시작한다. Readiness Probe 는 파드가 트래픽을 처리할 준비가 되어 있는지를 체크한다. 결과가 정상이 아니면 해당 파드는 로드밸런스에서 제외된다. 두가지 Probe 에 대하여 설정한 대로 노드의 kubelet 이 주기적으로 상태 체크를 하게 되며, 결과가 비정상일 경우 해당 파드는 not ready 상태로 변경된다. 


아래처럼 readiness/liveness probe 를 가진 파드를 생성해 보자.


apiVersion: v1
kind: Pod
metadata:
  name: "healthy-monolith"
  labels:
    app: monolith
spec:
  containers:
    - name: monolith
      image: kelseyhightower/monolith:1.0.0
      ports:
        - name: http
          containerPort: 80
        - name: health
          containerPort: 81
      resources:
        limits:
          cpu: 0.2
          memory: "10Mi"
      livenessProbe:
        httpGet:
          path: /healthz
          port: 81
          scheme: HTTP
        initialDelaySeconds: 5
        periodSeconds: 15
        timeoutSeconds: 5
      readinessProbe:
        httpGet:
          path: /readiness
          port: 81
          scheme: HTTP
        initialDelaySeconds: 5
        timeoutSeconds: 1
cs


각 Liveness/Readiness Probe 에 대해서 체크하는 방법으로는 Command / HTTP / TCP 등이 있는데 위 예제에서는 HTTP 를 사용하였다. livenessProbe 의 경우 http://ip:81/healthz 에 접근했을 때 응답코드가 2xx, 3xx 이면 정상이다. readinessProbe 도 마찬가지로 http://ip:81/readiness 에 접근했을 때 응답코드가 2xx, 3xx 이면 정상이다. initialDelaySeconds 는 컨테이너가 준비되고 probe 를 실행하기 까지의 대기 시간이다. periodSeconds 는 probe 체크를 반복할 시간 설정이다. 



Liveness 테스트


아래와 같이 토글 주소를 반복 실행하여 probe 의 성공과 실패를 반복할 경우 어떤 변화가 생기는지 알아보자. 아마도 실패를 할 경우 컨테이너의 restart 카운팅이 늘어나며, 컨테이너가 자동으로 재시작 될 것이다.


$ kubectl get pods healthy-monolith -w
NAME               READY     STATUS    RESTARTS   AGE
healthy-monolith   1/1       Running   0         29m
 
$ kubectl port-forward healthy-monolith 10081:81
$ curl http://127.0.0.1:10081/healthz/status
$ curl http://127.0.0.1:10081/healthz/status
 
$ kubectl get pods healthy-monolith -w
NAME               READY     STATUS    RESTARTS   AGE
healthy-monolith   1/1       Running   0         29m
healthy-monolith   0/1       Running   1         30m
healthy-monolith   1/1       Running   1         30m
healthy-monolith   0/1       Running   2         31m
healthy-monolith   1/1       Running   2         31m
cs



Readiness 테스트


아래와 같이 토글 주소를 반복 실행하여 probe 의 성공과 실패를 반복할 경우 어떤 변화가 생기는지 알아보자. 아마도 실패를 할 경우 해당 파드는 not ready 상태가 되며 로드밸런스에서 제외되는데, 로드밸런스 테스트는 생략한다 ^^;


$ kubectl port-forward healthy-monolith 10081:81
$ curl http://127.0.0.1:10081/readiness/status
$ curl http://127.0.0.1:10081/readiness/status
$ curl http://127.0.0.1:10081/readiness/status
 
$ kubectl get pods healthy-monolith -w
NAME               READY     STATUS    RESTARTS   AGE
healthy-monolith   1/1       Running   0          13m
healthy-monolith   0/1       Running   0          16m
healthy-monolith   1/1       Running   0          17m
healthy-monolith   0/1       Running   0          17m
 
$ kubectl describe pods healthy-monolith
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
 
Events:
  Type    Reason     Age   From                                              Message
  ----    ------     ----  ----                                              -------
  Normal  Scheduled  1m    default-scheduler                                 Successfully assigned default/healthy-monolith to gke-bootcamp-default-pool-bb4d9176-tpk5
  Normal  Pulling    1m    kubelet, gke-bootcamp-default-pool-bb4d9176-tpk5  pulling image "kelseyhightower/monolith:1.0.0"
  Normal  Pulled     1m    kubelet, gke-bootcamp-default-pool-bb4d9176-tpk5  Successfully pulled image "kelseyhightower/monolith:1.0.0"
  Normal  Created    1m    kubelet, gke-bootcamp-default-pool-bb4d9176-tpk5  Created container
  Normal  Started    1m    kubelet, gke-bootcamp-default-pool-bb4d9176-tpk5  Started container
 Warning  Unhealthy  8s (x15 over 2m)  kubelet, gke-bootcamp-default-pool-bb4d9176-tpk5  Readiness probe failed: HTTP probe failed with statuscode: 503
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Google Cloud Platform 에서 쿠버네티스를 운영하기 위한 방법으로 Kubernetes Engine 과 Kubernetes API 를 사용하여 어플리케이션을 배포 및 관리 할 수 있다. 간단하게 쿠버네티스를 이용하여 어플리케이션을 테스트 해보자.


GKE(Google Kubernetes Engine) 를 사용하여 쿠버네티스 클러스터 생성

kubectl 를 사용하여 Docker 컨테이너를 배포 및 관리

쿠버네티스의 Deployment 와 Service 를 사용하여 마이크로 서비스로 어플리케이션 분리



1. 구성 연결


GCP 콘솔의 APIs & services 에서 Kubernetes Engine API 와 Container Registry API 이 활성화 되어 있는지 체크하고, Cloud Shell 이나 Cloud SDK 를 사용하여 GCP 계정, 프로젝트, zone 설정 등을 확인한다.


> gcloud config list



2. 클러스터-노드 생성


> gcloud container clusters create bootcamp --num-nodes 5 --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"


NAME      LOCATION       MASTER_VERSION  MASTER_IP     MACHINE_TYPE   NODE_VERSION   NUM_NODES  STATUS

bootcamp  us-central1-a  1.11.7-gke.12   35.202.79.78  n1-standard-1  1.11.7-gke.12  5          RUNNING


위의 명령으로 클러스터(bootcamp) 와 node 가 5개 생성된다. --scopes 인수는 나중에 사용할 프로젝트 호스팅과 Google Cloud Storage API 에 대한 액세스를 제공한다.


> kubectl get nodes

NAME                                      STATUS    ROLES     AGE       VERSION

gke-bootcamp-default-pool-654208f7-2pc5   Ready     <none>    8m        v1.11.7-gke.12

gke-bootcamp-default-pool-654208f7-4hbc   Ready     <none>    8m        v1.11.7-gke.12

gke-bootcamp-default-pool-654208f7-9wxw   Ready     <none>    8m        v1.11.7-gke.12

gke-bootcamp-default-pool-654208f7-qf9k   Ready     <none>    8m        v1.11.7-gke.12

gke-bootcamp-default-pool-654208f7-x9vz   Ready     <none>    8m        v1.11.7-gke.12


GCP 콘솔에서 확인하고 싶다면 클러스터는 [Kubernetes Engine > Cluster], 노드는 [Compute Engine > VM Instances] 에서 확인할 수 있다. 아래 예제처럼 GCP 콘솔에서 직접 클러스터를 생성할 수도 있다.






3. 어플리케이션 배포


> kubectl create deployment nginx --image=nginx:1.10.0

deployment.apps/nginx created


> kubectl get pods -o wide

NAME                     READY   STATUS    RESTARTS  IP          NODE

nginx-7d79bd4478-86289   1/1     Running   0         10.48.1.5   gke-bootcamp-default-pool-654208f7-4hbc


위 명령으로 nginx 컨테이너를 담은 파드가 생성되고 노드에 배치됐다.



4. 서비스 생성 (외부IP 노출)


> kubectl expose deployment nginx --port 80 --type LoadBalancer

service/nginx exposed


> kubectl get services

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE

kubernetes   ClusterIP      10.51.240.1     <none>          443/TCP        18m

nginx        LoadBalancer   10.51.250.242   34.66.113.107   80:32693/TCP   1m


위 명령으로 LoadBalancer 타입의 서비스를 생성하여 nginx 컨테이너를 외부에서 접근할 수 있게 한다. 생성된 External-IP 와 port 는 서비스가 유지되는 동안만 유효하다. (External-IP 생성에 일정 시간이 소요될 수 있음)



5. pod 수 확장


> kubectl scale deployment nginx --replicas 3

deployment.extensions/nginx scaled


> kubectl get pods -o wide

NAME                     READY   STATUS    RESTARTS  IP          NODE                                      NOMINATED NODE

nginx-7d79bd4478-86289   1/1     Running   0         10.48.1.5   gke-bootcamp-default-pool-654208f7-4hbc

nginx-7d79bd4478-j6wql   1/1     Running   0         10.48.2.4   gke-bootcamp-default-pool-654208f7-9wxw

nginx-7d79bd4478-zznhd   1/1     Running   0         10.48.3.5   gke-bootcamp-default-pool-654208f7-2pc5


위 명령은 생성해 놓은 nginx 배포(deployment) 의 pod 수를 3 개로 늘린다. 마스터는 요청에 따라 적절한 노드를 찾아 2개의 파드를 각각 추가로 배치한다. 트래픽이 많거나 적을 경우 위와 같이 파드 수를 늘리거나 줄일 수 있다.



6. 어플리케이션 테스트


> curl http://<External IP>:80





7. 삭제


파드나 서비스를 더 이상 사용하지 않을 경우 아래와 같이 삭제한다.


> kubectl delete deployment nginx

deployment.extensions "nginx" deleted


> kubectl get pods

No resources found.


> kubectl delete service nginx




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

hello minikube 글에서 어플리케이션 배포부터 노출까지 알아봤었는데 그 때의 배포 명령이 기억 나는가?


$ kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node

deployment.extensions "hello-node" created


위와 같이 kubectl create deployment 명령 다음에 배포에 관련된 정보나 상태 등의 spec 을 inline 으로 나열하였었다. 명령의 이러한 파라미터들은 JSON 형식으로 변환되어 쿠버네티스 API 로 전달된 후 처리된다. 이렇게 kubectl 명령에 inline 으로 파라미터나 플러그 등을 나열하는 것을 명령형(Imperative) 커맨드라고 하며, 주로 일회성 작업을 할 때 사용한다. 나열될 파라미터 수가 적을 때 사용하면 유용하다.


또 한가지 배포에 관련된 정보나 상태 등의 spec 을 상세하게 나열하는 대신 파일(.yaml) 안에 정의하는 방법을 사용할 수도 있는데, 이것을 명령형 오브젝트 구성(Imperative object configuration) 이라고 한다. 다음과 같이 로컬 파일이나 url 상의 파일을 지정하여 사용할 수 있다.


$ kubectl create -f deployment.yaml

$ kubectl create -f https://k8s.io/examples/application/deployment.yaml


위 yaml 예제 파일에는 다음과 같이 3개의 nginx 파드를 생성하는 내용이 담겨 있다.


apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx-deployment

  labels:

    app: nginx

spec:

  replicas: 3

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80


.yaml(야믈) 파일은 위처럼 공백 문자를 이용한 들여쓰기로 구조체를 구분하며, 리스트, 해시, 스칼라 데이터의 조합을 모두 표현할 수 있다. 각 항목들을 살펴보면 통신할 api 버전, 생성할 오브젝트 종류, 이름, 식별자, 파드 수, 어플리케이션 이름, 컨테이너 이미지 정보, 연결포트 등이 정의되어 있으며, 쿠버네티스 API 는 이 정의대로 Deployment 를 생성하게 된다. 운영시에는 inline 방식의 명령형 커맨드 보다는 .yaml 파일에 오브젝트를 정의하는 명령형 오브젝트 구성을 주로 사용하게 되며, 위처럼 아주 깔끔하고, 명확하게 오브젝트의 의도를 한눈에 파악할 수 있다. 물론 .yaml 파일을 작성하는 방법이나 오브젝트 정의 방법을 숙지해야 하는 것은 함정!



오브젝트 정의 방법을 간단하게 살펴보자.


쿠버네티스에서 가장 중요한 것은 무엇일까. 아마도 위에 정의한 것 처럼 사용자가 원하는 리소스 및 스펙이 계속해서 유지되는 것이 가장 중요할 것이다. 즉, 사용자가 바라는 상태(desired state) 를 계속해서 유지해야 한다. 배포될 어플리케이션(pod)의 워크로드 정보를 나타내는 클러스터 정보(namespace), 네트워크(service), 디스크 리소스(volume) 를 쿠버네티스의 기본 오브젝트라고 한다. 또한 기본 오브젝트들을 편리하게 관리하기 위한 컨트롤러들이 있다. 파드 복제 수(ReplicaSet), 배포(Deployment), 상태관리API(StatefulSet), 파드를 모든 노드에 복제(DaemonSet), 단일실행(Job) 들이 그것이다. 이러한 오브젝트들은 위와 같이 .yaml 파일에 정의하여 생성/업데이트/삭제 등의 관리를 할 수 있다.


아래는 오브젝트 정의에 필요한 필수 요소이다.

  • apiVersion - 이 오브젝트를 생성하는데 사용할 API 버전
  • kind - 생성할 오브젝트 종류
  • metadata - 오브젝트를 식별할 수 있는 고유 이름
  • spec - 오브젝트 특유의 중첩된 필드를 포함하며, 오브젝트마다 정확한 포맷이 다르므로 관리할 오브젝트의 spec 포맷을 확인한다.


$ kubectl create -f deployment.yaml


위의 deployment 오브젝트 정보를 담은 .yaml 파일을 실행하면 아래와 같이 nginx 를 구동하는 3개의 파드가 생성된 것을 확인할 수 있다.


$ kubectl get pods -o wide

NAME                                READY     STATUS    RESTARTS   AGE       IP            NODE

nginx-deployment-76bf4969df-4tvtv   1/1       Running   0          30m       172.17.0.10   minikube

nginx-deployment-76bf4969df-8d5sk   1/1       Running   0          30m       172.17.0.9    minikube

nginx-deployment-76bf4969df-g6v79   1/1       Running   0          30m       172.17.0.8    minikube





WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,