EKS 클러스터 생성부터 서비스 배포까지 5. 마이크로서비스 배포
목차
EKS 클러스터 생성부터 서비스 배포까지 1. 쿠버네티스, EKS 기초
EKS 클러스터 생성부터 서비스 배포까지 2. EKS 환경 세팅하기
EKS 클러스터 생성부터 서비스 배포까지 3. eksctl을 사용하여 EKS실행하기, 노드그룹 설정하기
EKS 클러스터 생성부터 서비스 배포까지 4. K8s 대시보드 배포
EKS 클러스터 생성부터 서비스 배포까지 5. 마이크로서비스 배포
EKS 클러스터 생성부터 서비스 배포까지 6. HELM
애플리케이션 배포
Deployment와 Service를 사용하여 애플리케이션을 배포해보도록하겠습니다.
애플리케이션 이미지는 실습을 위해 미리 빌드된 brentley/ecsdemo-nodejs:latest 와 brentley/ecsdemo-nodejs:latest 를 사용하도록 하겠습니다.
예제 애플리케이션
sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecsdemo-nodejs
labels:
app: ecsdemo-nodejs
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ecsdemo-nodejs
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: ecsdemo-nodejs
spec:
containers:
- image: brentley/ecsdemo-nodejs:latest
imagePullPolicy: Always
name: ecsdemo-nodejs
ports:
- containerPort: 3000
protocol: TCP
위의 예제 Deployment파일은 서비스와 이것이 어떻게 배포되는지 서술되어있습니다. 이 내용을 kubectl을 아용하여 쿠버네티스 API에 쓰면 쿠버네티스는 애플리케이션이 배포될때 설정에 충족시키도록 환경을 구성합니다.
- apiVersion: 이 필드는 사용하는 Kubernetes API 버전을 나타냅니다. 이 예제에서는 **apps/v1**을 사용하고 있습니다.
- kind: 이 필드는 리소스의 종류를 정의합니다. 이 경우에는 "Deployment"를 나타냅니다.
- metadata: 이 섹션은 Deployment 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-nodejs"이고, 레이블은 "app: ecsdemo-nodejs"로 설정되어 있습니다.
- spec: Deployment의 세부 정보를 정의합니다.
- replicas: 원하는 파드 복제본 수를 나타냅니다. 이 경우에는 1개의 파드를 유지하려고 합니다.
- selector: 파드를 식별하기 위한 레이블 선택기를 지정합니다. 이 레이블 선택기는 "app: ecsdemo-nodejs" 레이블을 가진 파드를 대상으로 합니다.
- strategy: 롤링 업데이트 전략을 정의합니다.
- rollingUpdate: 롤링 업데이트를 사용하고 있으며, 최대 서지 및 최대 사용 불가능한 파드의 백분율을 설정합니다. 이 예제에서는 최대 서지와 최대 사용 불가능한 파드 모두 25%로 설정되어 있습니다.
- type: 롤링 업데이트의 타입을 "RollingUpdate"로 설정합니다.
- template: 파드 템플릿을 정의합니다.
- metadata: 파드 템플릿의 메타데이터를 정의합니다. 여기서는 레이블 "app: ecsdemo-nodejs"가 설정되어 있습니다.
- spec: 파드 스펙을 정의합니다.
- containers: 파드 내부에 실행되는 컨테이너를 정의합니다.
- image: 컨테이너 이미지를 지정합니다. 이 경우에는 "brentley/ecsdemo-nodejs:latest" 이미지를 사용합니다.
- imagePullPolicy: 이미지 풀 정책을 "Always"로 설정하여 항상 최신 이미지를 가져옵니다.
- name: 컨테이너의 이름을 정의합니다.
- ports: 컨테이너가 수신 대기하는 포트를 정의합니다. 이 경우에는 3000번 포트를 사용하고 TCP 프로토콜을 사용합니다.
- containers: 파드 내부에 실행되는 컨테이너를 정의합니다.
Node.js 백엔드 API 배포
Node.js 백엔드 API를 배포해보도록 하겠습니다.
kubectl apply -f ~/environment/ecsdemo-nodejs/kubernetes/deployment.yaml
kubectl apply -f ~/environment/ecsdemo-nodejs/kubernetes/service.yaml

각 파일의 내용은 다음과 같습니다.
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecsdemo-nodejs
labels:
app: ecsdemo-nodejs
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ecsdemo-nodejs
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: ecsdemo-nodejs
spec:
containers:
- image: brentley/ecsdemo-nodejs:latest
imagePullPolicy: Always
name: ecsdemo-nodejs
ports:
- containerPort: 3000
protocol: TCP
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **apps/v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Deployment"를 사용합니다.
- metadata: Deployment 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-nodejs"이고, 레이블은 "app: ecsdemo-nodejs"로 설정되어 있습니다.
- spec: Deployment의 세부 정보를 정의합니다.
- replicas: 원하는 파드 복제본 수를 나타냅니다. 이 경우에는 1개의 파드를 유지하려고 합니다.
- selector: 파드를 식별하기 위한 레이블 선택기를 지정합니다. 이 레이블 선택기는 "app: ecsdemo-nodejs" 레이블을 가진 파드를 대상으로 합니다.
- strategy: 롤링 업데이트 전략을 정의합니다. 롤링 업데이트를 사용하고 있으며, 최대 서지와 최대 사용 불가능한 파드의 백분율을 설정합니다.
- template: 파드 템플릿을 정의합니다. 파드 템플릿은 파드를 생성할 때 사용됩니다.
- metadata: 파드 템플릿의 메타데이터를 정의합니다. 레이블 "app: ecsdemo-nodejs"가 설정되어 있습니다.
- spec: 파드 스펙을 정의합니다.
- containers: 파드 내부에 실행되는 컨테이너를 정의합니다. "brentley/ecsdemo-nodejs:latest" 이미지를 사용하며, 포트 3000에서 수신 대기합니다.
service.yaml
apiVersion: v1
kind: Service
metadata:
name: ecsdemo-nodejs
spec:
selector:
app: ecsdemo-nodejs
ports:
- protocol: TCP
port: 80
targetPort: 3000
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Service"를 사용합니다.
- metadata: Service 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-nodejs"입니다.
- spec: Service의 세부 정보를 정의합니다.
- selector: 이 Service가 어떤 파드를 대상으로 하는지를 나타내는 레이블 선택기입니다. 이 경우에는 "app: ecsdemo-nodejs" 레이블을 가진 파드를 대상으로 합니다.
- ports: Service가 노출하는 포트 정보를 정의합니다. 이 Service는 80번 포트로 들어오는 요청을 파드 내의 3000번 포트로 전달합니다.
다음 명령으로 배포 현황을 확인할 수 있습니다.
kubectl get deployment ecsdemo-nodejs

크리스탈 백엔드 API 배포
이번에는 크리스탈 백엔드 API를 배포해보도록 하겠습니다.
kubectl apply -f ~/environment/ecsdemo-crystal/kubernetes/deployment.yaml
kubectl apply -f ~/environment/ecsdemo-crystal/kubernetes/service.yaml
파일 내용은 다음과 같습니다.
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecsdemo-crystal
labels:
app: ecsdemo-crystal
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ecsdemo-crystal
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: ecsdemo-crystal
spec:
containers:
- image: brentley/ecsdemo-crystal:latest
imagePullPolicy: Always
name: ecsdemo-crystal
ports:
- containerPort: 3000
protocol: TCP
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **apps/v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Deployment"를 사용합니다.
- metadata: Deployment 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-crystal"이고, 레이블은 "app: ecsdemo-crystal"로 설정되어 있습니다.
- spec: Deployment의 세부 정보를 정의합니다.
- replicas: 원하는 파드 복제본 수를 나타냅니다. 이 경우에는 1개의 파드를 유지하려고 합니다.
- selector: 파드를 식별하기 위한 레이블 선택기를 지정합니다. 이 레이블 선택기는 "app: ecsdemo-crystal" 레이블을 가진 파드를 대상으로 합니다.
- strategy: 롤링 업데이트 전략을 정의합니다. 롤링 업데이트를 사용하고 있으며, 최대 서지와 최대 사용 불가능한 파드의 백분율을 설정합니다.
- template: 파드 템플릿을 정의합니다. 파드 템플릿은 파드를 생성할 때 사용됩니다.
- metadata: 파드 템플릿의 메타데이터를 정의합니다. 레이블 "app: ecsdemo-crystal"가 설정되어 있습니다.
- spec: 파드 스펙을 정의합니다.
- containers: 파드 내부에 실행되는 컨테이너를 정의합니다. "brentley/ecsdemo-crystal:latest" 이미지를 사용하며, 포트 3000에서 수신 대기합니다.
service.yaml
apiVersion: v1
kind: Service
metadata:
name: ecsdemo-crystal
spec:
selector:
app: ecsdemo-crystal
ports:
- protocol: TCP
port: 80
targetPort: 3000
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Service"를 사용합니다.
- metadata: Service 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-crystal"입니다.
- spec: Service의 세부 정보를 정의합니다.
- selector: 이 Service가 어떤 파드를 대상으로 하는지를 나타내는 레이블 선택기입니다. 이 경우에는 "app: ecsdemo-crystal" 레이블을 가진 파드를 대상으로 합니다.
- ports: Service가 노출하는 포트 정보를 정의합니다. 이 Service는 80번 포트로 들어오는 요청을 파드 내의 3000번 포트로 전달합니다.
다음 명령으로 배포 현황을 확인할 수 있습니다.
kubectl get deployment ecsdemo-crystal
프론트엔드 서비스 생성 전 서비스 종류 확인
다음은 프론트엔드 서비스의 yaml입니다.
apiVersion: v1
kind: Service
metadata:
name: ecsdemo-frontend
spec:
selector:
app: ecsdemo-frontend
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 3000
이전에 배포하였던 백엔드 API서버와 달리 spec → type 이 LoadBalancer로 지정되어있습니다.
이는 ELB를 설정하여 서비스로 들어오는 트래픽을 처리하도록합니다.
이를 설정하지 않으면 기본적으로 ClusterIP로 지정되며, 위에서 배포한 백엔드 API서버들이 이것입니다.
ELB 서비스 롤 있는지 확인
이전에 로드밸런서를 생성하지 않은경우 롤이 존재하지 않을 수 있습니다.
롤을 확인하고 만약 롤이 존재하지 않는다면 이를 만들어주어야합니다.
aws iam get-role --role-name "AWSServiceRoleForElasticLoadBalancing" || aws iam create-service-linked-role --aws-service-name "elasticloadbalancing.amazonaws.com"
프론트엔드 서비스 배포
루비 on Rails 로 작성되어있는 프론트엔드를 배포해보도록 하겠습니다.
kubectl apply -f ~/environment/ecsdemo-frontend/kubernetes/deployment.yaml
kubectl apply -f ~/environment/ecsdemo-frontend/kubernetes/service.yaml
파일 내용은 다음과 같습니다.
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecsdemo-frontend
labels:
app: ecsdemo-frontend
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ecsdemo-frontend
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: ecsdemo-frontend
spec:
containers:
- image: brentley/ecsdemo-frontend:latest
imagePullPolicy: Always
name: ecsdemo-frontend
ports:
- containerPort: 3000
protocol: TCP
env:
- name: CRYSTAL_URL
value: "<http://ecsdemo-crystal.default.svc.cluster.local/crystal>"
- name: NODEJS_URL
value: "<http://ecsdemo-nodejs.default.svc.cluster.local/>"
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **apps/v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Deployment"를 사용합니다.
- metadata: Deployment 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-frontend"이고, 레이블은 "app: ecsdemo-frontend"로 설정되어 있습니다.
- spec: Deployment의 세부 정보를 정의합니다.
- replicas: 원하는 파드 복제본 수를 나타냅니다. 이 경우에는 1개의 파드를 유지하려고 합니다.
- selector: 파드를 식별하기 위한 레이블 선택기를 지정합니다. 이 레이블 선택기는 "app: ecsdemo-frontend" 레이블을 가진 파드를 대상으로 합니다.
- strategy: 롤링 업데이트 전략을 정의합니다. 롤링 업데이트를 사용하고 있으며, 최대 서지와 최대 사용 불가능한 파드의 백분율을 설정합니다.
- template: 파드 템플릿을 정의합니다. 파드 템플릿은 파드를 생성할 때 사용됩니다.
- metadata: 파드 템플릿의 메타데이터를 정의합니다. 레이블 "app: ecsdemo-frontend"가 설정되어 있습니다.
- spec: 파드 스펙을 정의합니다.
- containers: 파드 내부에 실행되는 컨테이너를 정의합니다. "brentley/ecsdemo-frontend:latest" 이미지를 사용하며, 포트 3000에서 수신 대기합니다.
- env: 환경 변수를 정의합니다. 이 파드에서는 두 개의 환경 변수를 정의하고 있으며, "CRYSTAL_URL"과 "NODEJS_URL"이라는 이름을 가지며 각각의 값이 설정되어 있습니다. 이러한 환경 변수는 애플리케이션 설정에 사용됩니다.
service.yaml
apiVersion: v1
kind: Service
metadata:
name: ecsdemo-frontend
spec:
selector:
app: ecsdemo-frontend
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 3000
- apiVersion: Kubernetes API 버전을 나타냅니다. 여기서는 **v1**을 사용하고 있습니다.
- kind: 리소스의 종류를 나타냅니다. 이 경우에는 "Service"를 사용합니다.
- metadata: Service 리소스의 메타데이터를 정의합니다. 이름은 "ecsdemo-frontend"입니다.
- spec: Service의 세부 정보를 정의합니다.
- selector: 이 Service가 어떤 파드를 대상으로 하는지를 나타내는 레이블 선택기입니다. 이 경우에는 "app: ecsdemo-frontend" 레이블을 가진 파드를 대상으로 합니다.
- type: Service의 유형을 나타냅니다. 이 경우에는 "LoadBalancer" 유형을 사용하고 있으므로 외부에서 접근 가능한 로드 밸런서가 생성됩니다.
- ports: Service가 노출하는 포트 정보를 정의합니다. 이 Service는 80번 포트로 들어오는 요청을 파드 내의 3000번 포트로 전달합니다.
다음 명령으로 배포 현황을 확인할 수 있습니다.
kubectl get deployment ecsdemo-frontend
서비스 주소 찾기
LoadBalancer 타입으로 생성된 Service에 접근해보기위해 조회해보도록 하겠습니다.
kubectl get service ecsdemo-frontend -o wide
EXTERNAL-IP 항목으로 조회되는 LoadBalancer의 DNS 주소로 접속해보겠습니다.

대쉬보드 확인
생성하였던 쿠버네티스 대쉬보드를 조회해보도록 하겠습니다.

배포하였던 디플로이먼트 3개가 정상적으로 생성된것을 확인해 볼 수 있고, 각 파드의 러닝상태를 조회할 수 있습니다.
백엔드 서비스 스케일링
서비스 시작시에 각각의 컨테이너를 1개씩만 런칭하였는데, 백엔드 서비스를 스케일아웃 해보도록 하겠습니다.
kubectl scale deployment ecsdemo-nodejs --replicas=3
kubectl scale deployment ecsdemo-crystal --replicas=3
다음 명령으로 레플리카셋이 3개로 증가하며, 총 파드는 6개가 되어야 합니다. 대쉬보드를 조회합니다.
스케일 아웃시에는 배포하는 시간이 어느정도 소요됩니다. 프론트를 포함, 총 7개의 파드가 생성되었습니다.
