2ํธ์์ K3s ํด๋ฌ์คํฐ๋ฅผ ๊ฒจ์ฐ ์ฌ๋ ธ๋ค๊ณ ํ์ฃ . ์ด๋ฒ ํธ์ ๊ทธ๊ฑธ ์ ๋ถ ๋ค ๋ ๋ฆฌ๊ณ ์ฒ์๋ถํฐ ๋ค์ ๋ง๋ ์ด์ผ๊ธฐ์ ๋๋ค. MetalLB ์ค์น ํ๋๊ฐ ํด๋ฌ์คํฐ ์ ์ฒด๋ฅผ ๋ฌด๋๋จ๋ ธ๊ณ , ์์ธ์ ํ๊ณ ๋ค๋ค๊ฐ ์ฌ๋ด๋ง DHCP์ ๋ ธ๋ IP๊ฐ ์ถฉ๋ํ๊ณ ์์๋ค๋ ๊ฑธ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ทธ ์ฝ์ง์ ํตํด ๊ฒฐ๊ตญ ํจ์ฌ ๊ฒฌ๊ณ ํ ์ํคํ ์ฒ๊ฐ ์์ฑ๋๊ณ , ๊ทธ ์์ GitOps ํ์ดํ๋ผ์ธ๊น์ง ์ฌ๋ผ๊ฐ์ต๋๋ค.
๐ DevOps ์ํค ์์ธ ๋ฌธ์: GitHub Wiki โ DevOps | GitOps ์ค์ฆ
๐ฅ Episode 5. MetalLB ์ค์น๊ฐ ํด๋ฌ์คํฐ๋ฅผ ํต์งธ๋ก ๋ฌด๋๋จ๋ ธ๋ค
LoadBalancer ํ์
์๋น์ค์ ์ธ๋ถ IP๋ฅผ ํ ๋นํ๊ธฐ ์ํด MetalLB v0.14.3์ ์ค์นํ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ํ๋๋ค์ด 7๋ถ ๋๊ฒ ContainerCreating์์ ๊ผผ์ง์ ์ ํฉ๋๋ค. ํ๋์ฉ ์ฆ์์ด ํฐ์ง๊ธฐ ์์ํ์ต๋๋ค.
์ฐ์ ์ฆ์๋ค:
speakerํ๋์์secret "memberlist" not found๋ฐ๋ณต- ํน์ Worker ๋
ธ๋์์๋ง
ErrImagePull(๋ค๋ฅธ ๋ ธ๋๋ Running) controllerํ๋CrashLoopBackOffโ ๋ก๊ทธ:dial tcp 10.43.0.1:443: connect: no route to hostkubectl delete namespace metallb-systemํ 20๋ถ ๋๊ฒTerminating๊ณ ์ฐฉ- Master โ Worker ๊ฐ ping์ด
137ms โ 959ms โ 128ms โ 959msํจํด์ผ๋ก ์ฃผ๊ธฐ์ ์ผ๋ก 1์ด ์ด์ ํ
์ฒ์์ MetalLB ์ค์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์๋ฌด๋ฆฌ ๋ค์ฌ๋ค๋ด๋ ์ด์์ด ์์ด์. IP ์ถฉ๋์ ์ฐํํ๋ ค๊ณ ์ค๋งํธํฐ ํซ์คํ์ผ๋ก ๋คํธ์ํฌ๋ฅผ ์ ํํ๋๋ ์ด๋ฒ์ ํด๋ฌ์คํฐ ๋ด๋ถ ํต์ ์ด ์์ ํ ๋จ์ ๋ฉ๋๋ค.
์์ธ์ ๋จ์ผ ์์ธ์ด ์๋ 3๊ฐ ๋ ์ด์ด์ ๋ณตํฉ ์ฅ์ ์์ต๋๋ค.
| ๋ ์ด์ด | ๋ฌธ์ | ์ํฅ |
|---|---|---|
| ๋คํธ์ํฌ | ์ฌ๋ด๋ง DHCP์ ๋ ธ๋ ๊ณ ์ IP ์ถฉ๋ | ping ์ง์ฐ, ์ด๋ฏธ์ง pull ์คํจ |
| K3s ์ค์น | --disable servicelb ๋๋ฝ | Klipper LB โ MetalLB ์ถฉ๋ |
| ์์ ์กฐ์น | ํซ์คํ ์ ํ | ํด๋ฌ์คํฐ ๋ด๋ถ ๋ผ์ฐํ ์์ค |
ํต์ฌ ์์ธ: ๋
ธ๋์ ๊ณ ์ IP(192.168.0.10~12)๋ฅผ ์ค์ ํ์ง๋ง, ์ฌ๋ด๋ง ๊ณต์ ๊ธฐ DHCP ๋ฒ์๊ฐ 192.168.0.2~254 ์ ์ฒด๋ฅผ ํฌํจํ๊ณ ์์์ต๋๋ค. ๊ณต์ ๊ธฐ๊ฐ ๋ค๋ฅธ ๊ธฐ๊ธฐ(์ค๋งํธํฐ, ๋
ธํธ๋ถ)์ ๊ฐ์ IP๋ฅผ ๋ฐฐํฌํ๋ฉด์ ARP Storm์ด ๋ฐ์ํ๋ ๊ฒ์
๋๋ค. ๊ณต์ ๊ธฐ ๊ด๋ฆฌ์ ๊ถํ์ด ์์ด์ DHCP ๋ฒ์๋ฅผ ์ง์ ์์ ํ ์๋ ์์์ด์.
๐จ ํด๊ฒฐ: ๋ ๋ฆฝ ๋์ญ์ผ๋ก ํด๋ฌ์คํฐ ์ ๋ฉด ์ฌ๊ตฌ์ถ
์ฌ๋ด๋ง DHCP๊ฐ ์ ๋ ์นจ๋ฒํ ์ ์๋ 10.10.10.x/24 ๋์ญ์ ํด๋ฌ์คํฐ ์ ์ฉ ๋คํธ์ํฌ๋ก ์ง์ ํ๊ณ , K3s๋ฅผ ์ฒ์๋ถํฐ ๋ค์ ์ค์นํ์ต๋๋ค.
Step 1. ๊ธฐ์กด K3s ์์ ์ฒ ๊ฑฐ
# Master ๋
ธ๋
/usr/local/bin/k3s-uninstall.sh
# Worker ๋
ธ๋ 1, 2
/usr/local/bin/k3s-agent-uninstall.sh
Step 2. nmtui๋ก ์ด๋๋ท IP๋ฅผ ๋ ๋ฆฝ ๋์ญ์ผ๋ก ๋ณ๊ฒฝ
| ์ญํ | ์ธํฐํ์ด์ค | ์ ๊ท IP |
|---|---|---|
| Master | eth0 | 10.10.10.10/24 |
| Worker 1 | eth0 | 10.10.10.11/24 |
| Worker 2 | eth0 | 10.10.10.12/24 |
| MetalLB Pool | โ | 10.10.10.200~220 |
โ ๏ธ Gateway ์นธ์ ๋ฐ๋์ ๊ณต๋์ผ๋ก ์ ์งํด์ผ ํฉ๋๋ค. ๊ฐ์ ์ ๋ ฅํ๋ฉด Wi-Fi ์ธํฐ๋ท ๋ผ์ฐํ ๊ณผ ์ถฉ๋ํด ์ด๋ฏธ์ง pull์ด ๋ถ๊ฐ๋ฅํด์ง๋๋ค.
Step 3. K3s ์ฌ์ค์น โ ๋ง ๋ถ๋ฆฌ ์ต์ + Klipper ๋นํ์ฑํ
# Master ๋
ธ๋
curl -sfL https://get.k3s.io | sh -s - \
--node-ip 10.10.10.10 \
--flannel-iface eth0 \
--disable servicelb # โ Klipper LB ๋นํ์ฑํ (MetalLB์ ์ถฉ๋ ๋ฐฉ์ง)
# Worker 1
curl -sfL https://get.k3s.io | \
K3S_URL=https://10.10.10.10:6443 \
K3S_TOKEN=<TOKEN> \
sh -s - \
--node-ip 10.10.10.11 \
--flannel-iface eth0
[์ต์ข
๋คํธ์ํฌ ์ํคํ
์ฒ]
์ด๋๋ท eth0 โ 10.10.10.x (ํด๋ฌ์คํฐ ๋ด๋ถ ํต์ ์ ์ฉ)
โโโ Master: 10.10.10.10
โโโ Worker1: 10.10.10.11
โโโ Worker2: 10.10.10.12
Wi-Fi wlan0 โ ์ฌ๋ด๋ง 192.168.0.x (์ธํฐ๋ท / ์ด๋ฏธ์ง pull ์ ์ฉ)
๐ก ๊ตํ: ๋ฒ ์ด๋ฉํ ํด๋ฌ์คํฐ๋ ์ค์น ์ ์ ๋คํธ์ํฌ ๊ตฌ์กฐ๋ฅผ ๋จผ์ ์ค๊ณํด์ผ ํฉ๋๋ค. ๋ ธ๋ IP ๋์ญ, DHCP ์ถฉ๋ ์ฌ๋ถ, CNI ์ธํฐํ์ด์ค, LB IP ํ ๋ฒ์๋ฅผ ํ์ ํ์ง ์์ผ๋ฉด ์ค์น ์ค ๋คํธ์ํฌ ํธ๋ฌ๋ธ์ํ ์ผ๋ก ์๊ฐ์ ๋๋ถ๋ถ ์๋ชจํ๊ฒ ๋ฉ๋๋ค.
๐ฅ Episode 6. Ingress ์ค์ โ StripPrefix๋ฅผ ๋นผ๋จน์ผ๋ฉด ํฐ ํ๋ฉด๋ง ๋์จ๋ค
ํด๋ฌ์คํฐ๋ฅผ ์ฌ๊ตฌ์ถํ๊ณ MetalLB๋ก ๋จ์ผ ๋ํ IP(10.10.10.200)๋ฅผ ๋ฐ์์ต๋๋ค. ์ด์ /longhorn, /dashboard ๊ฒฝ๋ก๋ก ์ฌ๋ฌ ์๋น์ค๋ฅผ ๋ฌถ์ด์ ์ ๊ทผํ๋ ค ํ๋๋ฐ, http://10.10.10.200/longhorn ์ ์ ์ HTML์ ์์ ๋๋๋ฐ CSS, JS๊ฐ ๋ก๋๋์ง ์์ ํฐ ํ๋ฉด๋ง ๋น๋๋ค.
์์ธ: Longhorn์ ๋น๋กฏํ ๋๋ถ๋ถ์ ์คํ์์ค ์น ์ฑ์ ์์ ์ด ๋ฃจํธ ๊ฒฝ๋ก(/)์์ ๋์ํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ์ธ๋ถ ๊ฒฝ๋ก๋ฅผ /longhorn์ผ๋ก ์ง์ ํ๋ฉด ์ฑ ๋ด๋ถ์ ์ ์ ํ์ผ ๊ฒฝ๋ก(/static/logo.png)์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ค์ ์์ฒญํ๋ ๊ฒฝ๋ก(10.10.10.200/static/logo.png) ์ฌ์ด์ ๋ถ์ผ์น๊ฐ ์๊น๋๋ค.
ํด๊ฒฐ: StripPrefix ๋ฏธ๋ค์จ์ด๋ก ๊ฒฝ๋ก๋ฅผ ๋ฒ๊ฒจ๋ด์ผ ํฉ๋๋ค.
# longhorn-route.yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: longhorn-stripprefix
namespace: longhorn-system
spec:
stripPrefix:
prefixes:
- /longhorn
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: longhorn-ingress
namespace: longhorn-system
annotations:
traefik.ingress.kubernetes.io/router.middlewares: longhorn-system-longhorn-stripprefix@kubernetescrd
spec:
rules:
- http:
paths:
- path: /longhorn
pathType: Prefix
backend:
service:
name: longhorn-frontend
port:
number: 80
Traefik ๋ด๋ถ ๋์๋ณด๋(api@internal)๋ ์ผ๋ฐ Ingress๊ฐ ์๋ IngressRoute๋ฅผ ์จ์ผ ํ๊ณ , /dashboard์ /api ๋ ๊ฒฝ๋ก๋ฅผ ๋ชจ๋ ํฌํจํด์ผ 404๊ฐ ๋์ง ์์ต๋๋ค.
๐ก ๊ตํ: ํ์ ๊ฒฝ๋ก์ ์๋น์ค๋ฅผ ๋ฐฐ์นํ ๋๋ StripPrefix๊ฐ ํ์์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ URL ๋์
/๋ฅผ ๋ฐ๋์ ๋ถ์ฌ์ผ ์๋ ๊ฒฝ๋ก ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
๐ฅ Episode 7~9. ArgoCD โ GitLab ์ฐ๋ ํธ๋ฌ๋ธ์ํ 3์ฐ์
ํด๋ฌ์คํฐ ์์ ArgoCD๋ฅผ ์ฌ๋ฆฌ๊ณ GitLab๊ณผ ์ฐ๋ํ๋ ค ํ์ต๋๋ค. ์๋ฌ๊ฐ ์ธ ๋ฒ ๋ฐ๋๋ฉด์ ์ฐ๋ฌ์ ํฐ์ก์ต๋๋ค.
1์ฐจ ์๋ฌ: argocd-repo-server๊ฐ Completed ์ํ
connection error: dial tcp 10.43.31.222:8081: connect: connection refused
ํ๋๊ฐ Running์ด ์๋ Completed๋ก ์ข
๋ฃ๋ ์ํ์์ต๋๋ค. ๋ง์น GitLab ์ฐ๊ฒฐ ์๋ฌ์ฒ๋ผ ๋ณด์ด์ง๋ง ์ฌ์ค์ ArgoCD ๋ด๋ถ ํ๋ ์ํ ๋ฌธ์ ์์ต๋๋ค.
# ํด๊ฒฐ: repo-server ์ฌ์์
kubectl rollout restart deployment/argocd-repo-server -n argocd
2์ฐจ ์๋ฌ: applicationset-controller CrashLoopBackOff
no matches for kind "ApplicationSet" in version "argoproj.io/v1alpha1"
ArgoCD v3.3.2๊ฐ ์ค์น๋์ง๋ง applicationsets.argoproj.io CRD๊ฐ ๋๋ฝ๋ ์ํ์์ต๋๋ค.
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.13.2/manifests/crds/applicationset-crd.yaml
3์ฐจ ์๋ฌ: remote repository is empty
unable to ls-remote HEAD: failed to list refs: remote repository is empty
GitLab ์ ์ฅ์๋ฅผ README ์์ด ์์ ํ ๋น ์ํ๋ก ์์ฑํ๊ธฐ ๋๋ฌธ์
๋๋ค. ArgoCD๋ ๋น ์ ์ฅ์๋ฅผ ์ฐ๊ฒฐ ์ฑ๊ณต์ผ๋ก ์ธ์ ํ์ง ์์ต๋๋ค. ์ดํ deployment.yaml์ pushํ๋ฉด์ ์์ฐ์ค๋ฝ๊ฒ ํด๊ฒฐ๋์ต๋๋ค.
๐ก ๊ตํ: ArgoCD ์ฐ๊ฒฐ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ๋คํธ์ํฌ๋ณด๋ค ํ๋ ์ํ๋ถํฐ ๋จผ์ ํ์ธํ๋ ์ต๊ด์ด ์ค์ํฉ๋๋ค.
kubectl get pods -n argocdํ ์ค์ด ๋ง์ ๊ฒ์ ์ค๋ช ํด ์ค๋๋ค.
๐ GitOps ํ์ดํ๋ผ์ธ ์์ฑ โ git push ํ ๋ฒ์ผ๋ก 3-Node ๋ฐฐํฌ
ํธ๋ฌ๋ธ์ํ ์ ๋ชจ๋ ํด๊ฒฐํ๊ณ ๋์, ๋๋์ด ์ํ๋ GitOps ํ์ดํ๋ผ์ธ์ด ์์ฑ๋์ต๋๋ค.
โ ์ฝ๋ ์์ (๋ก์ปฌ WSL)
โ git push
โผ
โก GitLab (10.10.10.100) โ ํ์๋ง ์์ฒด ํธ์คํ
โ 3๋ถ๋ง๋ค ํด๋ง
โผ
โข ArgoCD (10.10.10.201) โ ๋ณ๊ฒฝ ๊ฐ์ง
โ Helm ๋ ๋๋ง ํ Auto Sync
โผ
โฃ K3s 3-Node ํด๋ฌ์คํฐ ์๋ ๋ฐฐํฌ ์๋ฃ โ
ํ์๋ง์์ GitLab์ ์ง์ ํธ์คํ ํ๋ ์ด์ : ์ธํฐ๋ท์ด ์ฐจ๋จ๋ ์ฐ์ ํ์ฅ์์ GitHub์ ์ฌ์ฉํ๋ฉด ArgoCD๊ฐ ์ ์ฅ์์ ์ ๊ทผํ ์ ์์ต๋๋ค. Host PC์ Docker์ GitLab ์ปจํ ์ด๋๋ฅผ ์ฌ๋ ค์ ์ธํฐ๋ท ์์ด GitOps ํ์ดํ๋ผ์ธ์ ์๊ฒฐํ์ต๋๋ค.
Helm Chart๋ก ์ค์ ์ ์ฝ๋๋ก ๊ด๋ฆฌ
AI ํ๋๋ค์ Helm Chart๋ก ๊ด๋ฆฌํฉ๋๋ค. values.yaml ํ ์ค๋ง ๋ฐ๊พธ๋ฉด ์ด๋ฏธ์ง ํ๊ทธ, replicas, Failover ๊ฐ์ง ์๊ฐ์ด ์๋์ผ๋ก ๋ฐ์๋ฉ๋๋ค.
# ai-apps/values.yaml
integratedAi:
image: "minsoo0919/safe-edge-integrated-ai:v7"
replicas: 1
tolerationSeconds: 30 # โ ์ด ์ซ์ ํ๋๊ฐ Failover ๊ฐ์ง ์๊ฐ์ ๊ฒฐ์ ํฉ๋๋ค
audio:
image: "minsoo0919/safe-edge-audio:v3"
replicas: 1
| ์๋๋ฆฌ์ค | ๋ณ๊ฒฝ ํญ๋ชฉ | ํจ๊ณผ |
|---|---|---|
| ์ด๋ฏธ์ง ์ ๋ฐ์ดํธ | image: v7 โ v8 | AI ํ๋ ์๋ ์ฌ๋ฐฐํฌ |
| ๊ธด๊ธ ์ค์ผ์ผ ์์ | replicas: 1 โ 2 | ํ๋ ์ฆ์ 2๊ฐ๋ก ์ฆ๊ฐ |
| Failover ์๊ฐ ๋จ์ถ | tolerationSeconds: 30 โ 15 | ๋ ๋น ๋ฅธ ์ฅ์ ๊ฐ์ง |
โ 2ํธ~3ํธ์ ๊ฑฐ์น ์ต์ข ์ธํ๋ผ ์ํ
| ๊ตฌ์ฑ ์์ | ์ํ |
|---|---|
| K3s 3-Node ํด๋ฌ์คํฐ (10.10.10.x ๋ ๋ฆฝ๋ง) | โ |
MetalLB โ VIP 10.10.10.200~220 ํ ๋น | โ |
| Traefik Ingress + StripPrefix ๋ฏธ๋ค์จ์ด | โ |
Longhorn ๋์๋ณด๋ /longhorn ์ ๊ทผ | โ |
| GitLab ์์ฒด ํธ์คํ (Host PC Docker) | โ |
| ArgoCD Auto Sync + Helm Chart ์ฐ๋ | โ |
| git push โ 3-Node ์๋ ๋ฐฐํฌ | โ |
์ด์ ์ธํ๋ผ๊ฐ ์์ ๋์ต๋๋ค. ๋ค์์ ์ด ์์ Edge AI๋ฅผ ์ฌ๋ฆฌ๋ ์ฐจ๋ก์ ๋๋ค. ์นด๋ฉ๋ผ ์ธ์์ด v7๊น์ง ๊ฐ๋ ์ฌ์ ์ ๊ธฐ๋ค๋ ค์ฃผ์ธ์.
๐ GitOps ์ค์ฆ ์์ธ: GitHub Wiki โ Proof CI ๐ ๋ค์ ํธ: 4ํธ โ Edge AI: YOLOv8 ์นด๋ฉ๋ผ ์ธ์์ด v7๊น์ง ๊ฑธ๋ฆฐ ์ด์