Navisafe/Infrastructure

Kubernetes 환경 구성 (2) - NaviSafe 배포를 위한 사전 준비 (이미지, Helm, 공통 리소스)

jjaehyeok 2026. 4. 20. 14:19

1. 문제 배경

클러스터를 생성한 이후 바로 서비스를 배포하려 했지만, Kubernetes는 단순히 컨테이너를 실행하는 구조가 아니라 이미지, 설정, 권한, 저장소가 분리된 상태에서 동작한다.

이 상태에서 바로 배포를 진행할 경우 다음과 같은 문제가 발생할 수 있다.

  • 클러스터에서 이미지를 인식하지 못하는 문제
  • 환경 변수와 설정이 코드에 종속되는 구조
  • Pod가 외부 리소스에 접근하지 못하는 문제
  • Pod 재시작 시 데이터가 유실되는 문제

따라서 실제 서비스 배포 이전에 공통적으로 필요한 구성 요소를 먼저 정리했다.


2. 목표

  • Kubernetes 실행에 필요한 공통 리소스 구성
  • 환경 설정과 코드 분리
  • 서비스 간 연결 정보 외부화
  • 데이터 유지가 가능한 구조 확보

3. 이미지 준비 방식

Kubernetes는 컨테이너 이미지를 기반으로 Pod를 생성하기 때문에 클러스터에서 접근 가능한 위치에 이미지를 준비해야 한다.

이미지를 사용하는 방식은 크게 두 가지가 있다.

  • 로컬 이미지를 클러스터 내부로 직접 주입하는 방식 (kind load)
  • 외부 레지스트리를 통해 이미지를 공유하는 방식 (push / pull)

로컬 개발 환경에서는 kind load 방식이 빠르지만, 다른 서버나 클러스터에서도 동일한 이미지를 사용해야 하는 경우에는 레지스트리를 통한 방식이 더 적합하다.

이번 구성에서는 이후 배포 환경 확장을 고려해 레지스트리를 기준으로 이미지를 관리했다.

docker tag navisafe-producer:latest <dockerhub-username>/navisafe-producer:latest
docker push <dockerhub-username>/navisafe-producer:latest
 

※ 실제 계정 정보는 보안상 제외하고 구조만 정리했다.


4. Helm 및 Spark Operator 설치

Spark 작업을 Kubernetes에서 실행하기 위해 Operator를 사용했다.

helm-canary-windows-amd64.zip
18.89MB

  1. 위 zip 파일을 다운로드 한 후에, 실행 파일을 아래와 같은 경로에 위치

 

2. 실행 파일을 위와 같이 위치한 후 환경변수를 설정

  • Spark Application을 리소스로 정의 가능
  • Pod를 직접 관리하지 않고 선언형으로 실행
helm repo add spark-operator https://kubeflow.github.io/spark-operator

helm install spark-operator spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace


5. Namespace 구성

리소스를 역할별로 분리하기 위해 namespace를 구성했다.

kubectl create namespace spark-operator
kubectl create namespace airflow

namespace를 기준으로 리소스를 분리하면 서비스 간 충돌을 방지하고 관리 단위를 나눌 수 있다.


6. Secret 생성

외부 서비스 연결 정보는 코드에 포함하지 않고
Kubernetes Secret으로 분리했다.

kubectl create secret generic navisafe-producer-secret \
  --from-literal=KAFKA_BOOTSTRAP=<kafka-bootstrap-server> \
  --from-literal=REDIS_HOST=<redis-host> \
  --from-literal=MYSQL_HOST=<mysql-host> \
  --from-literal=MYSQL_USER=<username> \
  --from-literal=MYSQL_PASSWORD=<password>
 

※ 실제 값은 보안상 제외하고 구조만 정리했다.


7. ServiceAccount 생성

Pod가 Kubernetes 리소스에 접근할 수 있도록 ServiceAccount를 생성했다.

kubectl create serviceaccount spark

8. ConfigMap 구성

설정 파일과 초기 SQL 스크립트를 이미지와 분리하기 위해 ConfigMap을 사용했다.

kubectl create configmap mysql-init-script --from-file=init.sql
 

또한 Airflow에서 사용할 Pod 템플릿도 ConfigMap으로 관리했다.

kubectl create configmap airflow-pod-template \
--from-file=airflow-pod-template.yaml -n airflow
 

이 방식은 설정 변경 시 이미지를 다시 빌드하지 않아도 된다는 점에서
운영 관점에서 유리하다.


9. 스토리지 구성 (PVC)

Pod 재시작 시 데이터가 유지될 수 있도록 Persistent Volume을 구성했다.

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
 

이를 통해 데이터와 로그를 지속적으로 유지할 수 있는 환경을 구성했다.


10. 정리

이번 단계에서는 서비스를 바로 배포하기보다, Kubernetes에서 실행에 필요한 요소를 먼저 분리해서 준비했다.

  • 클러스터에서 접근 가능한 이미지 관리 방식 구성
  • Spark Operator 설치
  • Secret, ConfigMap을 통한 설정 분리
  • ServiceAccount를 통한 권한 관리
  • PVC를 통한 데이터 유지

특히 이미지 관리 방식은 단순한 선택이 아니라 배포 범위(로컬 vs 서버)에 따라 달라지는 구조적인 선택이라는 점을 확인할 수 있었다.

 

 

Kubernetes 환경 구성 (3) - NaviSafe 서비스 배포와 Kafka Topic 초기화

1. 문제 배경사전 준비 단계에서 이미지, 설정, 권한, 저장소를 분리했지만 실제 서비스는 아직 실행되지 않은 상태였다.Kubernetes에서는 서비스를 단순히 실행하는 것이 아니라, 각 서비스의 역할

jjaehyeok.tistory.com