Google Cloud Study Jam 쿠버네티스 입문편 후기와 간단 정리

문지은·2023년 5월 15일
0
post-thumbnail

후기

최근에 진행하는 스터디도 없고 스스로 공부에 대한 목마름이 있던 찰나...! Google Study Jam 이라는 걸 발견하게 되었다. 구글에서 제공하는 스터디 플랫폼인 퀵랩을 활용해서 하나의 퀘스트를 완수하면 되는 프로젝트였고 이번 주제는 쿠버네티스 입문편이었다! 마침 회사에서도 쿠버네티스를 사용하고 있기 때문에 공부가 필요하기도 해서 너무 좋은 기회라고 생각했다.
개인으로 참여하거나 그룹으로 참여가 가능했고 나는 다같이 동기 부여도 하고 질문도 할 겸 대학교 동기들을 불러 모았다!무려 수료 기념품도 있어서 더 열심히 열정을 불태울 수 있었다.🔥 (수료한 대학교 동기들과 함께 이 모자 쓰고 인생 네컷 찍으러 가는 게 목표였다!)

대학 동기들과 이 과정을 관리하기 위한 노션 페이지도 만들었는데 언제나 그렇듯... 첫 1주차에는 관리가 잘 됐지만 그 이후로는 관리가 안 되어서 마지막 주에 다같이 몰아서 들었다...🥲 그래도 다들 수료 뱃지를 받았다는 거에 의의를 두기로 했다.

학습 내용에 대한 후기를 말하자면 일단 나에게 딱 알맞은 난이도라고 생각했다. 나는 쿠버네티스를 제대로 공부한 적은 없지만 회사에서 이미 사용중이기 때문에 어떤 상황때문에 필요하고 어떤 파일들이 어떤 역할을 하는지 대략적으로만 파악하고 있었다. (나의 추측..) 하지만 이번 기회에 확실히 쿠버네티스의 역할과 각 구성 요소들의 역할을 파악하면서 개념을 확립할 수 있어서 좋았다. 특히 회사에서 사용하고 있으면서도 정확히 이해가 되지 않아서 의문을 가지고 있었던 canary 배포에 대한 부분이나 deploy, service 의 차이에 대해서도 명확하게 정리를 해주어서 매우 만족스럽다.😸 내용도 그렇게 길지 않고 하나의 Lab에 대략 1시간정도 소요되어서 다음에도 Google Study Jam이 열린다면 참여할 의향이 매우 있다!

간단 정리

Lab 1 - Introduction To Docker

로컬(pwd)에 app.js 라는 애플리케이션 파일이 있다고 가정

Dockerfile 만들기

# Dockerfile 이용해서 node:lts 이미지 실행하는데
FROM node:lts
# 컨테이너 안에서 working directory를 /app으로 설정하고
WORKDIR /app
# 로컬 파일들을 컨테이너의 /app 으로 복사한 다음에
ADD . /app
# 80번 포트를 외부에 공개해서 
EXPOSE 80
# 어플리케이션 실행
CMD ["node", "app.js"]

Dockerfile 이용해서 컨테이너에 이미지 실행하기

# 위의 Dockerfile 이용해서 이미지 생성
docker build -t node-app:0.1 .

# my-app 이라는 이미지 이름으로 4000번 포트와 컨테이너의 80번 포트 포워딩 후 이미지 run
# 로컬에서 접속 시 4000번 포트로 접근해야 함
docker run -p 4000:80 --name my-app node-app:0.1

컨테이너 디버깅하기

# 컨테이너의 working directory 에 접근
docker exec -it [container_id] bash

# 컨테이너 메타 데이터 확인
docker inspect [container_id]

Lab 2 - Kubernetes Engine: Qwik Start

클러스터 생성

# gcloud에서 클러스터 생성
gcloud container clusters create --machine-type=e2-medium --zone=assigned_at_lab_start lab-cluster 

배포해서 외부 접속하기

쿠버네티스를 이용해서 클러스터의 리소스를 관리할 수 있다.

  • deployment : web 서버와 같은 stateless한 배포를 가능하게 함
  • service : 인터넷을 통해 어플리케이션에 접속할 때 rule이나 load balancing을 설정
# hello-app:1.0 이미지 이용해서 deployment 생성
kubectl create deployment hello-server --image=gcr.io/google-samples/hello-app:1.0

# 외부로 노출할 포트와 LoadBalancer 설정해서 service 생성
kubectl expose deployment hello-server --type=LoadBalancer --port 8080

# hello-server 의 EXTERNAL-IP 확인 후 curl로 외부 접속 가능
kubectl get service

Lab 3 - Orchestrating the Cloud with Kubernetes

pod

  • pod란 1개 이상의 컨테이너가 포함된 모음
  • pod엔 volume이 존재.
    • volume이란 pod 안에 존재하는 데이터 디스크
    • pod 안에서 namespace를 제공하며 안에 존재하는 컨테이너는 이를 공유하여 서로 통신하거나 volume 공유 가능
  • pod는 네트워크 namespace를 공유하여 IP주소를 1개씩 가짐
# pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: monolith
  labels:
    app: monolith
spec:
  containers:
  	# monolith 라는 이름의 1개의 컨테이너로만 구성된 pod 이므로 모놀리식 구성
    - name: monolith
      image: kelseyhightower/monolith:1.0.0
      args:
      	# 컨테이너가 시작할 때 전달되는 인수
        - "-http=0.0.0.0:80"
        - "-health=0.0.0.0:81"
        - "-secret=secret"
      ports:
      	# http 트래픽용 포트 80 개방
        - name: http
          containerPort: 80
        - name: health
          containerPort: 81
      resources:
        limits:
          cpu: 0.2
          memory: "10Mi"
  • pod와 관련된 각종 명령어들
# port forwarding
kubectl port-forward monolith 10080:80

# 로그 보기
kubectl logs monolith

# 실시간 로그 보기
kubectl logs -f monolith

# 대화형 shell 실행 후 ping 테스트
kubectl exec monolith --stdin --tty -c monolith /bin/sh
ping -c 3 google.com

service

  • pod는 영구적이지 않으며 다양한 이유로 종료/시작을 반복하며 이 때마다 IP 주소가 변경
  • 이 때 pod와 통신하기 위해서 안정적인 엔드 포인트가 필요
  • 이를 위해서 service가 존재
  • 라벨을 사용하여 어떤 pod에서 작동할 지 결정
  • pod 집합에 대한 access 수준 결정
    • ClusterIP(내부), NodePort(IP 주소 제공), LoadBalancer(LB가 부하 분산)
# service.yaml

kind: Service
apiVersion: v1
metadata:
  name: "monolith"
spec:
  selector:
    app: "monolith"
    # secure: "enabled"가 있는 라벨이 지정된 pod를 찾아 노출
    secure: "enabled"
  ports:
    # 외부의 31000 포트를 pod의 443 포트로 전달
    - protocol: "TCP"
      port: 443
      targetPort: 443
      nodePort: 31000
  # NodePort 타입을 사용하여 외부에 IP 노출
  type: NodePort
  • pod에 라벨 추가하여 외부 접속
# pod에 secure=enabled 라벨 추가 후 확인
kubectl label pods secure-monolith 'secure=enabled'
kubectl get pods secure-monolith --show-labels

# 엔드포인트 확인 후 curl 명령으로 접속
kubectl describe services monolith | grep Endpoints

deployment

  • 컨테이너를 확장하고 관리
  • 실행중인 pod 개수를 동일하게 유지
  • replica set를 관리
  • node에 문제가 생겨서 종료되더라도 deployment가 새로운 pod를 만들어 개수를 동일하게 유지
deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
spec:
  selector:
    matchlabels:
      app: auth
  # replica 본 1개
  replicas: 1
  template:
    metadata:
      labels:
        app: auth
        track: stable
    spec:
      containers:
        - name: auth
          image: "kelseyhightower/auth:2.0.0"
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
...

Lab 4 - Managing Deployments Using Kubernetes Engine

replica 설정

# replica 개수 설정
kubectl scale deployment hello --replicas=5

rollout 배포

# deployment 파일 수정 후 저정하면 배포 시작됨

# 배포 history 확인
kubectl rollout history deployment/hello

# 배포 중지
kubectl rollout pause deployment/hello

# 배포 상태 확인
kubectl rollout status deployment/hello

# 배포 재개
kubectl rollout resume deployment/hello

# 배포 롤백 후 위의 history 명령어로 확인
kubectl rollout undo deployment/hello

Canary 배포

Canary로 작은 규모의 일부 사용자에게만 변경 사항을 릴리즈하여 테스트한 후에 전체 배포를 진행하는 형식

# canary-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
        track: canary
        # 2.0.0 버전을 사용하여 서비스 선택기의 버전과 일치시킵니다
        version: 2.0.0
    spec:
      containers:
        - name: hello
          image: kelseyhightower/hello:2.0.0
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81

이 때 한번 canary pod에 접속한 사용자는 계속 canary pod에 접속해야 변경 사항이 일관성 있게 적용되므로 이를 위해서 service 파일에 sessionAffinity 필드를 이용한다.

canary-service.yaml

kind: Service
apiVersion: v1
metadata:
  name: "hello"
spec:
  # 동일한 사용자에게 항상 동일한 버전을 제공하게 해줌
  sessionAffinity: ClientIP
  selector:
    app: "hello"
  ports:
    - protocol: "TCP"
      port: 80
      targetPort: 80

Blue/Green 배포

최소한의 다운 타임을 위해서 배포를 모두 완료한 후에 부하 분산기를 수정하여 새 버전을 가리키도록 하는 배포. 큰 단점은 이를 사용하려면 클러스터에 최소 2배의 리소스가 필요하다는 것이다.

이 때는 blue용 deploy yaml 파일, green용 yaml 파일을 만들고
green용 yaml 파일을 수정하여 배포가 완료되면 서비스가 새 버전인 green을 가리키도록 한다.

# 배포가 완료된 green 서비스를 가리키도록 수정
kubectl apply -f services/hello-green.yaml

Lab 5 - Continuous Delivery with Jenkins in Kubernetes Engine

젠킨스를 이용한 CI/CD 환경을 구축하는 과정에 대한 장이었다. 이 부분은 git 저장소를 클러스터 위에 띄운 젠킨스와 연결하여 파이프라인 생성하여 master 브랜치에 push가 일어날 경우 배포가 발생하게 했다.

profile
백엔드 개발자입니다.

0개의 댓글