[카테고리:] 미분류

  • 우분투 서버에 AI 학습 파이프라인 구축하기: 완벽 가이드

    클라우드 서비스는 편리하지만, 자체 서버에 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 엔지니어가 더 중요한 작업에 집중할 수 있게 해줍니다.