3. Kubernetes의 이해

3.1 Kubernetes 설명

ㅇ Kubernetes Fact 정리
  • (과거)
    • 1주일에 20억개의 컨테이너를 생성하는 google이 컨테이너 배포 시스템으로 사용하던 borg를 기반으로 만든 오픈소스

    • Google에서 만들어서 Cloud Native Computing Foundation(CNCF)  재단에 기부했다.

    • Kubernetes는 다른 컨테이너 오케스트레이션 도구보다 비교적 늦게 등장 (AWS ECS, 하시코프 Nomad ...)

  • (현재)
    • 쿠버네티스가 현재 컨테이너 오케스트레이션 도구의 표준이라고 볼 수 있다.

    • 구글의 노하우와 강력한 확장성, MS, Red Hat, IBM 등 수 많은 기업의 참여가 쿠버네티스의 발전에 기여했다.

    • Rancher 2.0, Openshift(Redhat) 등은 Kubernetes 기반으로 플랫폼을 만들었고, Public Cloud 사업자들도 관리형 서비스를 내놓았다.


ㅇ Kubernetes 정의
  • 쿠버네티스는 컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼

  • kubernetes가 너무 길어서 k8s(케이에이츠) or kube(큐브) 로 줄여서 부름


ㅇ 기본 기능
  • 상태관리 : 상태를 선언하고 선언한 상태를 유지 / 노드가 죽거나 컨테이너 응답이 없을 경우 자동으로 복구

  • 스케줄링 : 클러스터의 여러 노드 중 조건에 맞는 노드를 찾아 컨테이너를 배치

  • 클러스터 : 가상 네트워크를 통해 하나의 서버에 있는 것처럼 통신

  • 서비스 디스커버리 : 서로 다른 서비스를 쉽게 찾고 통신할 수 있음

  • 리소스 모니터링 : cAdvisor를 통한 리소스 모니터링

  • 스케일링 : 리소스에 따라 자동으로 서비스를 조정함

  • RollOut/RollBack : 배포/롤백 및 버전 관리


ㅇ Kubernetes 특징
  • Eco Systemd

    • CNCF Trail Map
    • 단순한 컨테이너 플랫폼이 아닌 마이크로서비스, 클라우드 플랫폼을 지향하고 컨테이너로 이루어진 것들을 손쉽게 담고 관리할 수 있는 그릇 역할을 합니다. 서버리스, CI/CD, 머신러닝 등 다양한 기능이 쿠버네티스 플랫폼 위에서 동작
  • 다양한 배포 방식
    • 쿠버네티스는 위 5가지 배포 방식을 지원한다

      • Deployment : 새로운 버전의 애플리케이션을 다양한 전략으로 배포가 가능.

      • StatefulSets : 실행 순서를 보장하여 순서나 데이터가 중요한 경우에 사용

      •  

        Damon Set : 로그나 모니터링 등 모든 노드에 설치가 필요한 경우에 사용

      •  

        Job / CronJob : 배치성 작업에 사용

    • 다양한 클라우드 지원
      • Cloud Controller Manager(CCM)
        • 클라우드 벤더에 특화된 코드와 쿠버네티스 코어가 상호 독립적으로 진화할 수 있도록 해주기 위해 생성
        • 다른 마스터 컴포넌트와 함께 동작
        • 클라우드 컨트롤러 매니저의 디자인은 새로운 클라우드 제공사업자가 플러그인을 이용하여 쉽게 쿠버네티스와 함께 통합하도록 허용해 주는 플러그인 메커니즘을 토대로 한다. 
    • Namespace & Label
      • Namespace와 Label을 통해서 논리적으로 구분하여 사용할 수 있습니다.
    • CRD (Custom Resource Definition)
    • Federation, Multi Cluster

ㅇ Kubernetes 단점
  • Kubernetes는 확실히 복잡하고 초반에 개념을 이해하기 어렵다.


ㅇ Kubernetes 기본 개념
  • Desired State

    • Current state : 현재상태

    • Desired state :  서버 관리자가 원하는 상태

    • 서버 관리자가 원하는 상태로 현재상태를 변화시키는 과정

  • 명령(imperative) vs 선언(declarative)

    • 명령(imperative) : $ docker run # 명령
    • 선언(declarative) : $ kubectl create # 상태 생성 (kubectl run도 있지만 잘 사용하지 않는다.)

ㅇ Kubernetes Object
  • 종류 : Pod, Service, Volume, namespace

  • POD
    • 쿠버네티스에서 배포할 수 있는 가장 작은 단위
  • Service
    • 네트워크와 관련된 오브젝트로, Pod를 외부 네트워크와 연결해주고 여러 개의 Pod를 바라보는 내부 로드 밸런서를 생성할 때 사용한다. 내부 DNS에 서버스 이름을 도메인으로 등록하기 때문에 서비스 디스커버리 역할도 한다
  • Replica Set
    • Pod을 여러 개 복제하여 관리하는 오브젝트입니다.
    • Pod를 생성하고 개수를 유지하려면 반드시 ReplicaSet을 사용해야 합니다.
  • Object Spec - YAML
    • 상태를 이런 YAML 파일로 관리한다. 
    • apiVersion: v1
      kind: Pod
      metadata:
          name: ubuntu-example
      spec:
          containers:
          - name: ubuntu
              image: ubuntu:latest


ㅇ Kubernetes 아키텍처
  • 마스터 - 노드 구조


      • Master - 마스터 서버는 다양한 모듈이 확장성을 고려하여 기능별로 쪼개져 있는 것이 특징. 관리자만 접근할 수 있게 보안 설정을 해야 하고 마스터 서버가 죽으면 클러스터를 관리할 수 없기 때문에 보통 3중화로 구성한다.
      • Node - 노드 서버는 마스터 서버와 통신하면서 필요한 Pod를 생성한다.
      • Kubelet - 명령 도구
  • Master 구성 요소

      • API server (kube-apiserver)
        • 모든 요청을 처리하는 마스터의 핵심 모듈이다. desired state를 key-value 저장소에 저장하고, 저장된 상태를 조회하는 역할
      • etcd
        • 분산 데이터 저장소로 단순히 값을 저장하고 읽는 기능뿐만 아니라 watch 기능이 있어 어떤 상태가 변경되면 바로 체크하여 로직을 실행시킬 수 있다.
        • 클러스터의 모든 설정, 상태 데이터는 여기 저장되므로 etcd만 잘 백업해두면 언제든지 클러스터를 복구할 수 있다.
        • etcd는 api-server와만 통신
      • kube-scheduler
        • 스케줄러는 할당되지 않은 Pod를 필요한 자원,라벨에 따라 적절한 노드 서버에 할당해준다.
      • kube-controller
        • kubernetes에 있는 거의 모든 object 상태를 관리한다.
        • 오브젝트별로 철저하게 분업화되어 Deployment는 ReplicaSet을 생성하고 ReplicaSet은 Pod를 생성하고 Pod는 스케줄러가 관리하는 식이다.

3.2 Kubernetes 실습

ㅇ 실습 내용
  • kubectl
  • pod
  • ReplicaSet
  • Deployment
  • Service
ㅇ 사전 준비 내용
  • cluster 생성
  • 포트포워딩 (22번)
    • echo "root:kubernetes" | chpasswd
    • master node에 접속하기 위한 ${pw}는 메일로 전송됨. 
  • ssh root@${공인 ip} -p {22번 포트포워딩한 port번호}로 접속

ㅇ kubectl
  • kubectl
    • alias k = 'kubectl'
    • apply : Apply a configuration to a resource by filename or stdin
    • get : Display one or many resources
    • describe : Show details of a specific resource or group of resources
    • delete : Delete resources by filenames, stdin, resources and names, or by resources and label selector
    • logs : Print the logs for a container in a pod
    • exec :Execute a command in a container
  • 전체 Object 검색
    • kubectl api-resources
      k api-resources
  • 실습
    • get
      • # pod, replicaset, deployment, service 조회
        kubectl get all
        
        # node 조회
        kubectl get no
        kubectl get node
        kubectl get nodes
        
        # 결과 포멧 변경
        kubectl get nodes -o wide
        kubectl get nodes -o yaml
        kubectl get nodes -o json
    • describe
      • # kubectl describe type/name
        # kubectl describe type name
        kubectl describe node <node name>
        kubectl describe node/<node name>
    • 그 외
      • kubectl exec -it <POD_NAME>
        kubectl logs -f <POD_NAME|TYPE/NAME>
        
        kubectl apply -f <FILENAME>
        kubectl delete -f <FILENAME>
ㅇ pod
  • 기본 예제
    • kubectl run test --image brenden0730/kt-workshop # deprecated soon..
      kubectl get po
      kubectl get pod
      kubectl get pods
      kubectl get pods -o wide
      kubectl get pods -o yaml
      kubectl get pods -o json
      kubectl logs test-<xxxx>
      kubectl logs -f test-<xxxx>
      kubectl exec -it test-<xxxx> sh
      kubectl describe pods test-<xxxx>
      kubectl delete pods test-<xxxx>
      kubectl get pods
      kubectl get all
      kubectl delete deployment/test
  • YAML 파일 관리
    • kubectl apply -f <filename>
      kubectl delete -f <filename>
  • 기본 예제
    • pod.yml
    • apiVersion: v1
      kind: Pod
      metadata:
        name: kt-workshop
        labels:
          type: app
      spec:
        containers:
        - name: app
          image: brenden0730/kt-workshop:latest
    • multi-pod.yml
    • apiVersion: v1
      kind: Pod
      metadata:
        name: kt-workshop-redis
        labels:
          type: stack
      spec:
        containers:
        - name: app
          image: brenden0730/kt-workshop-redis
          env:
          - name: REDIS_HOST
            value: "localhost"
        - name: db
          image: redis
    • kubectl get all
      kubectl logs kt-workshop-redis
      kubectl logs kt-workshop-redis app
      kubectl logs kt-workshop-redis db
      kubectl exec -it kt-workshop-redis
      kubectl exec -it kt-workshop-redis -c db sh
      kubectl exec -it kt-workshop-redis -c app sh
        apk add curl busybox-extras # install telnet
        curl localhost:4567
        telnet localhost 6379
          dbsize
          KEYS *
          GET count
          quit
      kubectl get pod/kt-workshop-redis
      kubectl get pod/kt-workshop-redis -o yaml

ㅇ ReplicaSet
  • 기본 예제
  • apiVersion: apps/v1beta2
    kind: ReplicaSet
    metadata:
      name: kt-workshop-rs
    spec:
      replicas: 1
      selector:
        matchLabels:
          type: app
          service: kt-workshop
      template:
        metadata:
          labels:
            type: app
            service: kt-workshop
        spec:
          containers:
          - name: kt-workshop
            image: brenden0730/kt-workshop
            livenessProbe:
              httpGet:
                path: /
                port: 4567
  • kubectl get pods --show-labels
    kubectl label pod/kt-workshop-rs-<xxxx> service-
  • rs.yml 파일에서 replicas=3으로 바꾸고 다시 apply 해보자!

ㅇ Deployment
  • 기본 예제
  • vim deployment.yml
  • apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      name: kt-workshop-deploy
    spec:
      replicas: 3
      selector:
        matchLabels:
          type: app
          service: kt-workshop
      template:
        metadata:
          labels:
            type: app
            service: kt-workshop
        spec:
          containers:
          - name: kt-workshop
            image: brenden0730/kt-workshop:1
            livenessProbe:
              httpGet:
                path: /
                port: 4567
  • kubectl set image deploy/kt-workshop-deploy kt-workshop=brenden0730/kt-workshop:2
    kubectl apply -f deployment.yml
    kubectl get rs -w
  • kubectl describe deploy/kt-workshop-deploy
    kubectl rollout history -f deployment.yml
    kubectl set image deploy/kt-workshop-deploy kt-workshop=brenden0730/kt-workshop:1 --record=true
    kubectl rollout history -f deployment.yml
    kubectl rollout history -f deployment.yml --revision=2
    kubectl rollout status deploy/kt-workshop-deploy
    kubectl rollout undo deploy/kt-workshop-deploy
    kubectl rollout undo deploy/kt-workshop-deploy --to-revision=3


ㅇ Service
  • redis-app.yml
  • apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      name: redis
    spec:
      selector:
        matchLabels:
          type: db
          service: redis
      template:
        metadata:
          labels:
            type: db
            service: redis
        spec:
          containers:
          - name: redis
            image: redis
            ports:
            - containerPort: 6379
              protocol: TCP
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
    spec:
      ports:
      - port: 6379
        protocol: TCP
      selector:
        type: db
        service: redis
  • kt-workshop-deploy.yml
  • apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      name: kt-workshop
    spec:
      selector:
        matchLabels:
          type: app
          service: kt-workshop
      template:
        metadata:
          labels:
            type: app
            service: kt-workshop
        spec:
          containers:
          - name: kt-workshop
            image: brenden0730/kt-workshop-redis
            env:
            - name: REDIS_HOST
              value: "redis"
            - name: REDIS_PORT
              value: "6379"
  • kubectl get ep
    kubectl exec -it kt-workshop-<xxxxx> sh
      apk add curl busybox-extras # install telnet
      curl localhost:4567
      curl localhost:4567
      telnet localhost 6379
      telnet redis 6379
        dbsize
        KEYS *
        GET count
        quit