Kiến trúc tốt nhất với Docker và Kubernetes - huyền thoại hay hiện thực?

Thế giới phát triển phần mềm đã thay đổi như thế nào trong kỷ nguyên của Docker và Kubernetes? Có thể xây dựng một kiến ​​trúc một lần và mãi mãi bằng cách sử dụng các công nghệ này? Có thể thống nhất các quá trình phát triển và tích hợp khi tất cả mọi thứ đều được đóng gói trong các thùng chứa? Các yêu cầu cho các quyết định như vậy là gì? Những hạn chế nào họ đưa vào chơi? Họ sẽ làm cho cuộc sống của các nhà phát triển dễ dàng hơn hay, thay vào đó, thêm các biến chứng không cần thiết vào nó?

Nó thời gian để làm sáng tỏ những câu hỏi này (và một số khác)! (Trong văn bản và minh họa gốc.)

Bài viết này sẽ đưa bạn vào một hành trình từ đời thực đến quá trình phát triển đến kiến ​​trúc và trở lại cuộc sống thực, đưa ra câu trả lời cho những câu hỏi quan trọng nhất ở mỗi điểm dừng trên đường đi. Chúng tôi sẽ cố gắng xác định một số thành phần và nguyên tắc sẽ trở thành một phần của kiến ​​trúc và trình bày một vài ví dụ mà không đi sâu vào lĩnh vực thực hiện chúng.

Kết luận của bài viết có thể gây khó chịu hoặc làm hài lòng bạn. Tất cả phụ thuộc vào kinh nghiệm của bạn, nhận thức của bạn về câu chuyện ba chương này và có lẽ cả tâm trạng của bạn tại thời điểm đọc. Hãy cho tôi biết những gì bạn nghĩ bằng cách đăng bình luận hoặc câu hỏi dưới đây!

Từ cuộc sống thực đến quy trình phát triển

Đối với hầu hết các phần, tất cả các quy trình phát triển mà tôi từng thấy hoặc vinh dự được thiết lập đều phục vụ một mục tiêu đơn giản - giảm thời gian giữa lúc đưa ra ý tưởng và đưa nó vào sản xuất, trong khi vẫn duy trì một mức độ nhất định về chất lượng mã.

Nó không quan trọng cho dù ý tưởng đó là tốt hay xấu. Những ý tưởng tồi tệ đến và đi nhanh chóng - bạn chỉ cần thử chúng và biến chúng xuống để tan rã. Điều đáng nói ở đây là việc quay trở lại từ một ý tưởng tồi tệ rơi vào vai một con robot tự động hóa quy trình làm việc của bạn.

Tích hợp và phân phối liên tục có vẻ như một sự cứu rỗi trong thế giới phát triển phần mềm. Điều gì có thể đơn giản hơn thế, sau tất cả? Bạn có một ý tưởng, bạn có mã, vì vậy hãy đi cho nó! Nó sẽ hoàn hảo nếu không phải là một vấn đề nhỏ - quá trình tích hợp và phân phối khá khó khăn để chính thức hóa tách biệt với các quy trình công nghệ và kinh doanh dành riêng cho công ty của bạn.

Tuy nhiên, mặc dù nhiệm vụ có vẻ phức tạp, cuộc sống liên tục ném vào những ý tưởng tuyệt vời mang lại cho chúng ta (chắc chắn là bản thân tôi) gần hơn một chút để xây dựng một cơ chế hoàn hảo có thể hữu ích trong hầu hết mọi trường hợp. Bước gần đây nhất đối với cơ chế như vậy đối với tôi là Docker và Kubernetes, với mức độ trừu tượng và cách tiếp cận ý thức hệ khiến tôi nghĩ rằng 80% các vấn đề hiện nay có thể được giải quyết bằng các phương pháp thực tế giống nhau.

20% còn lại rõ ràng đã không đi đâu cả. Nhưng đây chính xác là nơi bạn có thể tập trung thiên tài sáng tạo bên trong của mình vào công việc thú vị, thay vì xử lý các công việc thường xuyên lặp đi lặp lại. Chăm sóc khung kiến ​​trúc của thành phố, chỉ một lần sẽ giúp bạn quên đi 80% các vấn đề được giải quyết.

Tất cả những điều này có ý nghĩa gì, và Docker giải quyết chính xác các vấn đề của quy trình phát triển như thế nào? Hãy cùng xem xét một quy trình đơn giản, điều này cũng đủ cho phần lớn các môi trường làm việc:

Với phương pháp đúng hạn, bạn có thể tự động hóa và thống nhất mọi thứ từ chuỗi bên dưới và quên nó trong nhiều tháng tới.

Thiết lập môi trường phát triển

Một dự án nên chứa tệp docker-compose.yml, điều này có thể giúp bạn tránh khỏi suy nghĩ về những gì và cách bạn cần làm để chạy ứng dụng / dịch vụ trên máy cục bộ. Một lệnh soạn thảo docker đơn giản sẽ khởi động ứng dụng của bạn với tất cả các phụ thuộc của nó, điền vào cơ sở dữ liệu các đồ đạc, tải lên mã cục bộ bên trong container, kích hoạt theo dõi mã để biên dịch và cuối cùng bắt đầu phản hồi tại cổng dự kiến. Ngay cả khi thiết lập một dịch vụ mới, bạn không cần lo lắng về việc bắt đầu như thế nào, nơi để cam kết thay đổi hoặc sử dụng khung nào. Tất cả điều này nên được mô tả trước trong các hướng dẫn tiêu chuẩn và được quyết định bởi các mẫu dịch vụ cho các thiết lập khác nhau: frontend, backend và worker.

Kiểm tra tự động

Tất cả những gì bạn muốn biết về hộp màu đen của Wap (thêm về lý do tại sao tôi gọi container này sẽ xuất hiện sau trong văn bản) là tất cả mọi thứ mà ngay bên trong nó. Có hay không. 1 hoặc 0. Có số lượng lệnh hữu hạn có thể được thực thi bên trong container và docker-compose.yml mô tả tất cả các phụ thuộc của nó, bạn có thể dễ dàng tự động hóa và thống nhất kiểm tra mà không cần tập trung quá nhiều vào các chi tiết triển khai.

Ví dụ như thế này!

Ở đây kiểm thử có nghĩa là không chỉ và không quá nhiều kiểm thử đơn vị, mà còn kiểm tra chức năng, kiểm thử tích hợp, kiểm tra (kiểu mã) và sao chép, kiểm tra các phụ thuộc lỗi thời, vi phạm giấy phép cho các gói đã sử dụng và nhiều thứ khác. Vấn đề là tất cả những điều này nên được gói gọn trong hình ảnh Docker của bạn.

Hệ thống giao hàng

Nó không quan trọng khi bạn muốn cài đặt dự án của mình. Kết quả, giống như quá trình cài đặt, phải luôn giống nhau. Cũng không có sự khác biệt nào về phần nào của toàn bộ hệ sinh thái mà bạn sẽ cài đặt hoặc git repo mà bạn sẽ nhận được từ đó. Thành phần quan trọng nhất ở đây là idempotence. Điều duy nhất mà bạn nên chỉ định là các biến kiểm soát cài đặt.

Ở đây, thuật toán có vẻ như khá hiệu quả trong việc giải quyết vấn đề này:

  1. Thu thập hình ảnh từ tất cả các Dockerfiles của bạn (ví dụ như thế này)
  2. Sử dụng một siêu dự án, phân phối những hình ảnh này đến Kubernetes thông qua API Kube. Bắt đầu phân phối thường yêu cầu một số tham số đầu vào:
  • Điểm cuối API Kube
  • một đối tượng bí mật của người Viking khác nhau cho các bối cảnh khác nhau (địa phương / phòng trưng bày / dàn dựng / sản xuất)
  • tên của các hệ thống sẽ hiển thị và các thẻ của hình ảnh Docker cho các hệ thống này (thu được ở bước trước)
Như một ví dụ về một siêu dự án bao gồm tất cả các hệ thống và dịch vụ (nói cách khác, một dự án mô tả cách sắp xếp hệ sinh thái và cách cập nhật cho nó), tôi thích sử dụng các playbook Ansible với mô-đun này để tích hợp với Kube API. Tuy nhiên, các nhà sản xuất ô tô tinh vi có thể tham khảo các tùy chọn khác và tôi sẽ tự mình lựa chọn sau. Tuy nhiên, bạn phải nghĩ ra một cách quản lý kiến ​​trúc tập trung / thống nhất. Có một cái sẽ cho phép bạn quản lý thuận tiện và thống nhất tất cả các dịch vụ / hệ thống và vô hiệu hóa mọi sự phức tạp mà các công nghệ và hệ thống sắp tới thực hiện các chức năng tương tự có thể ném vào bạn.

Thông thường, cài đặt môi trường là bắt buộc trong:

  • Hiện ShowRoom - để kiểm tra thủ công hoặc gỡ lỗi hệ thống
  • Staging Staging - dành cho các môi trường gần như sống và tích hợp với các hệ thống bên ngoài (thường nằm trong DMZ, trái ngược với ShowRoom)
  • Sản xuất của hoàng tử - môi trường thực tế cho người dùng cuối

Sự liên tục trong hội nhập và giao hàng

Nếu bạn có một cách thống nhất để kiểm tra các hình ảnh Docker - hoặc các hộp đen trên mạng - bạn có thể cho rằng kết quả của các thử nghiệm đó sẽ cho phép bạn tích hợp (và với lương tâm rõ ràng) tích hợp nhánh tính năng trong nhánh ngược dòng hoặc nhánh chính của git của bạn kho.

Có lẽ, công cụ thỏa thuận duy nhất ở đây là chuỗi tích hợp và phân phối. Khi không có bản phát hành, làm thế nào để bạn ngăn chặn tình trạng chủng tộc trên một hệ thống với một nhánh các tính năng song song?

Do đó, quá trình này chỉ nên được bắt đầu khi không có sự cạnh tranh, nếu không, điều kiện cuộc đua trên đường cao tốc sẽ tiếp tục ám ảnh bạn:

  1. Cố gắng cập nhật nhánh tính năng lên thượng nguồn (git rebase / merge)
  2. Xây dựng hình ảnh từ Dockerfiles
  3. Kiểm tra tất cả các hình ảnh được xây dựng
  4. Bắt đầu và đợi cho đến khi các hệ thống có hình ảnh từ bước 2 được phân phối
  5. Nếu bước trước không thành công, hãy khôi phục hệ sinh thái về trạng thái trước đó
  6. Hợp nhất dòng tính năng nhánh và gửi nó đến kho lưu trữ

Bất kỳ lỗi nào ở bất kỳ bước nào cũng nên chấm dứt quá trình phân phối và trả lại nhiệm vụ cho nhà phát triển để sửa lỗi, cho dù đó là một thử nghiệm thất bại hay xung đột hợp nhất.

Bạn có thể sử dụng quy trình này để làm việc với nhiều hơn một kho lưu trữ. Chỉ cần thực hiện từng bước cho tất cả các kho lưu trữ cùng một lúc (bước 1 cho repos A và B, bước 2 cho repos A và B, v.v.), thay vì thực hiện toàn bộ quá trình lặp lại cho từng kho lưu trữ riêng lẻ (bước 1 Nott6 cho repo A , bước 1 Ném6 cho repo B, v.v.).

Ngoài ra, Kubernetes cho phép bạn tung ra các bản cập nhật trong các phần để thực hiện các thử nghiệm AB khác nhau và phân tích rủi ro. Kubernetes thực hiện nội bộ bằng cách tách các dịch vụ (điểm truy cập) và ứng dụng. Bạn luôn có thể cân bằng các phiên bản mới và cũ của một thành phần theo tỷ lệ mong muốn để tạo điều kiện cho việc phân tích vấn đề và mở đường cho việc khôi phục tiềm năng.

Hệ thống rollback

Một trong những yêu cầu bắt buộc đối với khung kiến ​​trúc là khả năng đảo ngược mọi triển khai. Điều này, đến lượt nó, đòi hỏi một số sắc thái rõ ràng và tiềm ẩn. Dưới đây là một số trong những quan trọng nhất của họ:

  • Một dịch vụ sẽ có thể thiết lập môi trường cũng như thay đổi rollback. Ví dụ: di chuyển cơ sở dữ liệu, lược đồ RabbitMQ, v.v.
  • Nếu nó không thể phục hồi môi trường, dịch vụ phải đa hình và hỗ trợ cả phiên bản cũ và phiên bản mới của mã. Ví dụ: di chuyển cơ sở dữ liệu không nên phá vỡ các phiên bản cũ của dịch vụ (thông thường, 2 hoặc 3 phiên bản trước)
  • Khả năng tương thích ngược của bất kỳ cập nhật dịch vụ. Thông thường, đây là khả năng tương thích API, định dạng thông báo, v.v.
Khá đơn giản để quay lại trạng thái trong cụm Kubernetes (chạy triển khai kubectl hoàn tác triển khai / triển khai một số và Kubernetes sẽ khôi phục "ảnh chụp nhanh" trước đó), nhưng để hoạt động này, dự án meta của bạn nên chứa thông tin về ảnh chụp nhanh này. Các thuật toán rollback phân phối phức tạp hơn rất không được khuyến khích, mặc dù đôi khi chúng là cần thiết.

Ở đây, những gì có thể kích hoạt cơ chế rollback:

  • Tỷ lệ lỗi ứng dụng cao sau khi phát hành
  • Tín hiệu từ các điểm giám sát quan trọng
  • Kiểm tra khói thất bại
  • Chế độ thủ công - yếu tố con người

Đảm bảo an ninh thông tin và kiểm toán

Không có quy trình làm việc nào có thể tạo ra bảo mật chống đạn một cách kỳ diệu và bảo vệ hệ sinh thái của bạn khỏi các mối đe dọa bên ngoài và bên trong, vì vậy bạn cần đảm bảo rằng khung kiến ​​trúc của bạn được thực thi theo từng tiêu chuẩn và chính sách bảo mật của công ty cấp độ và trong tất cả các hệ thống con.

Tôi sẽ giải quyết cả ba cấp độ của giải pháp được đề xuất sau, trong phần về giám sát và cảnh báo, bản thân chúng cũng rất quan trọng đối với tính toàn vẹn của hệ thống.

Kubernetes có một bộ các cơ chế tích hợp tốt để kiểm soát truy cập, chính sách mạng, kiểm toán các sự kiện và các công cụ mạnh mẽ khác liên quan đến bảo mật thông tin, có thể được sử dụng để xây dựng một vành đai bảo vệ tuyệt vời có thể chống lại các cuộc tấn công và rò rỉ dữ liệu .

Từ quy trình phát triển đến kiến ​​trúc

Một nỗ lực để xây dựng một sự tích hợp chặt chẽ giữa các quy trình phát triển và hệ sinh thái nên được thực hiện nghiêm túc. Thêm một yêu cầu tích hợp như vậy vào tập hợp các yêu cầu truyền thống vào kiến ​​trúc (tính linh hoạt, khả năng mở rộng, tính sẵn sàng, độ tin cậy, bảo vệ chống lại các mối đe dọa, v.v.), có thể làm tăng đáng kể giá trị của khung kiến ​​trúc của bạn. Đây là một khía cạnh rất quan trọng mà nó đã dẫn đến sự xuất hiện của một khái niệm có tên là Dev Devpsps (Hoạt động phát triển), đây là một bước hợp lý để hoàn toàn tự động hóa và tối ưu hóa cơ sở hạ tầng. Tuy nhiên, được cấp một kiến ​​trúc được thiết kế tốt và các hệ thống con đáng tin cậy, các tác vụ DevOps có thể được giảm thiểu.

Kiến trúc vi dịch vụ

Không cần phải đi sâu vào chi tiết về lợi ích của kiến ​​trúc hướng dịch vụ - SOA, bao gồm cả lý do tại sao các dịch vụ nên là micro micro. Tôi sẽ chỉ nói rằng nếu bạn đã quyết định sử dụng Docker và Kubernetes, thì rất có thể bạn hiểu (và chấp nhận) rằng nó khó khăn và thậm chí sai về mặt ý thức hệ khi có một kiến ​​trúc nguyên khối. Được thiết kế để chạy một quy trình duy nhất và hoạt động bền bỉ, Docker buộc chúng ta phải suy nghĩ trong khuôn khổ DDD (Phát triển theo hướng tên miền). Trong Docker, mã đóng gói được coi là một hộp đen với một số cổng bị lộ.

Các thành phần quan trọng và giải pháp của hệ sinh thái

Từ kinh nghiệm của tôi về thiết kế các hệ thống với độ khả dụng và độ tin cậy cao hơn, có một số thành phần rất quan trọng đối với hoạt động của các dịch vụ vi mô. Sau đó, tôi liệt kê và nói về từng thành phần này và mặc dù tôi sẽ đề cập đến chúng trong bối cảnh môi trường Kubernetes, bạn có thể xem danh sách của tôi như một danh sách kiểm tra cho bất kỳ nền tảng nào khác.

Nếu bạn (như tôi) sẽ đưa ra kết luận rằng thật tuyệt vời khi quản lý từng thành phần này như một dịch vụ Kubernetes thông thường, thì tôi sẽ khuyên bạn nên chạy chúng trong một cụm riêng biệt ngoài sản xuất ra. Ví dụ, một cụm staging của nhóm vì, nó có thể cứu mạng bạn khi môi trường sản xuất không ổn định và bạn rất cần một nguồn hình ảnh, mã hoặc các công cụ giám sát của nó. Điều đó giải quyết vấn đề gà và trứng, có thể nói như vậy.

Dịch vụ nhận dạng

Như thường lệ, tất cả bắt đầu với quyền truy cập - vào máy chủ, máy ảo, ứng dụng, thư văn phòng, v.v. Nếu bạn đang hoặc muốn trở thành khách hàng của một trong những nền tảng doanh nghiệp lớn (IBM, Google, Microsoft), vấn đề truy cập sẽ được xử lý bởi một trong các dịch vụ của nhà cung cấp. Tuy nhiên, nếu bạn muốn có giải pháp của riêng mình, chỉ do bạn quản lý và trong ngân sách của bạn?

Danh sách này sẽ giúp bạn quyết định giải pháp phù hợp và ước tính nỗ lực cần thiết để thiết lập và duy trì nó. Tất nhiên, sự lựa chọn của bạn phải phù hợp với chính sách bảo mật của công ty và được bộ phận bảo mật thông tin chấp thuận.

Cung cấp dịch vụ tự động

Mặc dù Kubernetes yêu cầu chỉ có một số thành phần nhỏ trên các máy vật lý / máy ảo đám mây (docker, kubelet, kube proxy, etcd cluster), bạn vẫn cần tự động hóa việc bổ sung các máy mới và quản lý cụm. Đây là một vài cách đơn giản để làm điều đó:

  • KOPS - công cụ này cho phép bạn cài đặt một cụm trên một trong hai nhà cung cấp đám mây - AWS hoặc GCE
  • Teraform - điều này cho phép bạn quản lý cơ sở hạ tầng cho bất kỳ môi trường nào và tuân theo hệ tư tưởng của IAC (Cơ sở hạ tầng dưới dạng mã)
  • Ansible - công cụ đa năng để tự động hóa dưới mọi hình thức
Cá nhân, tôi thích tùy chọn thứ ba (với một mô-đun tích hợp Kubernetes nhỏ), vì nó cho phép tôi làm việc với cả máy chủ và các đối tượng k8 và thực hiện bất kỳ loại tự động hóa nào. Tuy nhiên, không có gì ngăn bạn sử dụng Teraform và mô-đun Kubernetes của nó. KOPS không hoạt động tốt với các kim loại trần, nhưng nó vẫn là một công cụ tuyệt vời để sử dụng với AWS / GCE!

Kho Git và trình theo dõi tác vụ

Không cần phải nói rằng để cung cấp cho công việc đầy đủ của các nhà phát triển và các vai trò liên quan khác, bạn cần có một nơi để thảo luận về làm việc theo nhóm và lưu trữ mã. Tôi sẽ khó có thể xác định dịch vụ nào là tốt nhất cho việc này, nhưng tiêu chuẩn vàng cá nhân của tôi để theo dõi nhiệm vụ là redmine (miễn phí) hoặc Jira (trả phí) và cho kho lưu trữ mã - trường cũ cũ [gerrit] ( https://www.gerritcodereview.com/) (miễn phí) hoặc bitbucket (trả phí).

Điều đáng chú ý là hai ngăn xếp nhất quán (mặc dù thương mại) cho công việc hợp tác trong môi trường công ty: Atlassian và Jetbrains. Bạn có thể sử dụng một trong hai giải pháp độc lập hoặc kết hợp các thành phần khác nhau của cả hai.

Để tận dụng tối đa sự kết hợp giữa trình theo dõi và kho lưu trữ, hãy nghĩ về chiến lược tích hợp của chúng. Ví dụ: một số mẹo để đảm bảo tính toàn vẹn của mã và các tác vụ liên quan (tất nhiên bạn có thể chọn cách tiếp cận của riêng mình):

  • Chỉ nên bật khả năng đẩy đẩy vào một kho lưu trữ từ xa nếu một nhánh mà một người đang cố gắng đẩy để có số nhiệm vụ tương ứng (TASK-1 / Feature-34)
  • Bất kỳ chi nhánh nào cũng có sẵn để hợp nhất chỉ sau một số lần lặp lại đánh giá mã tích cực nhất định
  • Bất kỳ chi nhánh nào cũng nên bị chặn và vô hiệu hóa để cập nhật trong tương lai nếu tác vụ tương ứng không phải là trong Chế độ tiến bộ hoặc trạng thái tương tự
  • Bất kỳ bước nào dành cho tự động hóa không nên có sẵn trực tiếp cho các nhà phát triển
  • Chỉ những nhà phát triển được ủy quyền mới có thể sửa đổi trực tiếp nhánh chính - mọi thứ khác được điều khiển bởi robot tự động
  • Không nên có sẵn một chi nhánh để hợp nhất nếu tác vụ tương ứng ở bất kỳ trạng thái nào khác ngoài Giao hàng cho Giao hàng hoặc tương tự

Docker đăng ký

Cần chú ý đặc biệt đến hệ thống quản lý hình ảnh Docker, vì nó cực kỳ quan trọng để lưu trữ và cung cấp dịch vụ. Ngoài ra, hệ thống này nên hỗ trợ quyền truy cập cho người dùng và nhóm người dùng, có thể xóa các hình ảnh cũ và không cần thiết, cung cấp GUI và API RESTful.

Bạn có thể sử dụng giải pháp đám mây (ví dụ: hub.docker.com) hoặc dịch vụ lưu trữ riêng, thậm chí có thể được cài đặt trong cụm Kubernetes của bạn. Vmware Harbor, được định vị là một giải pháp công ty cho Docker Registry, là một ví dụ điển hình về cái sau. Trường hợp xấu nhất, bạn thậm chí có thể sử dụng Docker Registry cũ nếu bạn chỉ muốn lưu trữ hình ảnh và không có nhu cầu trong một hệ thống phức tạp.

CI / CD và hệ thống cung cấp dịch vụ

Không có thành phần nào chúng ta đã thảo luận trước đó (git repo, tác vụ theo dõi, dự án meta với Ansible Playbooks, phụ thuộc bên ngoài) có thể hoạt động tách biệt với nhau như thể bị treo trong chân không. Những gì kết nối chúng là dịch vụ tích hợp và phân phối liên tục.

CI - CD tích hợp liên tục - Giao hàng liên tục

Dịch vụ này khá đơn giản và không có bất kỳ logic nào liên quan đến việc phân phối hoặc cấu hình hệ thống. Tất cả những gì dịch vụ CI / CD nên làm là phản ứng với các sự kiện từ thế giới bên ngoài (thay đổi kho lưu trữ git, di chuyển các tác vụ xung quanh trình theo dõi tác vụ) và khởi chạy các hành động được mô tả trong dự án meta. Ngoài ra, dịch vụ này là điểm kiểm soát tất cả các kho lưu trữ và một công cụ để quản lý chúng (hợp nhất chi nhánh, cập nhật từ thượng nguồn / chính).

Trước đây, tôi đã sử dụng một công cụ khá đơn giản nhưng rất mạnh mẽ từ Jetbrains - TeamCity, nhưng tôi không thấy bất kỳ vấn đề gì nếu bạn quyết định thử một thứ khác, ví dụ như Jenkins miễn phí.

Trong sơ đồ mà chúng tôi đã mô tả ở trên, dịch vụ tích hợp về cơ bản chịu trách nhiệm khởi chạy bốn quy trình chính và một quy trình phụ trợ, như sau:

  • Kiểm tra dịch vụ tự động - thông thường, đối với một kho lưu trữ duy nhất, khi trạng thái chi nhánh đã thay đổi hoặc khi trạng thái đã được thay đổi thành Hồi đang chờ Autotests Hồi (hoặc tương tự)
  • Cung cấp dịch vụ - thông thường, từ một siêu dự án và cho một số dịch vụ (tương ứng là một số kho lưu trữ), khi trạng thái đã thay đổi thành Phòng trưng bày của Awaiting, hoặc một cách chờ đợi Giao hàng cho QA và triển khai môi trường sản xuất, tương ứng
  • Phục hồi - theo quy định, từ một dự án meta và cho một phần cụ thể của một dịch vụ hoặc toàn bộ dịch vụ, được kích hoạt bởi một sự kiện bên ngoài hoặc trong trường hợp giao hàng không thành công
  • Xóa dịch vụ - điều này là cần thiết để loại bỏ hoàn toàn toàn bộ hệ sinh thái khỏi một môi trường thử nghiệm duy nhất (phòng trưng bày), khi trạng thái Trong QA đã hết hạn hoặc môi trường không còn cần thiết nữa
  • Trình tạo hình ảnh (quy trình phụ trợ) - có thể được tích hợp trong quy trình cung cấp dịch vụ hoặc được sử dụng độc lập để biên dịch hình ảnh Docker và gửi chúng đến Docker Registry. Thường xử lý các hình ảnh được sử dụng rộng rãi (DB, dịch vụ chung hoặc dịch vụ không yêu cầu thay đổi thường xuyên)

Hệ thống thu thập và phân tích nhật ký

Cách duy nhất để bất kỳ bộ chứa Docker nào có thể truy cập nhật ký của nó là ghi chúng vào STDOUT hoặc STDERR của tiến trình gốc đang chạy trong vùng chứa. Nhà phát triển dịch vụ không thực sự quan tâm đến những gì xảy ra tiếp theo với dữ liệu nhật ký, điều chính là chúng nên có sẵn khi cần thiết và tốt nhất là chứa các bản ghi đến một điểm nhất định trong quá khứ. Tất cả trách nhiệm thực hiện những kỳ vọng này thuộc về Kubernetes và các kỹ sư hỗ trợ hệ sinh thái.

Trong tài liệu chính thức, bạn có thể tìm thấy một mô tả về chiến lược cơ bản (và tốt) để làm việc với nhật ký, điều này sẽ giúp bạn chọn một dịch vụ để tổng hợp và lưu trữ dữ liệu văn bản khổng lồ.

Trong số các dịch vụ được đề xuất cho một hệ thống ghi nhật ký, cùng một tài liệu có đề cập đến việc thu thập dữ liệu (khi được khởi chạy như một tác nhân trên mỗi nút của cụm) và Elaticsearch để lưu trữ và lập chỉ mục dữ liệu. Ngay cả khi hiệu quả của một trong hai Bạn có thể không đồng ý với hiệu quả của giải pháp này, nhưng nó lại đáng tin cậy và dễ sử dụng nên tôi nghĩ rằng nó ít nhất là một khởi đầu tốt.

Elaticsearch là một giải pháp sử dụng nhiều tài nguyên nhưng nó có khả năng mở rộng tốt và có các hình ảnh Docker đã sẵn sàng để chạy cả một nút riêng lẻ và một cụm có kích thước cần thiết.

Hệ thống truy tìm

Hoàn hảo như mã của bạn có thể xảy ra, thất bại xảy ra và sau đó bạn muốn nghiên cứu chúng với một chiếc lược răng tinh xảo trong quá trình sản xuất và cố gắng hiểu điều gì đã xảy ra nếu mọi thứ hoạt động tốt trên máy cục bộ của tôi? Truy vấn cơ sở dữ liệu chậm, bộ nhớ đệm không đúng cách, đĩa chậm hoặc kết nối với tài nguyên bên ngoài, giao dịch trong hệ sinh thái, tắc nghẽn và dịch vụ điện toán dưới quy mô là một số lý do khiến bạn sẽ buộc phải theo dõi và ước tính thời gian thực hiện mã của mình theo tải thực.

Opentracing và Zipkin đối phó với nhiệm vụ này đối với hầu hết các ngôn ngữ lập trình hiện đại và không thêm bất kỳ gánh nặng nào sau khi sử dụng mã. Tất nhiên tất cả các dữ liệu thu thập nên được lưu trữ ở một nơi thích hợp, được sử dụng như một trong các thành phần.

Sự phức tạp nảy sinh khi sử dụng mã và chuyển tiếp Trace Idace thông qua tất cả các dịch vụ, hàng đợi tin nhắn, cơ sở dữ liệu, v.v ... được giải quyết bằng các tiêu chuẩn phát triển và mẫu dịch vụ nêu trên. Sau này cũng quan tâm đến tính đồng nhất của phương pháp này.

Giám sát và cảnh báo

Prometheus đã trở thành tiêu chuẩn thực tế trong các hệ thống hiện đại và quan trọng hơn, nó được hỗ trợ trong Kubernetes gần như vượt trội. Bạn có thể tham khảo tài liệu chính thức của Kubernetes để tìm hiểu thêm về giám sát và cảnh báo.

Giám sát là một trong số ít các hệ thống phụ trợ phải được cài đặt bên trong một cụm. Và cụm là một thực thể có thể theo dõi. Nhưng việc giám sát một hệ thống giám sát (tha thứ cho tautology) chỉ có thể được thực hiện từ bên ngoài (ví dụ, từ cùng một môi trường dàn dựng của Wap). Trong trường hợp này, kiểm tra chéo có ích như một giải pháp thuận tiện cho mọi môi trường phân tán, điều này sẽ làm phức tạp kiến ​​trúc của hệ sinh thái thống nhất cao của bạn.

Toàn bộ phạm vi giám sát được chia thành ba cấp độ cách ly hoàn toàn hợp lý. Đây là những gì tôi nghĩ là những ví dụ quan trọng nhất về điểm theo dõi ở mỗi cấp độ:

  • Cấp vật lý: - Tài nguyên mạng và tính khả dụng của chúng - Đĩa (i / o, dung lượng trống) - Tài nguyên cơ bản của các nút riêng lẻ (CPU, RAM, LA)
  • Cấp độ cụm: - Tính khả dụng của các hệ thống cụm chính trên mỗi nút (kubelet, kubeAPI, DNS, v.v.) - Số lượng tài nguyên miễn phí và phân phối thống nhất của chúng - Giám sát mức tiêu thụ tài nguyên thực tế được cho phép bởi các dịch vụ - Tải lại vỏ quả
  • Cấp độ dịch vụ: - Bất kỳ loại giám sát ứng dụng nào - từ nội dung cơ sở dữ liệu đến tần suất các lệnh gọi API - Số lỗi HTTP trên cổng API - Kích thước của hàng đợi và mức độ sử dụng của công nhân - Nhiều số liệu cho cơ sở dữ liệu (độ trễ sao chép, thời gian sao chép và số lượng giao dịch, yêu cầu chậm và hơn thế nữa) - Phân tích lỗi cho các quy trình không phải HTTP - Giám sát các yêu cầu được gửi đến hệ thống nhật ký (bạn có thể chuyển đổi bất kỳ yêu cầu nào thành số liệu)

Đối với các thông báo cảnh báo ở mỗi cấp độ, I Khănd muốn khuyên bạn nên sử dụng một trong vô số dịch vụ bên ngoài có thể gửi thông báo đến email, SMS hoặc thực hiện cuộc gọi đến số di động. I hèll cũng đề cập đến một hệ thống khác - OpsGenie - có tích hợp chặt chẽ với trình cảnh báo Prometheus.

OpsGenie là một công cụ linh hoạt để cảnh báo giúp đối phó với sự leo thang, nhiệm vụ suốt ngày đêm, lựa chọn kênh thông báo và nhiều hơn nữa. Nó cũng dễ dàng phân phối cảnh báo giữa các đội. Ví dụ: các cấp độ giám sát khác nhau sẽ gửi thông báo đến các nhóm / phòng ban khác nhau: vật lý - Infra + Devops, cluster - Devops, ứng dụng - mỗi nhóm cho một nhóm có liên quan.

Cổng API và Đăng nhập một lần

Để xử lý các tác vụ như ủy quyền, xác thực, đăng ký người dùng (người dùng bên ngoài - khách hàng của công ty) và các loại kiểm soát truy cập khác, bạn sẽ cần một dịch vụ có độ tin cậy cao có thể duy trì tích hợp linh hoạt với cổng API của bạn. Không có hại khi sử dụng cùng một giải pháp như đối với dịch vụ Nhận dạng Nhận diện, tuy nhiên bạn có thể muốn tách hai tài nguyên để đạt được mức độ sẵn có và độ tin cậy khác nhau.

Việc tích hợp giữa các dịch vụ không nên phức tạp và các dịch vụ của bạn không nên lo lắng về việc ủy ​​quyền và xác thực người dùng và nhau. Thay vào đó, kiến ​​trúc và hệ sinh thái nên có một dịch vụ proxy xử lý tất cả lưu lượng truyền thông và HTTP.

Hãy cùng xem xét cách tích hợp phù hợp nhất với cổng API, do đó với toàn bộ hệ sinh thái của bạn - mã thông báo. Phương pháp này tốt cho cả ba kịch bản truy cập: từ UI, từ dịch vụ đến dịch vụ và từ hệ thống bên ngoài. Sau đó, nhiệm vụ nhận mã thông báo (dựa trên thông tin đăng nhập và mật khẩu) nằm ở chính giao diện người dùng hoặc với nhà phát triển dịch vụ. Cũng có ý nghĩa để phân biệt giữa thời gian tồn tại của các mã thông báo được sử dụng trong Giao diện người dùng (TTL ngắn hơn) và trong các trường hợp khác (TTL dài hơn và tùy chỉnh).

Dưới đây là một số vấn đề mà cổng API giải quyết:

  • Truy cập vào các dịch vụ của hệ sinh thái từ bên ngoài và bên trong (các dịch vụ không giao tiếp trực tiếp với nhau)
  • Tích hợp với dịch vụ Đăng nhập một lần: - Chuyển đổi mã thông báo và nối thêm yêu cầu HTTPS với các tiêu đề có chứa dữ liệu nhận dạng người dùng (ID, vai trò, chi tiết khác) cho dịch vụ được yêu cầu - Bật / tắt kiểm soát truy cập vào dịch vụ được yêu cầu dựa trên vai trò nhận được từ dịch vụ Đăng nhập một lần
  • Điểm giám sát duy nhất cho lưu lượng HTTP
  • Kết hợp tài liệu API từ các dịch vụ khác nhau (ví dụ: kết hợp các tệp json / yml của Swagger
  • Khả năng quản lý định tuyến cho toàn bộ hệ sinh thái dựa trên các miền và URI được yêu cầu
  • Điểm truy cập duy nhất cho lưu lượng truy cập bên ngoài và tích hợp với nhà cung cấp truy cập

Xe buýt sự kiện và Tích hợp doanh nghiệp / Xe buýt dịch vụ

Nếu hệ sinh thái của bạn chứa hàng trăm dịch vụ hoạt động trong một miền vĩ mô, bạn sẽ phải đối phó với hàng ngàn cách có thể mà các dịch vụ có thể giao tiếp. Để hợp lý hóa luồng dữ liệu, bạn nên nghĩ đến khả năng phân phối tin nhắn qua một số lượng lớn người nhận khi xảy ra một số sự kiện nhất định, bất kể bối cảnh của các sự kiện. Nói cách khác, bạn cần một xe buýt sự kiện để xuất bản các sự kiện dựa trên giao thức chuẩn và đăng ký chúng.

Là một xe buýt sự kiện, bạn có thể sử dụng bất kỳ hệ thống nào có thể vận hành một nhà môi giới được gọi là: RabbitMQ, Kafka, ActiveMQ và các hệ thống khác. Nhìn chung, tính sẵn sàng cao và tính nhất quán của dữ liệu rất quan trọng đối với các dịch vụ vi mô, nhưng bạn vẫn phải hy sinh một cái gì đó để đạt được sự phân phối và phân cụm xe buýt hợp lý, do định lý CAP.

Đương nhiên, xe buýt sự kiện sẽ có thể giải quyết tất cả các vấn đề của giao tiếp liên dịch vụ, nhưng khi số lượng dịch vụ tăng từ hàng trăm đến hàng nghìn đến hàng nghìn, ngay cả kiến ​​trúc dựa trên xe buýt sự kiện tốt nhất cũng sẽ thất bại, và bạn sẽ cần tìm giải pháp khác Một ví dụ điển hình là cách tiếp cận xe buýt tích hợp, có thể mở rộng khả năng của đường ống Dumb - Các chiến thuật của người tiêu dùng thông minh được mô tả ở trên.

Có hàng tá lý do để sử dụng cách tiếp cận Bus Tích hợp / Dịch vụ của Bus Enterprise, nhằm mục đích giảm sự phức tạp của kiến ​​trúc hướng dịch vụ. Đây chỉ là một vài trong số những lý do sau:

  • Tổng hợp nhiều tin nhắn
  • Chia một sự kiện thành nhiều sự kiện
  • Phân tích đồng bộ / giao dịch của phản ứng của hệ thống đối với một sự kiện
  • Phối hợp các giao diện, đặc biệt quan trọng để tích hợp với các hệ thống bên ngoài
  • Logic nâng cao của định tuyến sự kiện
  • Nhiều tích hợp với cùng các dịch vụ (từ bên ngoài và bên trong)
  • Tập trung không thể mở rộng của bus dữ liệu
Là một phần mềm nguồn mở cho xe buýt tích hợp doanh nghiệp, bạn có thể muốn xem xét Apache ServiceMix, bao gồm một số thành phần thiết yếu để thiết kế và phát triển loại SOA này.

Cơ sở dữ liệu và các dịch vụ nhà nước khác

Cũng như Kubernetes, Docker đã thay đổi quy tắc của trò chơi một lần và mãi mãi đối với các dịch vụ yêu cầu sự kiên trì dữ liệu và hoạt động chặt chẽ với đĩa. Một số người nói rằng các dịch vụ nên trực tiếp trên mạng theo cách cũ trên các máy chủ vật lý hoặc máy ảo. Tôi tôn trọng ý kiến ​​này và tôi đã chiến thắng các cuộc tranh luận về ưu và nhược điểm của nó, nhưng tôi khá chắc chắn rằng những tuyên bố đó chỉ tồn tại do thiếu kiến ​​thức, giải pháp và kinh nghiệm trong việc quản lý các dịch vụ nhà nước trong môi trường Docker.

Tôi cũng nên đề cập rằng một cơ sở dữ liệu thường chiếm vị trí trung tâm trong thế giới lưu trữ và do đó, giải pháp bạn chọn phải được chuẩn bị đầy đủ để hoạt động trong môi trường Kubernetes.

Dựa trên kinh nghiệm của tôi và tình hình thị trường, tôi có thể phân biệt các nhóm dịch vụ trạng thái sau đây cùng với các ví dụ về các giải pháp định hướng Docker phù hợp nhất cho từng nhóm:

  • Hệ thống quản lý cơ sở dữ liệu - PostDock là một giải pháp đơn giản và đáng tin cậy cho PostgreSQL trong bất kỳ môi trường Docker nào
  • Nhà môi giới hàng đợi / tin nhắn - RabbitMQ là một phần mềm cổ điển để xây dựng hệ thống xếp hàng tin nhắn và định tuyến tin nhắn. Tham số cluster_ information trong cấu hình của RabbitMQ là không thể thiếu đối với thiết lập cụm
  • Dịch vụ lưu đệm - được xem là một trong những giải pháp lưu trữ dữ liệu linh hoạt và đáng tin cậy nhất
  • Tìm kiếm toàn văn bản - ngăn xếp Elaticsearch mà tôi đã đề cập ở trên, ban đầu được sử dụng cho tìm kiếm toàn văn bản, nhưng cũng tốt trong việc lưu trữ nhật ký và cho bất kỳ loại công việc nào có lượng dữ liệu văn bản lớn
  • Dịch vụ lưu trữ tệp - một nhóm dịch vụ tổng quát cho bất kỳ loại lưu trữ và phân phối tệp nào (ftp, sftp, v.v.)

Gương phụ thuộc

Nếu bạn chưa gặp phải tình huống mà các gói hoặc phần phụ thuộc bạn cần đã bị xóa hoặc tạm thời không có sẵn từ máy chủ công cộng, thì don sắt nghĩ rằng điều này sẽ không bao giờ xảy ra. Để tránh mọi trường hợp không mong muốn và cung cấp bảo mật cho các hệ thống nội bộ, hãy đảm bảo rằng cả việc xây dựng cũng như cung cấp dịch vụ của bạn đều không cần kết nối Internet. Định cấu hình phản chiếu và sao chép tất cả các phụ thuộc vào mạng bên trong: Hình ảnh Docker, gói vòng / phút, kho lưu trữ nguồn, mô-đun python / go / js / php.

Mỗi trong số này và bất kỳ loại phụ thuộc khác có giải pháp riêng của họ. Phổ biến nhất có thể được googled bởi gương truy vấn phụ thuộc riêng của Truy vấn

Từ kiến ​​trúc đến đời thực

Dù muốn hay không, sớm hay muộn toàn bộ kiến ​​trúc của bạn sẽ phải chịu thất bại. Điều đó luôn xảy ra: các công nghệ trở nên lỗi thời nhanh chóng (1 năm5 năm), các phương pháp và cách tiếp cận - chậm hơn một chút (5 bền10 năm), các nguyên tắc thiết kế và nguyên tắc cơ bản - đôi khi (102020 năm), nhưng không thể tránh khỏi.

Lưu tâm đến sự lỗi thời của công nghệ, luôn cố gắng giữ cho hệ sinh thái của bạn luôn ở đỉnh cao của đổi mới công nghệ, lên kế hoạch và triển khai các dịch vụ mới để đáp ứng nhu cầu của các nhà phát triển, doanh nghiệp và người dùng cuối, quảng bá các tiện ích mới cho các bên liên quan của bạn, cung cấp kiến ​​thức để di chuyển nhóm và công ty chuyển tiếp.

Luôn dẫn đầu trong trò chơi bằng cách hòa nhập vào cộng đồng chuyên nghiệp, đọc các tài liệu liên quan và giao tiếp với các đồng nghiệp. Hãy nhận biết các cơ hội của bạn cũng như việc sử dụng đúng các xu hướng mới trong dự án của bạn. Thử nghiệm và áp dụng các phương pháp khoa học để phân tích kết quả nghiên cứu của bạn, hoặc dựa vào kết luận của người khác mà bạn tin tưởng và tôn trọng.

Thật khó để chuẩn bị cho mình những thay đổi cơ bản, nhưng có thể nếu bạn là một chuyên gia trong lĩnh vực của bạn. Tất cả chúng ta sẽ chỉ chứng kiến ​​một vài thay đổi công nghệ lớn trong suốt cuộc đời mình, nhưng nó không phải là lượng kiến ​​thức trong đầu khiến chúng ta trở thành chuyên gia và đưa chúng ta lên đỉnh cao, nó cởi mở với những ý tưởng của chúng ta và khả năng chấp nhận sự biến thái.

Quay trở lại với câu hỏi từ tiêu đề, có thể xây dựng một kiến ​​trúc tốt hơn không? chắc chắn sẽ thành công!

Tái bút

Bài viết gốc được viết bằng tiếng Nga, vì vậy cảm ơn đồng nghiệp của tôi ở Lazada Sergey Rodin vì đã giúp đỡ tuyệt vời để dịch nó!