들어가며
MSA에 입문한 뒤로 블로그에 글을 올라는 횟수가 대폭 줄었다.. 회사에 제안한 MSA 기반 프로젝트를 진행하면서 학습량이 많이 증가했기 때문이다.
(서비스 나누는 법을 알기 위해 이벤트 스토밍을 공부하고.. 서비스를 잘 만들기 위해 DDD와 객체 지향도 들여다보고.. Spring framework와도 이제 아주 조금은 친해진것 같기도 합니다.)
3번째로 진행하는 MSA 기반 프로젝트는 시스템 규모가 좀 있다 보니 마이크로 서비스가 18개 정도 도출되었다.
1, 2번째 진행한 MSA 기반 프로젝트들은 서비스 개수가 6~8개 정도였기 때문에 Kong 기반 API gateway + Docker compose 환경에서 처리가 가능했다. 하지만 진행 중인 프로젝트는 서비스의 개수도 많고, 상황에 따른 인프라 확장성(Scalability)이 요구되므로 쿠버네티스 환경에서 배포하기로 했다.
이를 위해 3개월간 Udemy CKA 과정을 수강하며 장님 코끼리 다리 만지듯 쿠버네티스를 접했는데, 현시점에서는 어느 정도 감을 잡은 것 같아서 간단한 프로젝트를 진행해 보았다 :)
목표 구조
CKA 과정과 이상희 교수님과 조훈 선생님의 쿠버네티스 교육과정에 굉장히 많은 구성 요소들이 담겨 있었지만, 필자가 생각했을 때 진행하고 있는 프로젝트를 쿠버네티스에 배포하기 위한 최소한의 요소와 요소들의 관계는 아래의 그림과 같았다.
구현
Ingress (참고)
외부 접근을 내부 서비스로 라우팅 해주는 역할을 수행한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx-pjt
spec:
rules:
- http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
본 예제에서는 여러 가지를 라우팅 할 필요 없이 동작 유무만 확인해보기 위해 간단히 Ingress를 만들었다. 실제 서비스를 배포할 때는 URI와 서비스들을 매핑해 주면 될 것 같다.
LoadBalancer Service (참고)
클러스터 전역에 퍼져있는(필자의 환경) Deployment App을 외부로 노출시킨다.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx-deploy
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Service 생성 시에 selector.app에는 배포한 Deployment의 app label을 기입해줘야 연결된다.
Deployment(참고)
선언적 애플리케이션 업데이트를 수행하기 위해 디플로이먼트 형태로 App을 배포한다.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy
name: nginx-deploy
spec:
selector:
matchLabels:
app: nginx-deploy
replicas: 3
template:
metadata:
labels:
app: nginx-deploy
spec:
containers:
- image: nginx:1.16
name: nginx
volumeMounts:
- mountPath: /app
name: nginx-storage
volumes:
- name: nginx-storage
persistentVolumeClaim:
claimName: nginx-volume-claim
디플로이먼트의 replicas는 3개로 설정한다. 이미지는 nginx:1.16 버전을 사용하고, 볼륨 관련 설정을 해준다.
spec.template.spec.containers.volumeMounts.mountPath는 컨테이너 상에서의 /app 디렉터리를 의미하는데, 본 예제에서는 설정해도 큰 의미가 없다. 실제 서비스를 배포할 때 만들어지는 log를 이 방식으로 PV에 저장할 예정이다.
volumes 설정에서는 PVC 이름을 설정해 줘야 하고, 아래에서 만드는 PVC 이름을 지정해야 연결된다.
PVC(참고)
PV(Persistent Volume)을 사용하기 위해 사용자가 요청하는 것이다. 컨셉은 1) 개발자가 물리적인 스토리지 스펙을 모르는 상황에서 2) 필요한 자원에 대한 스펙만 쿠버네티스에 요청하여, 3) 미리 생성되어있는 PV와 매칭 되는 것이다.
(필자가 관리도 하고 개발도 하는 입장에서는 PV, PVC를 다 써야 해서 번거롭긴 하다. 더 큰 팀은 다르겠죠..? ㅎㅎ)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-volume-claim
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 10Mi
PVC를 선언할 때는 서로 다른 노드에서도 접근할 수 있도록 spec.accessModes를 ReadWriteMany로, resource는 그냥 쪼금.. 10Mi 정도를 요청한다.
PV(참고)
스토리지다. 외부 스토리지를 사용할 수도 있고, 클러스터 스토리지를 사용할 수도 있다. 위에서 설명한 PVC에서 요구하는 스펙에 맞는 PV가 있으면 연결되어 사용된다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-volume
spec:
capacity:
storage: 10Mi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
hostPath:
path: /Users/mac/Desktop/kubernetes/test
PV를 생성할 때는 PVC의 요구사항을 만족하도록 만들어 둬야 한다. spec.capacity.storage와 spec.accessModes가 동일한 것을 알 수 있다. hostPath는 host의 특정 경로를 설정해준다. (CKA 과정에서 PVC 가 PV를 찾을 때 스펙이 일치하지 않아도 가장 적합한 PV를 고른다고 한다.)
이렇게 해서 배포를 하면 다음과 같이 app이 잘 실행되는 것을 확인할 수 있다.
주의사항
PV를 우선적으로 만들어야한다. 그래야 디플로이먼트가 PVC를 이용해 볼륨을 얻을 수 있기 때문이다.
아래의 링크에 필자가 만든 yaml 파일을 공유한다.
https://github.com/devlos0322/study-kubernetes-with-nginx
마치며
이번 글에서는 CKA 과정의 개념들을 이용하여 nginx 이미지를 기반으로 간단하게 애플리케이션을 배포하는 프로젝트를 소개했다. 프로젝트 하드웨어 인프라가 곧 갖춰지니, 마이크로 서비스 컨테이너들을 기반으로 yaml 파일들을 만들어 나가 봐야겠다 :)
9월에는 쿠버네티스에 잘 배포된 서비스들을 보면서 흐뭇해하고 있었으면 좋겠다. (제발!!)
'클라우드 컴퓨팅 & NoSQL > Kubernetes' 카테고리의 다른 글
[Istio] Istio Service mesh 튜토리얼 후기 (3) | 2022.12.31 |
---|---|
[Kubernetes] DEVOCEAN - 김정기 전문가(SK Telecom)님의 멘토링 (2) | 2022.10.09 |
쿠버네티스(Kubernetes) 공식 튜토리얼 #7 (0) | 2021.04.04 |
쿠버네티스(Kubernetes) 공식 튜토리얼 #6 (0) | 2021.04.04 |
쿠버네티스(Kubernetes) 공식 튜토리얼 #5 (0) | 2021.04.03 |