본 포스트는 'MLOps for MLE'를 참고해서 공부한 내용으로 작성되었습니다.
MLOps for MLE
부스트캠프때부터 engineering에 관련된 툴을 익히기 위해서 참고했던 'MLOps for MLE'에 대한 공부를 다시 진행해보려고 한다. 서비스 개발 측면에서는 아직 첫 걸음 수준이라 꾸준히 학습을 해나가려고 한다. 학습 순서는 위의 참고자료에 정리된 순서대로 진행할 예정이다.
우선, DB를 사용해보자!
DB(Database)라는 말을 정말 많이 접했고 또 대략적으로는 어떤 것인지에 대해서도 알고 있지만, 프로젝트를 진행해보면서 DB에 대한 조금 더 디테일한 정보를 알고 있다면 처음 시스템을 설계하고 서비스의 목적에 맞춘 DB를 선택하는데 시간을 아낄 수 있고 더 효율적인 시스템을 구축할 수 있을 것이라고 생각했다.
(DB에 대한 종류와 그 특징에 대해서는 따로 포스팅을 할 예정이다.)
여기서는 PostgreSQL을 사용하는데, 이에 대한 추가적인 내용은 아래 포스트를 더 읽어보면 좋을 것 같다!
https://d2.naver.com/helloworld/227936
1. PostgreSQL 서버 만들기
postgresql을 직접 로컬에 다운받아서 사용할 수도 있지만, 굳이 로컬에서 작업할 필요성은 없기에 docker를 사용해서 진행한다.(docker의 사용법에 대해서도 포스트를 작성 할 예정)
docker를 설치했다고 가정하고,
- postgresql DB서버를 생성
docker run -d \ --name postgres-server \ -p 5432:5432 \ -e POSTGRES_USER=myuser \ -e POSTGRES_PASSWORD=mypassword \ postgres:14.0
- 위 커맨드를 실행하면 docker에서 postgres의 14.0 버전 이미지를 pull해서 container를 생성해준다. (나머지는 option)
docker image를 가져오는 docker pull
이라는 명령어도 따로 존재하지만, docker run
을 실행하면 Image가 없는 경우 알아서 Pull을 해주기 때문에 run만 실행해도 가능
option에 대한 정리를 좀 해보자면,
-d : container가 detached 모드로 실행됨. -d가 없는 경우, 터미널이 종료되면 컨테이너도 함께 종료됨
-name : 컨테이너의 이름 지정
-p : 컨테이너에서 외부로 노출할 port forwarding 설정 (host:container)
-e : 환경변수 설정
container가 잘 띄워졌는지에 대한 확인은 docker ps
postgresql DB에 대한 서버를 확인할 때에는 postgresql의 CLI인 psql을 활용한다고 한다. 따라서 psql을 설치해주자
(psql 설치 : https://www.postgresql.org/download/)
이제, psql을 통해 생성된 서버로 접속해서 만들어진 DB 서버 확인PGPASSWORD=mypassword psql -h localhost -p 5432 -U myuser -d mydatabase
- DB의 role name과 attribute를 확인하려면
\du
를 입력하면 된다 - Options
PGPASSWORD : 접속할 유저의 비밀번호 입력 \ -h : 호스트 지정 \ -p : 포트 지정 \ -U : 접속할 유저 이름 입력 \ -d : DB의 이름 입력
2. DB에 Table 생성하기
python을 사용해서 PostgreSQL DB서버에 접근하는 방법 중, psycopg2
패키지를 이용해서 진행
# 패키지 설치
pip install pandas psycopg2-binary
python 스크립트로 DB에 연결하기
import psycopg2
db_connect = psycopg2.connect(
user="myuser",
pssword="mypassword",
host="localhost",
port=5432,
database="mydatabase"
)
본 자료에서는 scikit-learn에서 제공하는 'iris data'를 사용하기 때문에
pip install scikit-learn
를 먼저 해주자
iris data의 경우, Dtype이 int64
, float64
로 구성이 되어있는데 DB에서 지원하지 않는 dtype이기 때문에 각각 int
, float8
로 선언 해준다
또한, 컬럼 이름 중에 '('가 포함된 경우도 지원하지 않으므로 제거
create_table_query = """
CREATE TABLE IF NOT EXISTS iris_data (
id SERIAL PRIMARY KEY,
timestamp timestamp,
sepal_length float8,
sepal_width float8,
petal_length float8,
petal_width float8,
target int
);"""
쿼리를 작성했으니, 이제 작성한 쿼리를 DB에 전송한다.
- Connector 에서 cursor를 열고, cursor에 query를 전달
- query를 실행시키기 위해 connector에 Commit
- cursor close
with db_connect.cursor() as cur:
cur.execute(create_table_query)
db.connect.commit()
테이블 생성 쿼리 작성, connector로 DB 연결, cursor로 쿼리 전달 및 실행의 과정을 하나의 함수로 합쳐서 사용하는 것이 더 깔끔하고 사용하기 편할듯 하다
3. 데이터 삽입
테이블을 생성했으니 테이블에 데이터를 삽입할 차례이다
테이블 생성과 마찬가지로 데이터 삽입 쿼리 작성, connector로 연결, cursor로 쿼리 전달 및 실행의 과정을 함수화 해서 작성하면 된다.
# 데이터 삽입 query
INSERT INTO {table_name} (col_1, col_2, ...) VALUES (val_1, val_2, ...)
4. docker로 python script 띄우기
- 1~3의 과정을 하나의 python script file(ex. data_generator.py)로 만들고,
- 해당 스크립트를 docker image로 build한 뒤에
- container로 실행시킨다.
우선, python script file을 만드는 과정은 1~3을 참고해서 만들면 되기 때문에 따로 적어놓지는 않겠다.
Dockerfile은 다음과 같이 작성하면 될 듯 하다
FROM amd64/python:3.9-slim
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/app
RUN pip install -U pip &&\
pip install scikit-learn pandas psycopg2-binary
COPY data_generator.py data_generator.py
ENTRYPOINT ["python", "data_generator.py", "--db-host"]
# Change CMD to solve host finding error
CMD ["localhost"]
이렇게 작성된 dockerfile을 통해서 docker image를 build한다.
docker build -t data-generator .
여기서 -t 옵션은 image의 tag를 설정할 수 있는 옵션을 나타낸다.
그 다음으로, build된 image를 통해서 docker container를 생성한다.
docker run data-generator
하지만 run을 하게 되면 error가 발생하면서 container가 생성되지 않는다. 왜일까??
DB container를 띄울 때는 5432:5432
옵션을 사용했기 때문에, localhost:5432로 접근하게 되면 DB의 5432 포트로 연결되어 사용이 가능했다.
하지만, data-generator를 띄울 때는 해당 옵션을 사용하지 않았기 때문에, data-generator의 입장에서는 localhost:5432로 접근을 해도 아무것도 찾을 수 없는 상황이다.
이때, 사용할 수 있는 방법이 docker network
이다.
docker network
- 두 컨테이너를 연결할 수 있는 방법의 하나
사용법은 다음과 같다.
- 컨테이너간 통신할 수 있는 네트워크 생성
docker network create my-network
- 실행 중인 컨테이너(DB)를 네트워크에 연결
docker network connect my-network postgres-server
- data-generator를 DB가 연결된 네트워크를 통해 생성
- 컨테이너간 통신을 하는 경우, localhost가 아닌 각 컨테이너의 이름이 host가 되기 때문에 이미지 이름 뒤의 값("postgres-server") 옵션을 통해서 CMD를 수정
docker run -d \ --name data-generator \ --network "my-network" \ data-generator "postgres-server"
- network의 한계
- 컨테이너의 이름을 알아야 한다. 서로 연결이 필요한 컨테이너에게 다른 컨테이너의 이름은 전달해 주어야 한다.
- 컨테이너가 예상치 못하게 종료되는 경우, 사용된 이름을 이미 점유하고 있어 다시 실행하려면 삭제 후 다시 생성해야한다.
- 컨테이너의 실행 순서를 보장할 수 없다.
다음과 같은 이유로 인해 Container Orchestration이 필요하고, docker 자체적으로 docker compose
를 통해 제공한다.
docker compose
최종적으로 docker compose 파일(.yaml)을 이용해서 container orchestration을 적용한다.
Q. postgresql server container, data-generator container로 구분짓지 않고 하나의 container에서 다 해결할 수 있는 방법은 없나?
Further
- docker network
- docker compose
- dockerfile
등에 대한 정리
'ML,DL > Ops' 카테고리의 다른 글
Github Actions - CI/CD (2) | 2023.11.24 |
---|---|
SaaS란? (0) | 2023.02.20 |