저번 글에서는 Jenkins Pipeline 설정에 관해 작성하였다. 이번 글에는 나머지 deployment.yaml 와 ArgoCD 의 배포 과정에 대해서 작성해보도록 한다.
1. ArgoCD 사용 이유
ArgoCD 는 기본적으로 OKD/Kubernetes 의 배포(Deployment) 관리를 쉽게 하기 위해 사용하는 GitOps 기반의 CD 도구이다. 따라서 CD 를 위해 반드시 사용해야 하는 도구는 아니다. 즉, 실제 Pod 의 배포 및 관리는 OKD 가 담당하지만, ArgoCD 를 활용하여 이를 더 쉽게 관리하고 자동화할 수 있기 때문에 사용하게 되었다.
조금 더 쉽게 이해하기 위하여 굳이 비유하여 표현하자면 OKD 는 Docker 와 비슷하고, ArgoCD 는 Docker Compose 와 비슷한 맥락이라고 생각하면 된다. OKD 는 kubectl 을 사용해서 직접 컨테이너(Pod)를 배포 및 관리하고, Docker 는 docker run, docker stop 과 같은 CLI 명령어를 직접 입력하여 컨테이너를 관리하게 된다. 반면, ArgoCD 와 Docker Compose 의 경우 미리 설정한 .yaml 파일을 가지고 "딸깍" 만으로 관리가 가능하다는 점이다.
2. deployment.yaml 와 Helm 차트의 차이점 및 선택 이유
대게 K8S 에서 애플리케이션을 배포하는 방법에는 deployment.yaml 을 직접 작성하여 배포하는 방법과 Helm 차트를 작성하여 배포하는 방법 두가지로 나눌 수 있다. 대게 deployment.yaml 을 직접 작성하여 배포하는 방식은 간단한 애플리케이션이나, 개발자 입장에서 쉽게 이해하고 변경할때 사용되어지는 개념이라고 보면 된다. 반대로 Helm 차트를 작성하여 배포하는 방식은 복잡한 애플리케이션(수천개, 수만개 이상의 .env 가 설정되어있을 경우)이나, 인프라적 입장에서 사용되는 개념이라고 보면 된다.
필자의 경우 현재 유저서비스, 채팅서비스, 알림서비스, 친구서비스, 프론트(웹,앱) 총 5개로 구성되어 있기 때문에 빠른 배포를 위하여 deployment.yaml 을 직접 작성하여 ArgoCD 에 GitOps 로 설정하였다. 추후, 다른 서비스가 추가적으로 붙게 된다면 이후에 Helm 차트를 작성하여 배포하는 방식으로 변경할 예정이며, 현재는 deployment.yaml 설정과 Service.yaml 설정에 관해서만 작성해보도록 한다.
3. YAML 종류 및 작성 방법
ArgoCD 에서 GitOps 방식으로 배포를 자동화 하기 위해서는 다양한 리소스 파일 (.yaml) 을 정의해야 한다. 보통 다음과 같은 YAML 파일들을 작성하여 Git 저장소에 올려관리한다. 해당 YAML 파일들에 자세한 설명들은 다른 글에서 작성하도록 하고 필자가 정의한 YAML 은 Deployment 와 Service 로 총 2개를 사용하였다.
4. deployment 와 service 정의
apiVersion: apps/v1
kind: Deployment
metadata:
name: front
namespace: stoock
labels:
app: front
spec:
replicas: 1
selector:
matchLabels:
app: front
template:
metadata:
labels:
app: front
spec:
containers:
- name: front
image: Harbor 개인 레포지토리 주소/user:2025-02-20
imagePullPolicy: Always
ports:
- containerPort: 3000
protocol: TCP
env:
- name: 환경 변수
value: "환경 변수의 값"
---
apiVersion: v1
kind: Service
metadata:
name: front
namespace: stoock
spec:
type: LoadBalancer
selector:
app: front
ports:
- protocol: TCP
port: 80
targetPort: 3000
보통은 Helm 차트를 작성하여 배포하는 방식을 사용한다면 deployment.yaml 과 service.yaml 을 분리 하지만 그렇지 않을 경우 K8S 에서는 --- (YAML 문서 구분자) 를 사용하여 한 파일에 여러 리소스를 정의할 수 있는 기능을 제공한다.
4.1 Deployment 세부 설명
apiVersion: apps/v1
- K8S 의 API 버전을 지정.
- apps/v1 은 Deployment 리소스를 정의할 때 사용하는 최신버전.
- 만약 apiVersion 이 맞지 않으면 해당 리소스가 K8S 에서 정상적으로 생성되지 않음.
kind: Deployment
- 이 YAML 파일이 Deployment 리소스를 정의한다는 의미.
- K8S 에서 Pod 를 생성하고 관리하는 객체.
- Deployment 는 자동 롤백, 업데이트, 레플리카 관리 기능을 제공.
- Pod 를 직접 생성하는 것이 아닌, Deployment 가 Pod 를 관리하도록 함.
metadata:
name: front
namespace: stoock
labels:
app: front
- name : Deployment 의 이름을 front 로 설정.
- namespace : Deployment 가 배포될 네임스페이스를 stoock 으로 지정.
- labels : Deployment 에 app: front 라는 라벨을 추가, 이후 Service 가 Pod 를 찾을 때 selector 에서 동일한 라벨을 사용하여 연결함.
- name 과 namespace 는 Deployment 를 식별하는 중요한 요소, labels 는 K8S 리소스 간의 연결을 위해 필수적.
spec:
replicas: 1
- 실행할 Pod 개수를 1로 설정.
- replicas : 3 으로 변경하면 Pod 가 3개 생성됨.
selector:
matchLabels:
app: front
- Deployment 가 관리할 Pod 를 선택하는 기준.
- app : front 라벨이 포함된 Pod 만 관리함.
- Deployment가 Pod을 관리하려면 matchLabels과 Pod의 metadata.labels 값이 반드시 일치해야 함.
template:
metadata:
labels:
app: front
- 새로운 Pod을 생성할 때 사용할 템플릿.
- metadata.labels.app: front를 추가하여 이 Pod이 Service에서 참조될 수 있도록 함.
- Service가 selector를 통해 app: front 라벨을 가진 Pod을 찾을 수 있도록 설정.
spec:
containers:
- name: front
image:
imagePullPolicy: Always
ports:
- containerPort: 3000
protocol: TCP
- name : 컨테이너 이름을 front 로 설정, 같은 Pod 내에서 여러 개의 컨테이너가 있을 경우 이를 구분하는 용도.
- image : 사용할 Docker 이미지 경로 및 태그, Harbor 개인 레포지토리 주소에서 이미지를 가져옴.
- imagePullPolicy : 이미지를 언제 가지고 올지 설정. (Always 는 보통 개발환경에서 사용, 이미지가 변경 될 때마다 가지고 옴.)
- ports : 컨테이너 내부에서 서비스가 실행될 포트. 여기서는 3000번 포트가 사용됨.
env:
- name: 환경 변수
value: "환경 변수의 값"
- env→ 컨테이너에서 사용할 환경 변수를 설정함.
- name : 환경 변수 이름을 정의.
- value : 환경 변수의 값
4.2 Service 세부 설명
apiVersion: v1
kind: Service
- apiVersion : Service 는 v1 API 버전을 사용함.
- kind : 이 YAML 파일이 Service 객체를 정의하고 있음을 나타냄.
metadata:
name: front
namespace: stoock
- metadata : Service 의 메타데이터를 정의하는 부분.
- name : Service 의 이름을 front 로 지정.
- namespace : stoock 네임스페이스에 이 Service 를 생성.
spec:
type: LoadBalancer
- spec : Service 의 동작을 정의하는 부분.
- type : 이 Service 를 LoadBalancer 타입으로 설정.
ports:
- protocol: TCP
port: 80
targetPort: 3000
- ports : 이 Service 가 사용하는 포트를 정의.
- protocol : TCP 프로토콜을 사용.
- port : 외부에서 Service 에 접근할 때 사용할 포트.
- targetPort : Service 가 내부적으로 트래픽을 보낼 컨테이너의 포트 (앞서 Deployment 에서 정의한 containerPort 번호).
4.3 전체 동작 흐름
- Deployment 가 실행되면서 front 라는 Pod 가 생성된다.
- Pod 내부에서는 Harbor 레포지토리에서 이미지를 가져와 실행한다.
- 컨테이너는 3000번 포트에서 애플리케이션을 실행한다.
- Service 는 app:front 레이블을 가진 Pod 를 찾아 트래픽을 전달한다.
- 외부 사용자는 LoadBalancer 를 통해 http://<외부 IP 주소>:80 으로 접근 가능하다.
- LoadBalancer 가 Service 로 요청을 전달하고, Service 는 이를 3000번 포트에서 실행중인 컨테이너로 라우팅한다.
5. 결과
작성된 deployment.yaml 은 GitHub 에 Private 로 등록되어 있는 레포지토리에 커밋이 된다. 해당 deployment.yaml 은 각 서비스마다 필요한 env 와 service 타입을 변경하여 작성한다. 또한 ArgoCD Settings 에서 해당 레포지토리를 GitOps 로 등록해놓으면 이미지가 변경될 때마다 자동으로 Pod 를 재배치 하는 작업을 거친다. 여기서 만약 이미지가 같을경우, 예를 들어 필자는 이미지 끝에 해당 날짜 태그를 활용하는 중인데 같은날 여러개의 이미지가 변경될 경우 이미지는 변경이 되지만 태그는 변경이 되지 않기 때문에 ArgoCD 에서 자동으로 인식하지 못한다. 이의 경우 Pod 를 임의적으로 삭제 시키면 등록된 새로운 이미지로 재배치 시키는 과정을 거친다.
이번 글에서 deployment.yaml 작성에 대하여 마무리 짓고 다음 글에 이어서 Jenkins Pipeline 에서 빠진 Dockerfile 에 대해 추가적으로 설명하고 배포 과정에 관한 작성은 끝내보려 한다.
'Project > ST00CK' 카테고리의 다른 글
gRPC로 오프라인 유저를 찾기 위한 로직 구현 (0) | 2025.02.24 |
---|---|
Jenkins Pipeline 설정 및 K8S 배포를 위한 deployment 작성 (3) (1) | 2025.02.21 |
Jenkins Pipeline 설정 및 K8S 배포를 위한 deployment 작성 (1) (0) | 2025.02.20 |
KafkaJS 경고문 해결하기 (0) | 2025.02.10 |
배포환경에서 Socket.IO 의 연결 끊김 이슈 및 해결방법 (1) | 2025.01.16 |