Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

Istio+Kiali๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Canary ๋ฐฐํฌ ์‹œ์ž‘ ๋ฐ ์‹œ๊ฐํ™”

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

์ด ์‹œ๋ฆฌ์ฆˆ์˜ ๊ธฐ์‚ฌ

  1. Kubernetes #1์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Gitlab CI
  2. Kubernetes์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ #2: Argo ๋กค์•„์›ƒ
  3. (์ด ๊ธฐ์‚ฌ)
  4. Jenkins-X Istio Flagger๋ฅผ ์‚ฌ์šฉํ•œ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ

์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ

์šฐ๋ฆฌ๋Š” ๋‹น์‹ ์ด ์ฝ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค ์ œ ๋ถ€์—ฌ๊ธฐ์„œ๋Š” Canary ๋ฐฐํฌ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ณ  ํ‘œ์ค€ Kubernetes ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด์Šค ํ‹ฐ์˜ค

๊ทธ๋ฆฌ๊ณ  ์ด ๊ธฐ์‚ฌ๋ฅผ ์ฝ์œผ๋ฉด Istio๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—.

ํ…Œ์ŠคํŠธ ์‹ ์ฒญ

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

๊ฐ ํฌ๋“œ์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ istio-proxy๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

frontend-nginx ๋ฐ ๋ฐฑ์—”๋“œ Python Pod์™€ ํ•จ๊ป˜ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. nginx ํฌ๋“œ๋Š” ๊ฐ ์š”์ฒญ์„ ๋ฐฑ์—”๋“œ ํฌ๋“œ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๊ณ  ํ”„๋ก์‹œ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์„ธ๋ถ€์ •๋ณด๋Š” ๋‹ค์Œ yaml์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง์ ‘ ์‹คํ–‰

๋‚ด ์˜ˆ๋ฅผ ๋”ฐ๋ผ ์ด ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”. ํ”„๋กœ์ ํŠธ ์ฝ์–ด๋ณด๊ธฐ.

์ดˆ๊ธฐ ๋ฐฐํฌ

์ฒซ ๋ฒˆ์งธ ๋ฐฐํฌ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํฌ๋“œ์— ์ปจํ…Œ์ด๋„ˆ๊ฐ€ 2๊ฐœ๋งŒ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, Istio ์‚ฌ์ด๋“œ์นด๊ฐ€ ์ด์ œ ๋ง‰ ๊ตฌํ˜„๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

๊ทธ๋ฆฌ๊ณ  ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— Istio Gateway Loadbalancer๋„ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. istio-system:

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

ํŠธ๋ž˜ํ”ฝ ์ƒ์„ฑ

๋‹ค์Œ IP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ŸฐํŠธ์—”๋“œ ํฌ๋“œ์—์„œ ์ˆ˜์‹ ํ•˜๊ณ  ๋ฐฑ์—”๋“œ ํฌ๋“œ๋กœ ์ „๋‹ฌํ•  ํŠธ๋ž˜ํ”ฝ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done

์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค frontend.istio-test ํ˜ธ์ŠคํŠธ ํŒŒ์ผ์—.

Kiali๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ ๋ณด๊ธฐ

Tracing, Grafana, Prometheus ๋ฐ Kiali์™€ ํ•จ๊ป˜ ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ Istio๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค(์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ์กฐ). ํ”„๋กœ์ ํŠธ ์ฝ์–ด๋ณด๊ธฐ). ๋”ฐ๋ผ์„œ ๋‹ค์Œ์„ ํ†ตํ•ด Kiali๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

istioctl dashboard kiali # admin:admin

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

Kiali๋Š” ๋ฉ”์‹œ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ํŠธ๋ž˜ํ”ฝ์„ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋ณด์‹œ๋‹ค์‹œํ”ผ ํŠธ๋ž˜ํ”ฝ์˜ 100%๊ฐ€ ํ”„๋ŸฐํŠธ์—”๋“œ ์„œ๋น„์Šค๋กœ ์ด๋™ํ•œ ๋‹ค์Œ v1 ๋ผ๋ฒจ์ด ์žˆ๋Š” ํ”„๋ŸฐํŠธ์—”๋“œ ํฌ๋“œ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์„ ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๊ณ  ๋‹ค์‹œ ๋ฐฑ์—”๋“œ ํฌ๋“œ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๋Š” ๊ฐ„๋‹จํ•œ nginx ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. v1์ด๋ผ๋Š” ๋ผ๋ฒจ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

Kiali๋Š” Istio์™€ ์ž˜ ์ž‘๋™ํ•˜๋ฉฐ ๋ฐ•์Šคํ˜• ๋ฉ”์‹œ ๋ Œ๋”๋ง ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ •๋ง ์ข‹์•„์š”.

์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ

์šฐ๋ฆฌ ๋ฐฑ์—”๋“œ์—๋Š” ์ด๋ฏธ ๋‘ ๊ฐœ์˜ k8s ๋ฐฐํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” v1์šฉ์ด๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” v2์šฉ์ž…๋‹ˆ๋‹ค. ์ด์ œ Istio์—๊ฒŒ ํŠน์ • ๋น„์œจ์˜ ์š”์ฒญ์„ v2๋กœ ์ „๋‹ฌํ•˜๋„๋ก ์ง€์‹œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

1๋‹จ๊ณ„: 10%

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ํ•ด์•ผ ํ•  ์ผ์€ VirtualService์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์กฐ์ •ํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค. istio.yaml:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: backend
  namespace: default
spec:
  gateways: []
  hosts:
  - "backend.default.svc.cluster.local"
  http:
  - match:
    - {}
    route:
    - destination:
        host: backend.default.svc.cluster.local
        subset: v1
        port:
          number: 80
      weight: 90
    - destination:
        host: backend.default.svc.cluster.local
        subset: v2
        port:
          number: 80
      weight: 10

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

์š”์ฒญ์˜ 10%๊ฐ€ v2๋กœ ๋ฆฌ๋””๋ ‰์…˜๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๋‹จ๊ณ„: 50%

์ด์ œ 50%๊นŒ์ง€๋งŒ ๋Š˜๋ฆฌ๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: backend
  namespace: default
spec:
...
    - destination:
        host: backend.default.svc.cluster.local
        subset: v1
        port:
          number: 80
      weight: 50
    - destination:
        host: backend.default.svc.cluster.local
        subset: v2
        port:
          number: 80
      weight: 50

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

3๋‹จ๊ณ„: 100%

์ด์ œ Canary ๋ฐฐํฌ๊ฐ€ ์™„๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ชจ๋“  ํŠธ๋ž˜ํ”ฝ์ด v2๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

์นด๋‚˜๋ฆฌ์•„๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

์ด์ œ ๋ชจ๋“  ์š”์ฒญ์˜ 2%๋ฅผ v10 ๋ฐฑ์—”๋“œ๋กœ ๋ณด๋‚ธ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. v2๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

HTTP ํ—ค๋”๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํŠน๋ณ„ํ•œ ์ผ์น˜ ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: backend
  namespace: default
spec:
  gateways: []
  hosts:
  - "backend.default.svc.cluster.local"
  http:
  - match:
    - headers:
        canary:
          exact: "canary-tester"
    route:
    - destination:
        host: backend.default.svc.cluster.local
        subset: v2
        port:
          number: 80
      weight: 100
  - match:
    - {}
    route:
    - destination:
        host: backend.default.svc.cluster.local
        subset: v1
        port:
          number: 80
      weight: 90
    - destination:
        host: backend.default.svc.cluster.local
        subset: v2
        port:
          number: 80
      weight: 10

์ด์ œ ์ปฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ—ค๋”๋ฅผ ์ „์†กํ•˜์—ฌ v2 ์š”์ฒญ์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

ํ—ค๋”๊ฐ€ ์—†๋Š” ์š”์ฒญ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹1/10 ๋น„์œจ๋กœ ๊ตฌ๋™๋ฉ๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

๋‘ ๊ฐ€์ง€ ์ข…์† ๋ฒ„์ „์— ๋Œ€ํ•œ ์นด๋‚˜๋ฆฌ์•„

์ด์ œ ํ”„๋ŸฐํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ๋ชจ๋‘์— ๋Œ€ํ•ด ๋ฒ„์ „ v2๊ฐ€ ์žˆ๋Š” ์˜ต์…˜์„ ๊ณ ๋ คํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ํŠธ๋ž˜ํ”ฝ์˜ 10%๊ฐ€ v2๋กœ ์ด๋™ํ•˜๋„๋ก ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

ํ”„๋ŸฐํŠธ์—”๋“œ v1๊ณผ v2๋Š” ๋ชจ๋‘ ๋ฐฑ์—”๋“œ v1๊ณผ v10์— ๋Œ€ํ•ด 1/2์˜ ๋น„์œจ๋กœ ํŠธ๋ž˜ํ”ฝ์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

v2๊ณผ ํ˜ธํ™˜๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— frontend-v2์˜ ํŠธ๋ž˜ํ”ฝ์„ backend-v1๋กœ๋งŒ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์ด๋ฅผ ์œ„ํ•ด ํ˜‘์ƒ์„ ํ†ตํ•ด backend-v1์— ๋„๋‹ฌํ•˜๋Š” ํŠธ๋ž˜ํ”ฝ์„ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹ํ”„๋ŸฐํŠธ์—”๋“œ์— 10/2 ๋น„์œจ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. sourceLabels :

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: backend
  namespace: default
spec:
  gateways: []
  hosts:
  - "backend.default.svc.cluster.local"
  http:
...
  - match:
    - sourceLabels:
        app: frontend
        version: v2
    route:
    - destination:
        host: backend.default.svc.cluster.local
        subset: v2
        port:
          number: 80
      weight: 100

๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ํ•„์š”ํ•œ ๊ฒƒ์„ ์–ป์Šต๋‹ˆ๋‹ค.

Kubernetes #3์˜ ์นด๋‚˜๋ฆฌ์•„ ๋ฐฐํฌ: Istio

์ˆ˜๋™ Canary ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ์˜ ์ฐจ์ด์ 

ะ’ ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„ ๋‘ ๊ฐœ์˜ k8s ๋ฐฐํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Canary ๋ฐฐํฌ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ๋ณต์ œ๋ณธ ์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์š”์ฒญ ๋น„์œจ์„ ์ œ์–ดํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ํšจ๊ณผ์ ์ด์ง€๋งŒ ์‹ฌ๊ฐํ•œ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Istio๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์ œ๋ณธ ์ˆ˜์— ๊ด€๊ณ„์—†์ด ์š”์ฒญ ๋น„์œจ์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด HPA(Horizontal Pod Autoscalers)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ Canary ๋ฐฐํฌ์˜ ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๊ตฌ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ•ฉ๊ณ„

Istio๋Š” ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ Kiali์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ์กฐํ•ฉ์ด ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ด€์‹ฌ ๋ชฉ๋ก์€ ์ž๋™ํ™” ๋ฐ Canary ๋ถ„์„์„ ์œ„ํ•ด Spinnaker์™€ Istio๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€