Hình ảnh sẵn sàng sản xuất cho k8s

Câu chuyện này nói về cách chúng tôi sử dụng container trong môi trường sản xuất, cụ thể là Kubernetes. Bài viết tập trung vào việc thu thập số liệu và nhật ký từ vùng chứa cũng như xây dựng hình ảnh.

Hình ảnh sẵn sàng sản xuất cho k8s

Chúng tôi đến từ công ty fintech Exness, công ty phát triển các dịch vụ giao dịch trực tuyến và các sản phẩm fintech cho B2B và B2C. R&D của chúng tôi có nhiều đội khác nhau, bộ phận phát triển có hơn 100 nhân viên.

Chúng tôi đại diện cho nhóm chịu trách nhiệm về nền tảng để các nhà phát triển của chúng tôi thu thập và chạy mã. Đặc biệt, chúng tôi chịu trách nhiệm thu thập, lưu trữ và báo cáo số liệu, nhật ký và sự kiện từ các ứng dụng. Chúng tôi hiện vận hành khoảng ba nghìn container Docker trong môi trường sản xuất, duy trì bộ lưu trữ dữ liệu lớn 50 TB và cung cấp các giải pháp kiến ​​trúc được xây dựng xung quanh cơ sở hạ tầng của chúng tôi: Kubernetes, Rancher và nhiều nhà cung cấp đám mây công cộng khác nhau. 

Động lực của chúng tôi

Cái gì đang cháy? Không ai có thể trả lời. Lò sưởi ở đâu? Thật khó hiểu. Nó bốc cháy khi nào? Bạn có thể tìm hiểu, nhưng không phải ngay lập tức. 

Hình ảnh sẵn sàng sản xuất cho k8s

Tại sao một số container đứng vững trong khi một số khác lại rơi xuống? Thùng chứa nào bị đổ lỗi? Xét cho cùng thì bên ngoài các thùng chứa đều giống nhau nhưng bên trong mỗi thùng đều có Neo riêng.

Hình ảnh sẵn sàng sản xuất cho k8s

Các nhà phát triển của chúng tôi là những người có năng lực. Họ làm ra những dịch vụ tốt mang lại lợi nhuận cho công ty. Nhưng vẫn có những lỗi xảy ra khi các thùng chứa ứng dụng bị sai lệch. Một vùng chứa tiêu thụ quá nhiều CPU, một vùng chứa khác tiêu tốn mạng, vùng thứ ba tiêu thụ các hoạt động I/O và vùng thứ tư hoàn toàn không rõ nó làm gì với ổ cắm. Tất cả rơi xuống và con tàu chìm. 

đại lý

Để hiểu những gì đang xảy ra bên trong, chúng tôi quyết định đặt các tác nhân trực tiếp vào các thùng chứa.

Hình ảnh sẵn sàng sản xuất cho k8s

Các tác nhân này đang hạn chế các chương trình giữ các thùng chứa ở trạng thái sao cho chúng không làm vỡ nhau. Các đại lý được tiêu chuẩn hóa và điều này cho phép một cách tiếp cận được tiêu chuẩn hóa để phục vụ các thùng chứa. 

Trong trường hợp của chúng tôi, các đại lý phải cung cấp nhật ký ở định dạng chuẩn, được gắn thẻ và điều chỉnh. Họ cũng phải cung cấp cho chúng tôi các số liệu được tiêu chuẩn hóa có thể mở rộng từ góc độ ứng dụng kinh doanh.

Tác nhân cũng có nghĩa là các tiện ích vận hành và bảo trì có thể hoạt động trong các hệ thống điều phối khác nhau hỗ trợ các hình ảnh khác nhau (Debian, Alpine, Centos, v.v.).

Cuối cùng, các tác nhân phải hỗ trợ CI/CD đơn giản bao gồm các tệp Docker. Nếu không, con tàu sẽ vỡ vụn vì container sẽ bắt đầu được vận chuyển dọc theo đường ray “quanh co”.

Xây dựng quy trình và thiết bị hình ảnh mục tiêu

Để giữ cho mọi thứ được chuẩn hóa và có thể quản lý được, cần phải tuân theo một số loại quy trình xây dựng tiêu chuẩn. Vì vậy, chúng tôi quyết định thu thập container bằng container - đây là đệ quy.

Hình ảnh sẵn sàng sản xuất cho k8s

Ở đây các thùng chứa được thể hiện bằng các đường viền liền nét. Đồng thời, họ quyết định đặt các bộ phân phát vào đó để “cuộc sống không giống như quả mâm xôi”. Tại sao điều này được thực hiện, chúng tôi sẽ giải thích dưới đây.
 
Kết quả là một công cụ xây dựng—một vùng chứa dành riêng cho phiên bản tham chiếu các phiên bản phân phối cụ thể và các phiên bản tập lệnh cụ thể.

Chúng ta sử dụng nó như thế nào? Chúng tôi có Docker Hub chứa một container. Chúng tôi phản ánh nó bên trong hệ thống của mình để loại bỏ sự phụ thuộc bên ngoài. Kết quả là một thùng chứa được đánh dấu màu vàng. Chúng tôi tạo một mẫu để cài đặt tất cả các bản phân phối và tập lệnh mà chúng tôi cần vào vùng chứa. Sau đó, chúng tôi tập hợp một hình ảnh sẵn sàng để sử dụng: các nhà phát triển đặt mã và một số phần phụ thuộc đặc biệt của riêng họ vào đó. 

Cách tiếp cận này có gì tốt? 

  • Đầu tiên, kiểm soát phiên bản đầy đủ của các công cụ xây dựng - các phiên bản vùng chứa, tập lệnh và phân phối xây dựng. 
  • Thứ hai, chúng tôi đã đạt được tiêu chuẩn hóa: chúng tôi tạo các mẫu, hình ảnh trung gian và hình ảnh sẵn sàng sử dụng theo cách tương tự. 
  • Thứ ba, container mang lại cho chúng ta tính di động. Hôm nay chúng tôi sử dụng Gitlab và ngày mai chúng tôi sẽ chuyển sang TeamCity hoặc Jenkins và chúng tôi sẽ có thể chạy các container của mình theo cách tương tự. 
  • Thứ tư, giảm thiểu sự phụ thuộc. Không phải ngẫu nhiên mà chúng tôi đặt các bộ phân phối vào thùng chứa, vì điều này cho phép chúng tôi tránh phải tải chúng xuống từ Internet mỗi lần. 
  • Thứ năm, tốc độ xây dựng đã tăng lên - sự hiện diện của các bản sao hình ảnh cục bộ cho phép bạn tránh lãng phí thời gian tải xuống vì có hình ảnh cục bộ. 

Nói cách khác, chúng tôi đã đạt được một quy trình lắp ráp linh hoạt và được kiểm soát. Chúng tôi sử dụng các công cụ tương tự để xây dựng mọi vùng chứa có phiên bản đầy đủ. 

Quy trình xây dựng của chúng tôi hoạt động như thế nào

Hình ảnh sẵn sàng sản xuất cho k8s

Quá trình lắp ráp được khởi chạy bằng một lệnh, quá trình này được thực hiện trong hình ảnh (được đánh dấu màu đỏ). Nhà phát triển có tệp Docker (được đánh dấu màu vàng), chúng tôi kết xuất nó, thay thế các biến bằng các giá trị. Và trong quá trình thực hiện, chúng tôi thêm đầu trang và chân trang - đây là những đại lý của chúng tôi. 

Tiêu đề thêm phân phối từ các hình ảnh tương ứng. Và phần chân trang sẽ cài đặt các dịch vụ của chúng tôi bên trong, định cấu hình khởi chạy khối lượng công việc, ghi nhật ký và các tác nhân khác, thay thế điểm vào, v.v. 

Hình ảnh sẵn sàng sản xuất cho k8s

Chúng tôi đã suy nghĩ rất lâu về việc có nên cài đặt một người giám sát hay không. Cuối cùng, chúng tôi quyết định rằng chúng tôi cần anh ấy. Chúng tôi đã chọn S6. Người giám sát cung cấp khả năng quản lý vùng chứa: cho phép bạn kết nối với nó nếu quy trình chính gặp sự cố và cung cấp khả năng quản lý vùng chứa theo cách thủ công mà không cần tạo lại nó. Nhật ký và số liệu là các quá trình chạy bên trong vùng chứa. Chúng cũng cần được kiểm soát bằng cách nào đó và chúng tôi thực hiện việc này với sự giúp đỡ của người giám sát. Cuối cùng, S6 đảm nhiệm công việc quản lý, xử lý tín hiệu và các nhiệm vụ khác.

Vì chúng tôi sử dụng các hệ thống điều phối khác nhau nên sau khi xây dựng và chạy, vùng chứa phải hiểu nó đang ở trong môi trường nào và hành động tùy theo tình huống. Ví dụ:
Điều này cho phép chúng tôi xây dựng một hình ảnh và chạy nó trong các hệ thống điều phối khác nhau và nó sẽ được khởi chạy có tính đến các chi tiết cụ thể của hệ thống điều phối này.

 Hình ảnh sẵn sàng sản xuất cho k8s

Đối với cùng một vùng chứa, chúng tôi nhận được các cây quy trình khác nhau trong Docker và Kubernetes:

Hình ảnh sẵn sàng sản xuất cho k8s

Tải trọng được thực thi dưới sự giám sát của S6. Hãy chú ý đến người thu thập và sự kiện - đây là những đại lý của chúng tôi chịu trách nhiệm về nhật ký và số liệu. Kubernetes không có chúng, nhưng Docker thì có. Tại sao? 

Nếu chúng ta xem xét thông số kỹ thuật của “pod” (sau đây gọi là Kubernetes pod), chúng ta sẽ thấy rằng bộ chứa sự kiện được thực thi trong một nhóm, có bộ chứa bộ thu thập riêng biệt thực hiện chức năng thu thập số liệu và nhật ký. Chúng ta có thể sử dụng các khả năng của Kubernetes: chạy các container trong một nhóm, trong một quy trình duy nhất và/hoặc không gian mạng. Thực tế giới thiệu đại lý của bạn và thực hiện một số chức năng. Và nếu cùng một vùng chứa được khởi chạy trong Docker, nó sẽ nhận được tất cả các khả năng giống như đầu ra, tức là nó sẽ có thể phân phối nhật ký và số liệu vì các tác nhân sẽ được khởi chạy nội bộ. 

Số liệu và nhật ký

Cung cấp số liệu và nhật ký là một nhiệm vụ phức tạp. Có một số khía cạnh trong quyết định của cô ấy.
Cơ sở hạ tầng được tạo ra để thực hiện tải trọng chứ không phải để phân phối nhật ký hàng loạt. Nghĩa là, quá trình này phải được thực hiện với yêu cầu tài nguyên vùng chứa tối thiểu. Chúng tôi cố gắng giúp các nhà phát triển của mình: “Nhận bộ chứa Docker Hub, chạy nó và chúng tôi có thể phân phối nhật ký”. 

Khía cạnh thứ hai là giới hạn khối lượng nhật ký. Nếu khối lượng nhật ký tăng vọt xảy ra trong một số vùng chứa (ứng dụng xuất ra dấu vết ngăn xếp trong một vòng lặp), thì tải trên CPU, kênh liên lạc và hệ thống xử lý nhật ký sẽ tăng lên và điều này ảnh hưởng đến hoạt động của máy chủ như một toàn bộ và các thùng chứa khác trên máy chủ, thì đôi khi điều này dẫn đến sự “thất thủ” của máy chủ. 

Khía cạnh thứ ba là cần phải hỗ trợ càng nhiều phương pháp thu thập số liệu càng tốt. Từ việc đọc tệp và thăm dò điểm cuối Prometheus cho đến sử dụng các giao thức dành riêng cho ứng dụng.

Và khía cạnh cuối cùng là giảm thiểu tiêu thụ tài nguyên.

Chúng tôi đã chọn giải pháp Go nguồn mở có tên Telegraf. Đây là đầu nối đa năng hỗ trợ hơn 140 loại kênh đầu vào (plugin đầu vào) và 30 loại kênh đầu ra (plugin đầu ra). Chúng tôi đã hoàn thiện nó và bây giờ chúng tôi sẽ cho bạn biết cách chúng tôi sử dụng nó bằng Kubernetes làm ví dụ. 

Hình ảnh sẵn sàng sản xuất cho k8s

Giả sử nhà phát triển triển khai một khối lượng công việc và Kubernetes nhận được yêu cầu tạo nhóm. Tại thời điểm này, một vùng chứa có tên Collector sẽ tự động được tạo cho mỗi nhóm (chúng tôi sử dụng webhook đột biến). Collector là đại lý của chúng tôi. Khi bắt đầu, vùng chứa này tự cấu hình để hoạt động với Prometheus và hệ thống thu thập nhật ký.

  • Để làm điều này, nó sử dụng các chú thích nhóm và tùy thuộc vào nội dung của nó, nó sẽ tạo ra một điểm cuối Prometheus; 
  • Dựa trên thông số kỹ thuật của nhóm và cài đặt vùng chứa cụ thể, nó sẽ quyết định cách phân phối nhật ký.

Chúng tôi thu thập nhật ký thông qua API Docker: nhà phát triển chỉ cần đặt chúng vào thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn và Collector sẽ sắp xếp nó. Nhật ký được thu thập theo từng khối với độ trễ nhất định để ngăn chặn tình trạng quá tải máy chủ có thể xảy ra. 

Số liệu được thu thập trên các phiên bản khối lượng công việc (quy trình) trong vùng chứa. Mọi thứ đều được gắn thẻ: không gian tên, bên dưới, v.v., sau đó được chuyển đổi sang định dạng Prometheus - và có sẵn để thu thập (ngoại trừ nhật ký). Chúng tôi cũng gửi nhật ký, số liệu và sự kiện tới Kafka và hơn thế nữa:

  • Nhật ký có sẵn trong Graylog (để phân tích trực quan);
  • Nhật ký, số liệu, sự kiện được gửi đến Clickhouse để lưu trữ lâu dài.

Mọi thứ hoạt động giống hệt nhau trong AWS, chỉ có điều chúng tôi thay thế Graylog bằng Kafka bằng Cloudwatch. Chúng tôi gửi nhật ký đến đó và mọi thứ trở nên rất thuận tiện: ngay lập tức xác định rõ chúng thuộc về cụm và vùng chứa nào. Điều này cũng đúng với Google Stackdriver. Nghĩa là, lược đồ của chúng tôi hoạt động cả tại chỗ với Kafka và trên đám mây. 

Nếu chúng ta không có Kubernetes với các nhóm, thì sơ đồ này sẽ phức tạp hơn một chút nhưng nó hoạt động trên các nguyên tắc tương tự.

Hình ảnh sẵn sàng sản xuất cho k8s

Các quy trình tương tự được thực thi bên trong vùng chứa, chúng được điều phối bằng S6. Tất cả các quy trình tương tự đang chạy bên trong cùng một vùng chứa.

Như một kết quả,

Chúng tôi đã tạo ra một giải pháp hoàn chỉnh để xây dựng và khởi chạy hình ảnh, với các tùy chọn thu thập và phân phối nhật ký cũng như số liệu:

  • Chúng tôi đã phát triển một phương pháp tiêu chuẩn hóa để tập hợp các hình ảnh và dựa trên đó, chúng tôi đã phát triển các mẫu CI;
  • Tác nhân thu thập dữ liệu là phần mở rộng Telegraf của chúng tôi. Chúng tôi đã thử nghiệm chúng tốt trong quá trình sản xuất;
  • Chúng tôi sử dụng webhook đột biến để triển khai các vùng chứa với tác nhân trong nhóm; 
  • Tích hợp vào hệ sinh thái Kubernetes/Rancher;
  • Chúng tôi có thể thực thi cùng một vùng chứa trong các hệ thống điều phối khác nhau và nhận được kết quả như mong đợi;
  • Đã tạo cấu hình quản lý vùng chứa hoàn toàn động. 

Đồng tác giả: Ilya Prudnikov

Nguồn: www.habr.com

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