본문 바로가기
AI 빅데이터/Google Cloud Platform

[GCP] GKE로 쿠버네티스 운영하기 완전 기본

by 마고커 2020. 6. 9.


쿠버네티스가 컨테이너 운영의 기본이 된다는 건 이미 주지의 사실이지만 사실 개념대로 따라가기는 만만치 않았다. 개념적으로 이해 되도 활용가능한 수준으로 익힐 수 있을까 하다가 아주 기본 적인 것을 한번 만들어 보기로 했다. 사실, 만든 것은 아니고 아래 조병욱님의 예제를 그대로 따라한 수준이다. 컨텐츠에 관한 모든 권리는 조병욱님에게 있음을 알린다.

 

 

쿠버네티스 #6 - 실제 서비스 배포해보기

쿠버네티스 #6 Replication Controller를 이용하여 서비스 배포하기 조대협 (http://bcho.tistory.com) 1. 도커 파일 만들기 node.js로 간단한 웹서버를 만들어서 도커로 패키징 해보자. 실습을 진행하기 위해서..

bcho.tistory.com

 

1) node.js 기반 webapp 만들기

 

node.js를 잘 알지 못해 거의 따라하는 수준. step-by-step으로 기록하기로 했으니 우선 node.js 설치부터 해야하는데, 간단히 아래 세 명령으로 끝났다.

 

// 노드 버전 매니저 다운로드
$ curl https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash

// 쉘 다시 시작
$ source ~/.bash_profile

// node.js 설치
$ nvm install stable

 

컨테이너는 아주 간단하게 8080번 포트로 hello, world를 출력하는 것으로 (server.js)

 

var os = require('os');
var http = require('http');

var handleRequest = function(request, response) {
  response.writeHead(200);
  response.end("Hello World! I'm "+os.hostname());

  //log

  console.log("["+
                Date(Date.now()).toLocaleString()+
                "] "+os.hostname());
}

var www = http.createServer(handleRequest);

www.listen(8080);

 

$ node server.js 를 수행하고 브라우저에서 http://localhost.8080을 수행하면 위의 respond에 해당하는 결과가 찍힌다.

 

2) 도커 컨테이너 만들기 및 GCR(Google Container Registry) 등록

 

위에서 만든 서버를 컨테이너로 배포할 것이므로 아래의 Dockerfile을 만들자

 

FROM node:carbon
EXPOSE 8080
COPY server.js .
CMD node server.js > log.out

 

간단히 node.js 서버를 설치하고 8080번 포트를 노출하도록 하고, 위에서 만든 server.js를 수행하는 것이 전부다.

 

$ docker build -t gcr.io/<project-id>/nodejs .

Sending build context to Docker daemon  6.144kB
Step 1/4 : FROM node:carbon
 ---> 8eeadf3757f4
Step 2/4 : EXPOSE 8080
 ---> Using cache
 ---> e4117ff95545
Step 3/4 : COPY server.js .
 ---> Using cache
 ---> 352f7b882828
Step 4/4 : CMD node server.js > log.out
 ---> Using cache
 ---> 871ee7e589a7
Successfully built 871ee7e589a7
Successfully tagged gcr.io/<project-id>/nodejs:latest

 

GKE를 통해 컨테이너를 배포할 것이므로 GCR(Google Container Registry)를 사용할 수 있도록 gcr.io 경로와 본인의 GCP project id를 넣어서 docker를 build한다. (nodejs는 그냥 컨테이너의 이름으로 각자 좋은 이름 붙이면 된다.)

 

% docker run -d -p 8080:8080 gcr.io/<project id>/nodejs:latest

 

localhost:8080으로 아래와 같이 나오면 일단 docker 만들기는 성공

 

만들어진 컨테이너를 GCR에 등록하자. GCR과 아래에서 나올 kubectl을 활용하기 위해서는 gcloud sdk를 우선 설치해야 한다.

 

gcloud sdk는 gcp console 외부에서 gcp의 내 project에 접근하게 해 주는 sdk라고 이해하면 빠르다. 즉, gcp의 콘솔에서는 gcloud sdk를 설치할 필요가 없다. 나는 맥 터미널에서 쿠버네티스를 운영할 것이므로 아래의 설명을 따라 설치할 것이다.

 

빠른 시작  |  Cloud SDK 문서  |  Google Cloud

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trade

cloud.google.com

gcloud 설치를 마친 후 아래 명령을 통해 GCR에 접근할 수 있는 권한을 얻고, 컨테이너를 등록한다.

 

// GCR 접근 권한 획득
% gcloud auth configure-docker

// GCR에 컨테이너 등록
% docker push gcr.io/<project id>/nodejs:latest

 

GCP Console의 GCR 메뉴에서 해당 도커 이미지가 보인다면 제대로 Docker 등록까지 끝난 것이다.

 

3) GKE 클러스터 만들기 및 gcloud sdk/ kubectl 설치

 

컨테이너를 여러개 만들어 하나하나 관리하는 것이 무척 헷갈리는 일이기 때문에 GKE나 AWS의 EKS를 통해 운영한다(라고는 하지만 이를 배우는 것도 만만찮은 일이긴 하다).

 

GKE의 기능을 익히는 것은 아니기 때문에 위와 같이 이름과 리전만 지정하고 나머지는 default로 두고 생성한다. 그러면, 낮은 사양의 인스턴스 3개가 만들어진다. 

 

gcloud sdk가 gcp project에 접근할 수 있게 해준다면, kubectl은 쿠버네티스를 운영할 수 있게 해주는 도구다. GKE의 컨테이너를 조작할 것이므로 gcloud를 설치한 다음에 아래의 명령을 수행한다. 박스 하단처럼 GKE console로 만든 cluster의 정보가 나온다면 GKE Cluster 생성 관련한 일은 끝난 것이다.

 

// kubectl 설치
% gcloud components install kubectl

// 외부에서 생성한 cluster에 접근할 수 있도록 허가
% gcloud container clusters get-credentials nodejs-cluster

// 컨테이너 리스트 보기
% gcloud container clusters list

NAME            LOCATION           MASTER_VERSION  MASTER_IP     MACHINE_TYPE   NODE_VERSION    NUM_NODES  STATUS
nodejs-cluster  asia-northeast3-a  1.14.10-gke.36  34.64.148.70  n1-standard-1  1.14.10-gke.36  3          RUNNING

 

4) 컨테이너 배포하기

 

컨테이너 배포는 YAML(Yet Another Markup Language) 파일을 통해 만들어진다. 쿠버네티스를 다루는 책에서 여러 구성 요소를 설명하지만, 기본만 할 것이므로 pod의 replicaset 하나와 이를 외부에 노출할 service 하나만을 만들 것이다. 인스턴스 하나에 컨테이너 하나만 있다면 replicaset도 필요 없지만, 3개의 instance로 구성된 cluster에 컨테이너를 모두 배포할 것이므로 replicaset을 구성했다고 보면 된다.

 

아래는 replicaset을 구성한 파일이다(nodejs_pod.yaml). pod하나만 만든다면 template아래 내용 위에 kind: Pod으로 지정해서 만들면 된다. 주의할 점은 yaml 파일에서는 tab을 허락하지 않는다. 스페이스로 indent를 정확하게 적용해야 한다. (이거 때문에 엄청 헤맴)

 

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: simple-nodejs-rc
  labels:
    app: simple-nodejs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: simple-nodejs
  template:
    metadata:
      labels: 
        app: simple-nodejs
    spec:
      containers:
      - name: simple-nodejs
        image: gcr.io/project-ryuks/nodejs
        ports:
        - containerPort: 8080

 

아래의 명령을 통해 replicaset을 생성하고 pod가 제대로 running하는 지 확인할 수 있다.

 

// replicaset 적용
% kubectl apply -f nodejs-pod.yaml

// pod running 확인
% kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
simple-nodejs-rc-22m4n   1/1     Running   0          23h
simple-nodejs-rc-4h6vh   1/1     Running   0          23h
simple-nodejs-rc-hb5f7   1/1     Running   0          23h

// pod 정보 확인
% kubectl describe pod simple-nodejs-rc-22m4n
Name:               simple-nodejs-rc-22m4n
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               gke-nodejs-cluster-default-pool-d5c8a55e-2dhs/10.178.0.5
Start Time:         Mon, 08 Jun 2020 23:44:27 +0900
Labels:             app=simple-nodejs
Annotations:        kubernetes.io/limit-ranger: LimitRanger plugin set: cpu request for container simple-nodejs
Status:             Running
IP:                 10.12.0.7
......

// pod이 제대로 working하는 지 확인
% kubectl exec -it simple-nodejs-rc-22m4n -- curl 10.12.0.7:8080 
Hello World! I'm simple-nodejs-rc-22m4n

 

pod은 node 내부에서만 돌고 있어, 이를 외부에서 접근할 수 있도록 해 주는 것이 service다. service도 yaml 파일(nodejs-svc.yaml)로 만들어 적용해 주면 된다. 

 

apiVersion: v1
kind: Service
metadata:
  name: simple-nodejs-svc
spec:
  selector:
    app: simple-nodejs
  ports:
    - port: 80
      protocol: TCP
      targetPort: 8080
  type: LoadBalancer

 

상대적으로 단순하다. selector의 app으로 pod 정의할 때 사용한 app의 이름을 지정하고 LoadBalancer를 통해 8080 포트로 routing할 port(여기서는 80)만 지정해 주면 끝난다. 

 

// service를 실행하도록 적용
% kubectl apply -f nodejs_svc.yaml 
service/simple-nodejs-svc created

// service 실행 여부를 확인. 외부 ip가 할당 될 때까지 확인
% kubectl get svc
NAME                TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes          ClusterIP      10.77.0.1     <none>        443/TCP        28h
simple-nodejs-svc   LoadBalancer   10.77.11.88   <pending>     80:30886/TCP   6s

// 외부 ip 할당
% kubectl get svc
NAME                TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
kubernetes          ClusterIP      10.77.0.1     <none>         443/TCP        28h
simple-nodejs-svc   LoadBalancer   10.77.11.88   34.64.232.17   80:30886/TCP   79s

 

마지막 라인에 보면 외부 IP가 할당되었다. 

 

외부 ip를 브라우저에서 입력하면 컨테이너가 제대로 동작하고 있음을 확인할 수 있다. 간단한 예제임에도 험난한 과정을 겪어왔다. 하지만, 여기서부터 다양하게 활용이 뻗어 나갈 수 있다고 믿는다. 



댓글