Quay lại microservice với Istio. Phần 2

Quay lại microservice với Istio. Phần 2

Ghi chú. bản dịch.: Phần đầu tiên Loạt bài này được dành riêng để giới thiệu các khả năng của Istio và thể hiện chúng trong thực tế. Bây giờ chúng ta sẽ nói về các khía cạnh phức tạp hơn của cấu hình và cách sử dụng lưới dịch vụ này, đặc biệt là về việc định tuyến và quản lý lưu lượng mạng được tinh chỉnh.

Chúng tôi cũng xin nhắc bạn rằng bài viết sử dụng cấu hình (tệp kê khai cho Kubernetes và Istio) từ kho lưu trữ làm chủ istio.

Quản lý giao thông

Với Istio, các khả năng mới xuất hiện trong cụm để cung cấp:

  • Định tuyến yêu cầu động: triển khai canary, thử nghiệm A/B;
  • Cân bằng tải: đơn giản và nhất quán, dựa trên giá trị băm;
  • Phục hồi sau vấp ngã: hết thời gian chờ, thử lại, ngắt mạch;
  • Chèn lỗi: sự chậm trễ, yêu cầu bị loại bỏ, v.v.

Khi bài viết tiếp tục, những khả năng này sẽ được minh họa bằng ứng dụng đã chọn làm ví dụ và các khái niệm mới sẽ được giới thiệu trong quá trình thực hiện. Khái niệm đầu tiên như vậy sẽ là DestinationRules (tức là các quy tắc về người nhận lưu lượng truy cập/yêu cầu - bản dịch xấp xỉ), với sự trợ giúp của nó, chúng tôi kích hoạt thử nghiệm A/B.

Thử nghiệm A/B: Quy tắc đích trong thực tế

Thử nghiệm A/B được sử dụng trong trường hợp có hai phiên bản của một ứng dụng (thường chúng khác nhau về mặt hình ảnh) và chúng tôi không chắc chắn 100% phiên bản nào sẽ cải thiện trải nghiệm người dùng. Do đó, chúng tôi chạy đồng thời cả hai phiên bản và thu thập số liệu.

Để triển khai phiên bản thứ hai của giao diện người dùng, cần thiết để trình diễn thử nghiệm A/B, hãy chạy lệnh sau:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

Tệp kê khai triển khai cho phiên bản màu xanh lá cây khác nhau ở hai chỗ:

  1. Hình ảnh dựa trên một thẻ khác - istio-green,
  2. Vỏ có nhãn version: green.

Vì cả hai quá trình triển khai đều có nhãn app: sa-frontend,các yêu cầu được định tuyến bằng dịch vụ ảo sa-external-services cho dịch vụ sa-frontend, sẽ được chuyển hướng đến tất cả các phiên bản của nó và tải sẽ được phân phối thông qua thuật toán quay vòng, sẽ dẫn đến tình trạng sau:

Quay lại microservice với Istio. Phần 2
Không tìm thấy tập tin được yêu cầu

Không tìm thấy những tệp này vì chúng được đặt tên khác nhau trong các phiên bản khác nhau của ứng dụng. Hãy đảm bảo điều này:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

Nó có nghĩa là index.html, yêu cầu một phiên bản của tệp tĩnh, có thể được bộ cân bằng tải gửi đến các nhóm có phiên bản khác, trong đó, vì lý do rõ ràng, các tệp đó không tồn tại. Do đó, để ứng dụng có thể hoạt động, chúng ta cần đặt ra hạn chế: “cùng một phiên bản ứng dụng đã phân phát index.html sẽ phân phát các yêu cầu tiếp theo'.

Chúng tôi sẽ đạt được điều đó bằng cách cân bằng tải dựa trên hàm băm nhất quán (Cân bằng tải băm nhất quán)... Trong trường hợp này yêu cầu từ cùng một khách hàng được gửi đến cùng một phiên bản phụ trợ, trong đó sử dụng thuộc tính được xác định trước - ví dụ: tiêu đề HTTP. Được triển khai bằng cách sử dụng DestinationRules.

Quy tắc đích

Sau khi Dịch vụ ảo đã gửi yêu cầu đến dịch vụ mong muốn, bằng cách sử dụng DestinationRules, chúng tôi có thể xác định các chính sách sẽ được áp dụng cho lưu lượng truy cập dành cho các phiên bản của dịch vụ này:

Quay lại microservice với Istio. Phần 2
Quản lý lưu lượng truy cập với tài nguyên Istio

Ghi: Tác động của tài nguyên Istio đến lưu lượng mạng được trình bày ở đây một cách dễ hiểu. Nói chính xác, quyết định gửi yêu cầu đến phiên bản nào sẽ được đưa ra bởi Envoy trong Cổng vào được định cấu hình trong CRD.

Với Quy tắc đích, chúng tôi có thể định cấu hình cân bằng tải để sử dụng hàm băm nhất quán và đảm bảo rằng cùng một phiên bản dịch vụ phản hồi cho cùng một người dùng. Cấu hình sau cho phép bạn đạt được điều này (Destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 - hàm băm sẽ được tạo dựa trên nội dung của tiêu đề HTTP version.

Áp dụng cấu hình bằng lệnh sau:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

Bây giờ hãy chạy lệnh bên dưới và đảm bảo bạn nhận được đúng tệp khi chỉ định tiêu đề version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

Ghi: Để thêm các giá trị khác nhau vào tiêu đề và kiểm tra kết quả trực tiếp trên trình duyệt, bạn có thể sử dụng phần mở rộng này tới Chrome (hoặc Với cái này dành cho Firefox - khoảng. dịch.).

Nhìn chung, DestinationRules có nhiều khả năng hơn trong lĩnh vực cân bằng tải - hãy kiểm tra chi tiết trong tài liệu chính thức.

Trước khi nghiên cứu sâu hơn về VirtualService, hãy xóa “phiên bản xanh” của ứng dụng và quy tắc hướng giao thông tương ứng bằng cách chạy các lệnh sau:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted

Phản chiếu: Dịch vụ ảo trong thực tế

Bóng (“che chắn”) hoặc Phản ánh (“phản chiếu”) được sử dụng trong trường hợp chúng tôi muốn thử nghiệm một thay đổi trong quá trình sản xuất mà không ảnh hưởng đến người dùng cuối: để thực hiện việc này, chúng tôi sao chép các yêu cầu (“sao chép”) sang phiên bản thứ hai nơi các thay đổi mong muốn đã được thực hiện và xem xét hậu quả. Nói một cách đơn giản, đây là khi đồng nghiệp của bạn chọn vấn đề quan trọng nhất và đưa ra yêu cầu kéo dưới dạng một đống rác khổng lồ mà không ai có thể thực sự xem xét được.

Để kiểm tra kịch bản này trong thực tế, hãy tạo phiên bản SA-Logic thứ hai có lỗi (buggy) bằng cách chạy lệnh sau:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

Và bây giờ hãy chạy lệnh để đảm bảo rằng tất cả các phiên bản có app=sa-logic Họ cũng có nhãn với các phiên bản tương ứng:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

Dịch vụ sa-logic nhắm mục tiêu nhóm có nhãn app=sa-logic, vì vậy tất cả các yêu cầu sẽ được phân phối giữa tất cả các phiên bản:

Quay lại microservice với Istio. Phần 2

... nhưng chúng tôi muốn gửi yêu cầu đến phiên bản v1 và được phản ánh sang phiên bản v2:

Quay lại microservice với Istio. Phần 2

Chúng tôi sẽ đạt được điều này thông qua VirtualService kết hợp với DestinationRule, trong đó các quy tắc sẽ xác định các tập hợp con và tuyến đường của VirtualService đến một tập hợp con cụ thể.

Xác định tập hợp con trong quy tắc đích

Tập hợp con (tập hợp con) được xác định bởi cấu hình sau (sa-logic-tập hợp con-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. Chủ nhà (host) định nghĩa rằng quy tắc này chỉ áp dụng cho trường hợp tuyến đường đi về phía dịch vụ sa-logic;
  2. Tiêu đề (name) các tập hợp con được sử dụng khi định tuyến đến các phiên bản tập hợp con;
  3. Nhãn (label) xác định các cặp khóa-giá trị mà các phiên bản phải khớp để trở thành một phần của tập hợp con.

Áp dụng cấu hình bằng lệnh sau:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic created

Bây giờ các tập hợp con đã được xác định, chúng ta có thể tiếp tục và định cấu hình VirtualService để áp dụng các quy tắc cho các yêu cầu đối với sa-logic để chúng:

  1. Được định tuyến đến một tập hợp con v1,
  2. Được nhân đôi thành một tập hợp con v2.

Bản tuyên ngôn sau đây cho phép bạn đạt được kế hoạch của mình (sa-logic-tập hợp con-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

Không cần giải thích ở đây, vì vậy hãy xem nó hoạt động như thế nào:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created

Hãy thêm tải bằng cách gọi lệnh sau:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "I love yogobella"}'; 
    sleep .8; done

Hãy xem kết quả trong Grafana, nơi bạn có thể thấy phiên bản có lỗi (buggy) không thành công đối với ~60% yêu cầu, nhưng không có lỗi nào trong số này ảnh hưởng đến người dùng cuối khi họ được một dịch vụ đang chạy phản hồi.

Quay lại microservice với Istio. Phần 2
Phản hồi thành công của các phiên bản khác nhau của dịch vụ sa-logic

Ở đây, lần đầu tiên chúng ta thấy cách VirtualService được áp dụng cho các Đặc phái viên của dịch vụ của chúng ta: khi sa-web-app đưa ra yêu cầu sa-logic, nó đi qua Envoy sidecar, - thông qua VirtualService - được định cấu hình để định tuyến yêu cầu đến tập hợp con v1 và phản ánh yêu cầu tới tập hợp con v2 của dịch vụ sa-logic.

Tôi biết, có thể bạn đã nghĩ rằng Dịch vụ ảo rất đơn giản. Trong phần tiếp theo, chúng tôi sẽ mở rộng điều đó bằng cách nói rằng chúng cũng thực sự tuyệt vời.

Triển khai Canary

Triển khai Canary là quá trình triển khai phiên bản mới của ứng dụng cho một số ít người dùng. Nó được sử dụng để đảm bảo rằng không có vấn đề gì trong quá trình phát hành và chỉ sau đó, đã tự tin vào chất lượng (của bản phát hành) của nó, mới phân phối nó cho những người dùng khác.оlượng khán giả lớn hơn.

Để chứng minh việc triển khai canary, chúng tôi sẽ tiếp tục làm việc với một tập hợp con buggy у sa-logic.

Chúng ta đừng lãng phí thời gian vào những chuyện vặt vãnh và ngay lập tức gửi 20% người dùng đến phiên bản có lỗi (điều này sẽ thể hiện việc triển khai chim hoàng yến của chúng tôi) và 80% còn lại chuyển sang dịch vụ thông thường. Để thực hiện việc này, hãy sử dụng VirtualService sau (sa-logic-tập hợp con-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 là trọng lượng (weight), chỉ định tỷ lệ phần trăm yêu cầu sẽ được chuyển hướng đến người nhận hoặc một tập hợp con của người nhận.

Hãy cập nhật cấu hình VirtualService trước đó cho sa-logic bằng lệnh sau:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

... và chúng ta sẽ thấy ngay rằng một số yêu cầu dẫn đến lỗi:

$ while true; do 
   curl -i http://$EXTERNAL_IP/sentiment 
   -H "Content-type: application/json" 
   -d '{"sentence": "I love yogobella"}' 
   --silent -w "Time: %{time_total}s t Status: %{http_code}n" 
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500

Dịch vụ ảo cho phép triển khai canary: Trong trường hợp này, chúng tôi đã thu hẹp tác động tiềm ẩn của sự cố xuống còn 20% cơ sở người dùng. Tuyệt vời! Bây giờ, trong mọi trường hợp khi chúng tôi không chắc chắn về mã của mình (nói cách khác - luôn luôn...), chúng tôi có thể sử dụng phản chiếu và triển khai canary.

Hết thời gian chờ và thử lại

Nhưng lỗi không phải lúc nào cũng xuất hiện trong mã. Trong danh sách từ "8 quan niệm sai lầm về máy tính phân tán“Đầu tiên là niềm tin sai lầm rằng “mạng lưới đáng tin cậy”. Trong thực tế mạng không đáng tin cậy và vì lý do này chúng tôi cần thời gian chờ (hết thời gian) và thử lại (thử lại).

Để trình diễn, chúng tôi sẽ tiếp tục sử dụng phiên bản có vấn đề tương tự sa-logic (buggy) và chúng tôi sẽ mô phỏng tính không đáng tin cậy của mạng với các lỗi ngẫu nhiên.

Hãy để dịch vụ có lỗi của chúng tôi có 1/3 cơ hội mất quá nhiều thời gian để phản hồi, 1/3 cơ hội kết thúc với Lỗi Máy chủ Nội bộ và 1/3 cơ hội trả lại trang thành công.

Để giảm thiểu tác động của những vấn đề như vậy và giúp cuộc sống của người dùng tốt hơn, chúng tôi có thể:

  1. thêm thời gian chờ nếu dịch vụ mất hơn 8 giây để phản hồi,
  2. thử lại nếu yêu cầu không thành công.

Để triển khai, chúng tôi sẽ sử dụng định nghĩa tài nguyên sau (sa-logic-retries-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. Thời gian chờ cho yêu cầu được đặt thành 8 giây;
  2. Yêu cầu được thử lại 3 lần;
  3. Và mỗi lần thử được coi là không thành công nếu thời gian phản hồi vượt quá 3 giây.

Đây là một sự tối ưu hóa vì người dùng sẽ không phải đợi quá 8 giây và chúng tôi sẽ thực hiện ba lần thử mới để nhận được phản hồi trong trường hợp thất bại, tăng cơ hội phản hồi thành công.

Áp dụng cấu hình cập nhật bằng lệnh sau:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

Và kiểm tra biểu đồ Grafana để biết số lượng phản hồi thành công đã tăng lên ở trên:

Quay lại microservice với Istio. Phần 2
Những cải tiến về thống kê phản hồi thành công sau khi thêm thời gian chờ và thử lại

Trước khi chuyển sang phần tiếp theo (hay đúng hơn là đến phần tiếp theo của bài viết, vì trong phần này sẽ không còn thí nghiệm thực tế nào nữa - khoảng.), xóa bỏ sa-logic-buggy và VirtualService bằng cách chạy các lệnh sau:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

Mẫu ngắt mạch và vách ngăn

Chúng ta đang nói về hai mẫu quan trọng trong kiến ​​trúc microservice cho phép bạn đạt được khả năng tự phục hồi (tự chữa lành) dịch vụ.

Ngắt mạch ("ngắt mạch") được sử dụng để chấm dứt các yêu cầu đến một phiên bản của dịch vụ được coi là không tốt và khôi phục nó trong khi các yêu cầu của khách hàng được chuyển hướng đến các phiên bản tốt của dịch vụ đó (điều này làm tăng tỷ lệ phản hồi thành công). (Lưu ý: Có thể tìm thấy mô tả chi tiết hơn về mẫu, ví dụ: đây.)

Vách ngăn ("vách ngăn") cách ly các lỗi dịch vụ khỏi ảnh hưởng đến toàn bộ hệ thống. Ví dụ: Dịch vụ B bị hỏng và một dịch vụ khác (máy khách của Dịch vụ B) đưa ra yêu cầu tới Dịch vụ B, khiến dịch vụ này cạn kiệt nhóm luồng và không thể phục vụ các yêu cầu khác (ngay cả khi chúng không đến từ Dịch vụ B). (Lưu ý: Có thể tìm thấy mô tả chi tiết hơn về mẫu, ví dụ: đây.)

Tôi sẽ bỏ qua chi tiết triển khai của các mẫu này vì chúng dễ tìm thấy trong tài liệu chính thức, và tôi cũng thực sự muốn hiển thị xác thực và ủy quyền, điều này sẽ được thảo luận trong phần tiếp theo của bài viết.

Tái bút từ người dịch

Đọc thêm trên blog của chúng tôi:

Nguồn: www.habr.com

Thêm một lời nhận xét