Kubernetes study (2)

 

Hello Node Kubernetes

ba830277f2d92e04.png

Why Containers?

Kubernetes 오픈소스로, 다양한 환경에서 실행될 수 있으며 컨테이너 매니징 해주는 컨테이너 운영 환경 이다. 컨테이너 스케쥴링, 모니터링, 삭제 관리 등 컨테이너를 종합적으로 관리해주는 운영환경이다.

간단한 Docker container 만들기

const http = require('http');
const handleRequest = (req, res) => {
	res.writeHead(200);
	res.end("Hello World!");
}

const www = http.createServer(handleRequest);
www.listen(8080);

간단한 node 앱

docker 를 이용하기 위해서 Dockerfile 파일 정의

FROM node:10.14.2
EXPOSE 8080
COPY server.js .
CMD node server.js

docker hub 에서 node의 10.14.2 tag 이미지를 찾아서 시작한다.

8080포트를 외부와 연결할 수 있게 열어두고

server.js 파일을 image 로 복사한다.

docker 빌드 밑 실행

docker build -t gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v1 .
docker run -d -p 8080:8080 gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v1

gcr 에 푸쉬하기 위해서 image 이름을 gcr.io/프로젝트ID/프로젝트명 로 만든다.

다음 명령어로 gcr 에 container 를 푸쉬한다.

gcloud docker -- push gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v1

– 와 push 사이에 공백이 한번 있다. 주의하자.

Cluster 생성하기

cluster 는 구글에서 호스팅하는 Kubernetes master API server 와 worker nodes 들의 집합으로 구성되어있다.

img

Worker node 들은 쿠버네티스 클러스터 내 워커 머신으로써 동작하는 VM 또는 물리적인 컴퓨터 이다.

Application 을 kubernetes 에 배포한다는것은, 마스터에 app container 를 구동하라고 지시하는것이다.

마스터는 container를 어떤 cluster 에 구동시킬지 스케쥴한다.

node들은 마스터가 제공하는 k8s api 를 통해서 마스터와 통신한다.

최종적으로 사용자는 k8s api 를 통해 클러스터와 상호작용 한다.

gcloud 를 통해서 cluster 를 생성하보자

gcloud container clusters create hello-world \
                --num-nodes 2 \
                --machine-type n1-standard-1 \
                --zone us-central1-a

n1-standard-1 머신 사용하는 노드 2개를 하나의 클러스터로 설정해서 생성한다.

클러스터의 이름은 hello-world 이고 VM 은 us-central1-a 에 생성한다.

시스템 이름 설명 가상 CPU1 메모리(GB) PD(영구 디스크) 최대 개수2 최대 총 PD 크기(TB)
n1-standard-1 1개의 가상 CPU, 3.75GB 메모리를 사용하는 표준 머신 유형입니다. 1 3.75 16(베타는 32) 64

아래와같은 log 가 뜨면 성공적으로 cluster 가 생성된것이다.

Creating cluster hello-world in us-central1-a...done.
Created [https://container.googleapis.com/v1/projects/qwiklabs-gcp-8ad3c094cf3410ed/zones/us-central1-a/clusters/hello-world].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-a/hello-world?project=qwiklabs-gcp-8ad3c094cf3410ed
kubeconfig entry generated for hello-world.
NAME         LOCATION       MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
hello-world  us-central1-a  1.10.9-gke.5    35.225.105.202  n1-standard-1  1.10.9-gke.5  2          RUNNING

또한 GCP 의 console 을 통해서도 cluster 를 생성할 수 있다.

Kubernetes Engine > Kubernetes clusters > Create cluster

Pod 생성하기

kubernetes pod 은 container들의 그룹으로 kubernetes 에서 가장 기본적인 배포 단위다.

kubernetes 는 하나의 컨테이너를 개별적으로 배포하지 않고, Pod 단위로 배포하며 Pod 은 하나 이상의 컨테이너를 가지고 있다.

Pod 에는 몇가지 특징들이 있다.

  • Pod 내부의 컨테이너들은 IP 와 Port 정보를 공유한다. 이렇게 되면, 다른 컨테이너를 localhost 를 통해서 접근할 수 있게 된다.
  • Pod 내부의 컨테이너들은 디스크 볼륨을 공유한다. 따라서 같은 Pod 이라면 다른 컨테이너의 디스크 볼륨에 접근할 수 있게 된다.

Pod 이 시작/재시작 될때, 컨테이너마다 로컬 디스크를 생성하여 시작하게 되는데, 이 로컬 디스크는 시작/재시작 될때마다 새롭게 정의되어 정보가 사라지게 된다.

DB 같이 영구적으로 데이터를 보관해야 하는경우, 시작과 재시작에 영향을 받지 않아야 하는 경우, volumn 이라는 스토리지를 사용해야 한다.

Volumn 은 컨테이너 입장에서는 외장하드 느낌으로, Pod 이 시작/재시작 할때 컨테이너에 마운트해서 사용할 수 있다.

kubectl run 을 통해서 Pod 을 생성할 수 있다.

kubectl run hello-node \
    --image=gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v1 \
    --port=8080
deployment.apps "hello-node" created

log 에 deployment.apps 라고 뜬것을 볼 수 있듯이, deployment object 를 생성하면 Pod이 생성된다.

새로운 deployment 는 single pod replica

아래 명령어를 통해서 deployment 들의 정보들을 볼 수 있다.

kubectl get deployments
google2202782_student@cloudshell:~ (qwiklabs-gcp-14dd3142938af82d)$ kubectl get deployments
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-node   1         1         1            1           39s

아래 명령어를 통해서 deployment 에 의해 생성된 pod 의 정보를 볼 수 있다.

kubectl get pods
google2202782_student@cloudshell:~ (qwiklabs-gcp-14dd3142938af82d)$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
hello-node-68847f89d4-d75jc   1/1       Running   0          55s

아래는 몇가지 kubetl 명령어 들이다

kubectl cluster-info
	cluster 의 정보를 불러온다
kubectl config view
	# Show Merged kubeconfig settings.
아래 명령어들은 trobuleshooting 을 위한 명령어들이다.
kubectl get events
kubectl logs <pod-name>

Allow external traffic

기본적으로, Pod 은 cluster의 internal IP를 통해서만 접근할 수 있다. 쿠버네티스 외부에서 app에 접근하기 위해서는 kubernetes service 를 통해 expose 해야한다.

Pod을 public internet으로 expose 하기 위해선 아래와 같은 명령어를 사용한다.

kubectl expose deployment hello-node --type="LoadBalancer"

expose 하는 대상은, deployment 이여야 한다. Pod 을 expose 하면 안된다.

service 가 트래픽을 deployment 에 포함되는 모든 Pod들을 대상으로 Load Balancing 하면서 모든 Pod들을 관리해야하기 떄문이다.

google2202782_student@cloudshell:~ (qwiklabs-gcp-14dd3142938af82d)$ kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
hello-node   LoadBalancer   10.31.244.254   35.226.201.119   8080:30430/TCP   3m
kubernetes   ClusterIP      10.31.240.1     <none>           443/TCP          26m

hello-node deployment 의 External IP 가 35.226.201.119 이므로

http://35.226.201.119:8080/ 로 접속해보자.

google2202782_student@cloudshell:~ (qwiklabs-gcp-14dd3142938af82d)$ curl http://35.226.201.119:8080/
Hello World!

Scale up your service

kubernetes 의 강력한 기능중 하나는, 바로 application 을 쉽게 scaling 할 수 있다는것이다.

Scale Up 하기 위해서 는 Replication controller 에게 명령을 내리면 된다.

Replication controller 는 Pod 의 replica 를 더 생성하게 된다.

kubectl scale deployment hello-node --replicas=4
$ kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-node   4         4         4            4           35m

$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
hello-node-68847f89d4-5llq6   1/1       Running   0          1m
hello-node-68847f89d4-d75jc   1/1       Running   0          35m
hello-node-68847f89d4-jlktx   1/1       Running   0          1m
hello-node-68847f89d4-stpcn   1/1       Running   0          1m

Roll out an upgrade to your service

일부 버그fix 등의 코드에서 변경점이 있을경우 새로운 버전을 deploy 해야할때, 어떻게 해야할까?

일단, 코드를 수정후 docker를 다른 tag 로 빌드한 후 새로운 container image 를 publish 한다.

docker build -t gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v2 .
gcloud docker -- push gcr.io/qwiklabs-gcp-14dd3142938af82d/hello-node:v2

그 후 kubectl 의 에서 image 설정을 바꿔주면 된다.

kubectl edit deployment hello-node
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: 2016-03-24T17:55:28Z
  generation: 3
  labels:
    run: hello-node
  name: hello-node
  namespace: default
  resourceVersion: "151017"
  selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/hello-node
  uid: 981fe302-f1e9-11e5-9a78-42010af00005
spec:
  replicas: 4
  selector:
    matchLabels:
      run: hello-node
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: hello-node
    spec:
      containers:
      #- image: gcr.io/PROJECT_ID/hello-node:v1     # v1 을 v2 로 변경
      - image: gcr.io/PROJECT_ID/hello-node:v2
        imagePullPolicy: IfNotPresent
        name: hello-node
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      securityContext: {}
      terminationGracePeriodSeconds: 30

이 작업을 하는동안, 유저는 서비스에서 어떤 interruption 도 경험하지 못하게 된다. 초기에 잠깐 버전을 바꾸는 작업이 있는 후에, 정상적으로 접근할 수 있게 된다.

Kubernetes graphical dashboard

Kubernetes 를 gui dashborad 로 관리


참고문서

http://bcho.tistory.com/1255

https://kubernetes.io/ko/docs/concepts/overview/what-is-kubernetes/

https://lng1982.tistory.com/270