Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

๋ฉ”๋ชจ. ๋ฒˆ์—ญ: ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„ ์ด ์‹œ๋ฆฌ์ฆˆ๋Š” Istio์˜ ๊ธฐ๋Šฅ์„ ์•Œ์•„๋ณด๊ณ  ์‹ค์ œ๋กœ ์ด๋ฅผ ์‹œ์—ฐํ•˜๋Š” ๋ฐ ์ „๋…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ดˆ โ€” ์„ธ๋ฐ€ํ•˜๊ฒŒ ์กฐ์ •๋œ ๋ผ์šฐํŒ… ๋ฐ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๊ด€๋ฆฌ. ์ด์ œ ๋ณด์•ˆ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์™€ ๊ด€๋ จ๋œ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ์ž๋Š” Auth0 ID ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๊ณต๊ธ‰์ž๋„ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” Istio์˜ ๊ธฐ๋Šฅ์„ ์‹œ์—ฐํ•˜๊ธฐ ์œ„ํ•ด Istio์™€ ์˜ˆ์ œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ธ Sentiment Analysis๋ฅผ ๋ฐฐํฌํ•œ Kubernetes ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

Istio๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์žฌ์‹œ๋„, ์‹œ๊ฐ„ ์ดˆ๊ณผ, ํšŒ๋กœ ์ฐจ๋‹จ๊ธฐ, ์ถ”์ , ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๊ฐ™์€ ๋ ˆ์ด์–ด๋ฅผ ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋น„์Šค๋ฅผ ์†Œ๊ทœ๋ชจ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ A/B ํ…Œ์ŠคํŠธ, ๋ฏธ๋Ÿฌ๋ง, ์นด๋‚˜๋ฆฌ์•„ ๋กค์•„์›ƒ ๋“ฑ ๊ณ ๊ธ‰ ํ…Œ์ŠคํŠธ ๋ฐ ๋ฐฐํฌ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

์ƒˆ๋กœ์šด ์ž๋ฃŒ์—์„œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜๋ฅผ ํ–ฅํ•œ ๊ธธ์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์ธ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Istio์—์„œ๋Š” ์ •๋ง ๊ธฐ์ฉ๋‹ˆ๋‹ค!

Istio์˜ ์ธ์ฆ ๋ฐ ์Šน์ธ

๋‚˜๋Š” ์ธ์ฆ๊ณผ ๊ถŒํ•œ ๋ถ€์—ฌ์—์„œ ์˜๊ฐ์„ ๋ฐ›์„ ๊ฒƒ์ด๋ผ๊ณ  ๊ฒฐ์ฝ” ๋ฏฟ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ฃผ์ œ๋ฅผ ์žฌ๋ฏธ์žˆ๊ณ , ๋”์šฑ ์˜๊ฐ์„ ์ฃผ๊ธฐ ์œ„ํ•ด Istio๋Š” ๊ธฐ์ˆ ์  ๊ด€์ ์—์„œ ๋ฌด์—‡์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋Œ€๋‹ต์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. Istio๋Š” ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ฑ…์ž„์„ ์„œ๋น„์Šค์—์„œ Envoy ํ”„๋ก์‹œ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์ด ์„œ๋น„์Šค์— ๋„๋‹ฌํ•  ๋•Œ์ฏค์—๋Š” ์ด๋ฏธ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋˜์—ˆ์œผ๋ฏ€๋กœ ๋น„์ฆˆ๋‹ˆ์Šค์— ์œ ์šฉํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ข‹์€ ๊ฒƒ ๊ฐ™๋‚˜์š”? ๋‚ด๋ถ€๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

Auth0์œผ๋กœ ์ธ์ฆ

ID ๋ฐ ์•ก์„ธ์Šค ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์„œ๋ฒ„๋กœ ํ‰๊ฐ€ํŒ์ด ์žˆ๊ณ  ์‚ฌ์šฉ์ด ์ง๊ด€์ ์ด๋ฉฐ ๋งˆ์Œ์— ๋“œ๋Š” Auth0์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋™์ผํ•œ ์›์น™์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋„ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. OpenID Connect ๊ตฌํ˜„: KeyCloak, IdentityServer ๋ฐ ๊ธฐํƒ€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€.

์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•˜์„ธ์š”. ์ธ์ฆ0 ํฌํ„ธ ๊ท€ํ•˜์˜ ๊ณ„์ •์œผ๋กœ ํ…Œ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•˜์‹ญ์‹œ์˜ค (ํ…Œ๋„ŒํŠธ - "ํ…Œ๋„ŒํŠธ", ๊ฒฉ๋ฆฌ์˜ ๋…ผ๋ฆฌ์  ๋‹จ์œ„, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜ - ๋Œ€๋žต. ๋ฒˆ์—ญ) ๊ทธ๋ฆฌ๊ณ  ๊ฐ€๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ > ๊ธฐ๋ณธ ์•ฑ๊ณ ๋ฅด๋Š” ๋„๋ฉ”์ธ, ์•„๋ž˜ ์Šคํฌ๋ฆฐ์ƒท๊ณผ ๊ฐ™์ด:

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

ํŒŒ์ผ์— ์ด ๋„๋ฉ”์ธ์„ ์ง€์ •ํ•˜์„ธ์š”. resource-manifests/istio/security/auth-policy.yaml (์†Œ์Šค ์ฝ”๋“œ):

apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
  name: auth-policy
spec:
  targets:
  - name: sa-web-app
  - name: sa-feedback
  origins:
  - jwt:
      issuer: "https://{YOUR_DOMAIN}/"
      jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json"
  principalBinding: USE_ORIGIN

์ด๋Ÿฌํ•œ ์ž์›์„ ๋ฐ”ํƒ•์œผ๋กœ Pilot (Istio์˜ ์„ธ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์ œ์–ด ํ‰๋ฉด ๊ตฌ์„ฑ ์š”์†Œ ์ค‘ ํ•˜๋‚˜ - ๋Œ€๋žต ๋ฒˆ์—ญ) ์š”์ฒญ์„ ์„œ๋น„์Šค๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ์š”์ฒญ์„ ์ธ์ฆํ•˜๋„๋ก Envoy๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. sa-web-app ะธ sa-feedback. ๋™์‹œ์— ์„œ๋น„์Šค Envoy์—๋Š” ๊ตฌ์„ฑ์ด ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. sa-frontend, ํ”„๋ŸฐํŠธ์—”๋“œ๋ฅผ ์ธ์ฆ๋˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์ฑ…์„ ์ ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์‹ญ์‹œ์˜ค.

$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml
policy.authentication.istio.io โ€œauth-policyโ€ created

ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€ ์š”์ฒญ์„ ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํƒœ๋กœ ๋๋‚˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌด๋‹จ 401. ์ด์ œ Auth0์œผ๋กœ ์ธ์ฆํ•˜๋„๋ก ํ”„๋ŸฐํŠธ์—”๋“œ ์‚ฌ์šฉ์ž๋ฅผ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Auth0์œผ๋กœ ์š”์ฒญ ์ธ์ฆ

์ตœ์ข… ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ธ์ฆํ•˜๋ ค๋ฉด ์ธ์ฆ๋œ ์„œ๋น„์Šค(๋ฆฌ๋ทฐ, ์„ธ๋ถ€ ์ •๋ณด ๋ฐ ํ‰๊ฐ€)๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” API๋ฅผ Auth0์— ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. API๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•˜์„ธ์š”. Auth0 ํฌํ„ธ > API > API ์ƒ์„ฑ ์–‘์‹์„ ์ž‘์„ฑํ•˜์„ธ์š”.

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ •๋ณด๋Š” ํ™•์ธ, ๋‚˜์ค‘์— ์Šคํฌ๋ฆฝํŠธ์—์„œ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์–ด๋ณด์ž:

  • ์˜ค๋””์–ธ์Šค (Audience): {YOUR_AUDIENCE}

ํ•„์š”ํ•œ ๋‚˜๋จธ์ง€ ์„ธ๋ถ€ ์ •๋ณด๋Š” ์„น์…˜์˜ Auth0 ํฌํ„ธ์— ์žˆ์Šต๋‹ˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ - ๊ณ ๋ฅด๋‹ค ์‹œํ—˜ ์ ์šฉ (API์™€ ํ•จ๊ป˜ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋จ)

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์“ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

  • ๋„๋ฉ”์ธ: {YOUR_DOMAIN}
  • ๊ณ ๊ฐ ID: {YOUR_CLIENT_ID}

๋‹ค์Œ์œผ๋กœ ์Šคํฌ๋กค ์‹œํ—˜ ์ ์šฉ ํ…์ŠคํŠธ ํ•„๋“œ๋กœ ํ—ˆ์šฉ๋œ ์ฝœ๋ฐฑ URL (์ฝœ๋ฐฑ์— ๋Œ€ํ•ด ํ™•์ธ๋œ URL), ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ํ›„ ํ˜ธ์ถœ์ด ์ „์†ก๋˜์–ด์•ผ ํ•˜๋Š” URL์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

http://{EXTERNAL_IP}/callback

๊ทธ๋ฆฌ๊ณ  ํ—ˆ์šฉ๋˜๋Š” ๋กœ๊ทธ์•„์›ƒ URL (๋กœ๊ทธ์•„์›ƒ์ด ํ—ˆ์šฉ๋œ URL) ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

http://{EXTERNAL_IP}/logout

ํ”„๋ก ํŠธ์—”๋“œ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ”„๋ŸฐํŠธ์—”๋“œ ์—…๋ฐ์ดํŠธ

์ง€์ ์œผ๋กœ ์ „ํ™˜ auth0 ์ €์žฅ์†Œ [istio-mastery]. ์ด ๋ถ„๊ธฐ์—์„œ๋Š” ์ธ์ฆ์„ ์œ„ํ•ด ์‚ฌ์šฉ์ž๋ฅผ Auth0์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๊ณ  ๋‹ค๋ฅธ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์š”์ฒญ์— JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ”„๋ŸฐํŠธ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ›„์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค(์•ฑ.js):

analyzeSentence() {
    fetch('/sentiment', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token
        },
        body: JSON.stringify({ sentence: this.textField.getValue() })
    })
        .then(response => response.json())
        .then(data => this.setState(data));
}

Auth0์—์„œ ํ…Œ๋„ŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ”„๋ŸฐํŠธ์—”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์—ฝ๋‹ˆ๋‹ค. sa-frontend/src/services/Auth.js ์œ„์—์„œ ์“ด ๊ฐ’์„ ๊ทธ ์•ˆ์— ๋ฐ”๊พธ์‹ญ์‹œ์˜ค (Auth.js):

const Config = {
    clientID: '{YOUR_CLIENT_ID}',
    domain:'{YOUR_DOMAIN}',
    audience: '{YOUR_AUDIENCE}',
    ingressIP: '{EXTERNAL_IP}' // ะ˜ัะฟะพะปัŒะทัƒะตั‚ัั ะดะปั ั€ะตะดะธั€ะตะบั‚ะฐ ะฟะพัะปะต ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ
}

์‹ ์ฒญ์„œ๊ฐ€ ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•  ๋•Œ ์•„๋ž˜ ๋ช…๋ น์— Docker ID๋ฅผ ์ง€์ •ํ•˜์„ธ์š”.

$ docker build -f sa-frontend/Dockerfile 
 -t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 
 sa-frontend

$ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0

$ kubectl set image deployment/sa-frontend 
 sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0

์•ฑ์„ ์‚ฌ์šฉํ•ด ๋ณด์„ธ์š”! ๋กœ๊ทธ์ธ(๋˜๋Š” ๋“ฑ๋ก)์ด ํ•„์š”ํ•œ Auth0์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋˜๋ฉฐ, ๊ทธ ํ›„ ์ด๋ฏธ ์ธ์ฆ๋œ ์š”์ฒญ์ด ์ด๋ฃจ์–ด์ง€๋Š” ํŽ˜์ด์ง€๋กœ ๋‹ค์‹œ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ์ปฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์‚ฌ์˜ ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ช…๋ น์„ ์‹œ๋„ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 401 ์ƒํƒœ ์ฝ”๋“œ, ์š”์ฒญ์ด ์Šน์ธ๋˜์ง€ ์•Š์•˜์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„์ธ ์š”์ฒญ ์Šน์ธ์„ ์ง„ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Auth0์„ ํ†ตํ•œ ์Šน์ธ

์ธ์ฆ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‚ฌ์šฉ์ž๊ฐ€ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ƒ์„ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. Istio๋Š” ์ด๋ฅผ ์œ„ํ•œ ๋„๊ตฌ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‘ ๊ฐœ์˜ ์‚ฌ์šฉ์ž ๊ทธ๋ฃน์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค(์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ ์ฐธ์กฐ).

  • ํšŒ์› (์‚ฌ์šฉ์ž) โ€” SA-WebApp ๋ฐ SA-Frontend ์„œ๋น„์Šค์—๋งŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ค‘์žฌ์ž (์‚ฌํšŒ์ž) โ€” ์„ธ ๊ฐ€์ง€ ์„œ๋น„์Šค ๋ชจ๋‘์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€
๊ถŒํ•œ ๋ถ€์—ฌ ๊ฐœ๋…

์ด๋Ÿฌํ•œ ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Auth0 Authorization ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๊ณ  Istio๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ˆ˜์ค€์˜ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Auth0 ์ธ์ฆ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ

Auth0 ํฌํ„ธ์—์„œ ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ(ํ™•์žฅ) ๋ฐ ์„ค์น˜ ์ธ์ฆ0 ์ธ์ฆ. ์„ค์น˜ ํ›„ ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์Šน์ธ ํ™•์žฅ, ๊ทธ๋ฆฌ๊ณ  ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ์„ ํด๋ฆญํ•˜๊ณ  ์ ์ ˆํ•œ ๋ฉ”๋‰ด ์˜ต์…˜์„ ์„ ํƒํ•˜์—ฌ ํ…Œ๋„ŒํŠธ ๊ตฌ์„ฑ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. (๊ตฌ์„ฑ). ๊ทธ๋ฃน ํ™œ์„ฑํ™” (์—ฌ๋Ÿฌ ๋–ผ) ๊ทœ์น™ ๊ฒŒ์‹œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”. (๊ฒŒ์‹œ ๊ทœ์น™).

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

๊ทธ๋ฃน ๋งŒ๋“ค๊ธฐ

์ธ์ฆ ํ™•์žฅ์—์„œ ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•˜์„ธ์š”. ๊ทธ๋ฃน ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ฃน์„ ๋งŒ๋“ค์–ด์š” ์šด์˜์ž. ์ธ์ฆ๋œ ๋ชจ๋“  ์‚ฌ์šฉ์ž๋ฅผ ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋กœ ์ทจ๊ธ‰ํ•˜๋ฏ€๋กœ ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€ ๊ทธ๋ฃน์„ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฃน ์„ ํƒ ์šด์˜์ž, ๋ˆ„๋ฅด๋‹ค ํšŒ์› ์ถ”๊ฐ€, ๊ธฐ๋ณธ ๊ณ„์ •์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. ์ผ๋ถ€ ์‚ฌ์šฉ์ž๋Š” ๊ทธ๋ฃน ์—†์ด ๊ทธ๋Œ€๋กœ ๋‘์–ด ์•ก์„ธ์Šค๊ฐ€ ๊ฑฐ๋ถ€๋˜๋„๋ก ํ•˜์„ธ์š”. (์ƒˆ ์‚ฌ์šฉ์ž๋Š” ๋‹ค์Œ์„ ํ†ตํ•ด ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Auth0 ํฌํ„ธ > ์‚ฌ์šฉ์ž > ์‚ฌ์šฉ์ž ์ƒ์„ฑ.)

์•ก์„ธ์Šค ํ† ํฐ์— ๊ทธ๋ฃน ํด๋ ˆ์ž„ ์ถ”๊ฐ€

์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๋ฃน์— ์ถ”๊ฐ€๋˜์—ˆ์ง€๋งŒ ์ด ์ •๋ณด๋Š” ์•ก์„ธ์Šค ํ† ํฐ์—๋„ ๋ฐ˜์˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. OpenID Connect๋ฅผ ์ค€์ˆ˜ํ•˜๊ณ  ๋™์‹œ์— ํ•„์š”ํ•œ ๊ทธ๋ฃน์„ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด ํ† ํฐ์— ์ž์ฒด ํ† ํฐ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งž์ถค ์ฒญ๊ตฌ. Auth0 ๊ทœ์น™์„ ํ†ตํ•ด ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.

๊ทœ์น™์„ ๋งŒ๋“ค๋ ค๋ฉด Auth0 ํฌํ„ธ๋กœ ์ด๋™ํ•˜์„ธ์š”. ๊ทœ์น™, ๋ˆ„๋ฅด๋‹ค ๊ทœ์น™ ๋งŒ๋“ค๊ธฐ ํ…œํ”Œ๋ฆฟ์—์„œ ๋นˆ ๊ทœ์น™์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

Istio๋ฅผ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. 3 ๋ถ€

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ ๊ทœ์น™์œผ๋กœ ์ €์žฅํ•˜์„ธ์š”. ๊ทธ๋ฃน ํด๋ ˆ์ž„ ์ถ”๊ฐ€ (๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ทธ๋ฃน.js):

function (user, context, callback) {
    context.accessToken['https://sa.io/group'] = user.groups[0];
    return callback(null, user, context);
}

์ฃผ์˜: ์ด ์ฝ”๋“œ๋Š” ๊ถŒํ•œ ๋ถ€์—ฌ ํ™•์žฅ์— ์ •์˜๋œ ์ฒซ ๋ฒˆ์งธ ์‚ฌ์šฉ์ž ๊ทธ๋ฃน์„ ๊ฐ€์ ธ์™€ ์ด๋ฅผ ์‚ฌ์šฉ์ž ์ง€์ • ํด๋ ˆ์ž„์œผ๋กœ ์•ก์„ธ์Šค ํ† ํฐ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(Auth0์—์„œ ์š”๊ตฌํ•˜๋Š” ๋Œ€๋กœ ํ•ด๋‹น ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์•„๋ž˜).

ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ ๊ทœ์น™ ๋‹ค์Œ ์ˆœ์„œ๋กœ ์ž‘์„ฑ๋œ ๋‘ ๊ฐ€์ง€ ๊ทœ์น™์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

  • auth0-์ธ์ฆ-ํ™•์žฅ
  • ๊ทธ๋ฃน ํด๋ ˆ์ž„ ์ถ”๊ฐ€

๊ทธ๋ฃน ํ•„๋“œ๋Š” ๊ทœ์น™์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜์‹ ํ•˜๋ฏ€๋กœ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. auth0-์ธ์ฆ-ํ™•์žฅ ๊ทธ ํ›„์—๋Š” ๋‘ ๋ฒˆ์งธ ๊ทœ์น™์— ๋”ฐ๋ผ ํด๋ ˆ์ž„์œผ๋กœ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์•ก์„ธ์Šค ํ† ํฐ์ž…๋‹ˆ๋‹ค.

{
 "https://sa.io/group": "Moderators",
 "iss": "https://sentiment-analysis.eu.auth0.com/",
 "sub": "google-oauth2|196405271625531691872"
 // [ัะพะบั€ะฐั‰ะตะฝะพ ะดะปั ะฝะฐะณะปัะดะฝะพัั‚ะธ]
}

์ด์ œ ๊ทธ๋ฃน์„ ํด๋ ˆ์ž„์—์„œ ๊ฐ€์ ธ์˜ฌ ์‚ฌ์šฉ์ž ์•ก์„ธ์Šค๋ฅผ ํ™•์ธํ•˜๋„๋ก Envoy ํ”„๋ก์‹œ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(https://sa.io/group) ๋ฐ˜ํ™˜๋œ ์•ก์„ธ์Šค ํ† ํฐ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๊ธฐ์‚ฌ์˜ ๋‹ค์Œ ์„น์…˜์˜ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.

Istio์˜ ์Šน์ธ ๊ตฌ์„ฑ

์Šน์ธ์ด ์ž‘๋™ํ•˜๋ ค๋ฉด Istio์šฉ RBAC๋ฅผ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
  name: default
spec:
  mode: 'ON_WITH_INCLUSION'                     # 1
  inclusion:
    services:                                   # 2
    - "sa-frontend.default.svc.cluster.local"
    - "sa-web-app.default.svc.cluster.local"
    - "sa-feedback.default.svc.cluster.local" 

์„ค๋ช… :

  • 1 - ํ•„๋“œ์— ๋‚˜์—ด๋œ ์„œ๋น„์Šค ๋ฐ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ๋Œ€ํ•ด์„œ๋งŒ RBAC๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. Inclusion;
  • 2 โ€” ์šฐ๋ฆฌ๋Š” ์„œ๋น„์Šค ๋ชฉ๋ก์„ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑ์„ ์ ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default created

์ด์ œ ๋ชจ๋“  ์„œ๋น„์Šค์—๋Š” ์—ญํ•  ๊ธฐ๋ฐ˜ ์•ก์„ธ์Šค ์ œ์–ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด ๊ธˆ์ง€๋˜๋ฉฐ ์ด์— ๋Œ€ํ•œ ๋Œ€์‘์ด ์ด๋ฃจ์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. RBAC: access denied. ์ด์ œ ์Šน์ธ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜ ์‚ฌ์šฉ์ž์˜ ์ ‘๊ทผ ๊ตฌ์„ฑ

๋ชจ๋“  ์‚ฌ์šฉ์ž๋Š” SA-Frontend ๋ฐ SA-WebApp ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ Istio ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค ์—ญํ•  โ€” ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ถŒ๋ฆฌ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ServiceRoleBinding โ€” ์ด ServiceRole์ด ๋ˆ„๊ตฌ์—๊ฒŒ ์†ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜ ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ ํŠน์ • ์„œ๋น„์Šค(servicerole.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: regular-user
  namespace: default
spec:
  rules:
  - services: 
    - "sa-frontend.default.svc.cluster.local" 
    - "sa-web-app.default.svc.cluster.local"
    paths: ["*"]
    methods: ["*"]

๊ทธ๋ฆฌ๊ณ  ํ†ตํ•ด regular-user-binding ๋ชจ๋“  ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ์ž์—๊ฒŒ ServiceRole์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค(์ผ๋ฐ˜ ์‚ฌ์šฉ์ž ์„œ๋น„์Šค ์—ญํ•  ๋ฐ”์ธ๋”ฉ.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: regular-user-binding
  namespace: default
spec:
  subjects:
  - user: "*"
  roleRef:
    kind: ServiceRole
    name: "regular-user"

"๋ชจ๋“  ์‚ฌ์šฉ์ž"๋Š” ์ธ์ฆ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๋„ SA ์›น์•ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๊นŒ? ์•„๋‹ˆ์š”, ์ •์ฑ…์€ JWT ํ† ํฐ์˜ ์œ ํšจ์„ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ์„ ์ ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ kubectl apply -f resource-manifests/istio/security/user-role.yaml
servicerole.rbac.istio.io/regular-user created
servicerolebinding.rbac.istio.io/regular-user-binding created

์ค‘์žฌ์ž๋ฅผ ์œ„ํ•œ ์•ก์„ธ์Šค ๊ตฌ์„ฑ

์ค‘์žฌ์ž์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ์„œ๋น„์Šค(๋ชจ๋“œ-์„œ๋น„์Šค-role.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: mod-user
  namespace: default
spec:
  rules:
  - services: ["*"]
    paths: ["*"]
    methods: ["*"]

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์•ก์„ธ์Šค ํ† ํฐ์— ํด๋ ˆ์ž„์ด ํฌํ•จ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ๋งŒ ๊ทธ๋Ÿฌํ•œ ๊ถŒ๋ฆฌ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. https://sa.io/group ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  Moderators (๋ชจ๋“œ ์„œ๋น„์Šค ์—ญํ•  ๋ฐ”์ธ๋”ฉ.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: mod-user-binding
  namespace: default
spec:
  subjects:
  - properties:
      request.auth.claims[https://sa.io/group]: "Moderators"
  roleRef:
    kind: ServiceRole
name: "mod-user" 

๊ตฌ์„ฑ์„ ์ ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ kubectl apply -f resource-manifests/istio/security/mod-role.yaml
servicerole.rbac.istio.io/mod-user created
servicerolebinding.rbac.istio.io/mod-user-binding created

ํŠน์‚ฌ์˜ ์บ์‹ฑ์œผ๋กœ ์ธํ•ด ์Šน์ธ ๊ทœ์น™์ด ์ ์šฉ๋˜๋Š” ๋ฐ ๋ช‡ ๋ถ„ ์ •๋„ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์‚ฌ์šฉ์ž์™€ ์ค‘์žฌ์ž์˜ ์•ก์„ธ์Šค ์ˆ˜์ค€์ด ์„œ๋กœ ๋‹ค๋ฅธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์— ๋Œ€ํ•œ ๊ฒฐ๋ก 

ํ•˜์ง€๋งŒ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ์— ๋Œ€ํ•œ ๋” ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ„ํŽธํ•˜๋ฉฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ณ  ์•ˆ์ „ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋ณธ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์„œ๋น„์Šค์— ๋Œ€ํ•œ ์ตœ์ข… ์‚ฌ์šฉ์ž ์•ก์„ธ์Šค์˜ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๋ฐ๋Š” ์„ธ ๊ฐ€์ง€ Istio ๋ฆฌ์†Œ์Šค(RbacConfig, ServiceRole ๋ฐ ServiceRoleBinding)๋งŒ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์šฐ๋ฆฌ๋Š” ํŠน์‚ฌ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋‹ค์Œ์„ ๋‹ฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๋ณด์•ˆ ๋ฌธ์ œ ๋ฐ ๋ฒ„๊ทธ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š” ์ผ๋ฐ˜ ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ž…๋‹ˆ๋‹ค.
  • ํ•˜๋‚˜์˜ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์‚ฌ์‹ค์ด ๋ฐํ˜€์ง€๊ณ  ์ด๋ฅผ ๋ณด๊ณ ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๋Š” ์–ด๋ฆฌ์„์€ ์ƒํ™ฉ์˜ ์ˆ˜๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค.
  • ์ƒˆ๋กœ์šด ์—ญํ• ์ด๋‚˜ ๊ถŒํ•œ์ด ์ถ”๊ฐ€๋  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์„œ๋น„์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ƒˆ๋กœ์šด ์„œ๋น„์Šค๋Š” ์—ฌ์ „ํžˆ ๋‹จ์ˆœํ•˜๊ณ  ์•ˆ์ „ํ•˜๋ฉฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

์ถœ๋ ฅ

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

์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ Istio๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ์ง€์‹๊ณผ ๋ฏธ๋ฆฌ ์ค€๋น„๋œ ์‹ค์šฉ์ ์ธ ์ง€์นจ์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฒˆ์—ญ๊ฐ€์˜ ์ถ”์‹ 

๋ธ”๋กœ๊ทธ์—์„œ๋„ ์ฝ์–ด๋ณด์„ธ์š”.

์ถœ์ฒ˜ : habr.com

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