초보개발자의 Kubernetes 사용해보기 #1(feat. GCP)

이현빈·2020년 6월 26일
3

간단한 서비스 배포하기

도커 컨테이너가 많아지면 컨테이너를 관리해야할 필요성이 생긴다. 이를 오케스트레이션이라 하는데 쿠버네티스는 오픈소스 컨테이너 오케스트레이션 툴 중 최고라고 알려져 있다. 이 포스팅에서는 쿠버네티스를 사용해 간단한 서비스를 배포하는 과정을 알아보려 한다.
최대한 쉽게 사용 가능하고 실제 운영 단계에서 구축해보기 위해 클라우드 환경인 GKE (Google Kubernetes Engine) 사용하였다. GKE를 사용하게 되면 도커나 쿠버네티스 설치가 따로 필요없고, 클라우드 플랫폼에 종속적인 기능도 사용 가능하다.

이 시리즈는 이정운님의 글을 참고하여 작성하였음을 알려드립니다.

1. 도커 파일 만들기

1. 애플리케이션 준비하기

node.js를 사용하여 배포할 간단한 애플리케이션을 제작한다.
server.js

const os = require("os");

const http = require("http");

const handleRequest = function (request, response) {
  response.writeHead(200);

  response.end("Hello World! I'm " + os.hostname());

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

let www = http.createServer(handleRequest);

www.listen(8080);

2. 도커로 패키징하기

# 생설할 이미지의 베이스가 될 이미지
FROM node:12

# 앱 디렉터리 생성
WORKDIR /usr/src/app

COPY server.js .

# 앱 의존성 설치
RUN npm install

# 앱 소스 추가
COPY . .

# 이미지에서 노출할 포트 설정
EXPOSE 8080

# 컨테이너가 시작될 때마다 실행할 명령어 설정
CMD [ "node", "server.js" ]

이 코드는 node.js 컨테이너 이미지를 베이스로 한 후, 앞서 작성한 server.js 코드를 복사하여 node server.js 명령어를 실행하도록 하는 컨테이너를 만드는 설정파일이다.

설정 파일이 준비되었으면, 도커 컨테이너 파일을 만들어보자

  • docker build: 컨테이너 만들기
    • -t: 이미지에 태그 정하는 옵션
  • [HOST_NAME]/[GOOGLE_PROJECT_ID]/[IMAGE_NAME] : 후에 구글 컨테이너 레지스트리(GCR)에 올리기 위한 이름 규칙

docker build -t gcr.io/my-ssafy-01/hello-node:v1 .
명령어로 컨테이너 이미지를 생성한다. 그 후

docker run -d -p 9090:8080 gcr.io/my-ssafy-01/hello-node:v1
명령어로 컨테이너를 실행한다. -d 옵션은 컨테이너를 실행하되, 백그라운드 모드로 실행하도록 하는 것이고, -p 옵션은 포트 매핑으로 뒤의 포트가 도커 컨테이너에서 돌고 있는 포트이고, 앞의 포트가 이를 밖으로 노출시키는 포트이다.

2. 쿠버네티스 클러스터 준비

gcloud와 kubectl 이용하기

클러스터 설정이 끝났으면 gloud (Google Cloud SDK 이하 gcloud)를 인스톨한다. 로컬에서 만든 도커 이미지를 GCR에 등록하기 위해 필요한 과정이다. google cloud SDK 문서를 참고하여 최신 클라우드 SDK 버전을 설치한다.
kubectl은 쿠버네티스의 CLI (Command Line Interface)로, gcloud를 인스톨한후에,

gcloud components install kubectl

명령을 이용하면 인스톨할 수 있다.
git bash에서 명령어를 실행하고 싶으면 .bashrc 파일에 다음의 내용을 추가한다.

alias gcloud="gcloud.cmd"

source ~/.bashrc 명령어를 사용하고 git bash창을 재실행시키면 gcloud 명령어를 사용할 수 있다. 먼저 gcloud config set project [PROJECT_ID] 명령어로 내 프로젝트를 등록한다. 프로젝트 ID는 여기서 확인할 수 있다.

다음으로 쿠버네티스에 대한 인증을 해줘야한다. 인증을 위해 GCP의 Kubernetes Engine 항목에서 클러스터를 만들어보자.

클러스터 만들기를 눌러 옵션들을 모두 기본 설정으로 한 다음에 클러스터를 만든다. 클러스터가 만들어지면 다음과 같은 화면을 볼 수 있는데, 연결을 눌러 나오는 코드를 복사하여 로컬 터미널에서 입력하면 간단히 인증을 마칠 수 있다.

인증이 끝났으면, gcloud 명령이 제대로 작동하는지를 확인하기 위해서, 현재 구글 클라우드내에 생성된 클러스터 목록을 읽어오는 gcloud container clusters list 명령어를 실행해보자.

기존에 클러스터 목록이 존재해서 올바른 목록이 나오지 않는다면 gcloud init을 통해 현재 내 설정을 확인하고 gcloud config 로 재설정을 해준다.

3. 쿠버네티스에 배포하기

도커 컨테이너 이미지 등록하기

앞서 만든 도커 이미지를 구글 클라우드 컨테이너 레지스트리(GCR)에 등록한다. GCR은 구글 클라우드에서 제공하는 컨테이너 이미지 저장 서비스이다. 저장 뿐만 아니라 CI/CD 도구와 연동하여 자동으로 컨테이너 이미지를 빌드하는 기능, 그리고 등록되는 컨테이너 이미지에 대해서 보안적인 문제가 있는지 보안 결함을 스캔해주는 기능과 같은 다양한 기능을 제공한다.

컨테이너 이미지를 로컬환경에서 도커 컨테이너 저장소에 저장하려면 docker push라는 명령을 사용하는데, 여기서는 GCR을 컨테이너 이미지 저장소로 사용할 것이기 때문에, GCR에 대한 인증이 필요하다. 인증은 한번만 해놓으면 되는데 git bash 터미널에서 gcloud auth configure-docker 명령어를 이용하면, 인증 정보가 로컬 환경에 자동으로 저장된다.

인증이 완료되었으면, docker push 명령을 이용하여 이미지를 GCR에 저장한다. 도커 이미지는 앞의 도커로 패키징하기 항목에서 만든 도커 이미지를 활용한다.

docker push gcr.io/my-ssafy-01/hello-node:v1

이미지가 GCR에 잘 저장되었는지를 확인하려면 구글 클라우드 콘솔에 Container Registry (GCR)메뉴에서 Images라는 메뉴를 들어가보면 된다.
저장한 이미지는 gcloud container images delete [IMAGE_NAME] 명령어로 삭제할 수 있다. 명령어에 관한 자세한 내용은 여기서 확인할 수 있다. GUI 환경에서 삭제하고 싶으면 GCR에서 이미지를 클릭하여 하나씩 삭제하면 된다.

Deployment, Service

만든 애플리케이션을 배포하기 위해서 쿠버네티스에서는 Deployment와 Service 오브젝트를 만들어줘야 한다. 이 오브젝트들은 YAML파일로 정의할 수 있다.

apiVersion: apps/v1
# 리소스의 종류
kind: Deployment
# 디플로이먼트 이름 정의
metadata:
  name: sample-backend-prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample_back
  # 포드 정의
  template:
    metadata:
      name: back
      labels:
        app: sample_back
    spec:
      containers:
      - name: nodejs
        image: gcr.io/my-ssafy-01/hello-node:v1 # gcr에 있는 이미지
        imagePullPolicy: IfNotPresent
        ports:
        - name: backend
          containerPort: 80

kubectl apply -f backend_prod.yaml 명령어로 디플로이먼트를 생성하고 kubectl get deployment 명령어로 목록을 확인할 수 있다. YAML에서 -를 사용하는 항목은 여러 개의 항목을 정의할 수 있음을 의미한다. apiVersion 항목이 궁금하다면 이곳을 참고하도록 하자.

apiVersion: v1
kind: Service
metadata:
  name: sample-backend
spec:
  type: LoadBalancer # 포트를 외부로 노출시켜 서비스할 수 있다.
  ports:
  - name: http
    port: 80 # 서비스의 IP에 접근할 때 사용할 포트를 설정
    targetPort: 80 # 포드에 접근할 수 있는 포트
    protocol: TCP
  selector:
    app: sample_back # 포드에서 정의한 app 이름과 동일해야 한다.

kubectl apply -f backend_svc.yaml 명령어로 서비스를 생성한다. 마찬가지로 kubectl get svc 명령을 통해서 목록을 확인할 수 있다.
external-ip를 웹브라우저에 입력하여 실제 서비스를 확인할 수 있다.

.yaml 파일을 사용하지 않고 명령어를 사용해서 서비스를 만들 수도 있다.
kubectl expose deployment sample_backend-prod --type LoadBalancer --port 80 --target-port 80

profile
익숙해질때까지 한걸음씩

0개의 댓글