Microservices

Microservices: Từ Thiết Kế Đến Triển Khai – Phần 6: Chiến lược triển khai (Deployment Strategy) cho Microservices

Đây là bài viết thứ sáu trong loạt bài về Microservices: Từ Thiết Kế Đến Triển Khai. Trong bài đầu tiên, mô hình kiến trúc Microservices đã được giới thiệu và thảo luận về những ưu điểm và hạn chế trong việc ứng dụng và triển khai. Bài thứ hai mô tả về cách thức mà các client tương tác với các microservice thông qua một phương tiện trung gian gọi là API GatewayBài thứ ba tìm hiểu về cách mà các microservices trong cùng một hệ thống giao tiếp với nhau thông qua IPC (Inter-process Communication). Bài thứ tư chúng ta đã tìm hiểu qua về truy tìm service (Service Discovery). Bài thứ năm đã xem xét các vấn đề về quản lý dữ liệu phân tán trong kiến ​​trúc microservices. Trong bài viết này, hãy cùng xem xét các chiến lược để triển khai (deploy) các dịch vụ microservices.

(Các bạn có thể đọc bài viết gốc tiếng Anh tại đây: https://www.nginx.com/blog/deploying-microservices/)

Motivations

Triển khai một ứng dụng nguyên khối có nghĩa là chạy nhiều bản sao giống hệt nhau của một ứng dụng trên một hoặc nhiều máy chủ. Thường sẽ có N các máy chủ (vật lý hoặc ảo) và chạy M các instance của ứng dụng trên mỗi máy chủ. Việc triển khai ứng dụng nguyên khối không phải lúc nào cũng đơn giản, nhưng nó đơn giản hơn nhiều so với việc triển khai một ứng dụng microservices.

Một ứng dụng microservices bao gồm hàng chục hoặc thậm chí hàng trăm dịch vụ. Các dịch vụ được viết bằng nhiều ngôn ngữ và khuôn khổ khác nhau. Mỗi ứng dụng là một ứng dụng nhỏ với các yêu cầu về triển khai, tài nguyên, nhân rộng và theo dõi cụ thể của riêng mình. Ví dụ, bạn cần phải chạy một số lượng các instances nhất định của mỗi dịch vụ dựa trên nhu cầu cho dịch vụ đó. Ngoài ra, mỗi instances phải được cung cấp với các tài nguyên CPU, bộ nhớ và I/O thích hợp. Ngoài ra, việc triển khai các dịch vụ phải nhanh chóng, đáng tin cậy và hiệu quả về chi phí.

Dưới đây sẽ chỉ ra 3 cách triển khai microservice

Deploy nhiều loại service trên cùng một máy chủ

Khi sử dụng pattern này, bạn cung cấp một hoặc nhiều máy chủ vật lý hoặc ảo và chạy nhiều phiên bản dịch vụ trên mỗi máy chủ. Đây là cách tiếp cận truyền thống để triển khai ứng dụng. Mỗi cá thể dịch vụ chạy tại một cổng biết trước trên một hoặc nhiều máy chủ.
(Read more: http://microservices.io/patterns/deployment/multiple-services-per-host.html)

Sơ đồ sau đây cho thấy kiến trúc của pattern này.

1

Pattern này có cả lợi ích và nhược điểm. Một lợi ích lớn là việc sử dụng tài nguyên của nó là tương đối hiệu quả. Nhiều service instance chia sẻ máy chủ và hệ điều hành của nó. Nó thậm chí còn hiệu quả hơn nếu một process hoặc process group chạy nhiều cá thể dịch vụ, ví dụ nhiều ứng dụng web chia sẻ cùng một máy chủ Apache Tomcat và JVM.

Một lợi ích khác của pattern này là triển khai một cá thể dịch vụ tương đối nhanh. Bạn chỉ cần sao chép dịch vụ vào một máy chủ và khởi động nó. Nếu dịch vụ được viết bằng Java thì cần sao chép tệp JAR hoặc WAR. Đối với các ngôn ngữ khác, chẳng hạn như Node.js hoặc Ruby thì chỉ cần sao chép mã nguồn.

Ngoài ra, do không bị overhead nên việc khởi động một dịch vụ thường rất nhanh.

Tuy nhiên, pattern này cũng có một số hạn chế đáng kể. Một nhược điểm lớn là có rất ít hoặc không có sự cô lập của các cá thể dịch vụ, trừ khi mỗi cá thể dịch vụ là một tiến trình riêng biệt. Trong khi có thể giám sát chính xác việc sử dụng tài nguyên của từng cá thể dịch vụ, bạn không thể giới hạn các tài nguyên mà mỗi cá thể sử dụng. Có thể cho một service instance bị lỗi để tiêu thụ tất cả bộ nhớ hoặc CPU của máy chủ.

Một vấn đề quan trọng khác với phương pháp này là operations team triển khai dịch vụ phải biết chi tiết cụ thể về cách thức triển khai. Các dịch vụ có thể được viết bằng nhiều ngôn ngữ và khuôn khổ khác nhau, do đó có rất nhiều chi tiết mà nhóm phát triển phải chia sẻ với operations team. Sự phức tạp này làm tăng nguy cơ lỗi trong quá trình triển khai.

Như bạn thấy, mặc dù pattern này khá quen thuộc nhưng lại có một số hạn chế đáng kể. Bây giờ chúng ta hãy xem xét các cách triển khai các dịch vụ microservices khác để tránh những vấn đề này.

Deploy chỉ duy nhất 1 loại service lên máy chủ

Khi sử dụng pattern này, bạn chạy từng cá thể dịch vụ riêng biệt trên máy chủ riêng của nó. Có hai cách: mỗi service instance trong một máy ảo (VM) hoặc mỗi service instance trong một Container.

(Read more: http://microservices.io/patterns/deployment/single-service-per-host.html)

Mỗi service instance trong một máy ảo

Khi sử dụng pattern mỗi service instance trong một máy ảo, bạn đóng gói từng dịch vụ dưới dạng một máy ảo image như Amazon EC2 AMI. Mỗi cá thể dịch vụ là một máy ảo (ví dụ, một cá thể EC2) được khởi chạy bằng cách sử dụng VM image đó.

(Read more: http://microservices.io/patterns/deployment/service-per-vm.html)

Sơ đồ sau đây cho thấy cấu trúc của pattern này:

2

Đây là phương pháp chính được Netflix sử dụng để triển khai dịch vụ phát trực tuyến video của mình. Netflix gói mỗi dịch vụ của nó thành các AMI EC2 sử dụng Aminator. Mỗi cá thể dịch vụ đang chạy là một cá thể EC2.

Có một số công cụ có thể sử dụng để xây dựng các máy ảo của riêng bạn. Bạn có thể cấu hình continuous integration (CI) server (ví dụ, Jenkins) để gọi Aminator đóng gói các dịch vụ thành các AMI EC2. Packer.io là một tùy chọn khác để tạo VM image tự động. Không giống như Aminator, nó hỗ trợ nhiều công nghệ ảo hóa bao gồm EC2, DigitalOcean, VirtualBox và VMware.

Công ty Boxfuse có một cách để xây dựng VM image, vượt qua những hạn chế của máy ảo. Boxfuse gói ứng dụng Java thành một VM image tối thiểu. Những image này rất nhanh để xây dựng, khởi động nhanh và an toàn hơn.

Công ty CloudNative có Bakery, một sản phẩm SaaS để tạo ra EC2 AMIs. Có thể cấu hình máy chủ CI để gọi Bakery để đóng gói dịch vụ thành một AMI, giúp bạn không phải lãng phí thời gian quý báu khi thiết lập cơ sở hạ tầng tạo AMI.

Một lợi ích chính của VM là mỗi cá thể dịch vụ chạy trong sự cô lập hoàn toàn. Nó có một số lượng cố định của CPU và bộ nhớ và không thể lấy tài nguyên từ các dịch vụ khác.

Một lợi ích khác là có thể tận dụng cơ sở hạ tầng đám mây. Các đám mây như AWS cung cấp các tính năng hữu ích như cân bằng tải và tự động tính toán.

Một lợi ích to lớn khác nữa là nó đóng gói công nghệ triển khai dịch vụ. Một khi một dịch vụ đã được đóng gói như một máy ảo, nó sẽ trở thành một black-box. VM’s management API trở thành API để triển khai dịch vụ. Triển khai trở nên đơn giản và đáng tin cậy hơn nhiều.

Tuy nhiên nó cũng có một số hạn chế. Một nhược điểm là sử dụng tài nguyên kém hiệu quả hơn. Mỗi cá thể dịch vụ có phí trên toàn bộ máy ảo, bao gồm cả hệ điều hành. Hơn nữa, trong một public IaaS điển hình, các máy ảo có kích thước cố định và có thể máy ảo sẽ không được sử dụng đúng mức.

Nữa là, một public IaaS thường tính phí cho máy ảo bất kể là nó có được xài hay không. IaaS của AWS cung cấp tính năng tự động tính toán nhưng rất khó để phản ứng nhanh chóng với những thay đổi về nhu cầu. Do đó, bạn thường phải dự phòng thêm máy ảo và điều đó sẽ làm tăng chi phí triển khai.

Một nhược điểm khác của phương pháp này là triển khai phiên bản dịch vụ mới thường chậm. VM image build rất chậm do kích thước của chúng. Ngoài ra, các máy ảo cũng chậm khi khởi động lại. Ngoài ra, một hệ điều hành thường tốn thời gian để khởi động. Tuy nhiên, lưu ý rằng điều này không đúng hoàn toàn, bạn có thể sử dụng Boxfuse để giải quyết các vấn đề đó.

Một nhược điểm khác của việc triển khai mỗi service instance trong một máy ảo là bạn (hoặc một người nào đó trong tổ chức) phải làm thêm rất nhiều công việc về xây dựng và quản lý máy ảo. Trừ khi bạn sử dụng công cụ như Boxfuse xử lý cho việc xây dựng và quản lý các máy ảo, còn không thì đó là trách nhiệm của bạn. Việc này là cần thiết nhưng sẽ gây tốn nhiều thời gian trong việc xây dựng ứng dụng chính.

Bây giờ chúng ta hãy xem xét một cách khác để triển khai các dịch vụ nhẹ nhàng hơn nhưng vẫn có nhiều lợi ích của các máy ảo.

Mỗi service instance trong một Container

Mỗi cá thể dịch vụ chạy trong container riêng của nó. Container là một cơ chế ảo hóa ở cấp hệ điều hành. Container bao gồm một hoặc nhiều process chạy trong hộp sandbox. Từ quan điểm của các process, chúng có không gian port và hệ thống tập tin root filesystem riêng của chúng. Có thể giới hạn bộ nhớ và tài nguyên CPU của container. Ví dụ về công nghệ container bao gồm DockerSolaris Zones.

(Read more: http://microservices.io/patterns/deployment/service-per-container.html)

Sơ đồ sau đây cho thấy cấu trúc của pattern này:

3

Để sử dụng pattern này, bạn đóng gói dịch vụ của mình dưới dạng container image. Container image là hình ảnh hệ thống tệp bao gồm các ứng dụng và thư viện cần thiết để chạy dịch vụ. Một số container image bao gồm một hệ thống tập tin Linux hoàn chỉnh. Những image khác sẽ nhẹ hơn. Để triển khai một dịch vụ Java, bạn xây dựng một container image chứa Java runtime, một máy chủ Apache Tomcat và ứng dụng Java đã biên dịch.

Khi đóng gói dịch vụ của mình dưới dạng container image, bạn sẽ khởi chạy một hoặc nhiều container. Bạn thường chạy nhiều container trên mỗi máy chủ ảo hoặc vật lý. Có thể sử dụng trình quản lý cluster như Kubernetes hoặc Marathon để quản lý container của mình. Cluster manager xử lý các máy chủ như một nhóm tài nguyên. Nó quyết định vị trí đặt từng container dựa trên các tài nguyên theo yêu cầu của container và tài nguyên có sẵn trên mỗi máy chủ lưu trữ.

Pattern này có cả lợi ích và hạn chế. Lợi ích của các container tương tự như của các máy ảo. Chúng tách biệt các cá thể dịch vụ của bạn với nhau. Bạn có thể dễ dàng theo dõi các tài nguyên được tiêu thụ bởi mỗi container. Ngoài ra, giống như các máy ảo, các container đóng gói công nghệ được sử dụng để triển khai các dịch vụ. API quản lý container cũng hoạt động như API để quản lý dịch vụ của bạn.

Tuy nhiên, không giống như các máy ảo, các container nhẹ hơn nhiều. Build các container image rất nhanh. Ví dụ, trên máy tính xách tay của tôi chỉ tốn khoảng là 5 giây để đóng gói một ứng dụng Spring Boot dưới dạng một container Docker. Các container cũng khởi động rất nhanh vì không cần khởi động hệ điều hành. Khi một container start, các dịch vụ sẽ được start ngay lập tức.

Có một số nhược điểm khi sử dụng các container. Đó là công nghệ này chưa ổn định như máy ảo. Ngoài ra, các container không an toàn như các máy ảo vì các chúng chia sẻ kernel của hệ điều hành chủ với nhau.

Một nhược điểm khác của các container là bạn chịu trách nhiệm cho việc quản lý các container image. Ngoài ra, trừ khi bạn đang sử dụng một giải pháp lưu trữ container như Google Container Engine hoặc Amazon EC2 Container Service (ECS), thì bạn phải quản lý cơ sở hạ tầng container và có thể là cả cơ sở hạ tầng VM mà nó chạy.

Ngoài ra, các container thường được triển khai trên cơ sở hạ tầng có định giá theo từng VM. Do đó, như đã mô tả ở trên, bạn có thể sẽ phải trả thêm chi phí cho các máy ảo quá mức để xử lý các tải đột biến.

Thật thú vị, sự khác biệt giữa các container và máy ảo có vẻ như đang bị xóa bỏ. Như đã đề cập trước đó, các máy ảo Boxfuse rất nhanh để build và start. Dự án Clear Containers nhằm tạo ra các máy ảo nhẹ. Docker, Inc. gần đây đã mua lại Unikernel Systems nhằm cải tiến việc xây dựng các image nhanh hơn và nhẹ hơn.

Ngoài ra còn có khái niệm mới hơn và ngày càng phổ biến như server-less deployment, đó là một cách tiếp cận để tránh sự cố phải chọn giữa triển khai dịch vụ trong các container hoặc máy ảo. Hãy cùng xem xét.

Serverless Deployment

AWS Lambda là một dịch vụ tính toán nơi mà bạn có thể upload code của mình lên, và dịch vụ AWS Lambda sẽ giúp bạn chạy đoạn code đó bằng việc sử dụng các tài nguyên sẵn có của AWS. Sau khi bạn upload code, và bạn tạo ra một Lambda function, AWS sẽ cung cấp và quản lý các server mà bạn sử dụng để chạy code. Về phần sử dụng AWS, bạn có thể làm như sau:

Một dịch vụ tính toán hướng sự kiện nơi mà AWS Lambda chạy code của bạn và trả về các sự kiện, những thay đổi về data được đẩy vào một bucket của Amazon S3 hoặc là một bảng của Amazon DynamoDB. ( bạn có thể tìm hiểu thêm về Amazon DynamoDB)

Dịch vụ tính toán để chạy code và sẽ trả về các HTTP request sử dụng Amazon API Gateway hoặc API dùng đến AWS SDKs.

AWS Lambda sẽ chạy code mà bạn upload trên môi trường có tính sẵn sàng cao và vận hành với quyền cao nhất đối với các tài nguyên tính toán, bao gồm server và hệ điều hành. Những gì bạn cần làm là chắc chắn code thuộc một trong những ngôn ngữ mà AWS Lambda đang hỗ trợ: Node.js, Java, Python.

Để vận hành code được tốt nhất, bạn có thể tham khảo cách xác định và tính toán tài nguyên cần dùng cho AWS Lambda tại Xác định tài nguyên cho AWS Lambda

AWS Lambda chỉ thực hiện code của bạn chỉ khi cần thiết, và được mở rộng một cách tự động, từ một vài request đến hàng ngàn request/ giây. Với khả năng đó, bạn có thể sử dụng Lambda dễ dàng để build dữ liệu cho các dịch vụ AWS S3 và Amazon DynamoDB, luồng xử lý dữ liệu trong Amazon Kinesis hoặc tạo back end riêng mà AWS thực hiện có quy mô, năng suất và bảo mật.

AWS Lambda tự động chạy đủ các phiên bản của microservice của bạn để xử lý các yêu cầu. Bạn chỉ đơn giản là thanh toán cho mỗi yêu cầu dựa trên thời gian thực hiện và bộ nhớ được tiêu thụ. Tất nhiên, đi sâu vào các chi tiết và bạn sẽ thấy ngay rằng AWS Lambda có những hạn chế. Nhưng quan điểm cho rằng cả bạn lẫn nhà phát triển cũng như bất kỳ ai trong tổ chức của bạn cũng không cần lo lắng về bất kỳ khía cạnh nào của máy chủ, máy ảo hoặc container đều hấp dẫn.

Đọc thêm về AWS Lamba tại đây:
https://viblo.asia/p/gioi-thieu-ve-aws-lambda-mot-dich-vu-cua-amazon-l5XRBJD4RqPe

Tóm lược

Triển khai một ứng dụng microservices là một thách thức. Có hàng chục hoặc thậm chí hàng trăm dịch vụ được viết bằng nhiều ngôn ngữ và khuôn khổ khác nhau. Mỗi ứng dụng là một ứng dụng nhỏ với các yêu cầu triển khai, tài nguyên, nhân rộng và theo dõi cụ thể của riêng mình. Có một số pattern triển khai dịch vụ microservice bao gồm mỗi Service Instance trong mỗi máy ảo và mỗi Service Instance trong mỗi Container. Một lựa chọn hấp dẫn khác để triển khai các dịch vụ nhỏ là AWS Lambda, một cách tiếp cận không có máy chủ (Serverless). Trong phần tiếp theo và cuối cùng của loạt bài này, chúng ta sẽ xem xét cách chuyển đổi một ứng dụng nguyên khối thành microservices.

Read more:
https://www.nginx.com/blog/deploying-microservices/

Đây là loạt bài viết về Microservices mình đã đọc, đúc kết và sưu tầm được trong quá trình tìm hiểu về nó. Hi vọng nó cũng giúp ích được cho bạn trong quá trình architecture design và deploy các ứng dụng microservices.

Tổng hợp và dịch by edwardthienhoang

1 thought on “Microservices: Từ Thiết Kế Đến Triển Khai – Phần 6: Chiến lược triển khai (Deployment Strategy) cho Microservices”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.