본문으로 건너뛰기

하이라이트

GitLab은 MLOps를 어떻게 최적화할까?

머신러닝(ML) 워크플로와 배포를 자동화하고 간소화하는 관행인 MLOps의 중요성이 날로 커지고 있습니다. GitLab은 이러한 흐름에 발맞춰 최근 MLOps 기능을 강화했습니다. 이 글은 MLOps 개념과 구성 요소, MLOps 필요성과 플랫폼 역할, GitLab의 주요 MLOps 기능을 다뤘습니다.

자세히 보기

포스트

HOME/BLOG
페어 프로그래밍을 위한 4가지 팁페어 프로그래밍을 위한 4가지 팁

GitLab 및 여러 기업은 페어 프로그래밍(짝 프로그래밍)을 통해 혼자 해결하기 어려운 과제들을 해결해 나가고 있습니다. 이 글에서는 페어 프로그래밍이 무엇이고, 어떤 장점이 있는지 확인해보고, 또 원격 페어 프로그래밍의 장점 및 적절한 활용을 위한 4가지 팁을 알아보겠습니다.

Fabbro
Fabbro | Software Engineer
Signoz 소개Signoz 소개

최근 IT 업계에서 마이크로서비스 아키텍처, 클라우드 네이티브와 같은 최신 기술 트렌드가 빠르게 채택되고 있습니다. 그러나 규모가 확장되면서 복잡해진 아키텍처에 대해 사용자들이 어려움을 겪고 있습니다.

Lucas
Lucas | DevOps Engineer
Git 커밋 메시지는 왜 중요할까?Git 커밋 메시지는 왜 중요할까?

git 커밋 메시지가 모든 소프트웨어 엔지니어에게 중요하다는 것은 이미 알고 계실 거라 생각합니다. 잘 만든 커밋 메시지는 다른 개발자에게 변경 사항을 전달하는 가장 쉽고 간편한 방법이기 때문입니다. 그래서 기업의 대규모 프로젝트는 당연하고 협력의 비중이 낮은 소규모의 사이드 프로젝트에서도 커밋 컨벤션을 따로 만들어서 규칙을 지키기도 합니다.

이번 포스팅에서는 좋은 커밋 메시지의 중요성과 커밋 메시지 잘 쓰는 법을 알아봅니다. 더불어 인포그랩 프로덕트 팀의 커밋 컨벤션을 소개합니다.

Hailie
Hailie | Software Engineer
GCP에서 Docker와 Kubernetes를 이용하여 NestJS애플리케이션 배포하기GCP에서 Docker와 Kubernetes를 이용하여 NestJS애플리케이션 배포하기

DevOps 개발자들은 쿠버네티스를 설정하고 사용할 때 주로 매니페스트로 작업합니다. YAML 파일이나 Helm 파일을 이용해서 쿠버네티스를 설정하는데요. 오늘은 GUI를 이용하여 쿠버네티스를 설정하고, Node.js의 서버 프레임워크인 NestJS로 개발한 백엔드 애플리케이션을 배포하는 방법을 알아보겠습니다. 클라우드 플랫폼은 GCP를 이용하겠습니다. 우선 클러스터 생성, DB 생성, 클러스터와 DB를 연결함으로써 쿠버네티스 환경을 세팅하고, 세팅 이후에는 배포하고 싶은 애플리케이션을 쿠버네티스 환경에 배포함으로써 외부에서도 접근이 가능하도록 진행하겠습니다.

1. 쿠버네티스 사용 환경 세팅하기

1.1 클러스터 만들기

GCP에서 Kubernetes Engine > 클러스터로 들어갑니다. 그 다음 만들기를 클릭한 후 AutoPilot을 선택합니다. 쿠버네티스를 잘 알거나, ‘이 클러스터를 생성할 때 메모리, CPU가 얼마나 필요한지’ 알아서 아키텍처를 잘 설계할 수 있다면 ‘Standard’로 선택해도 됩니다. 하지만 쿠버네티스가 처음이라면 AutoPilot을 사용하는 걸 추천합니다. AutoPilot을 선택한 이후 이름과 리전(서울 : asia-northeast3)을 선택한 뒤 클러스터를 생성합니다.

‘AutoPilot’은 유저 접속량에 따라 노드 개수를 자동으로 늘리는 기능입니다. 접속자가 없으면 리소스를 낭비하지 않도록 필요없는 노드를 줄이고, 접속자가 많으면 노드를 자동으로 필요한 만큼 늘립니다.

1.2 CloudSQL를 이용한 데이터베이스 생성

클러스터를 생성했으니 이제는 SQL을 이용해 데이터베이스를 생성합니다. 먼저 SQL 대시보드에 접속합니다. 그다음 인스턴스 만들기를 클릭합니다. 여기서 사용하고 싶은 데이터베이스를 선택합니다. 또 인스턴스 ID비밀번호를 설정합니다. 시작할 구성 선택에서는 Development를 선택합니다. 만약 Production을 선택하면 컴퓨터가 2대이기 때문에 요금이 2배로 부과됩니다. 리전asia-northeast3, 영역가용성단일영역을 선택합니다. 많은 차이가 나지는 않지만, 비용을 절약하려면 머신유형 에서 CPU를 줄여서 선택합니다. DB이므로 공개가 되면 안 되기 때문에 연결 에서는 비공개IP 를 선택합니다. 네트워크default를 선택합니다. 그다음 인스턴스 만들기 클릭하면 DB 생성이 완료됩니다.

DB를 생성했다면 DB의 데이터베이스를 생성합니다. 데이터베이스 이름은 쿠버네티스 작업부하에서 배포했던 환경변수에 입력한 데이터베이스 이름으로 변경하면 됩니다. 만약 작업부하에서 배포했던 환경변수에 입력한 데이터베이스 이름이 기억나지 않는다면 쿠버네티스의 Kubernetes Engine > 보안 비밀 및 ConfigMap에 들어가서 확인할 수 있습니다. 구성 맵 세부정보에 들어가 보면 데이터 부분에서 데이터베이스 이름(=DATABASE_DATABASE)을 찾을 수 있습니다.

1.3 DB와 클러스터 연결

클러스터와 DB를 생성했으니, 이제는 이 둘을 연결하는 작업을 할 것입니다. SQL과 애플리케이션을 연결하려면 쿠버네티스의 보안 비밀 및 ConfigMap > 데이터에 gcloudSQL의 DB HOST를 적어야 합니다. 만약 DB HOST가 기억나지 않는다면 SQL 대시보드에서 확인할 수 있습니다. SQL > 개요 > 이 인스턴스에 연결 > 비공개IP 주소안의 주소를 복사한 뒤 보안 비밀 및 ConfigMap의 환경변수에 붙여넣기합니다. DB를 생성할 때 DB를 비공개 설정했기 때문에 비공개IP주소로 공개됩니다. 이렇게 확인한 HOST와 PASSWORD 등 DB 연결 정보를 입력하여 애플리케이션과 DB를 대응합니다. (또한 만약 환경변수를 수정해야 한다면 이곳에서 수정하면 됩니다)

1.4 Container Registry

쿠버네티스에서 도커 이미지를 사용하기 위해서는 도커 이미지를 생성 후 Container Registry에 해당 이미지를 업로드 해야합니다. 업로드 방법은 아래와 같습니다.

  1. docker build . : 현재 경로에서 이미지 빌드
  2. docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] : 도커이미지 경로/태그변경
  3. docker push REGISTRY/PROJECT-ID/IMAGE:TAG : 레지스트리에 이미지 올리기

[TAG]는 변경된 코드가 있을 때마다 버전을 다르게 해서 업로드 해야 합니다. 태그를 다르게 해야 GCP가 변경을 감지하기 때문입니다.

Kubernetes Engine 클러스터에서 Container Registry 이미지를 등록시키기 위해 image의 경로를 작성한 뒤 코드를 Push 합니다. Push가 완료되면 image: HOSTNAME/PROJECT-ID/IMAGE:TAG 경로를 찾아 해당 태그의 이미지가 Container Registry에 업로드됩니다. Push를 위한 명령어는 아래와 같습니다.

  • docker-compose -f docker-compose.prod.yaml build
  • docker-compose -f docker-compose.prod.yaml push
Cluster | 인포그랩 GitLab

생성된 이미지를 Container Registry에서 확인하실 수 있습니다.

1.5 Container Registry 이미지와 K8s 컨테이너 연결하기

쿠버네티스 클러스터를 만들었다면 이제는 Kubernetes Engine > 작업부하에서 컨테이너를 지정해야 합니다. 이미지 Push가 제대로 완료되었다면 Container Registry에 올라온 컨테이너 이미지를 선택할 수 있습니다. 원하는 이미지를 선택하고 환경변수를 설정합니다. VM 인스턴스에서는 $ vi .env.docker 같이 .env 파일을 생성한 뒤 설정했는데 GUI를 이용하면 환경변수를 UI에서 따로 지정할 수 있습니다. 만약 환경변수를 따로 지정하지 않으면 애플리케이션을 실행할 때 참조할 .env 파일이 없으므로 배포 시 에러가 발생합니다. 그러므로 애플리케이션을 개발할 때 사용한 .env가 있다면 반드시 환경 변수로 설정해야 합니다. 환경변수와 이미지를 선택한 뒤 하단의 구성 YAML을 보면 아래와 같은 YAML파일이 생성된 것을 확인할 수 있습니다.

---
apiVersion: "v1"
kind: "ConfigMap"
metadata:
  name: "nginx-2-config-f3jn"
  namespace: "default"
  labels:
    app: "nginx-2"
data:
  DATABASE_DATABASE: "sampleDB"
---
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: "nginx-2"
  namespace: "default"
  labels:
    app: "nginx-2"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: "nginx-2"
	template:
	  metadata:
	    labels:
	     app: nginx-2
	 spec:
     containers:
      - name: my-container
        image: my-image
				env:
        - name: nginx-2-config-f3jn
          value: DATABASE_DATABASE

2. 쿠버네티스로 배포하기

2.1 배포한 NestJS에 접속

지금까지 쿠버네티스에 작업했던 백엔드 애플리케이션 코드를 push 하는 작업까지 진행했습니다. 그러나 아직은 외부에서 백엔드 서버에 접속할 수 없습니다. 이유는 외부 IP를 노출시키지 않았기 때문인데요. 클러스터에 외부 IP를 통해 노출해 줘야 외부에서도 NestJS 애플리케이션에 접속할 수 있습니다.

외부 IP 노출은 작업부하에서 해줄 수 있습니다. 작업부하에서 노출을 해주면 되는데, 확인은 서비스 및 수신에서 할 수 있습니다. 배포된 작업부하에 들어가면 노출 중인 서비스노출 버튼을 클릭합니다. 이 전에 서비스 유형을 선택해 주어야 하는데, DB처럼 외부에 공개하는 게 위험하고, 클러스터 내부에서만 접속할 수 있게 하려면 클러스터 IP를 선택하고 만약 외부에서도 접속할 수 있게 하려면 부하 분산기를 선택하면 됩니다. 포트대상포드1도 애플리케이션이 실행되는 포트로 설정해 줍니다. 예를 들어 백엔드 서버 작업을 3000번 포트로 작업했다면 3000으로 작성합니다. 노출 버튼을 클릭하여 노출해 주면 서비스 및 수신에서 확인할 수 있습니다.

Cluster | 인포그랩 GitLab

설정을 마치면 엔드포인트가 생성된 것을 확인할 수 있습니다.

Cluster | 인포그랩 GitLab

이 엔드포인트로 브라우저에서 접속하면 접속이 되는 것을 확인할 수 있습니다.

2.2 이미 실행중인 클러스터 Update

DB와 애플리케이션을 연결했으니 이제 애플리케이션이 제대로 실행되는지 확인해야 합니다. 또한 더 좋은 코드를 위해 계속해서 수정하다 보면 이미지를 업데이트해야 하는 상황이 발생합니다. 이때는 새로운 태그를 생성한 뒤 실행 중인 쿠버네티스 클러스터를 업데이트해 주어야 합니다. 그래야 새로운 코드를 반영할 테니까요. 재시작 혹은 업데이트는 터미널에서 할 수 있는데, 터미널에 접속하기 위해서는 현재 실행 중인 클러스터에서 Kubernetes Engine > 클러스터 > 실행 중인 클러스터의 '...' 메뉴 > 연결을 클릭합니다. 클러스터에 연결이라는 창이 새로 뜨면 CLOUD SHELL에서 실행 버튼을 클릭합니다.

클릭하게 되면 브라우저 아래에 터미널 창이 뜨는데, 거기서 자동으로 현재 클러스터의 위치를 잡아줍니다. 자동으로 경로를 잡아주기 때문에 커서가 깜박이는 상태로 enter를 쳐주면 해당 클러스터 터미널에 접속한 것입니다. 터미널에서 쿠버네티스 pods를 업데이트하는 명령어를 적어줘야 합니다. 그런데 이때 클러스터와 프로젝트 등 여러 가지 내용을 적어야 합니다.

이 정보를 확인하는 방법에는

  • GUI로 확인하는 방법
  • YAML파일로 확인하는 방법

총 2가지가 있습니다.

  1. GUI에서 확인하는 방법: Kubernetes Engine > 작업부하 > 배포 세부정보로 들어가면 pods사양으로 확인할 수 있습니다.

    Cluster | 인포그랩 GitLab
  2. YAML파일에서 확인하는 방법: kubectl get pods -o yaml cli명령어를 통해 확인할 수 있습니다.

containerStatuses:
- containerID: containerd://b25
  ...중략...
  lastStatus:[]
  name: new-backend-sha256-1  //컨테이너이름
  ready: true
  restartCount: 0
  started: true

위 2개의 방법 중 하나를 선택해서 정보를 확인했으면 아래 명령어를 통해 쿠버네티스 업데이트를 해줍니다.

$ kubectl set image deployment/작업부하배포이름 컨테이너이름=ContainerRegistry이미지이름

그래서 1.4 Container Registry에서 예시로 든 이미지를 예로 들자면 kubectl set image deployment/mybackend-nestjs new-backend-sha256-1=asia.gcr.io/new-backend-372105/new-backend:0.9 으로 작성해 줄 수 있습니다. 업데이트가 완료되면

$ deployment.apps/mybackend-nestjs image updated

라는 명령어를 통해 업데이트가 완료되었는지 확인할 수 있습니다. 그리고 업데이트가 되고 pods가 잘 작동하는지 확인하려면

$ kubectl get pods

명령어를 통해 pods의 상태를 확인할 수 있습니다.

NAME								READY	STATUS		RESTARTS	AGE
mybackend-nests-65f6cdd775-rh6sg	1/1		Running		0			22h
mybackend-nests-b69869589-arrzp	    0/1		Pending		0			31s

현재 Pending 상태라는 것을 확인할 수 있는데 새로 만들고 있는 것을 확인할 수 있습니다. 새로 만들어진 pods는 Pending이었다가, Container Creating이었다가 시간이 조금 더 지나면 Running으로 변경됩니다. 그러면 기존에 Running이었던 것들이 Terminating으로 바뀌면서 사라집니다. 이제 새로 생성된(=업데이트된) pods가 잘 실행되고 있는지 확인해 봐야 합니다.

$ kubectl logs -f pods의NAME

pods의NAMENAME-f 뒤에 적어주면 됩니다. 그러니까 위 예시의 pod의 상태를 확인하려면 kubectl logs -f mybackend-nests-65f6cdd775-rh6sg 라는 명령어를 사용하여 현재 애플리케이션의 상태를 확인할 수 있습니다.

맺음말

지금까지 GCP에서 K8s와 Docker를 이용해서 NestJS 배포하는 법을 알아보았습니다. 주변에서 Backend 개발자들이 Backend와 배포를 모두 담당해야 하는 경우도 종종 찾아볼 수 있는데요. 이럴 때 GUI를 이용한다면 조금 더 쉽게, 낮은 진입장벽을 가지고 DevOps에 접근할 수 있을 것 같습니다.

인포그랩은 GitLab 및 DevOps에 대한 맞춤 기술 지원을 제공합니다. GitLab(Omnibus/Cloud Native Hybrid) 구축 관련한 지원이 필요하시면 문의하기 로 연락 주십시오.

<참고자료>

Google Cloud에서 Container Registry 사용

docker tag

Google Cloud Container Registry 이미지 가져오기 및 내보내기

Sky
Sky | Software Engineer
Pod Scheduling Readiness 소개Pod Scheduling Readiness 소개

Kubernetes 1.26에서 Scheduling gates라는 새로운 파드 옵션이 도입되었습니다. 이 옵션은 파드를 Readiness 상태로 두어, 스케줄러는 해당 파드를 무시하며 궁극적으로 스케줄링 주기의 속도를 향상시킬 수 있습니다. 그렇다면 스케줄링 게이트란 무엇일까요? 먼저, 파드의 스케줄링 방식을 알아봅시다.

Kane
Kane | DevOps Engineer
테크니컬 라이팅 깔끔하게 완성하는 10가지 원칙테크니컬 라이팅 깔끔하게 완성하는 10가지 원칙

기술 문서는 제품 개발, 사용을 위한 모든 문서와 자료입니다. 이는 제품 사용법, 기능, 아키텍처를 설명하죠. 혹자는 '이메일을 비롯해 회사에서 작성하는 모든 문서'를 기술 문서로 보기도 합니다. 기술 문서는 사용자에게 기술 정보를 틀림 없이, 이해하기 쉽게 전달해야 합니다. 사용자는 기술 문서에서 필요한 정보를 빠르고 쉽게 얻을 수 있어야 합니다. 이 글은 정확하고, 잘 읽히며, 유용한 기술 문서를 쓰기 위해 고려할 사항을 담았습니다.

*이 글은 테크니컬 라이팅 일반 원칙, 문장 원칙을 주로 다뤘습니다. 글 내용은 앞으로 상황과 필요에 따라 추가, 수정될 수 있습니다.

*이 글은 할 일 목록(To-Do List) 형태로 작성했습니다. 각 항목을 체크하며 글을 점검하길 권장합니다.

*이 글은 인포그랩 내부 스타일 가이드로, 8번 (GitLab 관련) 영문 표기는 타사에 일괄로 적용하기에 맞지 않을 수 있습니다.

*이 글은 테크니컬 라이팅·웹 글쓰기·우리말 관련 도서, 마이크로소프트·구글·GitLab 스타일 가이드, 카카오 엔터프라이즈·NHN 클라우드·토스의 테크니컬 라이팅 콘텐츠 등을 참고해 작성했습니다. 각 참고 자료에서 공통으로 다룬 내용, 실무에 먼저 필요한 내용을 글에 반영했습니다. 자세한 참고 자료는 이 글 맨 하단에서 볼 수 있습니다.

Grace
Grace | Technical Writer
2023년에 주목할 DevOps 트렌드 5�가지2023년에 주목할 DevOps 트렌드 5가지

이 글에서는 올해 DevOps 트렌드 가운데 5가지를 골라 살펴봅니다. 그동안 IT업계 전문가·기업, 관련 매체 등이 2023년 DevOps 트렌드를 다양하게 전망했는데요. 이 글에서는 여러 전망 가운데 3회 이상 지목된 트렌드 5개를 선정했고요. 해당 트렌드의 개념과 기능, 장점, 시장 전망, 성장요인 등을 들여다봤습니다. 2023년 DevOps 트렌드가 새롭지 않을 수도 있는데요. 그러나 반복해서 언급되는 개념을 따로 살펴보면 ‘업계에서 중요하게 생각하는 트렌드’를 쉽게 파악하는 데 도움될 수 있죠. 지금부터 하나하나 알아보겠습니다.

Grace
Grace | Technical Writer
쿠버네티스를 해킹하는 엔지니어를 위한 안내서쿠버네티스를 해킹하는 엔지니어를 위한 안내서

이번 포스팅에서는 Kubernetes 보안의 중요성을 강조하기 위해, 쿠버네티스를 해킹하여 secret 리소스에 저장된 비밀번호를 찾는 여러 가지 방법을 알아봅니다. 특히, etcd와 Pod를 해킹하는 실습으로 쿠버네티스 보안의 중요성을 알아보겠습니다.

Jeff
Jeff | DevOps Engineer
GitLab CI/CD 캐시: 파이프라인 속도 향상하기GitLab CI/CD 캐시: 파이프라인 속도 향상하기

GitLab의 중요한 기능 중 하나는 코드 빌드, 테스트 및 배포 과정을 자동화할 수 있는 CI/CD 파이프라인입니다. 그러나 프로젝트가 커지면 Job 수, 단계 수, 스크립트 및 의존성 수 등 많은 요소로 인해 파이프라인이 느려질 수 있습니다. 느린 파이프라인은 개발 프로세스에 부정적인 영향을 미칠 수 있으며, 시장 진입 시간이 증가하고 귀중한 자원을 낭비할 수 있습니다.

Jason
Jason | DevOps Architect
React App 테스트 자동화 with GitLabReact App 테스트 자동화 with GitLab

React는 사용자 인터페이스를 구축하기 위해 널리 사용되는 JavaScript 라이브러리입니다. 이 튜토리얼에서는 새로운 리액트 어플리케이션을 만들고 GitLab에서 CI 프로세스의 일부로 유닛 테스트를 실행하고 테스트 결과와 코드를 파이프라인에 출력하는 방법을 배울 수 있습니다.

Fabbro
Fabbro | Software Engineer
GitLab Value Stream Analytic 활용하기GitLab Value Stream Analytic 활용하기

오늘날 모든 회사는 소프트웨어 회사이므로 혁신 및 제공 수준이 수익 창출에 직접적인 영향을 미칩니다. 성공하기 위해 기업은 놀라운 디지털 경험을 제공하고, 최신 기술을 따라잡고, 고객이 요구하는 속도로 가치를 제공하고, 중단이나 보안 위반에 대해 무관용으로 모든 작업을 수행해야 합니다. 여기서 Value Stream Management(VSM)이 시작됩니다.

Rei
Rei | DevOps Engineer
MR로 협업하기 4편: Merge Request의 장점MR로 협업하기 4편: Merge Request의 장점

지난 MergeRequest로 개발 협업하기를 끝으로 디자이너, 개발자, PM이 서로 커뮤니케이션하고 협업하는 과정을 배워봤습니다.

하지만 구체적으로 뭐가 좋은지 아직 감이 안 잡히는 분들도 계실 겁니다.
그래서 역할별로 MR(Merge Request)의 장점을 총정리하는 시간을 가져 보겠습니다.

Michael
Michael | Software Engineer
Terraform 개념 잡기Terraform 개념 잡기

클라우드 시대가 되면서 인프라 엔지니어는 서버실에서 벗어나게 되었습니다. AWS 콘솔에서 클릭 몇 번으로 서버를 배포하고, 명령어 한 줄로 다양한 인프라를 구축할 수 있게 되었습니다. 더 나아가 인프라를 더 빠르고, 안전하게 관리하는 방법이 등장합니다.

Jeff
Jeff | DevOps Engineer
MR로 협업하기 3편: Merge Request로 개발 협업하기MR로 협업하기 3편: Merge Request로 개발 협업하기

지난 MergeRequest 만들기 포스트에서는 PM(Project Manager)이 이슈를 생성하고 디자이너와 협업하며 MR를 생성하는 부분까지 진행하였습니다.

이번엔 MR(MergeRequest)로 개발자와 협업하는 방법에 대해 자세히 알아보겠습니다.

Michael
Michael | Software Engineer
Docker 이미지 안전하게 만들기Docker 이미지 안전하게 만들기

애플리케이션을 Docker 이미지로 만들고, 배포해본 경험 다들 있으신가요? 무거운 이미지를 베이스 이미지로 사용해 한 번 다운받는 데 무척 오랜 시간이 걸리거나, 민감한 데이터를 포함하게 되어 보안상 문제가 생겼던 경험도 다들 있으실 겁니다. 이번 포스팅에서는 더 가볍고, 안전한 이미지를 만들기 위해서는 어떻게 해야 하는지 한 번 알아보겠습니다.

Jeff
Jeff | DevOps Engineer