| 구성 요소 | 역할 |
|---|---|
| CAS | 데이터 적재와 학습 |
| Model Manager | 모델 등록, 버전 관리, 테스트, 승격 |
| MAS (Micro Analytic Service) | 실시간 스코어링 |
| APRO (Application Runtime Operator) | Python·R·커스텀 모델을 실행할 런타임 컨테이너를 만들고 관리하는 Kubernetes 오퍼레이터 |
APRO 는 현장에서 "도커형" 이라고 부르기도 한다. 모델을 배포하면 APRO 가 런타임 컨테이너를 만들어 그 안에서 스코어링을 실행한다는 뜻이다. 실제 런타임은 클러스터의 컨테이너 런타임(containerd 등)이 담당한다.
Kubernetes
├─ CAS 데이터 처리
├─ Compute SAS 코드 실행
├─ Model Manager 모델 등록·버전
└─ APRO 모델 런타임 컨테이너
├─ python runtime
├─ java runtime
└─ custom model runtime
kubectl get pods -n <namespace> | grep -i appruntime
SASHELP 의 예제 데이터가 이미지에 포함되지 않은 환경이 있다. 그럴 때는 데이터를 직접 만들어 흐름만 확인한다.
cas mysess;
caslib _all_ assign;
/* 인공 데이터 생성 */
data casuser.demo_synth;
call streaminit(7);
length cat $1;
do id = 1 to 5000;
x1 = rand('normal', 0, 1);
x2 = rand('normal', 1, 2);
x3 = rand('uniform');
cat = byte(65 + int(rand('uniform') * 3));
lp = -0.5 + 0.8*x1 - 0.3*x2 + 1.2*x3;
y = (rand('uniform') < 1 / (1 + exp(-lp)));
output;
end;
run;
/* 학습·검증·테스트 분할 */
proc partition data=casuser.demo_synth samppct=60 samppct2=20 seed=1
partind;
output out=casuser.demo_part;
run;
그래디언트 부스팅으로 학습하고 애널리틱 스토어를 저장한다.
proc gradboost data=casuser.demo_part seed=1
ntrees=150 maxdepth=4 learningrate=0.05;
target y / level=nominal;
input x1 x2 x3 / level=interval;
input cat / level=nominal;
partition rolevar=_PartInd_(train='1' validate='2' test='3');
savestate rstore=casuser.gb_demo_astore;
ods output FitStatistics=work.gb_demo_fit;
run;
TARGET 문에서 event= 를 함께 주면 릴리스에 따라 문법 오류(22-322 · 202-322)가 난다. 지원하지 않는 버전이면 event= 를 빼고 실행한다.
저장한 애널리틱 스토어로 점수화한다.
proc astore;
score data=casuser.demo_part
rstore=casuser.gb_demo_astore
out=casuser.demo_scored;
quit;
Viya 와 Python 이 연동돼 있다면 sasctl 로 등록과 배포를 처리한다.
pip install sasctl scikit-learn pandas
import os
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sasctl import Session
from sasctl.tasks import register_model, publish_model
VIYA_HOST = os.environ["VIYA_HOST"]
VIYA_USER = os.environ["VIYA_USER"]
VIYA_PASS = os.environ["VIYA_PASS"]
PROJECT_NAME = "MLOPS_LAB"
MODEL_NAME = "GB_v1"
df = pd.read_csv("data/train.csv")
X = df.drop(columns=["y"])
y = df["y"]
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.25, random_state=42)
model = GradientBoostingClassifier(random_state=42)
model.fit(X_tr, y_tr)
with Session(VIYA_HOST, VIYA_USER, VIYA_PASS, verify_ssl=False):
mm_model = register_model(model, MODEL_NAME, PROJECT_NAME, X=X, force=True)
module = publish_model(MODEL_NAME, "maslocal", replace=True)
print("registered:", mm_model.name)
print("published:", module.name)
같은 프로젝트·모델 이름으로 다시 등록하면 Model Manager 쪽에 새 버전이 쌓인다. 운영 표준에 맞춘 패키징이 필요하면 sasctl 의 pzmm 모듈을 써서 스코어 코드와 메타데이터 구조까지 만들어 등록한다.
| 축 | 대상 |
|---|---|
| Git | 학습 코드, 피처 정의, 하이퍼파라미터, 테스트 |
| Model Manager | 등록된 모델 아티팩트, 버전, 승격 이력 |
Git 태그로 코드를 고정하고, 배포는 Model Manager 에서 승격된 버전만 하도록 통제한다.
Checkout -> 의존성 설치 -> 테스트 -> 학습 및 등록 -> 등록 후 스코어 테스트 -> 배포
pipeline {
agent any
environment {
VIYA_HOST = credentials('viya-host')
VIYA_USER = credentials('viya-user')
VIYA_PASS = credentials('viya-pass')
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Setup') {
steps {
sh '''
python -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install -r src/requirements.txt
'''
}
}
stage('Test') {
steps {
sh '. .venv/bin/activate && python -m pytest -q'
}
}
stage('Train and Register') {
steps {
sh '. .venv/bin/activate && python src/train.py'
}
}
stage('Score Test') {
steps {
sh '. .venv/bin/activate && python src/score_test.py'
}
}
stage('Deploy') {
when { branch 'main' }
steps {
sh '. .venv/bin/activate && python src/deploy.py'
}
}
}
}
Viya 접속 정보는 Jenkins Credentials 에 넣고, 가능하면 사용자·비밀번호 대신 토큰 기반 인증을 쓰며 만료·회전 정책을 둔다.
| 선택지 | 설명 |
|---|---|
| MAS publish 까지 | Model Manager 에서 승인된 버전을 MAS 대상(maslocal 등)에 배포하고 호출 테스트까지 한다. 실습에 적합하다 |
| 컨테이너 배포까지 | 승격된 버전의 런타임 아티팩트를 컨테이너 레지스트리에 올리고 Kubernetes 배포를 갱신한다. 조직 표준에 가깝다 |