Netramesh - giải pháp lưới dịch vụ nhẹ

Khi chúng tôi chuyển từ ứng dụng nguyên khối sang kiến ​​trúc vi dịch vụ, chúng tôi phải đối mặt với những thách thức mới.

Trong một ứng dụng nguyên khối, việc xác định lỗi xảy ra ở phần nào của hệ thống thường khá dễ dàng. Rất có thể, vấn đề nằm ở mã của chính khối nguyên khối hoặc ở cơ sở dữ liệu. Nhưng khi chúng ta bắt đầu tìm kiếm vấn đề trong kiến ​​trúc microservice, mọi thứ không còn quá rõ ràng nữa. Chúng ta cần tìm toàn bộ đường dẫn mà yêu cầu đã thực hiện từ đầu đến cuối và chọn nó từ hàng trăm vi dịch vụ. Hơn nữa, nhiều trong số chúng còn có phương tiện lưu trữ riêng, điều này cũng có thể gây ra lỗi logic cũng như các vấn đề về hiệu suất và khả năng chịu lỗi.

Netramesh - giải pháp lưới dịch vụ nhẹ

Tôi đã tìm kiếm một công cụ có thể giúp giải quyết những vấn đề như vậy từ lâu (tôi đã viết về điều này trên Habré: 1, 2), nhưng cuối cùng tôi đã tạo ra giải pháp nguồn mở của riêng mình. Trong bài viết này, tôi nói về lợi ích của phương pháp lưới dịch vụ và chia sẻ một công cụ mới để triển khai nó.

Truy tìm phân tán là một giải pháp phổ biến cho vấn đề tìm kiếm lỗi trong hệ thống phân tán. Nhưng điều gì sẽ xảy ra nếu phương pháp thu thập thông tin về tương tác mạng này chưa được triển khai trong hệ thống, hoặc tệ hơn là một phần của hệ thống đã hoạt động bình thường, nhưng một phần thì không, vì nó chưa được thêm vào các dịch vụ cũ ? Để xác định chính xác nguyên nhân cốt lõi của vấn đề, cần có một bức tranh hoàn chỉnh về những gì đang xảy ra trong hệ thống. Điều đặc biệt quan trọng là phải hiểu những dịch vụ vi mô nào tham gia vào các lộ trình quan trọng trong kinh doanh.

Ở đây, cách tiếp cận lưới dịch vụ có thể hỗ trợ chúng ta, nó sẽ xử lý tất cả các máy thu thập thông tin mạng ở mức thấp hơn mức mà chính các dịch vụ đó vận hành. Cách tiếp cận này cho phép chúng tôi chặn tất cả lưu lượng truy cập và phân tích nó một cách nhanh chóng. Hơn nữa, các ứng dụng thậm chí không cần phải biết gì về nó.

Phương pháp tiếp cận lưới dịch vụ

Ý tưởng chính của cách tiếp cận lưới dịch vụ là thêm một lớp cơ sở hạ tầng khác qua mạng, điều này sẽ cho phép chúng ta thực hiện bất kỳ điều gì với sự tương tác giữa các dịch vụ. Hầu hết các hoạt động triển khai đều hoạt động như sau: một thùng chứa sidecar bổ sung có proxy minh bạch được thêm vào mỗi vi dịch vụ, qua đó tất cả lưu lượng truy cập đến và đi của dịch vụ đều được chuyển qua. Và đây chính là nơi chúng tôi có thể cân bằng khách hàng, áp dụng các chính sách bảo mật, áp đặt các hạn chế về số lượng yêu cầu và thu thập thông tin quan trọng về sự tương tác của các dịch vụ trong sản xuất.

Netramesh - giải pháp lưới dịch vụ nhẹ

Giải pháp

Hiện đã có một số triển khai phương pháp này: Istio и linkerd2. Họ cung cấp rất nhiều tính năng vượt trội. Nhưng đồng thời, có một chi phí lớn về tài nguyên. Hơn nữa, cụm mà hệ thống như vậy hoạt động càng lớn thì càng cần nhiều tài nguyên để duy trì cơ sở hạ tầng mới. Tại Avito, chúng tôi vận hành các cụm kubernetes chứa hàng nghìn phiên bản dịch vụ (và số lượng của chúng tiếp tục tăng nhanh). Trong quá trình triển khai hiện tại, Istio tiêu thụ ~300Mb RAM cho mỗi phiên bản dịch vụ. Do có nhiều khả năng, cân bằng minh bạch cũng ảnh hưởng đến thời gian phản hồi chung của dịch vụ (lên tới 10ms).

Do đó, chúng tôi đã xem xét chính xác những khả năng mà chúng tôi cần ngay bây giờ và quyết định rằng lý do chính khiến chúng tôi bắt đầu triển khai các giải pháp đó là khả năng thu thập thông tin truy tìm từ toàn bộ hệ thống một cách minh bạch. Chúng tôi cũng muốn có quyền kiểm soát sự tương tác của các dịch vụ và thực hiện nhiều thao tác khác nhau với các tiêu đề được chuyển giữa các dịch vụ.

Kết quả là chúng tôi đã đi đến quyết định:  Netramesh.

Netramesh

Netramesh là một giải pháp lưới dịch vụ nhẹ với khả năng mở rộng quy mô vô hạn, bất kể số lượng dịch vụ trong hệ thống.

Mục tiêu chính của giải pháp mới là chi phí tài nguyên thấp và hiệu suất cao. Trong số các tính năng chính, chúng tôi ngay lập tức muốn có thể gửi các khoảng thời gian theo dõi tới hệ thống Jaeger của mình một cách minh bạch.

Ngày nay, hầu hết các giải pháp đám mây đều được triển khai ở Golang. Và tất nhiên, có những lý do cho việc này. Việc viết các ứng dụng mạng bằng Golang hoạt động không đồng bộ với I/O và mở rộng quy mô trên các lõi khi cần rất thuận tiện và khá đơn giản. Và điều cũng rất quan trọng là hiệu suất đủ để giải quyết vấn đề này. Đó là lý do tại sao chúng tôi cũng chọn Golang.

Năng suất

Chúng tôi đã tập trung nỗ lực để đạt được năng suất tối đa. Đối với giải pháp được triển khai bên cạnh mỗi phiên bản của dịch vụ, cần phải tiêu thụ một lượng nhỏ RAM và thời gian CPU. Và tất nhiên, độ trễ phản hồi cũng phải nhỏ.

Hãy xem kết quả chúng ta nhận được là gì.

RAM

Netramesh tiêu thụ ~10Mb khi không có lưu lượng truy cập và tối đa 50Mb với tải lên tới 10000 RPS mỗi phiên bản.

Proxy đặc phái viên Istio luôn tiêu thụ ~300Mb trong các cụm của chúng tôi với hàng nghìn phiên bản. Điều này không cho phép nó được thu nhỏ lại cho toàn bộ cụm.

Netramesh - giải pháp lưới dịch vụ nhẹ

Netramesh - giải pháp lưới dịch vụ nhẹ

Với Netramesh, chúng tôi đã giảm được ~10 lần mức tiêu thụ bộ nhớ.

CPU

Việc sử dụng CPU tương đối bằng nhau khi tải. Nó phụ thuộc vào số lượng yêu cầu trên một đơn vị thời gian đối với sidecar. Giá trị ở mức 3000 yêu cầu mỗi giây ở mức cao nhất:

Netramesh - giải pháp lưới dịch vụ nhẹ

Netramesh - giải pháp lưới dịch vụ nhẹ

Còn một điểm quan trọng nữa: Netramesh - một giải pháp không có mặt phẳng điều khiển và không tải sẽ không tiêu tốn thời gian của CPU. Với Istio, sidecar luôn cập nhật điểm cuối dịch vụ. Kết quả là chúng ta có thể thấy hình ảnh này mà không cần tải:

Netramesh - giải pháp lưới dịch vụ nhẹ

Chúng tôi sử dụng HTTP/1 để liên lạc giữa các dịch vụ. Thời gian phản hồi của Istio tăng lên khi ủy quyền thông qua envoy lên tới 5-10ms, khá nhiều đối với các dịch vụ sẵn sàng phản hồi trong một phần nghìn giây. Với Netramesh thời gian này đã giảm xuống còn 0.5-2ms.

Khả năng mở rộng

Lượng tài nguyên nhỏ mà mỗi proxy tiêu thụ giúp có thể đặt nó bên cạnh mỗi dịch vụ. Netramesh được cố tình tạo ra mà không có thành phần mặt phẳng điều khiển chỉ để giữ cho mỗi sidecar nhẹ. Thông thường trong các giải pháp lưới dịch vụ, mặt phẳng điều khiển phân phối thông tin khám phá dịch vụ cho từng sidecar. Cùng với đó là thông tin về thời gian chờ và cài đặt cân bằng. Tất cả điều này cho phép bạn làm được rất nhiều điều hữu ích, nhưng thật không may, nó làm tăng kích thước của sidecar.

Khám phá dịch vụ

Netramesh - giải pháp lưới dịch vụ nhẹ

Netramesh không thêm bất kỳ cơ chế bổ sung nào để khám phá dịch vụ. Tất cả lưu lượng truy cập được ủy quyền một cách minh bạch thông qua netra sidecar.

Netramesh hỗ trợ giao thức ứng dụng HTTP/1. Để xác định nó, một danh sách các cổng có thể cấu hình được sử dụng. Thông thường, hệ thống có một số cổng để thực hiện giao tiếp HTTP. Ví dụ: chúng tôi sử dụng 80, 8890, 8080 để tương tác giữa các dịch vụ và yêu cầu bên ngoài. Trong trường hợp này, chúng có thể được đặt bằng biến môi trường. NETRA_HTTP_PORTS.

Nếu bạn sử dụng Kubernetes làm bộ điều phối và cơ chế thực thể Dịch vụ của nó để liên lạc nội bộ cụm giữa các dịch vụ thì cơ chế này vẫn giống hệt nhau. Đầu tiên, microservice lấy địa chỉ IP dịch vụ bằng kube-dns và mở kết nối mới tới địa chỉ đó. Kết nối này lần đầu tiên được thiết lập với netra-sidecar cục bộ và tất cả các gói TCP ban đầu đều đến netra. Tiếp theo, netra-sidecar thiết lập kết nối với đích ban đầu. NAT trên pod IP trên nút vẫn giống hệt như không có netra.

Theo dõi phân tán và chuyển tiếp ngữ cảnh

Netramesh cung cấp chức năng cần thiết để gửi các khoảng theo dõi về tương tác HTTP. Netra-sidecar phân tích giao thức HTTP, đo độ trễ yêu cầu và trích xuất thông tin cần thiết từ các tiêu đề HTTP. Cuối cùng, chúng tôi nhận được tất cả dấu vết trong một hệ thống Jaeger duy nhất. Để có cấu hình chi tiết hơn, bạn cũng có thể sử dụng các biến môi trường do thư viện chính thức cung cấp thư viện jaeger go.

Netramesh - giải pháp lưới dịch vụ nhẹ

Netramesh - giải pháp lưới dịch vụ nhẹ

Nhưng có một vấn đề. Cho đến khi các dịch vụ tạo và gửi tiêu đề uber đặc biệt, chúng tôi sẽ không thấy các khoảng theo dõi được kết nối trong hệ thống. Và đây chính là điều chúng ta cần để nhanh chóng tìm ra nguyên nhân của vấn đề. Ở đây một lần nữa Netramesh có một giải pháp. Proxy đọc tiêu đề HTTP và nếu chúng không chứa id theo dõi uber, hãy tạo một tiêu đề. Netramesh cũng lưu trữ thông tin về các yêu cầu đến và đi trong một sidecar và khớp chúng bằng cách làm phong phú chúng bằng các tiêu đề yêu cầu gửi đi cần thiết. Tất cả những gì bạn cần làm trong dịch vụ là chỉ gửi một tiêu đề X-Request-Id, có thể được cấu hình bằng biến môi trường NETRA_HTTP_REQUEST_ID_HEADER_NAME. Để kiểm soát kích thước của ngữ cảnh trong Netramesh, bạn có thể đặt các biến môi trường sau: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (thời gian mà bối cảnh sẽ được lưu trữ) và NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (tần suất dọn dẹp bối cảnh).

Cũng có thể kết hợp nhiều đường dẫn trên hệ thống của bạn bằng cách đánh dấu chúng bằng mã thông báo phiên đặc biệt. Netra cho phép bạn cài đặt HTTP_HEADER_TAG_MAP để biến các tiêu đề HTTP thành các thẻ khoảng theo dõi tương ứng. Điều này có thể đặc biệt hữu ích cho việc thử nghiệm. Sau khi vượt qua bài kiểm tra chức năng, bạn có thể xem phần nào của hệ thống bị ảnh hưởng khi lọc theo khóa phiên tương ứng.

Xác định nguồn yêu cầu

Để xác định yêu cầu đến từ đâu, bạn có thể sử dụng chức năng tự động thêm tiêu đề cùng với nguồn. Sử dụng biến môi trường NETRA_HTTP_X_SOURCE_HEADER_NAME Bạn có thể chỉ định tên tiêu đề sẽ được cài đặt tự động. Bằng cách sử dụng NETRA_HTTP_X_SOURCE_VALUE bạn có thể đặt giá trị mà tiêu đề X-Source sẽ được đặt cho tất cả các yêu cầu gửi đi.

Điều này cho phép việc phân phối tiêu đề hữu ích này được phân bố đồng đều trên toàn mạng. Sau đó, bạn có thể sử dụng nó trong các dịch vụ và thêm nó vào nhật ký cũng như số liệu.

Định tuyến lưu lượng truy cập và nội bộ Netramesh

Netramesh bao gồm hai thành phần chính. Đầu tiên, netra-init, đặt quy tắc mạng để chặn lưu lượng truy cập. Anh ta sử dụng quy tắc chuyển hướng iptables để chặn tất cả hoặc một phần lưu lượng truy cập trên sidecar, thành phần chính thứ hai của Netramesh. Bạn có thể định cấu hình cổng nào cần chặn cho các phiên TCP đến và đi: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Công cụ này còn có một tính năng thú vị - định tuyến xác suất. Nếu bạn chỉ sử dụng Netramesh để thu thập các khoảng theo dõi thì trong môi trường sản xuất, bạn có thể tiết kiệm tài nguyên và bật định tuyến xác suất bằng cách sử dụng các biến NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (từ 0 đến 1). Giá trị mặc định là 1 (tất cả lưu lượng truy cập đều bị chặn).

Sau khi chặn thành công, netra sidecar chấp nhận kết nối mới và sử dụng SO_ORIGINAL_DST tùy chọn socket để có được đích ban đầu. Netra sau đó sẽ mở một kết nối mới tới địa chỉ IP ban đầu và thiết lập giao tiếp TCP hai chiều giữa các bên, lắng nghe tất cả lưu lượng truy cập đi qua. Nếu cổng được xác định là HTTP, Netra sẽ cố gắng phân tích cú pháp và theo dõi cổng đó. Nếu phân tích cú pháp HTTP không thành công, Netra sẽ quay trở lại TCP và ủy quyền các byte một cách minh bạch.

Xây dựng biểu đồ phụ thuộc

Sau khi nhận được một lượng lớn thông tin truy tìm trong Jaeger, tôi muốn có được một biểu đồ hoàn chỉnh về các tương tác trong hệ thống. Nhưng nếu hệ thống của bạn được tải khá nhiều và hàng tỷ nhịp theo dõi tích lũy mỗi ngày thì việc tổng hợp chúng không phải là một nhiệm vụ dễ dàng. Có một cách chính thức để làm điều này: phụ thuộc vào tia lửa. Tuy nhiên, sẽ mất hàng giờ để xây dựng một biểu đồ hoàn chỉnh và buộc bạn phải tải xuống toàn bộ tập dữ liệu từ Jaeger trong 24 giờ qua.

Nếu bạn đang sử dụng Elaticsearch để lưu trữ các khoảng theo dõi, bạn có thể sử dụng một tiện ích Golang đơn giản, sẽ xây dựng cùng một biểu đồ trong vài phút bằng cách sử dụng các tính năng và khả năng của Elaticsearch.

Netramesh - giải pháp lưới dịch vụ nhẹ

Cách sử dụng Netramesh

Netra có thể dễ dàng được thêm vào bất kỳ dịch vụ nào đang chạy bất kỳ bộ điều phối nào. Bạn có thể xem một ví dụ đây.

Hiện tại, Netra chưa có khả năng tự động triển khai sidecar cho các dịch vụ nhưng đã có kế hoạch triển khai.

Tương lai của Netramesh

mục tiêu chính Netramesh là để đạt được chi phí tài nguyên tối thiểu và hiệu suất cao, cung cấp các khả năng cơ bản để quan sát và kiểm soát giao tiếp giữa các dịch vụ.

Trong tương lai, Netramesh sẽ hỗ trợ các giao thức lớp ứng dụng khác ngoài HTTP. Định tuyến L7 sẽ có sẵn trong tương lai gần.

Sử dụng Netramesh nếu bạn gặp phải vấn đề tương tự và viết thư cho chúng tôi nếu có câu hỏi và đề xuất.

Nguồn: www.habr.com

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