Istio โhelloworldโ ๋ฐ๋ชจ
์ด๋ฒ ํฌ์คํธ์์๋ Istio์์ ์ ๊ณตํ๋ helloworld ์์ ๋ฅผ ํ์ฉํด Istio์ Virtual Service์ Destination Rule์ ๊ธฐ๋ฅ๋ค์ ์ง์ ์คํํด๋ณธ๋ค. ๐งช
์ฌ์ ์ค๋น
์ผ๋จ hello ์์ ๋ฅผ ๋์ธ ๋ค์์คํ์ด์ค์ label์ ๋ถ์ฌํด์ envoy sidecar๊ฐ ๋ถ์ ์ ์๋๋ก ๋ง๋ค์.
kubectl label ns default istio-injection=enabled
๊ทธ๋ฆฌ๊ณ ์์ ํฌ์คํธ๋ฅผ ์ฐธ๊ณ ํด Istio์ Kiali, Prometheus Addon์ ์ค์นํ๋ค.
โก๏ธ Install Istio and Addons(Prometheus, Kiali)
helloworld ์ดํ๋ฆฌ์ผ์ด์
istio์ ์์ ์ค ๊ฐ์ฅ ์ฌํํ ๋
์์ผ๋ก /hello
์๋ํฌ์ธํธ์ ์์ฒญ์ ๋ณด๋ด๋ฉด, ์์ ์ ๋ฒ์ ์ ๋ณด๋ฅผ ๋ฆฌํดํ๋ค.
$ curl -X GET localhost:5000/hello
Hello version: v1, instance: helloworld-v1-867747c89-n6sl2
์ฐ์ ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํด๋ณด์!
$ kubectl apply -n default -f https://raw.githubusercontent.com/istio/istio/1.20.2/samples/helloworld/helloworld.yaml
service/helloworld created
deployment.apps/helloworld-v1 created
deployment.apps/helloworld-v2 created
๊ทธ๋ฌ๋ฉด, ๋ฒ์ v1, v2์ helloworld
์ดํ๋ฆฌ์ผ์ด์
์ด ๋ฐฐํฌ๋๋ค.
์ง๊ธ ๋ง๋ค์ด์ง service/helloworld
๋ v1, v2๋ฅผ round robin์ผ๋ก ํธ๋ํฝ์ ๋ถ์ฐํ๋ค.
ํ ์คํธ๋ฅผ ์ํด ์๋ ๋ช ๋ น์ด๋ก ์์ Pod์ ๋์์ ํธ๋ํฝ ๋ผ์ฐํ ์ด ์ด๋ป๊ฒ ๋๋์ง ํ์ธํด๋ณด์. (์ด๋, k port-forwardํ ๊ฑธ๋ก ์ ์ํ๋ฉด ์ ๋๋ค. ๊ทธ ์ด์ ๋ ์ ๊นํ ์ด์๋ฅผ ์ฐธ๊ณ )
$ k run nginx --image=nginx
$ k exec -it nginx -- sh
# <on some pod>
while true; do curl "http://helloworld.default:5000/hello"; done
v1
5ํ, v2
8ํ. ๊ฑฐ์ ๋ฐ๋ฐ ์ ๋๋ก ๋ผ์ฐํ
๋๋ค!
์๋ , Virtual Service!
๊ทธ๋ผ ์ด์ istio์ Virtual Service๋ก v1๊ณผ v2์ ํธ๋ํฝ ๋น์จ์ ์กฐ์ ํด๋ณด์!
์ผ๋จ ์ง๊ธ์ v1
, v2
๋์ ๊ฐ์ด ์ฐ๋ K8s Service ํ๋๋ง ๊ตฌ์ฑํ๋๋ฐ, ๊ฐ๊ฐ์ผ๋ก ๋ผ์ฐํ
ํ๋ ์๋ก์ด K8s Service ๋์ ๊ตฌ์ฑํ์.
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: helloworld-v1
labels:
app: helloworld
service: helloworld
version: v1
spec:
ports:
- port: 5000
name: http
selector:
app: helloworld
version: v1
---
apiVersion: v1
kind: Service
metadata:
name: helloworld-v2
labels:
app: helloworld
service: helloworld
version: v2
spec:
ports:
- port: 5000
name: http
selector:
app: helloworld
version: v2
EOF
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด Virtual Service๋ฅผ ๊ตฌ์ฑํด์, v1
์๋ 10% ํธ๋ํฝ์ด, v2
์๋ 90%์ ํธ๋ํฝ์ด ํ๋ฅผ ์ ์๋๋ก ๊ตฌ์ฑํด๋ณด์.
# simple-virtual-service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-vs
spec:
hosts:
- "helloworld.default.svc.cluster.local"
http:
- route:
- destination:
host: helloworld-v1.default.svc.cluster.local
weight: 20 # 20% ํธ๋ํฝ
- destination:
host: helloworld-v2.default.svc.cluster.local
weight: 80 # 80% ํธ๋ํฝ
์์ Virtual Service๋ฅผ ์์ฑํ ํ์ ๋ค์ nginx
Pod์ ์ ์ํด์ ๋ค์ ํธ๋ํฝ์ ํ๋ ค๋ณด์.
$ kubectl apply -f simple-virtual-service.yaml
$ kubectl exec -it nginx -- sh
# <on nginx pod>
while true; do curl "http://helloworld.default:5000/hello"; done
์์ฐ!! ํธ๋ํฝ์ 20:80 ๋น์จ๋ก ๋ถ์ฐ๋์๋ค!! เดฆเตเดฆเดฟ หอฬ๊ณหอฬ )โง
Gateway์ ํจ๊ป Virtual Service๋ฅผ ๊ตฌ์ฑ
istio์์ ์ ๊ณตํ๋ ์์ ์์๋ helloworld-gateway.yaml
๋ผ๋ ํ์ผ์ IngressGateway์ VirtualService๋ฅผ ์ ์ํด์ ์ ๊ณตํ๊ณ ์๋ค.
์ด๋ฒ์๋ IngressGateway์ ํจ๊ป VirtualService๋ฅผ ๊ตฌ์ฑํด๋ณด์.
์ผ๋จ IngressGateway๋ถํฐ ์ด๋ ๊ฒ ์ ์ํ์.
# helloworld-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
๊ทธ๋ฆฌ๊ณ VirtualService๋ ์ด๋ ๊ฒ ๊ตฌ์ฑํ๋ค. ์ด๋ฒ์๋ ๊ตฌ๋ถ์ ์ํด์ v1:v2๋ฅผ 70:30์ผ๋ก ๊ตฌ์ฑํ์. ์ด๋ฒ์๋ v1 ํธ๋ํฝ์ด ๋ ๋ง๋ค!
# hellworld-vs-with-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-vs-w-gateway
spec:
hosts:
- "*"
gateways:
- helloworld-gateway
http:
- route:
- destination:
host: helloworld-v1.default.svc.cluster.local
port:
number: 5000
weight: 70 # 70% ํธ๋ํฝ
- destination:
host: helloworld-v2.default.svc.cluster.local
port:
number: 5000
weight: 30 # 30% ํธ๋ํฝ
๊ทธ๋ฆฌ๊ณ ๋ nginx
Pod์ ์ ์ํด์ ํธ๋ํฝ์ ํ๋ ค๋ณด์. ๊ทธ๋ฐ๋ฐ ์ด๋ฒ์๋ default
ns์ ์๋ helloworld
์ Service๊ฐ ์๋๋ผ istio-system
ns์ ์๋ istio-ingressgateway
์ ํธ๋ํฝ์ ๋ณด๋ด์ผ ํ๋ค.
$ kubectl apply -f helloworld-gateway.yaml
$ kubectl apply -f helloworld-vs-with-gateway.yaml
$ kubectl exec -it nginx -- sh
# <on nginx pod>
while true; do curl "http://istio-ingressgateway.istio-system/hello"; done
Kiali์์ ํธ๋ํฝ์ ํ์ธํด๋ณด๋ฉด,
์์ ! ์ด๋ฒ์๋ istio์ default ingress gateway๋ฅผ ํตํด์ ํธ๋ํฝ์ด ๋ถ์ฐ๋๊ณ ์๋ค! ูฉ(^แ^ )ู
VirtualService์ Gateway ์กฐ๊ธ ๋๋ณด๊ธฐ
์ ๋ถ๋ถ์ VirtualService์ Gateway ๋ฆฌ์์ค์ ๋ํด ์กฐ๊ธ๋ ๊น์ ๋ด์ฉ์ ๋ค๋ฃฌ๋ค. ์ด ๋ถ๋ถ์ ์คํตํด๋ helloworld ์์ ๋ฅผ ์งํํ๋๋ฐ ๋ฌธ์ ๊ฐ ์์ผ๋, Istio์ ์
๋ฌธํ์ง ์ผ๋ง ๋์ง ์์๋ค๋ฉด, ๊ณผ๊ฐํ DestinationRule
์ ์ฐ๋ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ์!
์ฌ๊ธฐ์ ์ ๊น! IngressGateway์ ํจ๊ป ์ฐ๋ฉด์, VirtualService์์ ๋ฐ๋ ๋ถ๋ถ์ hosts
์ gateways
๋ถ๋ถ์ด๋ค.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-vs-w-gateway
spec:
hosts: # ์๊ธฐ!
- "*"
gateways: # ์๊ธฐ๋!
- helloworld-gateway
...
์ด๋, hosts
๋ถ๋ถ์ *
๋ผ๋ ์์ผ๋์นด๋(wildcard)๊ฐ ์ฌ์ฉ๋์๋๋ฐ, ์ด ์์ผ๋์นด๋๋ ์ค์ง gateways
์์ฑ๊ณผ ํจ๊ป ์ธ ์ ์๋ค. ๋ง์ฝ gateways
์ ํจ๊ป ์ฐ์ง ์๋๋ค๋ฉด, ์๋์ ์๋ฌ๋ฅผ ๋ณด๊ฒ ๋๋ค.
admission webhook โvalidation.istio.ioโ denied the request:
configuration is invalid: wildcard host * is not allowed for virtual services bound to the mesh gateway
์ด๋, โmesh gatewayโ๋ผ๋ ํํ์ด ๋ฑ์ฅํ๋๋ฐ, ๊ฐ๋จํ๊ฒ ๋งํ์๋ฉด, istio์ ์ ์ฒด sidecar proxy์ ๋ชจ์์ ๋งํ๋ค. ์ฆ, sidecar ์ ์ฒด๋ฅผ ๋์์ผ๋ก ํ ๋๋ wildcard host *
๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋คํํ ์ฐ๋ฆฌ๋ helloworld-gateway
๋ผ๊ณ gateway๋ฅผ ๋ช
์ํด์ค์ wildcard host *
๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค. wildcard host๋ก ๋ช
์ํ๊ธฐ ๋๋ฌธ์ helloworld-gateway
์์ ๋ค์ด์ค๋ ๋ชจ๋ ์์ฒญ์ ์ VirtualService์์ ์ฒ๋ฆฌํ๊ฒ ๋๋ค!
๊ทธ๋ฐ๋ฐ, hosts
์ wildcard host *
๋ฅผ ์ฐ๋ ๋ถ๋ถ์ ๋ ์๋ค. ๋ฐ๋ก istio Gateway ๋ฆฌ์์ค์ ์ ๋ถ๋ถ์ด๋ค.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
hosts:
- "*" # ์๊ธฐ!
Gateway์ spec.servers[].hosts
๋ถ๋ถ์ ingress gateway๊ฐ ๋
ธ์ถํ๋ ํฌํธ๋ฅผ ์ฌ์ฉํ VirtualService์ hosts
์ ๋ํ ์กฐ๊ฑด์ ๋ช
์ํ๋ค. ๋ง์ฝ, Gateway serversp[].hosts
๊ฐ์ด *.example.com
์๋ค๋ฉด, dev.example.com
๊ณผ prod.example.com
๋ฅผ host๋ก ๊ฐ๋ VirtualService๋ ํด๋น Gateway๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง, example.com
์ด๋ newexample.com
๋ฅผ host๋ก ๊ฐ๋ VirtualService๋ ํด๋น Gateway๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด๋ฒ ๊ฒฝ์ฐ๋ Gateway์์ wildcard host *
๋ก ์ ์ฒด ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด๋ค VirtualService๋ helloworld-gateway
๋ฅผ ์ฌ์ฉํ ์ ์์๋ค!
์๋ , Destination Rule!
์ด๋ฒ์ DestinationRule ๋ฆฌ์์ค์ VirtualService๋ฅผ ์กฐํฉํด์ ํธ๋ํฝ์ ๋ถ์ฐํด๋ณด์!
์ผ๋จ ์์์ ์์ ์์์ ๋ง๋ค์ด๋๋ ๋ฆฌ์์ค๋ ๋ชจ๋ ์ง์๋์. ์ฒซ ์์ ์์ ๋ง๋ค์ด๋๋ v1
, v2
์ K8s Service๊น์ง ๋๋ค ์ง์ด๋ค!
kubectl delete vs helloworld-vs-w-gateway
kubectl delete gw helloworld-gateway
kubectl delete svc helloworld-v1 helloworld-v2
์ด์ ์๋์ ๊ฐ์ด DestinationRule์ ์ ์ํ๊ณ apply ํด๋ณด์!
# helloworld-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: helloworld-dr
spec:
host: helloworld.default.svc.cluster.local
subsets: # subset๋ค์ ์ ์ํ์!
- name: helloworld-v1
labels:
version: v1
- name: helloworld-v2
labels:
version: v2
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด VirtualService๋ฅผ ๊ตฌ์ฑํ๋ค.
# helloworld-vs-w-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-vs-w-dr
spec:
hosts:
- "helloworld.default.svc.cluster.local"
http:
- route:
- destination:
host: helloworld.default.svc.cluster.local
subset: helloworld-v1 # ์ด๋ฒ์๋ subset์ ์ด๋ค!
weight: 70 # 70% ํธ๋ํฝ
- destination:
host: helloworld.default.svc.cluster.local
subset: helloworld-v2
weight: 30 # 30% ํธ๋ํฝ
๋ฆฌ์์ค๋ฅผ ๋ง๋ ํ์ ํธ๋ํฝ์ ํ๋ ค์ฃผ๋ฉดโฆ
DestinationRule๋ก ๋ฒ์ ๋ณ subset์ ๋ง๋ค์์ ๋
์์ฐ! ์ด๋ฒ์๋ ํธ๋ํฝ์ด ๋น์จ๋๋ก ์ ๋ถ์ฐ๋์๋ค!! ๋๋ผ์ด ์ ์ ๊ฐ ๋ฒ์ ์ ๋์๋๋ K8s Service๋ฅผ ๋ง๋ค์ง ์๊ณ , DestinationRule์์ selector
๋ก subset์ ๋ง๋ค๊ธฐ๋ง ํ๋ ๊ฒ์ด๋ค!!
๋ฒ์ ์ ๋์๋๋ K8s Service๋ฅผ ๋ง๋ค์์ ๋
๋งบ์๋ง
์ง๊ธ๊น์ง helloworld ์์ ๋ฅผ ํตํด Istio VirtualService
, Gateway
, DestinationRule
์ ์์ฃผ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ์ตํ๋ค!
Istio๋ผ๋ ๋ ์์ด ์ฒ์๋ณด๋ฉด ๊ฐ ์ปดํฌ๋ํธ๋ค์ด ์ฝ๊ธฐ์ค๊ธฐ ์ฎ์ฌ ์์ฌ์ ํ์ ํ๊ธฐ๊ฐ ์ด๋ ค์ ๋ ๊ฒ ๊ฐ๋ค. ํนํ ์ด๋ฏธ Istio๋ก ์๋น์ค๋ฉ์๊ฐ ๊ตฌ์ถ๋ ์ํ์์ Istio๋ฅผ ๋ฐ์๋ค์ด๋ ค๊ณ ํ๋ ํนํ ๋จธ๋ฆฌ๊ฐ ๋ ๋ณต์กํ๋ ๊ฒ ๊ฐ๋ค (๐ฆนแฏ ๐ฆน)
๋ค์์ผ๋ก Istio์์ ์ ๊ณตํ๋ Book Info ์์ ๋ฅผ ํ๋ฒ ์ค์ตํ๊ณ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค. ๊ทธ๋ผ ๋น ์!