K8S 인프라 CI/CD 처리

사내 구축된 Kubernetes 인프라에 어플리케이션을 빌드하고 배포하는 프로세스에 대한 전반적인 설명 글입니다.


시작에 앞서

이 글은 Kubernetes 클러스터 환경 구축을 전제로 어플리케이션을 빌드하고 배포하는 과정의 프로세스를 설명하는 글이므로, 전반적인 Kubernetes의 구조와 개념에 대해서는 다루지 않음을 양해바랍니다.

CI/CD(지속적 통합/지속적 배포) 는 각각 Continuous Integration, Continuous Delivery(또는 Deploy)의 약자로, 짧은 주기를 두고 지속적으로 빌드/배포하는 것을 의미합니다.
짧은 주기의 빌드/배포가 가능하기 위해서는 빌드 및 배포 자동화가 선행되어야 하고, 자동화를 위해 사람인HR 에서 도입한 CI/CD 파이프라인 프로세스 소개를 하도록 하겠습니다.

GitOps 기반의 지속적 배포

gitops-logo

GitOps는 Kubernetes 클러스터를 관리하고 클러스터에 어플리케이션을 배포하는 방법론 중 하나로, Weaveworks에서 창안했습니다.
GitOps의 핵심은 어플리케이션 소스 뿐만 아니라, 배포 설정까지 Git 저장소(config 저장소)를 통해 관리한다는 것 입니다.
즉, Git 저장소에 선언적으로 기술 된 Kubernetes 매니페스트와 같은 파일을 저장하고, 이를 사용하여 배포를 진행하는 방식(개념) 입니다.

Weaveworks-GitOps

이로써 다음과 같은 이점이 발생합니다.

  • 시스템 구성에 대해 신뢰 가능한 단일 소스가 존재하게 됩니다.
  • 더 간편하고 빠른 배포가 가능해집니다.
  • 더 짧은 주기의 배포가 가능해집니다.
  • 모든 변경사항이 기록되어 추적이 가능합니다.
  • 필요한 경우 이전 매니페스트로 손쉽게 롤백할 수 있고 롤백 히스토리 역시 Git 저장소에 기록됩니다.


참고) Kubernetes 선언적 배포란

Desired State

Desired-State

Kubernetes에서 가장 중요한 것은 desired state (원하는 상태) 라는 개념입니다.
원하는 상태라 함은 사용자가 바라는 환경을 의미하고 좀 더 구체적으로는 얼마나 많은 웹서버가 떠 있으면 좋은지, 몇 번 포트로 서비스하기를 원하는지 등을 말합니다.

Kubernetes는 마이크로서비스 컴포넌트들로 구성되어 복잡하고 다양한 작업을 하지만, 핵심은 current state (현재 상태)를 모니터링 하면서 사용자가 설정한 원하는 상태를 유지 하려고 내부적으로 이런저런 작업을 하는 메카니즘을 가지고 있습니다.

Kubernetes의 핵심은 state(상태) 이며 Kubernetes를 사용하려면 어떤 상태가 있고 어떻게 상태를 선언하는지를 알아야 합니다.

간단한 Pod Object 선언 예시

apiVersion: v1
kind: Pod
metadata:
 name: example
spec:
 containers:
   - name: busybox
     image: busybox:1.25

Kubernetes는 다양한 오브젝트의 명세Spec을 YAML 파일로 정의하고 여기에 오브젝트의 종류와 원하는 상태를 입력하는 선언적 배포 방식으로 동작을 합니다.



프로세스

전체적인 CI/CD 프로세스는 다음과 같습니다.

Commit 된 개발 code로부터 컨테이너 이미지를 자동으로 빌드하는 CI/CD 파이프라인을 만들고, Container Registry에 이미지를 저장하고, 선언형 배포 작업 정의서 (Kubernetes 매니페스트)를 생성(업데이트)하고, 이 매니페스트를 사용하여 애플리케이션을 사내 Kubernetes 인프라에 배포하는 과정입니다.

아래는 프로세스를 보기쉽게 정리한 그림입니다.


CI/CD-프로세스

전체적인 Flow를 크게 2가지 단계로 나눌수 있습니다.

  1. GitLab 기반의 CI (빌드) 프로세스
  2. Rancher 기반의 CD (배포) 프로세스

CI와 CD의 분리가 되어 있는 구조이며, 각 단계의 기반이 되는 플랫폼인 GitLab-CIRancher 에 대해서는 뒤에서 다루도록 하겠습니다.


좀더 상세한 프로세스

보시는 바와 같이 GitOps의 방식으로 두 개의 Git 저장소를 사용하게 됩니다.

  • code 저장소: 어플리케이션 자체의 소스 코드를 저장.
  • config 저장소: Kubernetes 배포용 매니페스트 저장.
    .

Flow 설명

  1. 개발자가 git에 어플리케이션 code를 Push
  2. 푸시된 소스에 대해 GitLab CI 프로세스가 통합빌드를 진행
  3. 결과물로써 컨테이너 이미지가 생성되고, 사내 Docker Registry에 이미지를 Push
  4. 그후 등록된 배포 작업서에 변경 사항이 Update
  5. 아래의 배포방식에 의해 Kubernetes 인프라에 Deploy 및 Upgrade
    • 배포방식
      • 자동 : sync check 및 webhook 을 통한 자동 배포 처리
      • 수동 : 챠트 검색을 통한 수동 배포 처리


참고로,,  
개발환경에서는 자동으로 배포를 진행하지만, 운영환경에서는 실수로 인한 배포방지를 위해 배포 관리자가 수동 배포를 하는 방식으로 운영 중입니다.



CI 프로세스 - GitLab CI

다양한 CI툴이 존재하지만, GitLab에서도 강력하고 편리하게 CI기능을 제공을 합니다.
사내에서 이미 GitLab으로 어플리케이션 형상 관리를 하고 있었고, 프로젝트 소스에서 CI 프로세스를 확인 할 수 있어 운영 효율성 측면에서도 이점이 될거라 생각을 했습니다.

gitlab-runner
GitLab Architecture

사용법도 아주아주 간단하고 쉽습니다.

GitLab 프로젝트 Repository에 commit/push와 같은 이벤트가 발생하면,
gitlab-ci.yml에 작성된 파이프라인 스크립트가 실행되는 게 전체 프로세스 입니다.

  • 프로젝트 루트에 .gitlab-ci.yml이 존재하면 됩니다.
  • .gitlab-ci.yml 에 파이프라인(Job 묶음) 스크립트를 작성하면 트리거 형태로 실행이 됩니다.
  • job은 다음과 같은 기능들을 처리합니다.
    • 테스트: 유닛 테스트, 통합 테스트, E2E 테스트, 테스트 커버리지 측정
    • Lint: 코드 퀄리티 측정, 코드 컨벤션 점검
    • 빌드: 빌드, 번들링, Dockerfile 빌드 및 컨테이너 레지스트리 푸시
    • 배포: Helm Chart 및 App(컨테이너) 배포
  • 실제 작업은 gitlab-runner를 통해 실행됩니다.
    • Runner는 작업을 수행하고 결과를 GitLab으로 피드백.
    • gitlab-runner에 대한 자세한 설명은 gitlab docs 를 참고하시면 됩니다.


CI 파이프라인 (.gitlab-ci.yml)

아래 작성된 파이프라인에는 아래와 같은 작업을 처리하게 됩니다.

  1. 소스코드 컴파일 & 빌드
  2. 이미지 빌드
  3. 저장소에 푸시
  4. 자동 업데이트

.gitlab-ci.yml

# 4개의 stage를 지정
stages:
  - compile
  - build
  - push
  - deploy

# 스크립트에서 사용할 변수 설정
variables:
  CI_REGISTRY: docker-registry.saramin.co.kr/iris
  BUILD_TAG: $CI_COMMIT_REF_NAME-$CI_PIPELINE_ID
  WEBHOOK_URL: webhook.saramin.co.kr/api/auto-update
 
# maven 빌드 처리 
compile:
  stage: compile
  script:
    - mvn clean package

# Docekr 이미지 빌드  
build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY:$BUILD_TAG .  

# 이미지 Registry 저장
push:
  stage: push
  script:
    - docker push $CI_REGISTRY:$BUILD_TAG

# 배포 자동화 처리
auto-update:
  stage: deploy
  script:
    - curl -X POST "${WEBHOOK_URL}" -H "Content-Type:application/json" --data "{\"image\":\"${CI_REGISTRY}:${BUILD_TAG}\"}"
  only:
    - develop

추가적인 설명을 하자면,,

  • compile, buile, push, deploy 4단계의 스테이지로 구성되어 있습니다.
  • 하나의 스테이지에 여러 job이 포함될 수 있습니다.
    • 1개의 stage에 1개의 job만 포함된 예제.
  • script 항목에서 runner에 의해 수행될 쉘 스크립트를 작성합니다.
  • GitLab에서 사전 정의된 환경 변수를 활용해 이미지 tag명을 지정합니다.
    • CI_COMMIT_REF_NAME=”master”
    • CI_PIPELINE_ID=52666
  • BUILD_TAG는 $CI_COMMIT_REF_NAME-$CI_PIPELINE_ID 의 구성합니다.
    • master-52666 로 이미지 tag명이 지정됩니다.
  • only 항목으로 특정 브랜치 (develop) 이벤트가 발생했을 경우에만 동작하도록 설정이 가능합니다.

자세한 스크립트 사용법에 대해서는 공식문서를 참고하시면 됩니다.


Dockerfile

Docekr 이미지 빌드를 하기 위해서는 Dockerfile 이 존재해야 하며, Dockerfile 내용은 아래와 같이 정말 간단합니다.
spring boot 기반의 어플리케이션이라 빌드된 jar파일 하나만 copy를 하면 되고, java 명령어로 실행을 시켜주는게 다입니다.

FROM docker-registry.saramin.co.kr/alpine/openjdk-8:1.1.0 
LABEL maintainer="user@saramin.co.kr"

RUN mkdir -p /opt/app
COPY ./iris/target /opt/app

WORKDIR /opt/app
RUN cp iris-*.jar iris.jar

ENTRYPOINT exec java $JAVA_OPTS -jar iris.jar

.gitlab-ci 파이프라인에 docker image 빌드 job이 존재한다면 위의 Dockerfile이 존재해야 함으로 이점을 주의 해주시면 됩니다.

메뉴의 CI/CD > Pipelines 에 가면 해당 커밋에 대한 파이프라인의 실행 내역에 대해 확인이 가능합니다.

모든 브랜치의 커밋은 자동으로 빌드되어 바로 배포 가능한 도커 이미지가 생성이 되게 됩니다.
물론 CI 스크립트(.gitlab-ci.yml)를 수정하여 빌드 제외 할 브랜치 설정도 가능합니다.

gitlab-branches

pipeline 이 완료되면 이미지 저장소인 사내 도커 레지스트리에 생성된 Container Image 확인이 가능하고, 이제 우리의 어플리케이션을 어떤 환경이든지 배포를 할 첫번째 단계가 완료 되었습니다.


Docker Registry UI



CD 프로세스

기본적으로 Kubernetes 배포를 위해서는 다양한 오브젝트의 명세를 YAML 파일로 정의하고 kubectl CLI를 활용하여 명령어를 입력하는 방식으로 배포를 진행 하게 됩니다.
그 과정에서 불편한 배포방식과 YAML 파일 관리 및 변경에 대한 History 등,, 의 관리의 어려움이 발생을 하게 되는데, 이 문제 해결을 위해 Helm 을 도입하였습니다.

Helm 이란?

Helm 은 Kubernetes용 패키지 매니저로 kubernetes cluster에 어플리케이션을 배포하는 도구입니다.
node.js 의 npm 과 비슷한 형태로 Kubernetes 패키지 배포를 가능하게 하는 tool 이라고 보시면 됩니다.

helm-img

  • helm은 Kubernetes의 하위 프로젝트로 시작.
  • helm은 chart라는 개념으로 어플리케이션을 정의하고 관리.
  • YAML파일들의 집합을 차트(chart) 라고 보면 됨.
  • 차트들이 저장되어 있는 차트 저장소(chart repository)와 연계해서 Kubernetes 클러스터에 차트를 설치하거나 삭제.
  • 공식 Helm 차트 에 보면 incubator와 stable 하위에 수많은 차트들이 준비되어 있음.


Templates & Values

Helm은 기본적으로 템플릿 기능 을 제공합니다.
템플릿을 만들어놓은 후 사용자에 의해 자주 변경되는 값들이나 프로퍼티 값들로 Values.yaml 파일로 분리해서 차트 설치 시 동적으로 값을 변경 할수 있는 기능입니다. 간단히 아래의 그림과 같은 개념입니다.

helm-vlaue

Chart 구조

차트 생성은 helm create {챠트명} 을 통해 쉽게 생성 가능하고, 다음과 같은 기본적인 구조를 가지고 있습니다.

helm-structure

Helml Chart 에 대한 더 자세한 설명 및 사용법은 Helm 공식사이트 를 참고하시며 됩니다.

사내 프로젝트에 적용된 Deployment.yamlValues.yaml Sample 입니다.

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{'{{  include "fullname" . ' '}}}}
  labels:
{{'{{ include "labels" . | indent 4 '}}}}
spec: 
  replicas: {{'{{ .Values.replicaCount '}}}}
  selector:
    matchLabels:
{{'{{ include "labels" . | indent 6 '}}}}
  template:
    metadata:
      labels:
{{'{{ include "labels" . | indent 8 '}}}}
    spec:
    {{'{{- with .Values.imagePullSecrets '}}}}
      imagePullSecrets:
        {{'{{- toYaml . | nindent 8 '}}}}
    {{'{{- end '}}}}
      containers:
        - name: {{'{{ .Chart.Name '}}}}
          image: "{{'{{ .Values.image.repository '}}}}:{{'{{ .Values.image.tag '}}}}"
          imagePullPolicy: {{'{{ .Values.image.pullPolicy '}}}}
          env: 
            {{'{{ $root := .'}}}}
            {{'{{- range $key, $value := .Values.extraEnv '}}}}
            - name: {{'{{ $key '}}}}
              value: {{'{{ tpl ($value | quote) $root '}}}}
            {{'{{- end '}}}}
          ports:
            - name: http
              containerPort: {{'{{ .Values.containerPort '}}}}
              protocol: TCP
          resources:
          {{'{{- if .Values.resources.enabled -'}}}}
{{'{{ tpl (toYaml .Values.resources.resource | nindent 12) . '}}}}
          {{'{{- end '}}}}
        
    {{'{{- if .Values.affinity.enabled '}}}}
      affinity: 
        nodeAffinity: 
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: {{'{{ .Values.affinity.nodeAffinityKey '}}}}
                operator: In
                values: 
                - {{'{{ .Values.affinity.nodeAffinityValue '}}}}
  
    {{'{{- end '}}}}

values.yaml

## 1. pod count
replicaCount: 1

## 2. image info
image:
  repository: docker-registry.saramin.co.kr/iris
  tag: master-10502
  pullPolicy: IfNotPresent

imagePullSecrets: []
containerPort: 8000

## 3. environment
extraEnv: 
  SPRING_PROFILES_ACTIVE: development

## 4. resource
resources: 
  enabled: false
  resource:
    requests:
      cpu: "200m"
      memory: "128Mi"
    limits:
      cpu: "200m"
      memory: "128Mi"

## 5. affinity      
affinity: 
  enabled: false
  nodeAffinityKey: "sri-node-role"
  nodeAffinityValue: "iris-role"
  

values.yaml 으로 다음의 설정에 대해 수정이 가능하도록 Chart를 구성 하였습니다.

  1. 구동할 컨테이너수를 replicaCount로 조절이 가능.
  2. 이미지명태그를 변경하여 배포/업그레이드가 가능하도록 설정.
  3. 구동 시 spring 기반 어플리케이션의 Profile 설정 가능.
  4. Kubernetes 리소스(cpu,memory) 할당 설정 처리.
  5. 특정 노드에 배포되도록 nodeAffinity 설정.
이렇게 작성된 Chart(Kubernetes 배포용 매니페스트)는 Git의 config 저장소에 저장이 됩니다.

Chart 설치

배포 Chart도 만들어졌고, 이제 작성된 Chart를 Kubernetes에 설치하는 것만 남았습니다.
차트를 검색하고 설치하는 과정에 대해 이제 알아보겠습니다.

Rancher

Kubernetes 관리를 위해 저희는 Rancher 를 활용하고 있습니다.

Rancher를 간략히 설명을 하자면, 멀티 Kubernetes 클러스터 관리 플랫폼 이라고 할 수 있습니다.

Multi-Cluster Kubernetes Management
One Platform for Kubernetes Management
Rancher is open-source software for delivering Kubernetes-as-a-Service.

web UI 기반으로 멀티 k8s 클러스터를 배포, 관리, 모니터링할 수 있는 편리하고 다양한 기능을 제공하는 아주 유용한 도구 입니다.
rancher

Rancher Catalog

Rancher 유용한 기능 중 Helm 기반 의 Chart 를 검색하고 실행할 수 있는 Application Catalog 기능이 존재합니다.
사용자는 UI를 통해 쉽게 Chart를 검색하고 마우스 버튼을 한번 클릭하는 것으로 간단하게 어플리케이션을 배포 및 실행할 수 있습니다.

기존의 CLI 명령행 도구를 사용하는 것보다 좀 더 사용자 편의성이 고려된 UI 제공을 할 수 있고, Rancher 통해 chart 관리도 좀 더 쉽고 수월하게 할 수 있어 아주 유용하게 사용하는 기능 중 하나입니다.
Chart (Kubernetes 배포용 매니페스트)가 저장된 Git config 저장소 주소를 Catalogs 항목에 등록 해주기만 하면 바로 Chart 검색이 가능합니다.

Rancher 상단 메뉴의 Apps > Launch 버튼을 클릭하면 등록된 차트가 아래와 같이 리스트 되어 보여집니다.


Rancher Catalog - Chart List

Rancher Charts

Rancher에서는 Helm 기반의 Chart를 기본적으로 노출을 해주지만, 추가적으로 UI로 사용자 입력을 받을 수 있도록 할 수 있습니다. questions.yml 파일로 UI를 구성하면 Chart 설치 상세 페이지에서 사용자 입력을 받아 values.yaml 의 값을 대체 해주는 방식입니다.

values.yaml 파일의 key 값이 variable 의 값과 정확히 일치 해야만 변경되는 점에 유의 하시면 됩니다.
위의 values.yaml 의 5가지 조건에 대해서 UI 구성한 예제입니다.

questions.yml

questions: 
## 2. image info
- variable: image.repository
  default: "docker-registry.saramin.co.kr/iris"
  description: "Deploy Image Name"
  type: string
  label: Image Name
- variable: image.tag
  default: "master-7252"
  description: "Deploy image tag"
  type: string
  label: Image Tag

## 1. pod count
- variable: replicaCount
  default: 1
  description: "Container Image Replica Count"
  label: Replica Count
  type: int
  required: true

## 3. environment
- variable: extraEnv.SPRING_PROFILES_ACTIVE
  label: Spring Profile 
  default: "dev"
  description: "containers evn data"
  type: enum
  options: 
    - "dev"
    - "prod"
    
## 4. resource
- variable: resources.enabled
  label: Use Resource Limits
  default: true
  description: "Enable resource limit"
  type: boolean
  show_subquestion_if: true
  subquestions:
  - variable: resources.cpu
    label: CPU
    default: "100m"
    description: "CPU requests and limits"
    type: enum
    options: ["100m", "250m", "500m"]
  - variable: resources.memory
    label: Memory
    default: "128Mi"
    description: "Memory requests and limits"
    type: enum
    options: ["128Mi", "256Mi", "512Mi"]

## 5. affinity   
- variable: affinity.enabled
  label: Use Node Affinity
  default: false
  description: "true: specified node / false: all node"
  type: boolean
  show_subquestion_if: true
  group: "Affinity Configuration"
  subquestions:
  - variable: affinity.nodeAffinityKey
    label: Node Affinity Key
    default: "sri-node-role"
    description: "Node Label Key Name"
    type: string
  - variable: affinity.nodeAffinityValue
    label: Node Affinity Value
    default: "iris-role"
    description: "Node Label Value Name"
    type: string

위와 같이 questions.yaml을 생성 후 Chart에 반영을 하고 차트 설치를 위한 상세 페이지로 가보도록 하겠습니다.


Rancher Catalog - Chart Detail

이와 같이 화면이 렌더링이 되며, 각 영역은 다음과 같은 설정을 사용자로 부터 입력을 받게 됩니다.

  1. 구동할 컨테이너수를 replicaCount로 조절이 가능.
  2. 이미지명태그를 변경하여 배포/업그레이드가 가능하도록 설정.
  3. 구동 시 spring 기반 어플리케이션의 Profile 설정 가능.
  4. Kubernetes 리소스(cpu,memory) 할당 설정 처리.
  5. 특정 노드에 배포되도록 nodeAffinity 설정.

보시면 values.yaml 설정의 설명 내용과 동일 합니다.
즉, 사용자로부터 UI통해 입력을 받은 값으로 values config 값을 대체 하는 프로세스로 동작을 합니다.

더 자세한 설명은 하기 문서를 참고 바랍니다.

Rancher 공식 Docs
Rancher Chart


배포 자동화

Rancher Catalog 기능을 이용하면 Kubernetes 인프라에 컨테이너 Deploy 및 Upgrade 작업을 쉽고 간단하게 진행 할 수 있습니다.

배포된 Chart는 위와 같이 확인이 가능하며, 기본적인 어플리케이션 Patch 작업은 배포된 Chart의 Edit화면에서 Image Tag를 수정하는 방법으로 쉽게 Upgrade가 가능합니다.
운영환경에서는 지정된 시간에 지정된 배포 담당자가 Upgrade 를 진행하지만, 개발환경에서는 소스 커밋과 동시에 자동으로 Upgrade 처리가 진행되도록 한 부분에 대해 알아보겠습니다.

먼저, Kubernetes의 오브젝트들은 모두 API 를 통해 접근이 되며 관리(생성, 조회, 삭제)가 이루어 집니다. 사실 모든 K8s 컴포넌트들은 Kubernetes API (kube-apiserver) 를 통해 통신하며 동작 합니다. kubectl tool도 내부적으로는 Kubernetes API를 호출하는 방식이죠.

kubectl_1

간단한 서비스 어플리케이션 수정 건은 메니페스트 정보나 인프라 설정을 변경 할 필요가 없고, 빌드된 이미지를 바꿔주기만 하면 되는 배포 업무가 대다수 입니다.

아래의 그림과 같이 Kubernetes API를 통해 KubeCtl을 대신하여 Patch(이미지 태그 변경) 작업을 처리하는 모듈을 생성하여 Proxy 형태로 서비스 하도록 두었습니다.
CI 빌드 완료 시 webhook 방식으로 해당 proxy 모듈을 호출하는 프로세스로 자동화 배포 처리이 동작하게 됩니다.

kube-api

CI 파이프라인 스크립트의 deploy 스테이지의 auto-update 라는 job이 Proxy Api Service를 호출하고 있고, 빌드된 이미지:태그 정보를 파라미터로 전달하고 있습니다.

.gitlab-ci.yml
...
# 배포 자동화 처리
auto-update:
  stage: deploy
  script:
    - curl -X POST "${WEBHOOK_URL}" -H "Content-Type:application/json" --data "{\"image\":\"${CI_REGISTRY}:${BUILD_TAG}\"}"
  only:
    - develop
... 


Proxy Api Service

빌드 성공 시 Webhook방식으로 호출되며, 내부적으로 kubernetes API 를 호출하고 있고,
외부에서 쉽고 편리하게 k8s 조작 및 연동을 하기 위한 용도의 서비스라고 보시면 됩니다.

kubernetes API 연동을 위해 python 기반의 kubernetes-client 를 활용해서 어플리케이션 구축을 하였습니다.

Official Python client library

Update API

auto-update 단계에서 webhook으로 이미지:태그 파라미터를 전달받으면 이미지 정보를 가지고 배포된 deployment 를 찾아서 새로운 이미지로 업데이트 처리하는 API입니다.
아래는 python 으로 구현된 모듈내 포함된 update_image() Function 의 예시입니다.

...
def update_image(update_img):
    # 이미지명,태그명 분리
    img_name = update_img.rsplit(':', 1)[0]
    img_tag = update_img.rsplit(':', 1)[1]
    
    # 전체 Deployment 조회
    ret_list = self.apps_v1.list_deployment_for_all_namespaces()
    
    for item in ret_list.items:
        # 시스템 namespace 제외
        if item.metadata.namespace in ("cattle-system", "kube-system"):
                continue

        if img_name in item.spec.template.spec.containers[0].image:
            prev_img = item.spec.template.spec.containers[0].image
            item.spec.template.spec.containers[0].image = update_img

            # Update the deployment
            api_response = self.apps_v1.patch_namespaced_deployment(
                    name=item.metadata.name,
                    namespace=item.metadata.namespace,
                    body=item)

            logger.info("Deployment updated. status='%s'" % str(api_response.status))
            return "success", api_response
    
    # 구동된 Deployment 없을 시
    return "none", "Deployment Not Found"
...


API 문서

Proxy Api Service 는 배포 자동화 처리 뿐만 아니라, 다양한 End Point를 노출하며 여러 기능을 제공하고 있습니다.
K8S 연동을 위한 proxy 역활을 하고 있으며, RestEnd Point API 문서를 제공하고 있습니다. python Django 프레임워크 기반으로 하는 drf-yasg 패키지를 활용하여 자동으로 API 문서를 생성하도록 하였습니다.

해당 내용은 주제에서 벗어난 부분이기에 더이상 다루지 않으며, 참고용으로 봐주시길 바랍니다. 자세한 사용법은 하기 공식사이트 또는 검색을 통해 찾아보시면 자세하고 상세히 소개된 글들이 많이 존재합니다.

drf-yasg


Rest API Document



끝맺음

Kubernetes 환경의 어플리케이션 CI/CD 프로세스에 대한 전반적인 설명을 마치고자 합니다.

CI/CD에는 다양하고 수 많은 도구들과 방법들이 존재합니다.
그중에서 가장 저희 팀과 IT연구소에 맞는 방법이 무엇일까를 고민했고, 무엇보다도 쉽고 보편적인 방향성을 추구하려고 했습니다.
위와 같이 프로세스를 구성하고 나서도 더 편리한 도구는 없을까,, 더 좋은 방법은 없을까,, 하는 고민을 했었습니다.

하지만 결론적으로 제가 내린 결론은, 정답은 없다 입니다.

이렇게 저렇게 해야한다는 공식 보다는 각자의 시스템 특성 및 배포 성향에 맞게 최적을 위해 최선을 다해 구축한 프로세스야 말로 정답이 아닐까란 생각을 했습니다.
쿠버네티스 환경에서 GitOps 기반의 CI/CD를 도입하시는 분들에게 이글이 참고가 되었으면 하고, 추후 글쓰는 실력을 갈고 닦아 좀더 심도있고, 깊이있는 글로 찾아올수 있도록 노력하겠습니다.

이상입니다.