- 서비스 메시(Service Mesh)
- Istio Service Mesh
- AWS App Mesh
Istio
Istio는 서비스 메시 분야에서 오랫동안 주요 역할을 해온 Opensource Solution으로서 기존 분산 애플리케이션 계층에 투명성을 제공하는 완전한 오픈 소스 서비스 메시입니다. Istio를 사용하면 서비스에 대한 연결, 보안, 제어 및 모니터링을 할 수 있습니다. 높은 수준에서 Istio는 배포의 복잡성을 줄이고 개발 팀의 부담을 덜어줄 수 있습니다. Istio의 다양한 기능 세트를 사용하면 분산 마이크로 서비스 아키텍처를 성공적이고 효율적으로 실행할 수 있으며 마이크로 서비스를 보호, 연결 및 모니터링하는 일관된 방법을 제공받을 수 있습니다.
Istio 구조
Control Plain은 트래픽 동작을 제어하는 높은 수준의 라우팅 규칙을 Envoy Proxy전용 구성으로 변환하고 런타임에 사이드카로 전파합니다. Data Plane은 사이드카로 배포된 지능형 Proxy(Envoy) 세트로 구성됩니다. Envoy Proxy는 마이크로 서비스 간의 모든 네트워크 통신을 중재하며 모든 Mesh 트래픽에 대한 원격 분석 데이터를 수집하고 보고합니다.
EKS(Elastic Kubernetes Service)에 Istio Mesh 적용
Install Istioctl(Istio control)
$ curl -L https://git.io/getLatestIstio | sh - $ cd istio-* $ sudo mv -v bin/istioctl /usr/local/bin/
Install Istio
$ istioctl install This will install the default Istio profile into the cluster. Proceed? (y/N) y ✔ Istio core installed ✔ Istiod installed ✔ Ingress gateways installed ✔ Installation complete $ kubectl -n istio-system get deploy NAME READY UP-TO-DATE AVAILABLE AGE NAME READY UP-TO-DATE AVAILABLE AGE istio-ingressgateway 1/1 1 1 42s istiod 1/1 1 1 58s
Envoy 사이드카 Injection을 위한 label 설정
애플리케이션을 배포할 때 Istio가 Envoy 사이드카 Proxy를 자동으로 삽입하도록 지시하는 namespace label을 추가합니다. namespace에 istio-injection = enabled 레이블을 설정하고 injection webhook이 활성화되면 해당 namespace에서 생성된 모든 새 pod에는 자동으로 사이드카가 추가됩니다.
$ kubectl label namespace default istio-injection=enabled // 확인 $ kubectl get namespaces --show-labels NAME STATUS AGE LABELS default Active 3d8h istio-injection=enabled istio-system Active 2m28s istio-injection=disabled kube-node-lease Active 3d8h <none> kube-public Active 3d8h <none> kube-system Active 3d8h <none>
Sample App (BookInfo)
Istio 설치 시 제공되는 sample 애플리케이션을 구동하여 Mesh를 테스트 해보겠습니다. (istio-1.7.1/samples/bookinfo)
BookInfo는 총 4개의 마이크로 서비스로 나뉘어져 있습니다.
productpage
productpage 서비스는 Review, Detail 마이크로 서비스로 부터 데이터를 받아 Web Front 서비스를 제공합니다.
details
details 서비스는 book 정보를 제공합니다.
reviews
reviews 서비스는 book review 정보를 제공하며 내부적으로 ratings 마이크로 서비스를 호출합니다.
ratings
ratings 서비스는 book review와 함께 제공되는 book 등급 정보를 제공합니다.
reviews 서비스는 3가지 버전이 존재합니다.
Version v1
ratings 서비스를 호출하지 않습니다.
Version v2
ratings 서비스를 호출하고 등급은 1~5개의 검은 색 별표로 표시합니다.
Version v3
ratings 서비스를 호출하고 등급은 1~5개의 빨간 색 별표로 표시합니다.
Deply BookInfo
다음 명령을 통해 BookInfo 서비스를 EKS Cluster에 배포합니다.
################################################################################################## # Details service ################################################################################################## apiVersion: v1 kind: Service metadata: name: details labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-details labels: account: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: serviceAccountName: bookinfo-details containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 --- ################################################################################################## # Ratings service ################################################################################################## apiVersion: v1 kind: Service metadata: name: ratings labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-ratings labels: account: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: serviceAccountName: bookinfo-ratings containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 --- ################################################################################################## # Reviews service ################################################################################################## apiVersion: v1 kind: Service metadata: name: reviews labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-reviews labels: account: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v1 labels: app: reviews version: v1 spec: replicas: 1 selector: matchLabels: app: reviews version: v1 template: metadata: labels: app: reviews version: v1 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v2 labels: app: reviews version: v2 spec: replicas: 1 selector: matchLabels: app: reviews version: v2 template: metadata: labels: app: reviews version: v2 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v3 labels: app: reviews version: v3 spec: replicas: 1 selector: matchLabels: app: reviews version: v3 template: metadata: labels: app: reviews version: v3 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v3:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- ################################################################################################## # Productpage services ################################################################################################## apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-productpage labels: account: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {} ---
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
배포내역 확인
details, productpage, ratings의 경우는 v1만 배포되고 review의 경우는 v3까지 배포된것을 확인할 수 있습니다.
또한 Pod에 Envoy가 Injection되어 컨테이너 개수가 READY 2/2로 표시됩니다.
$ kubectl get pods NAME READY STATUS RESTARTS AGE details-v1-5974b67c8-6hsqt 2/2 Running 0 82s productpage-v1-64794f5db4-vgfpf 2/2 Running 0 82s ratings-v1-c6cdf8d98-rxdfc 2/2 Running 0 81s reviews-v1-7f6558b974-r57mj 2/2 Running 0 82s reviews-v2-6cb6ccd848-q6v9b 2/2 Running 0 82s reviews-v3-cc56b578-lzfnb 2/2 Running 0 82s
Request Routing
Istio ingress Gateway를 사용하여 서비스 메시 외부에 서비스를 노출하도록 구성할 수 있습니다. Gateway는 광범위한 사용자 정의 및 유연성을 제공하며 모니터링 및 라우팅 규칙과 같은 Istio 기능을 클러스터로 들어오는 트래픽에 적용할 수 있습니다.
예제에서는 80 port로 서비스되는 Istio Gateway를 만든 다음 VirtualService 설정을 통해 정의된 path로 들어오는 요청을 productService:9080 port에서 서비스 되도록 처리합니다.
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yamlbookinfo-gateway.yaml 펼치기
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage - uri: prefix: /static - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products route: - destination: host: productpage port: number: 9080
기본 설정으로 Gateway를 생성하면 Classic Load Balancer로 생성됩니다. Network Load Balancer로 생성하려면 아래 내용을 수행합니다.
istio_enable_nlb.yaml
apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: values: gateways: istio-ingressgateway: serviceAnnotations: service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
NLB 적용
$ istioctl upgrade -f istio_enable_nlb.yaml
확인
ingress gateway를 적용하면 loadbalancer가 생성되고 routing 규칙이 적용됩니다.
$ kubectl get svc istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.100.84.203 a03e42f6f424d465c949f29bcdcb592d-dceda3ad59570e1f.elb.ap-southeast-1.amazonaws.com 15021:30709/TCP,80:30936/TCP,443:32289/TCP,15443:30701/TCP 17m
새 브라우저를 열고 DNS 엔드 포인트를 붙여 넣습니다. 해당 DNS 엔드 포인트 끝에 /productpage를 추가하여 요청하면 Sample App을 확인할 수 있습니다. 리프레시 할 때마다 Review서비스의 다른 버전(v1, v2, v3)이 호출되어 화면 내용이 변경되는 것을 확인할 수 있습니다.
v1
v2
v3
Intelligent Routing
Istio 서비스 메시에 마이크로 서비스 기반 애플리케이션을 배포하면 일관된 방식으로 라우팅을 외부에서 제어할 수 있습니다.
Destination Rule 추가
Istio를 사용하여 버전 라우팅을 제어하려면 먼저 대상 규칙에서 사용 가능한 버전 (subset)을 정의해야 합니다.
아래와 같이 Destination Rule을 작성하여 Cluster에 적용합니다.
review 서비스의 경우 버전에 따라 subset이 3개가 작성됩니다.
destination-rule-all.yaml 펼치기apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: productpage spec: host: productpage subsets: - name: v1 labels: version: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: reviews spec: host: reviews subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - name: v3 labels: version: v3 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: ratings spec: host: ratings subsets: - name: v1 labels: version: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: details spec: host: details subsets: - name: v1 labels: version: v1 ---
$ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
특정 버전만 서비스하기
VirtualService에서 subset을 지정하면 특정 버전만 서비스할 수 있습니다. 아래 내용을 적용하면 review 서비스가 v1만 서비스 하게 됩니다.
virtual-service-all-v1.yaml 펼치기apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: productpage spec: hosts: - productpage http: - route: - destination: host: productpage subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ratings spec: hosts: - ratings http: - route: - destination: host: ratings subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: details spec: hosts: - details http: - route: - destination: host: details subset: v1 ---
$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
페이지를 여러 번 새로 고침하면 매번 v1의 리뷰만 표시되는 것을 확인할 수 있습니다.
특정 User에게 특정 버전만 서비스하기
아래 내용을 적용하면 Review서비스의 v1을 기본으로 서비스 하지만 jason으로 로그인한 경우에는 v2가 서비스 됩니다.
virtual-service-reviews-test-v2.yaml 펼치기apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - match: - headers: end-user: exact: jason route: - destination: host: reviews subset: v2 - route: - destination: host: reviews subset: v1
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
미로그인시
jason으로 로그인시
Fault Injection
애플리케이션의 복원력을 테스트하기 위해 오류를 삽입할 수 있습니다.
다음 내용을 적용하면 jason으로 로그인시 rating서비스가 100% 확률로 7초의 딜레이가 발생됩니다.
virtual-service-ratings-test-delay.yaml 펼치기apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ratings spec: hosts: - ratings http: - match: - headers: end-user: exact: jason fault: delay: percentage: value: 100.0 fixedDelay: 7s route: - destination: host: ratings subset: v1 - route: - destination: host: ratings subset: v1
$ kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml
다음 내용을 적용하면 json으로 로그인한 경우 Ratings 서비스에서 무조건 500 에러가 발생합니다.
virtual-service-ratings-test-abort.yaml 펼치기apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ratings spec: hosts: - ratings http: - match: - headers: end-user: exact: jason fault: abort: percentage: value: 100.0 httpStatus: 500 route: - destination: host: ratings subset: v1 - route: - destination: host: ratings subset: v1
$ kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml
한 버전에서 다른 버전으로 트래픽을 점진적으로 마이그레이션
아래 내용을 적용하면 모든 review 서비스 요청에 대해 트래픽의 50%는 v1으로 나머지 50%는 v3로 처리되도록 설정합니다.
review 서비스가 v1만 서비스 하도록 적용
virtual-service-all-v1.yaml 펼치기
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: productpage spec: hosts: - productpage http: - route: - destination: host: productpage subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ratings spec: hosts: - ratings http: - route: - destination: host: ratings subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: details spec: hosts: - details http: - route: - destination: host: details subset: v1 ---
$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
비율에 따라 v1, v3를 서비스하도록 적용
virtual-service-reviews-50-v3 펼치기
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 weight: 50 - destination: host: reviews subset: v3 weight: 50
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
테스트를 위해 브라우저를 여러번 리프레시 하면 v1과 v3버전이 전환되며 표시되는것을 확인 할 수 있습니다.
Circuit Breaking
Circuit breaking은 탄력적인 마이크로 서비스 애플리케이션을 만드는 데 중요한 패턴입니다. Circuit breaking을 사용하면 장애의 영향, 지연 시간 급증 및 기타 네트워크 특성의 바람직하지 않은 영향을 제한하는 애플리케이션을 작성할 수 있습니다.
- 만일 하나의 서비스가 장애가 발생하게 되면 장애 서비스를 호출하는 서비스는 대기 상태가 되고 다시 대기 중인 서비스를 호출하는 또 다른 서비스도 대기하게 되어 장애가 차례대로 전파됩니다.
- Circuit Breaker의 역할은 이렇게 문제가 되는 기능 자체를 동작하지 않도록하여 리소스 점유의 증가로 장애가 전파되지 않도록 하는데 목적이 있습니다.
circuit break 대상 대상이 되는 httpbin 앱을 설치합니다. httpbin 은 HTTP 프로토콜 echo 응답 앱입니다.
$ kubectl label namespace default istio-injection=enabled $ kubectl apply -f samples/httpbin/httpbin.yaml
마이크로서비스 로드 테스트 툴인 fortio를 설치합니다.
$ kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml $ kubectl get pods NAME READY STATUS RESTARTS AGE details-v1-5974b67c8-6hsqt 2/2 Running 0 24h fortio-deploy-7cb865f87f-vj22f 2/2 Running 0 25m httpbin-779c54bf49-lmrz5 2/2 Running 0 25m
fortio pod에 접속하여 httpbin 으로 요청해봅니다. 200(정상) 응답 코드가 리턴됩니다.
$ export FORTIO_POD=$(kubectl get pods -lapp=fortio -o 'jsonpath={.items[0].metadata.name}') $ kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl -quiet http://httpbin:8000/get HTTP/1.1 200 OK server: envoy date: Tue, 15 Sep 2020 02:24:38 GMT content-type: application/json content-length: 621 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 3 { "args": {}, "headers": { "Content-Length": "0", "Host": "httpbin:8000", "User-Agent": "fortio.org/fortio-1.6.8", "X-B3-Parentspanid": "173c3b9531a2da2c", "X-B3-Sampled": "1", "X-B3-Spanid": "a9b2ba6ff10a3e7d", "X-B3-Traceid": "64b2e647a1787138173c3b9531a2da2c", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=5f73a527d698903bbaffe50b5838079fc2f5be3ee394fe637e07c8efb1772475;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default" }, "origin": "127.0.0.1", "url": "http://httpbin:8000/get" }
kiali Dashboard Graph는 아래와 같습니다. circuit breaker가 설정되면 번개 표시로 나타납니다.
DestinationRule 작성
circuit break 설정을 적용하는 Destination Rule을 만들어 적용합니다. 테스트를 위해 최소한의 커넥션만 허용하도록 설정합니다.
Destination Rule 적용 펼치기circuitbreak_rule.yaml
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: httpbin spec: host: httpbin trafficPolicy: connectionPool: tcp: maxConnections: 1 http: http1MaxPendingRequests: 1 maxRequestsPerConnection: 1 outlierDetection: consecutiveErrors: 1 interval: 1s baseEjectionTime: 3m maxEjectionPercent: 100
DestinationRule 적용
$ kubectl apply -f circuitbreak_rule.yaml destinationrule.networking.istio.io/httpbin created
테스트
두 개의 동시 연결 ( -c 2)로 서비스를 호출하고 20 개의 요청 ( -n 20)을 보냅니다 . 요청의 85%가 성공했고 15%는 circuit breaker에 의해 차단되었습니다.
$ kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get 02:34:15 I logger.go:115> Log level is now 3 Warning (was 2 Info) Fortio 1.6.8 running at 0 queries per second, 2->2 procs, for 20 calls: http://httpbin:8000/get Starting at max qps with 2 thread(s) [gomax 2] for exactly 20 calls (10 per thread + 0) 02:34:15 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:34:15 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:34:15 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) Ended after 124.335657ms : 20 calls. qps=160.85 Aggregated Function Time : count 20 avg 0.011879563 +/- 0.009008 min 0.001159891 max 0.03371059 sum 0.237591251 # range, mid point, percentile, count >= 0.00115989 <= 0.002 , 0.00157995 , 5.00, 1 > 0.003 <= 0.004 , 0.0035 , 10.00, 1 > 0.004 <= 0.005 , 0.0045 , 30.00, 4 > 0.005 <= 0.006 , 0.0055 , 35.00, 1 > 0.006 <= 0.007 , 0.0065 , 45.00, 2 > 0.007 <= 0.008 , 0.0075 , 50.00, 1 > 0.008 <= 0.009 , 0.0085 , 55.00, 1 > 0.009 <= 0.01 , 0.0095 , 60.00, 1 > 0.011 <= 0.012 , 0.0115 , 65.00, 1 > 0.016 <= 0.018 , 0.017 , 75.00, 2 > 0.02 <= 0.025 , 0.0225 , 90.00, 3 > 0.025 <= 0.03 , 0.0275 , 95.00, 1 > 0.03 <= 0.0337106 , 0.0318553 , 100.00, 1 # target 50% 0.008 # target 75% 0.018 # target 90% 0.025 # target 99% 0.0329685 # target 99.9% 0.0336364 Sockets used: 5 (for perfect keepalive, would be 2) Jitter: false Code 200 : 17 (85.0 %) Code 503 : 3 (15.0 %) Response Header Sizes : count 20 avg 195.8 +/- 82.25 min 0 max 231 sum 3916 Response Body/Total Sizes : count 20 avg 759.8 +/- 217.9 min 241 max 852 sum 15196 All done 20 calls (plus 0 warmup) 11.880 ms avg, 160.9 qps
동시 연결 수를 최대 3 개로 늘리고 30개의 요청을 보냅니다. 요청의 60%가 성공했고 40%는 circuit breaker에 의해 차단되었습니다.
$ kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get 02:36:18 I logger.go:115> Log level is now 3 Warning (was 2 Info) Fortio 1.6.8 running at 0 queries per second, 2->2 procs, for 30 calls: http://httpbin:8000/get Starting at max qps with 3 thread(s) [gomax 2] for exactly 30 calls (10 per thread + 0) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) 02:36:18 W http_client.go:698> Parsed non ok code 503 (HTTP/1.1 503) Ended after 110.666685ms : 30 calls. qps=271.08 Aggregated Function Time : count 30 avg 0.0095096311 +/- 0.007669 min 0.001468498 max 0.032481834 sum 0.285288932 # range, mid point, percentile, count >= 0.0014685 <= 0.002 , 0.00173425 , 10.00, 3 > 0.003 <= 0.004 , 0.0035 , 20.00, 3 > 0.004 <= 0.005 , 0.0045 , 30.00, 3 > 0.005 <= 0.006 , 0.0055 , 40.00, 3 > 0.006 <= 0.007 , 0.0065 , 53.33, 4 > 0.007 <= 0.008 , 0.0075 , 63.33, 3 > 0.008 <= 0.009 , 0.0085 , 73.33, 3 > 0.011 <= 0.012 , 0.0115 , 76.67, 1 > 0.012 <= 0.014 , 0.013 , 80.00, 1 > 0.018 <= 0.02 , 0.019 , 86.67, 2 > 0.02 <= 0.025 , 0.0225 , 93.33, 2 > 0.025 <= 0.03 , 0.0275 , 96.67, 1 > 0.03 <= 0.0324818 , 0.0312409 , 100.00, 1 # target 50% 0.00675 # target 75% 0.0115 # target 90% 0.0225 # target 99% 0.0317373 # target 99.9% 0.0324074 Sockets used: 14 (for perfect keepalive, would be 3) Jitter: false Code 200 : 18 (60.0 %) Code 503 : 12 (40.0 %) Response Header Sizes : count 30 avg 138.2 +/- 112.8 min 0 max 231 sum 4146 Response Body/Total Sizes : count 30 avg 607.2 +/- 299 min 241 max 852 sum 18216 All done 30 calls (plus 0 warmup) 9.510 ms avg, 271.1 qps
circuit break가 작동되었을때 kiali 화면에는 아래와 같이 표시됩니다.
Visualizing Metrics
Prometheus
Prometheus는 오픈 소스 모니터링 시스템 및 시계열 데이터베이스입니다. Istio와 함께 Prometheus를 사용하여 Istio 및 서비스 메시 내 애플리케이션의 상태를 추적하는 메트릭을 기록할 수 있습니다. Grafana 및 Kiali와 같은 도구를 사용하여 메트릭을 시각화할 수 있습니다.
Prometheus Install
Prometheuse Install 펼치기$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/addons/prometheus.yaml serviceaccount/prometheus created configmap/prometheus created clusterrole.rbac.authorization.k8s.io/prometheus created clusterrolebinding.rbac.authorization.k8s.io/prometheus created service/prometheus created deployment.apps/prometheus created $ kubectl -n istio-system get svc prometheus NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus ClusterIP 10.100.160.49 <none> 9090/TCP 25s
Grafana
Grafana는 Istio 용 대시 보드를 구성하는 데 사용할 수 있는 오픈 소스 모니터링 Solution입니다. Grafana를 사용하여 Istio 및 서비스 메시 내 애플리케이션의 상태를 모니터링할 수 있습니다.
Grafana Install
Grafana Install 펼치기$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/addons/grafana.yaml serviceaccount/grafana created configmap/grafana created service/grafana created deployment.apps/grafana created configmap/istio-grafana-dashboards created configmap/istio-services-grafana-dashboards created $ kubectl -n istio-system get svc grafana NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana ClusterIP 10.100.182.135 <none> 3000/TCP 2m43s
Expose Service
grafana_service.yaml
apiVersion: v1 kind: Service metadata: name: grafana namespace: istio-system spec: selector: app: grafana type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 3000
$ kubectl apply -f grafana_service.yaml $ kubectl get svc grafana -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana LoadBalancer 10.100.235.59 a6542d4281e384e0cb34c8536eecz678-1918338663.ap-southeast-1.elb.amazonaws.com 80:32390/TCP 3m15s
kiali
Kiali는 서비스 메시 구성 및 유효성 검사 기능이 있는 Istio 용 관찰 콘솔입니다. 트래픽 흐름을 모니터링하여 토폴로지를 추론하고 오류를 보고함으로써 서비스 메시의 구조와 상태를 이해하는 데 도움이 됩니다. Kiali는 고급 쿼리에 사용할 수 있는 자세한 메트릭과 기본 Grafana 통합을 제공합니다. Jaeger와의 통합을 통해 분산 추적이 제공됩니다.
kiali Install
Kiali Install 펼치기$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/addons/kiali.yaml
Expose Service
kiali_service.yaml
apiVersion: v1 kind: Service metadata: name: kiali namespace: istio-system spec: selector: app: kiali type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 20001
$ kubectl apply -f kiali_service.yaml $ kubectl get svc kiali -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kiali LoadBalancer 10.100.205.7 aeae4ccc311404df4xc9b9e6d235377e-789779401.ap-southeast-1.elb.amazonaws.com 80:30653/TCP 8m46s
Jaeger
Jaeger는 오픈 소스 end to end 분산 추적 시스템으로, 사용자는 복잡한 분산 시스템에서 트랜잭션을 모니터링하고 문제를 해결할 수 있습니다. Jaeger를 이용하면 개별 분산 트렌젝션에 대해서 각 구간별 응답 시간을 모니터링할 수 있어 문제 지점을 파악하는데 도움을 받을 수 있습니다.
Jaeger Install 펼치기jaeger.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: jaeger namespace: istio-system labels: app: jaeger spec: selector: matchLabels: app: jaeger template: metadata: labels: app: jaeger annotations: sidecar.istio.io/inject: "false" prometheus.io/scrape: "true" prometheus.io/port: "14269" spec: containers: - name: jaeger image: "docker.io/jaegertracing/all-in-one:1.18" env: - name: BADGER_EPHEMERAL value: "false" - name: SPAN_STORAGE_TYPE value: "badger" - name: BADGER_DIRECTORY_VALUE value: "/badger/data" - name: BADGER_DIRECTORY_KEY value: "/badger/key" - name: COLLECTOR_ZIPKIN_HTTP_PORT value: "9411" - name: MEMORY_MAX_TRACES value: "50000" - name: QUERY_BASE_PATH value: /jaeger livenessProbe: httpGet: path: / port: 14269 readinessProbe: httpGet: path: / port: 14269 volumeMounts: - name: data mountPath: /badger resources: requests: cpu: 10m volumes: - name: data emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: tracing namespace: istio-system labels: app: jaeger spec: type: LoadBalancer ports: - name: http-query port: 80 protocol: TCP targetPort: 16686 selector: app: jaeger --- # Jaeger implements the Zipkin API. To support swapping out the tracing backend, we use a Service named Zipkin. apiVersion: v1 kind: Service metadata: labels: name: zipkin name: zipkin namespace: istio-system spec: ports: - port: 9411 targetPort: 9411 name: http-query selector: app: jaeger
$ kubectl apply -f jaeger.yaml $ kubectl get svc tracing -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tracing LoadBalancer 10.100.210.106 aa34a215874bf4a33b8d27d4fdb1c1dd-696488506.ap-southeast-1.elb.amazonaws.com 80:32018/TCP 11m
Uninstall Istio
$ kubectl delete -f samples/addons $ istioctl manifest generate --set profile=demo | kubectl delete --ignore-not-found=true -f -
namespaces는 지워지지 않으므로 아래와 같이 수동으로 삭제합니다.
$ kubectl delete namespace istio-system
[참고]
- https://istio.io
- https://awskrug.github.io/eks-workshop/servicemesh_with_istio
- https://gruuuuu.github.io/cloud/service-mesh-istio
- https://sarc.io/index.php/cloud/1418-istio
- https://jason-lim.tistory.com/5