클라우드 서비스는 편리하지만, 자체 서버에 AI 학습 파이프라인을 구축하면 더 많은 제어권과 비용 효율성을 얻을 수 있습니다. 이 포스팅에서는 우분투 서버에 MLflow, Airflow, MinIO를 활용하여 완전한 AI 학습 파이프라인을 구축하는 방법을 단계별로 알아보겠습니다.
1. 시스템 요구사항
우분투 서버에 AI 파이프라인을 구축하기 위한 기본 요구사항은 다음과 같습니다:
- Ubuntu 20.04 LTS 이상
- 최소 16GB RAM (딥러닝 모델의 경우 32GB 이상 권장)
- 다중 코어 CPU (최소 4코어 이상 권장)
- GPU (NVIDIA CUDA 지원 GPU 권장)
- 충분한 저장 공간 (SSD 500GB 이상 권장)
2. 시스템 준비 및 기본 설정
시스템 업데이트
sudo apt update
sudo apt upgrade -y
필수 패키지 설치
sudo apt install -y build-essential libssl-dev libffi-dev python3-dev python3-pip git
sudo apt install -y python3-venv
Docker 설치 (컨테이너 관리용)
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y docker-ce
sudo usermod -aG docker $USER
Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
NVIDIA 드라이버 및 CUDA 설치 (GPU 사용 시)
sudo apt install -y nvidia-driver-510
# 시스템 재부팅 후
wget https://developer.download.nvidia.com/compute/cuda/11.6.0/local_installers/cuda_11.6.0_510.39.01_linux.run
sudo sh cuda_11.6.0_510.39.01_linux.run
3. 파이프라인 핵심 구성요소 설치
3.1 Airflow 설치 (워크플로우 관리)
Airflow를 사용하여 데이터 수집부터 모델 배포까지의 워크플로우를 관리합니다.
# Airflow 설치 디렉토리 생성
mkdir -p ~/airflow
cd ~/airflow
# docker-compose.yaml 파일 생성
wget https://airflow.apache.org/docs/apache-airflow/2.3.0/docker-compose.yaml
# .env 파일 생성
echo "AIRFLOW_UID=$(id -u)" > .env
# Airflow 초기화
docker-compose up airflow-init
# Airflow 실행
docker-compose up -d
Airflow UI는 http://localhost:8080 에서 접근 가능합니다 (기본 계정: airflow/airflow).
3.2 MLflow 설치 (모델 관리)
MLflow를 사용하여 실험 추적, 모델 버전 관리, 모델 레지스트리를 구성합니다.
# MLflow 설치 디렉토리 생성
mkdir -p ~/mlflow
cd ~/mlflow
# docker-compose.yaml 파일 생성
cat > docker-compose.yaml << 'EOF'
version: '3'
services:
mlflow-db:
image: postgres:13
container_name: mlflow-db
environment:
- POSTGRES_USER=mlflow
- POSTGRES_PASSWORD=mlflow
- POSTGRES_DB=mlflow
volumes:
- mlflow-db-data:/var/lib/postgresql/data
networks:
- mlflow-network
mlflow-server:
image: ghcr.io/mlflow/mlflow:v2.3.1
container_name: mlflow-server
depends_on:
- mlflow-db
ports:
- "5000:5000"
environment:
- MLFLOW_TRACKING_URI=postgresql://mlflow:mlflow@mlflow-db:5432/mlflow
command: mlflow server --backend-store-uri postgresql://mlflow:mlflow@mlflow-db:5432/mlflow --default-artifact-root /mlflow/artifacts --host 0.0.0.0
volumes:
- mlflow-artifacts:/mlflow/artifacts
networks:
- mlflow-network
networks:
mlflow-network:
volumes:
mlflow-db-data:
mlflow-artifacts:
EOF
# MLflow 실행
docker-compose up -d
MLflow UI는 http://localhost:5000 에서 접근 가능합니다.
3.3 MinIO 설치 (객체 스토리지)
MinIO를 사용하여 데이터셋, 중간 결과물, 학습된 모델을 저장합니다.
# MinIO 설치 디렉토리 생성
mkdir -p ~/minio
cd ~/minio
# docker-compose.yaml 파일 생성
cat > docker-compose.yaml << 'EOF'
version: '3'
services:
minio:
image: minio/minio
container_name: minio
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
volumes:
- minio-data:/data
command: server /data --console-address ":9001"
volumes:
minio-data:
EOF
# MinIO 실행
docker-compose up -d
MinIO UI는 http://localhost:9001 에서 접근 가능합니다 (기본 계정: minioadmin/minioadmin).
4. 파이프라인 통합 및 설정
4.1 네트워크 통합
각 서비스를 하나의 네트워크로 통합하여 상호 통신이 가능하게 합니다.
# 공통 네트워크 생성
docker network create ai-pipeline-network
# 각 서비스 컨테이너를 네트워크에 연결
docker network connect ai-pipeline-network $(docker ps -aqf "name=airflow-webserver")
docker network connect ai-pipeline-network $(docker ps -aqf "name=mlflow-server")
docker network connect ai-pipeline-network $(docker ps -aqf "name=minio")
4.2 MLflow 클라이언트 설정
파이썬 환경에서 MLflow를 사용하기 위한 설정:
# 가상환경 생성
python3 -m venv ~/ml-env
source ~/ml-env/bin/activate
# 필요한 패키지 설치
pip install mlflow scikit-learn pandas numpy boto3 tensorflow
# MLflow 설정
cat > ~/.mlflow_config << 'EOF'
export MLFLOW_TRACKING_URI=http://localhost:5000
export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin
export MLFLOW_S3_ENDPOINT_URL=http://localhost:9000
EOF
# 설정 적용
source ~/.mlflow_config
5. AI 학습 파이프라인 구성
5.1 Airflow DAG 작성
간단한 이미지 분류 모델 학습 파이프라인의 DAG 예시:
mkdir -p ~/airflow/dags
cat > ~/airflow/dags/image_classification_pipeline.py << 'EOF'
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.bash import BashOperator
from airflow.operators.python import PythonOperator
default_args = {
'owner': 'airflow',
'depends_on_past': False,
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5),
}
dag = DAG(
'image_classification_pipeline',
default_args=default_args,
description='Image classification pipeline',
schedule_interval=timedelta(days=1),
start_date=datetime(2023, 1, 1),
catchup=False,
)
# 데이터 다운로드 및 준비
download_data = BashOperator(
task_id='download_data',
bash_command='python /opt/airflow/scripts/download_dataset.py',
dag=dag,
)
# 데이터 전처리
preprocess_data = BashOperator(
task_id='preprocess_data',
bash_command='python /opt/airflow/scripts/preprocess_data.py',
dag=dag,
)
# 모델 학습
train_model = BashOperator(
task_id='train_model',
bash_command='python /opt/airflow/scripts/train_model.py',
dag=dag,
)
# 모델 평가
evaluate_model = BashOperator(
task_id='evaluate_model',
bash_command='python /opt/airflow/scripts/evaluate_model.py',
dag=dag,
)
# 모델 등록
register_model = BashOperator(
task_id='register_model',
bash_command='python /opt/airflow/scripts/register_model.py',
dag=dag,
)
# 워크플로우 정의
download_data >> preprocess_data >> train_model >> evaluate_model >> register_model
EOF
5.2 스크립트 작성
모델 학습 스크립트 예시 (~/airflow/scripts/train_model.py):
mkdir -p ~/airflow/scripts
cat > ~/airflow/scripts/train_model.py << 'EOF'
import os
import mlflow
import mlflow.tensorflow
import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
# MLflow 연결 설정
mlflow.set_tracking_uri(os.environ.get("MLFLOW_TRACKING_URI", "http://mlflow-server:5000"))
mlflow.set_experiment("image_classification")
# 전처리된 데이터 로드
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/opt/airflow/data/processed/train',
image_size=(224, 224),
batch_size=32,
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
'/opt/airflow/data/processed/val',
image_size=(224, 224),
batch_size=32,
)
# 모델 구성
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(train_ds.num_classes, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
# 기본 모델 층 고정
for layer in base_model.layers:
layer.trainable = False
# 모델 컴파일
model.compile(
optimizer=Adam(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# MLflow로 학습 추적
with mlflow.start_run():
# 파라미터 기록
mlflow.log_param("model_type", "MobileNetV2")
mlflow.log_param("learning_rate", 0.001)
mlflow.log_param("batch_size", 32)
# 모델 학습
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=10,
callbacks=[
tf.keras.callbacks.ModelCheckpoint(
'/opt/airflow/models/best_model.h5',
save_best_only=True,
monitor='val_accuracy'
),
tf.keras.callbacks.TensorBoard(log_dir='/opt/airflow/logs/tensorboard')
]
)
# 메트릭 기록
for epoch in range(len(history.history['accuracy'])):
mlflow.log_metric("train_accuracy", history.history['accuracy'][epoch], step=epoch)
mlflow.log_metric("val_accuracy", history.history['val_accuracy'][epoch], step=epoch)
mlflow.log_metric("train_loss", history.history['loss'][epoch], step=epoch)
mlflow.log_metric("val_loss", history.history['val_loss'][epoch], step=epoch)
# 모델 저장
mlflow.tensorflow.log_model(model, "model")
EOF
6. 파이프라인 실행 및 모니터링
6.1 필요한 디렉토리 생성
mkdir -p ~/airflow/data/raw
mkdir -p ~/airflow/data/processed
mkdir -p ~/airflow/models
mkdir -p ~/airflow/logs/tensorboard
6.2 파이프라인 트리거
Airflow UI를 통해 파이프라인을 수동으로 트리거하거나 스케줄에 따라 자동 실행되도록 설정할 수 있습니다.
# CLI를 통한 트리거 (선택사항)
docker exec -it $(docker ps -aqf "name=airflow-webserver") airflow dags trigger image_classification_pipeline
6.3 모니터링
- Airflow UI (http://localhost:8080): 파이프라인 실행 상태 및 로그 확인
- MLflow UI (http://localhost:5000): 모델 성능, 파라미터, 아티팩트 확인
- TensorBoard: 학습 과정 시각화
# TensorBoard 실행source ~/ml-env/bin/activatetensorboard --logdir=~/airflow/logs/tensorboard
TensorBoard는 http://localhost:6006 에서 접근 가능합니다.
7. 파이프라인 확장
7.1 하이퍼파라미터 튜닝 추가
cat > ~/airflow/dags/hyperparameter_tuning_pipeline.py << 'EOF'
# Hyperparameter tuning pipeline 코드
# (내용 생략)
EOF
7.2 모델 서빙 추가
# TensorFlow Serving 설정
mkdir -p ~/serving/models/image_classifier/1
# 모델 내보내기 스크립트
cat > ~/airflow/scripts/export_model.py << 'EOF'
import tensorflow as tf
import mlflow
import os
# 최신 모델 가져오기
model_uri = "models:/ImageClassifier/Production"
model = mlflow.tensorflow.load_model(model_uri)
# SavedModel 형식으로 내보내기
export_path = "/opt/airflow/serving/models/image_classifier/1"
tf.saved_model.save(model, export_path)
EOF
# TensorFlow Serving 실행
docker run -d -p 8501:8501 --name tf-serving --mount type=bind,source=~/serving/models,target=/models -e MODEL_NAME=image_classifier tensorflow/serving
8. 보안 강화
8.1 서비스 접근 보안
# NGINX 설치
sudo apt install -y nginx
# SSL 인증서 생성
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
# NGINX 설정
sudo nano /etc/nginx/sites-available/ml-pipeline
# 적절한 프록시 설정 추가
# (내용 생략)
sudo ln -s /etc/nginx/sites-available/ml-pipeline /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
8.2 사용자 인증 설정
각 서비스의 기본 계정 대신 강력한 비밀번호를 가진 사용자 계정 설정:
# Airflow 사용자 생성
docker exec -it $(docker ps -aqf "name=airflow-webserver") airflow users create \
--username admin \
--firstname Admin \
--lastname User \
--role Admin \
--email admin@example.com
9. 유지보수 및 백업
9.1 로그 로테이션 설정
sudo nano /etc/logrotate.d/ml-pipeline
# 로그 로테이션 설정 추가
# (내용 생략)
9.2 백업 스크립트 작성
cat > ~/backup-ml-pipeline.sh << 'EOF'
#!/bin/bash
# 백업 디렉토리 생성
BACKUP_DIR="/backup/ml-pipeline/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# Docker 볼륨 백업
docker run --rm -v mlflow-artifacts:/source -v $BACKUP_DIR:/backup alpine tar -czf /backup/mlflow-artifacts.tar.gz -C /source .
docker run --rm -v mlflow-db-data:/source -v $BACKUP_DIR:/backup alpine tar -czf /backup/mlflow-db.tar.gz -C /source .
docker run --rm -v minio-data:/source -v $BACKUP_DIR:/backup alpine tar -czf /backup/minio-data.tar.gz -C /source .
# Airflow DAG 및 스크립트 백업
tar -czf $BACKUP_DIR/airflow-dags.tar.gz -C ~/airflow/dags .
tar -czf $BACKUP_DIR/airflow-scripts.tar.gz -C ~/airflow/scripts .
# 모델 백업
tar -czf $BACKUP_DIR/models.tar.gz -C ~/airflow/models .
EOF
chmod +x ~/backup-ml-pipeline.sh
10. 문제 해결 및 팁
10.1 서비스 상태 확인
# 모든 컨테이너 상태 확인
docker ps -a
# 컨테이너 로그 확인
docker logs $(docker ps -aqf "name=mlflow-server")
10.2 일반적인 문제 해결
- 메모리 부족: 컨테이너 메모리 제한 조정
# docker-compose.yaml 파일에 메모리 제한 추가 # 예: resources: limits: memory: 4G
- 디스크 공간 부족: 불필요한 데이터 및 로그 정리
# 사용하지 않는 Docker 이미지 및 볼륨 정리 docker system prune -a
- GPU 인식 문제: NVIDIA 드라이버 및 Docker 설정 확인
# NVIDIA 드라이버 상태 확인 nvidia-smi # Docker에 NVIDIA 런타임 추가 # /etc/docker/daemon.json 수정
결론
이 가이드를 통해 우분투 서버에 자체 AI 학습 파이프라인을 구축하는 방법을 알아보았습니다. Airflow, MLflow, MinIO를 함께 사용하여 클라우드 서비스와 유사한 기능을 갖춘 환경을 만들 수 있습니다. 자체 서버에 파이프라인을 구축함으로써 더 많은 제어권을 가지고, 비용을 절감하며, 특정 요구사항에 맞게 시스템을 커스터마이징할 수 있습니다.
이 시스템을 기반으로 하여 비즈니스 요구사항에 맞게 더 많은 기능을 추가하고 확장해 나갈 수 있습니다. 예를 들어, 분산 학습 지원, A/B 테스트 파이프라인, 자동 재학습 트리거 등을 구현할 수 있습니다.
AI 파이프라인 구축은 초기에는 복잡해 보일 수 있지만, 일단 구축되면 모델 개발과 배포 프로세스를 크게 간소화하고 자동화하여 데이터 과학자와 ML 엔지니어가 더 중요한 작업에 집중할 수 있게 해줍니다.