๐น ๊ฐ์
์ด๋ฒ ๊ธ์์๋ Canary ๋ฐฐํฌ ์ ๋ต์ ํ์ฉํ ํธ๋ํฝ ์ ์ด ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค.
**Canary ๋ฐฐํฌ(Canary Deployment)**๋ ์ผ๋ถ ์ฌ์ฉ์๋ง ์๋ก์ด ์๋น์ค๋ก ๋ผ์ฐํ
ํ์ฌ ์ ์ง์ ์ผ๋ก ๋ฐฐํฌ๋ฅผ ์งํํ๋ ์ ๋ต์
๋๋ค.
Istio์์๋ VirtualService์ DestinationRule์ ํ์ฉํ์ฌ Canary ๋ฐฐํฌ๋ฅผ ์ฝ๊ฒ ์ ์ฉํ ์ ์์ต๋๋ค.
์ด ๊ธ์์๋ Canary ๋ฐฐํฌ ๊ฐ๋
, ๊ฐ์ค์น ๊ธฐ๋ฐ ํธ๋ํฝ ๋ถ๋ฐฐ,
ํค๋ ๊ธฐ๋ฐ ๋ผ์ฐํ
์ ํ์ฉํ Canary ๋ฐฐํฌ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐น 1. Canary ๋ฐฐํฌ๋?
โ 1.1 Canary ๋ฐฐํฌ ๊ฐ๋
Canary ๋ฐฐํฌ๋ ๊ธฐ์กด ์๋น์ค(Stable)์ ์๋ก์ด ์๋น์ค(Canary)๋ฅผ ๋์์ ์ด์ํ๋ฉด์,
์ผ๋ถ ์ฌ์ฉ์์๊ฒ๋ง ์๋ก์ด ๋ฒ์ ์ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ๋ฐฐํฌ ์ ๋ต์
๋๋ค.
Canary ๋ฐฐํฌ์ ํน์ง
- ์ ์ง์ ์ธ ๋ฐฐํฌ ์งํ ๊ฐ๋ฅ
- ์ผ๋ถ ์ฌ์ฉ์์๊ฒ๋ง Canary ๋ฒ์ ์ ๊ณต ๊ฐ๋ฅ
- ๋ฐฐํฌ ํ ์ด์ ์ฌ๋ถ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฐ์ง ๊ฐ๋ฅ
- ๋ฌธ์ ๋ฐ์ ์ Canary ๋ฒ์ ๋ง ๋กค๋ฐฑ ๊ฐ๋ฅ
Canary ๋ฐฐํฌ์ ํ๋ฆ
- Canary(์ ๊ท ๋ฒ์ )๋ฅผ ๋ฐฐํฌํ์ง๋ง, ๊ธฐ๋ณธ์ ์ผ๋ก Stable(๊ธฐ์กด ๋ฒ์ )๋ง ์ฌ์ฉ์์๊ฒ ์ ๊ณต
- ์ผ๋ถ ํธ๋ํฝ์ Canary ๋ฒ์ ์ผ๋ก ์ ๋ฌํ์ฌ ํ ์คํธ ์งํ
- Canary ๋ฒ์ ์ด ์์ ์ ์ด๋ฉด ํธ๋ํฝ์ ์ ์ง์ ์ผ๋ก ์ฆ๊ฐ
- ์์ ํ Canary ๋ฒ์ ์ผ๋ก ์ ํ ํ, Stable ๋ฒ์ ์ ๊ฑฐ
๐น 2. Istio์์ Canary ๋ฐฐํฌ ์ ์ฉ ๋ฐฉ๋ฒ
โ 2.1 Canary ๋ฐฐํฌ๋ฅผ ์ํ DestinationRule ์ค์
์๋ YAML์ Stable(v1)๊ณผ Canary(v2)๋ฅผ ๊ตฌ๋ถํ๋ DestinationRule ์ค์ ์ ๋๋ค.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-service
spec:
host: my-service # ๋์ ์๋น์ค ์ด๋ฆ
subsets:
- name: v1 # Stable ๋ฒ์ (๊ธฐ์กด ์๋น์ค)
labels:
version: v1
- name: v2 # Canary ๋ฒ์ (์ ๊ท ์๋น์ค)
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN # ๋ผ์ด๋ ๋ก๋น ๋ฐฉ์์ผ๋ก ํธ๋ํฝ ๋ถ๋ฐฐ
์ค๋ช :
- subsets.name: v1 → ๊ธฐ์กด Stable ๋ฒ์ ์๋น์ค ์ ์
- subsets.name: v2 → ์ ๊ท Canary ๋ฒ์ ์๋น์ค ์ ์
- loadBalancer.simple: ROUND_ROBIN → ์๋ฒ ๊ฐ ํธ๋ํฝ์ ๊ณจ๊ณ ๋ฃจ ๋ถ๋ฐฐ
โ 2.2 ๊ฐ์ค์น ๊ธฐ๋ฐ Canary ๋ฐฐํฌ (VirtualService ์ ์ฉ)
์๋ VirtualService๋ 90%์ ํธ๋ํฝ์ ๊ธฐ์กด ์๋น์ค(v1), 10%๋ฅผ ์ ๊ท ์๋น์ค(v2)๋ก ๋ถ๋ฐฐํ๋ ์ค์ ์ ๋๋ค.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-service
spec:
hosts:
- my-service
http:
- route:
- destination:
host: my-service
subset: v1 # ๊ธฐ์กด ์๋น์ค (Stable)
weight: 90 # 90% ํธ๋ํฝ์ ๊ธฐ์กด ๋ฒ์ ์ผ๋ก ์ ๋ฌ
- destination:
host: my-service
subset: v2 # ์ ๊ท ์๋น์ค (Canary)
weight: 10 # 10% ํธ๋ํฝ์ ์ ๊ท ๋ฒ์ ์ผ๋ก ์ ๋ฌ
์ค๋ช :
- weight: 90 → ๊ธฐ์กด Stable ๋ฒ์ (v1)์ผ๋ก 90% ํธ๋ํฝ์ ๋ณด๋
- weight: 10 → ์ ๊ท Canary ๋ฒ์ (v2)์ผ๋ก 10% ํธ๋ํฝ์ ๋ณด๋
- Canary ๋ฒ์ ์ด ์์ ์ ์ด๋ฉด ์ ์ง์ ์ผ๋ก ํธ๋ํฝ ๋น์จ์ ์ฆ๊ฐ์ํด
๐น 3. ํค๋ ๊ธฐ๋ฐ Canary ๋ฐฐํฌ
โ 3.1 ํน์ ์ฌ์ฉ์๋ง Canary ๋ฒ์ ์ ์ฌ์ฉํ๋๋ก ์ค์
๋ชจ๋ ์ฌ์ฉ์๊ฐ ์๋, ํน์ ํค๋ ๊ฐ์ด ์๋ ์ฌ์ฉ์๋ง Canary ๋ฒ์ ์ผ๋ก ๋ผ์ฐํ
ํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด, X-Canary-User: true ํค๋๊ฐ ํฌํจ๋ ์์ฒญ๋ง Canary ๋ฒ์ ์ผ๋ก ๋ณด๋
๋๋ค.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-service
spec:
hosts:
- my-service
http:
- match:
- headers:
X-Canary-User:
exact: "true" # ํน์ ํค๋๊ฐ ์๋ ๊ฒฝ์ฐ Canary ๋ฒ์ ์ผ๋ก ๋ผ์ฐํ
route:
- destination:
host: my-service
subset: v2
- route:
- destination:
host: my-service
subset: v1 # ๊ธฐ๋ณธ์ ์ผ๋ก Stable ๋ฒ์ ์ผ๋ก ๋ผ์ฐํ
์ค๋ช :
- headers.X-Canary-User.exact: "true" → ํน์ ํค๋ ๊ฐ์ด **"true"**์ธ ์์ฒญ๋ง Canary ๋ฒ์ (v2)์ผ๋ก ์ ๋ฌ
- ๋๋จธ์ง ๋ชจ๋ ์์ฒญ์ ๊ธฐ๋ณธ์ ์ผ๋ก Stable ๋ฒ์ (v1)์ผ๋ก ์ ๋ฌ
๐น 4. Canary ๋ฐฐํฌ ์งํ ๋ฐฉ๋ฒ
1๏ธโฃ ์ด๊ธฐ ๋ฐฐํฌ ์ํ
- ๊ธฐ์กด Stable ๋ฒ์ (v1)์ผ๋ก ๋ชจ๋ ํธ๋ํฝ์ด ์ ๋ฌ๋จ
- ์ ๊ท Canary ๋ฒ์ (v2) ๋ฐฐํฌ ํ, Canary ํธ๋ํฝ์ 0%
2๏ธโฃ Canary ํธ๋ํฝ ์ ์ง์ ์ฆ๊ฐ
- 10% → 25% → 50% → 100% ์์ผ๋ก ํธ๋ํฝ ์ฆ๊ฐ
3๏ธโฃ Canary ์์ ์ฑ ๊ฒ์ฆ
- Canary ๋ฒ์ (v2)์ด ์ ์์ ์ผ๋ก ์ด์๋๋ฉด, 100% ํธ๋ํฝ์ Canary ๋ฒ์ ์ผ๋ก ์ด๋
4๏ธโฃ Stable ๋ฒ์ (v1) ์ ๊ฑฐ
- Canary ๋ฒ์ (v2)์ด ์์ ํ ์ด์๋๋ฉด Stable ๋ฒ์ (v1) ์ ๊ฑฐ
5๏ธโฃ ๋ฌธ์ ๋ฐ์ ์ ๋กค๋ฐฑ
- ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด VirtualService๋ฅผ ์์ ํ์ฌ 100% ํธ๋ํฝ์ ๊ธฐ์กด Stable ๋ฒ์ (v1)์ผ๋ก ์ฆ์ ๋ณต๊ตฌ ๊ฐ๋ฅ
๐ ๊ฒฐ๋ก
- Canary ๋ฐฐํฌ๋ ์ผ๋ถ ์ฌ์ฉ์์๊ฒ๋ง ์๋ก์ด ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ์ ์ง์ ๋ฐฐํฌ ์ ๋ต์ ๋๋ค.
- ๊ฐ์ค์น ๊ธฐ๋ฐ ํธ๋ํฝ ๋ถ๋ฐฐ๋ฅผ ํ์ฉํ์ฌ ์ ์ง์ ์ผ๋ก ์ ๊ท ๋ฒ์ ์ผ๋ก ํธ๋ํฝ์ ์ด๋ ๊ฐ๋ฅํฉ๋๋ค.
- ํค๋ ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฌ์ฉํ๋ฉด ํน์ ์ฌ์ฉ์ ๊ทธ๋ฃน๋ง Canary ๋ฒ์ ์ ์ฌ์ฉํ ์ ์๋๋ก ์ค์ ๊ฐ๋ฅํฉ๋๋ค.
- ๋ฌธ์ ๋ฐ์ ์ ๊ธฐ์กด Stable ๋ฒ์ ์ผ๋ก ๋น ๋ฅด๊ฒ ๋กค๋ฐฑ์ด ๊ฐ๋ฅํ์ฌ ์์ ์ ์ธ ๋ฐฐํฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.