Docker, Docker Compose, Github Actions, Helm, ArgoCD, Terraform์ ๊ฒฝํํด๋ณผ ์ ์๋ ํํ ๋ฆฌ์ผ์ ๋๋ค.
- docker, docker-compose
- k3s
- kubectl
- k9s
- helm
- argocd
- terraform
์ ํจํค์ง๋ค์ ์ค์นํ๋ ์คํฌ๋ฆฝํธ๋ install.sh์ ์์ต๋๋ค. ๋จ, ๋ฆฌ๋ ์ค ๊ธฐ์ค์ผ๋ก ์์ฑ๋์ด ์์ต๋๋ค.
./install.shdocker-compose.yaml ํ์ผ์ ์คํํฉ๋๋ค.
cd docker/nginx
sudo docker-compose up -dhttp://localhost:8080 ์ ์ ์ํ๋ฉด nginx ํ์ด์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
cd docker/nginx
sudo docker build -t nginx:custom .docker-compose.yaml ํ์ผ์ ์๋ ์ด๋ฏธ์ง ์ด๋ฆ์ ๋ณ๊ฒฝ
image: nginx:customdocker registry๊ฐ ์ค๋น๋์ด์์ง ์์ ๊ฒฝ์ฐ, pushํ์ง ์์๋ ๋ฉ๋๋ค.
๋ฐฐํฌ
sudo docker-compose up -dhttp://localhost:8080 ์ ์ ์ํ๋ฉด nginx ํ์ด์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
docker cli๋ฅผ ์ฌ์ฉํ์ง ์๊ณ github actions๋ก ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ณ ํธ์ํฉ๋๋ค. ๋จ, docker registry๊ฐ ์ค๋น๋์ด์์ด์ผ ํฉ๋๋ค. ์ค์ต์ ํ๊ธฐ ์ ์, https://hub.docker.com/ ์ ๊ฐ์ ํ์ ์ public docker registry๋ฅผ ๋ง๋ค์ด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
branch๋ฅผ ๋ณ๋๋ก ๋ง๋ค์ด์ ์์ ์ ์งํํฉ๋๋ค.
BRANCH="your_branch"
git checkout -b $BRANCH && git push origin $BRANCH --forcegithub actions์์ ์ฌ์ฉํ ์ํฌ๋ฆฟ ๋ณ์๋ค์ github ์ ์ฅ์ -> Settings -> Secrets and variables -> Actions -> New repository secret ์ ์ถ๊ฐํฉ๋๋ค.
REGISTRY_URL="docker.io"
REGISTRY_USERNAME="๊ฐ์ธ dockerhub ๊ณ์ ์ด๋ฆ(์: goranidocker)"
REGISTRY_PASSWORD="๊ฐ์ธ dockerhub ๊ณ์ ๋น๋ฐ๋ฒํธ or token"github actions์ workerflow ํ์ผ์์ pushํ target branch๋ช ์ ๋ณ๊ฒฝํฉ๋๋ค.
on:
push:
branches:
- $BRANCHgithub actions์ workerflow ํ์ผ์์ ์ด๋ฏธ์ง ์ด๋ฆ์ ๋ณ๊ฒฝํฉ๋๋ค. <๊ฐ์ธ dockerhub ๊ณ์ ์ด๋ฆ>/<์ด๋ฏธ์ง ์ด๋ฆ> ํ์์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
env:
IMAGE_NAME: <๊ฐ์ธ dockerhub ๊ณ์ ์ด๋ฆ>/nginxdocker/nginx/index.html ํ์ผ์ ๋ด์ฉ์ ๋ณ๊ฒฝํ๊ณ commit ํ pushํฉ๋๋ค.
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to Github Actions!</h1>
<p>This is a custom nginx container built by github actions.</p>
</body>
</html>์์ ํ ๋ชจ๋ ํ์ผ๋ค์ add ํ commit ํ pushํฉ๋๋ค.
git add .
git commit -m "update index.html and workflow"
git push origin $BRANCH --force์ด์ github actions๊ฐ ์๋์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ณ ํธ์ํฉ๋๋ค. ๋น๋ ๋ฐ Registry์ ํธ์๋ image name์ ./charts/example/values.yaml ํ์ผ์ ์ ๋ฐ์ดํธ๋ฉ๋๋ค.
image: docker.io/<IMAGE_NAME>/<IMAGE_TAG>์ image๋ฅผ docker-compose.yaml ํ์ผ์ image๋ก ๋ฎ์ด์์์ค๋๋ค.
image: docker.io/<IMAGE_NAME>/<IMAGE_TAG>๋ฐฐํฌ
cd docker/nginx
sudo docker-compose up -dhttp://localhost:8080 ์ ์ ์ํ๋ฉด nginx ํ์ด์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. docker/nginx/index.html์ ์๋ ๋ฉ์ธ์ง๊ฐ ๋ณด์ด๋ฉด ์ฑ๊ณต์ ๋๋ค.(์๋ก๊ณ ์นจ ํ ํ์ธ)
helm์ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํฉ๋๋ค.
NAMESPACE="your_namespace"
helm upgrade --install nginx-chart charts/example -n $NAMESPACE --create-namespaceNodePort ํ์ ์ ์๋น์ค๊ฐ ์์ฑ๋์์ต๋๋ค. ํฌํธ๋ฒํธ๋ฅผ ํ์ธํฉ๋๋ค.
NODE_PORT=$(kubectl get svc nginx-service -n $NAMESPACE -o jsonpath='{.spec.ports[0].nodePort}')
echo $NODE_PORT
echo "http://localhost:$NODE_PORT"http://localhost:$NODE_PORT ์ ์ ์ํ๋ฉด nginx ํ์ด์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์ ๋ฆฌํ๊ธฐ
helm uninstall nginx-chart -n $NAMESPACE
kubectl delete namespace $NAMESPACEapplicationset.yaml์ spec.source.targetRevision์ ๋ฐฐํฌํ branch๋ก ๋ณ๊ฒฝํฉ๋๋ค.
sed -i "s/BRANCH/$BRANCH/g" applicationset.yamlapplicationset.yaml์ template.spec.destination.namespace๋ฅผ ๋ฐฐํฌํ namespace๋ก ๋ณ๊ฒฝํฉ๋๋ค.
sed -i "s/NAMESPACE/$NAMESPACE/g" applicationset.yamlapplicationset.yaml์ metadata.name๊ณผ template.metadata.name์ ๋ฐฐํฌํ name์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
APPLICATION_NAME="๋ฐฐํฌํ ์ ํ๋ฆฌ์ผ์ด์
์ด๋ฆ"
sed -i "s/APPLICATION_NAME/$APPLICATION_NAME/g" applicationset.yamlk8s์ ArgoCD๊ฐ ์ค์น๋์ด์๊ณ current context๊ฐ ํด๋น ํด๋ฌ์คํฐ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฒฝ์ฐ, ์๋ ๋ช ๋ น์ด๋ก ArgoCD์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
ARGOCD_NAMESPACE="argocd๊ฐ ์ค์น๋ namespace"
kubectl apply -f applicationset.yaml -n $ARGOCD_NAMESPACEArgoCD์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฐฐํฌ๋์์ต๋๋ค. ArgoCD ์นํ์ด์ง์์๋ ํ์ธ๊ฐ๋ฅํ๋ฉฐ kubectl ๋ช ๋ น์ด๋ก๋ ํ์ธ๊ฐ๋ฅํฉ๋๋ค.
kubectl get applicationset -n $ARGOCD_NAMESPACENodePort ํ์ ์ ์๋น์ค๊ฐ ์์ฑ๋์์ต๋๋ค. ํฌํธ๋ฒํธ๋ฅผ ํ์ธํฉ๋๋ค.
NODE_PORT=$(kubectl get svc nginx-service -n $NAMESPACE -o jsonpath='{.spec.ports[0].nodePort}')
echo $NODE_PORT
echo "http://localhost:$NODE_PORT"http://localhost:$NODE_PORT ์ ์ ์ํ๋ฉด nginx ํ์ด์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
nginx content๋ฅผ ๋ณ๊ฒฝํ๊ณ commit ํ pushํฉ๋๋ค. charts/example/values.yaml ํ์ผ์ content๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
content: This will be changed by ArgoCD์์ ํ ๋ชจ๋ ํ์ผ๋ค์ add ํ commit ํ pushํฉ๋๋ค.
git add .
git commit -m "update nginx content"
git push origin $BRANCH --forceArgoCD๋ ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ๊ฐ์งํ๊ณ ๋ฐฐํฌํฉ๋๋ค. ์ ์ ํ์ ์๋ก์ด pod์ด ๋ฐฐํฌ๋๋ฉด์ ๋ณ๊ฒฝ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค. ๋ฐ๋ก ์ ์ฉํ๊ณ ์ถ์ผ์ค ๊ฒฝ์ฐ, ArgoCD ์นํ์ด์ง์์ Refresh ๋ฒํผ์ ๋๋ฌ์ฃผ์๋ฉด ๋ฉ๋๋ค.
http://localhost:$NODE_PORT ์ ์ ์ํด์ ์ ๋ด์ฉ์ด ๋ณด์ด๋ฉด ์ฑ๊ณต์ ๋๋ค.
https://github.com/akfmdl/mlops-lifecycle.git ๋ ํฌ์งํ ๋ฆฌ์ ์๋ mlops-platform helm chart๋ฅผ ์ฌ์ฉํ์ฌ Self-hoated runner๋ฅผ ์ค์นํด์ค๋๋ค. ์ด helm chart์๋ ๋ถํ์ํ sub chart๋ค์ด ๋ง์ผ๋ charts/mlops-platform/Chart.yaml ํ์ผ์์ harbar, gha-runner-scale-set-controller, gha-runner-scale-set๋ฅผ ์ ์ธํ ๋๋จธ์ง sub chart๋ค์ ๋ชจ๋ ์ฃผ์์ฒ๋ฆฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์.
helm dependency update charts/mlops-platformhelm chart๋ฅผ ์ค์นํ namespace๋ฅผ ์์ฑํฉ๋๋ค. mlops-platform helm chart๋ ๊ธฐ๋ณธ์ ์ผ๋ก mlops-platform namespace๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ค๋ฅธ namespace๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ์ค ๊ฒฝ์ฐ values.yaml ๋ชจ๋ namespace๊ด๋ จ ๋ด์ฉ์ ๋ณ๊ฒฝํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
NAMESPACE="mlops-platform"
kubectl create namespace $NAMESPACEGithub actions์์ ์ฌ์ฉํ ํ ํฐ์ ์์ฑํฉ๋๋ค. https://github.com/settings/tokens ์ ์ ์ํ์ฌ Personal access tokens (classic)์ ์์ฑํฉ๋๋ค.
ํ์ ๊ถํ:
- repo: ๊ถํ ์ ์ฒด
gha-runner-scale-set์์ ์ฌ์ฉ๋ github credential secret์ ์์ฑํฉ๋๋ค.
- username: github ์ฌ์ฉ์ ์ด๋ฆ
- email: github ์ฌ์ฉ์ ์ด๋ฉ์ผ
- token: github ํ ํฐ
kubectl create secret generic github-credential \
--from-literal=github_username=<github_username> \
--from-literal=github_email=<github_email> \
--from-literal=github_token=<github_token> \
-n $NAMESPACEcharts/mlops-platform/values.yaml ํ์ผ์ ์๋ ๋ด์ฉ์ ์์ ํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
- githubConfigUrl: ๋ณธ์ธ์ github ๋ ํฌ์งํ ๋ฆฌ url
- runnerScaleSetName: github actions runner์ ์ด๋ฆ์ด ๋ฉ๋๋ค. ์ํ๋ ์ด๋ฆ์ผ๋ก ์์ ํ์ ๋ ๋ฉ๋๋ค.
gha-runner-scale-set:
githubConfigUrl: <github ๋ ํฌ์งํ ๋ฆฌ url>
runnerScaleSetName: <runner์ ์ด๋ฆ>
githubConfigSecret: github-credential์ runner ์ด๋ฆ์ workflow์ ์ ์ฉํฉ๋๋ค.
jobs:
build:
runs-on: <runner์ ์ด๋ฆ>์ด์ ์๋ ์ค์น ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์.
helm upgrade --install gha-runner-scale-set charts/mlops-platform -n $NAMESPACE --create-namespacerunner-scale-set-listener๊ฐ ์ ์์ฑ๋์๋์ง ํ์ธํฉ๋๋ค. ์ด pod์ controller์์ ์์ฑ๋ runner๋ฅผ ๊ฐ์งํ๊ณ ํ ๋นํ๋ ์ญํ ์ ํฉ๋๋ค. github actions์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ์ด pod์ด ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๊ณ runner๋ฅผ ์๋์ผ๋ก ํ ๋นํฉ๋๋ค.
kubectl get pods -n $NAMESPACE -l app.kubernetes.io/component=runner-scale-set-listenerharbor๋ ์ ์์ฑ๋์๋์ง ํ์ธํฉ๋๋ค. harbor๋ NodePort ํ์ ์ ์๋น์ค๋ก ์์ฑ๋์์ต๋๋ค.
NODE_PORT=$(kubectl get svc harbor -n $NAMESPACE -o jsonpath='{.spec.ports[0].nodePort}')
echo $NODE_PORT
echo "http://localhost:$NODE_PORT"http://localhost:$NODE_PORT ์ ์ ์ํ๋ฉด harbor์ ์ ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ github actions์์ pushํ public ๋ชจ๋๋ก project๋ฅผ ์์ฑํฉ๋๋ค.
github actions์์ ์ฌ์ฉํ ์ด๋ฏธ์ง ์ด๋ฆ์ ๋ณ๊ฒฝํฉ๋๋ค.
- project ์ด๋ฆ์ harbor์์ ์์ฑํ project ์ด๋ฆ์ ์ฌ์ฉํฉ๋๋ค.
- ์ด๋ฏธ์ง ์ด๋ฆ์ ๋ณธ์ธ์ ์ด๋ฏธ์ง ์ด๋ฆ์ ์ฌ์ฉํฉ๋๋ค.
env:
IMAGE_NAME: <project ์ด๋ฆ>/<์ด๋ฏธ์ง ์ด๋ฆ>github actions์์ ์ฌ์ฉํ ์ํฌ๋ฆฟ ๋ณ์๋ค์ github ์ ์ฅ์ -> Settings -> Secrets and variables -> Actions -> New repository secret ์ ์ถ๊ฐํ๋ ๋ณ์๋ค์ ์๋์ ๊ฐ์ด ์์ ํฉ๋๋ค.
REGISTRY_URL="harbor.mlops-platform.svc.cluster.local"
REGISTRY_USERNAME="admin"
REGISTRY_PASSWORD="admin"์ด์ ๋ชจ๋ ์ค๋น๊ฐ ๋๋ฌ์ต๋๋ค. ์ด์ ๋ณธ์ธ์ github ๋ ํฌ์งํ ๋ฆฌ์์ github actions๋ฅผ ํ ์คํธํด๋ณด์ธ์.
docker/nginx/index.html ํ์ผ์ ๋ด์ฉ์ ๋ณ๊ฒฝํ๊ณ commit ํ pushํฉ๋๋ค.
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to Github Actions!</h1>
<p>This is a custom nginx container built by self-hosted runner.</p>
</body>
</html>์ดํ์ ๋ฐ์ํ๋ ์ผ
- runner-scale-set-controller๊ฐ ์๋์ผ๋ก runner๋ฅผ ์์ฑํฉ๋๋ค.
- runner-scale-set-listener๊ฐ ์๋์ผ๋ก runner๋ฅผ ๊ฐ์งํ๊ณ ํ ๋นํฉ๋๋ค.
- harbor private repository์ ์ด๋ฏธ์ง๊ฐ ํธ์๋ฉ๋๋ค.
- ./charts/example/values.yaml ํ์ผ์ image ์ด๋ฆ์ด harbor์ ํธ์๋ ์ด๋ฏธ์ง ์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
- ArgoCD๋ฅผ ํตํด ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณ๊ฒฝ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค.
kubectl delete -f applicationset.yaml -n $ARGOCD_NAMESPACE
kubectl delete namespace $NAMESPACEtest ํ๋ ๋ธ๋์น๋ฅผ ์ญ์ ํฉ๋๋ค.
git checkout main
git branch -d $BRANCH
git push origin -d $BRANCHdocker ๋ฐ๋ชฌ์ด ์ ์ฅํ๊ณ ์๋ ํ ๋น ํฌํธ ๋ฒํธ๋ฅผ ๋ฆฌ์ ํ๊ธฐ ์ํด ์ฌ์์ ํฉ๋๋ค.
sudo systemctl restart dockerdocker-compose๋ก ์คํํ ์ปจํ ์ด๋๋ฅผ ์ ๋ฆฌํฉ๋๋ค.
sudo docker-compose down