Các phương pháp thực hành tốt nhất cho vùng chứa Kubernetes: Kiểm tra tình trạng

Các phương pháp thực hành tốt nhất cho vùng chứa Kubernetes: Kiểm tra tình trạng

TL; DR

  • Để đạt được khả năng quan sát cao của vùng chứa và vi dịch vụ, nhật ký và số liệu chính là không đủ.
  • Để phục hồi nhanh hơn và tăng khả năng phục hồi, các ứng dụng nên áp dụng Nguyên tắc có khả năng quan sát cao (HOP).
  • Ở cấp độ ứng dụng, NOP yêu cầu: ghi nhật ký thích hợp, giám sát chặt chẽ, kiểm tra độ chính xác và theo dõi hiệu suất/chuyển đổi.
  • Sử dụng séc như một phần tử của NOR thăm dò sự sẵn sàng и Liveness Probe Kubernetes.

Mẫu kiểm tra sức khỏe là gì?

Khi thiết kế một ứng dụng quan trọng và có tính sẵn sàng cao, điều quan trọng là phải nghĩ đến khía cạnh như khả năng chịu lỗi. Một ứng dụng được coi là có khả năng chịu lỗi nếu nó phục hồi nhanh chóng sau khi gặp lỗi. Một ứng dụng đám mây điển hình sử dụng kiến ​​trúc microservices - trong đó mỗi thành phần được đặt trong một thùng chứa riêng biệt. Và để đảm bảo rằng ứng dụng trên k8s có tính sẵn sàng cao khi bạn thiết kế một cụm, bạn cần tuân theo một số mẫu nhất định. Trong số đó phải kể đến Mẫu Kiểm tra Sức khỏe. Nó xác định cách ứng dụng giao tiếp với k8 rằng nó hoạt động tốt. Đây không chỉ là thông tin về việc nhóm có đang chạy hay không mà còn về cách nó nhận và phản hồi các yêu cầu. Kubernetes càng biết nhiều về tình trạng của nhóm thì các quyết định càng thông minh hơn về định tuyến lưu lượng và cân bằng tải. Do đó, Nguyên tắc có khả năng quan sát cao cho phép ứng dụng phản hồi các yêu cầu một cách kịp thời.

Nguyên tắc có khả năng quan sát cao (HOP)

Nguyên tắc có khả năng quan sát cao là một trong những nguyên tắc nguyên tắc thiết kế các ứng dụng được đóng gói. Trong kiến ​​trúc vi dịch vụ, các dịch vụ không quan tâm đến cách xử lý yêu cầu của chúng (và đúng như vậy), mà điều quan trọng là cách chúng nhận được phản hồi từ dịch vụ nhận. Ví dụ: để xác thực người dùng, một vùng chứa sẽ gửi yêu cầu HTTP đến một vùng chứa khác, mong đợi phản hồi ở một định dạng nhất định - chỉ vậy thôi. PythonJS cũng có thể xử lý yêu cầu và Python Flask có thể phản hồi. Các container giống như những chiếc hộp đen có nội dung ẩn giấu với nhau. Tuy nhiên, nguyên tắc NOP yêu cầu mỗi dịch vụ phải hiển thị nhiều điểm cuối API cho biết mức độ hoạt động của dịch vụ cũng như trạng thái sẵn sàng và khả năng chịu lỗi của dịch vụ đó. Kubernetes yêu cầu các chỉ báo này để xem xét các bước tiếp theo trong việc định tuyến và cân bằng tải.

Một ứng dụng đám mây được thiết kế tốt sẽ ghi lại các sự kiện chính của nó bằng cách sử dụng các luồng I/O tiêu chuẩn STDERR và STDOUT. Tiếp theo là dịch vụ phụ trợ, ví dụ như filebeat, logstash hoặc Fluentd, cung cấp nhật ký đến hệ thống giám sát tập trung (ví dụ Prometheus) và hệ thống thu thập nhật ký (bộ phần mềm ELK). Sơ đồ bên dưới cho thấy cách ứng dụng đám mây hoạt động theo Mẫu kiểm tra tình trạng và Nguyên tắc khả năng quan sát cao.

Các phương pháp thực hành tốt nhất cho vùng chứa Kubernetes: Kiểm tra tình trạng

Làm cách nào để áp dụng Mẫu kiểm tra tình trạng trong Kubernetes?

Khi ra khỏi hộp, k8s sẽ theo dõi trạng thái của nhóm bằng một trong các bộ điều khiển (Triển khai, Bản sao, DaemonSets, Bộ trạng thái Vân vân.). Sau khi phát hiện ra rằng pod đã bị rơi vì lý do nào đó, bộ điều khiển sẽ cố gắng khởi động lại nó hoặc di chuyển nó sang một nút khác. Tuy nhiên, một nhóm có thể báo cáo rằng nó đang hoạt động nhưng bản thân nó lại không hoạt động. Hãy đưa ra một ví dụ: ứng dụng của bạn sử dụng Apache làm máy chủ web, bạn đã cài đặt thành phần này trên một số nhóm của cụm. Vì thư viện được định cấu hình không chính xác nên tất cả yêu cầu tới ứng dụng đều phản hồi bằng mã 500 (lỗi máy chủ nội bộ). Khi kiểm tra giao hàng, kiểm tra tình trạng pod cho kết quả thành công nhưng khách hàng lại nghĩ khác. Chúng tôi sẽ mô tả tình huống không mong muốn này như sau:

Các phương pháp thực hành tốt nhất cho vùng chứa Kubernetes: Kiểm tra tình trạng

Trong ví dụ của chúng tôi, k8s có kiểm tra chức năng. Trong loại xác minh này, kubelet liên tục kiểm tra trạng thái của quy trình trong vùng chứa. Khi anh ấy hiểu rằng quá trình đã dừng lại, anh ấy sẽ khởi động lại nó. Nếu lỗi có thể được khắc phục bằng cách chỉ cần khởi động lại ứng dụng và chương trình được thiết kế để tắt bất kỳ lỗi nào thì bạn chỉ cần kiểm tra tình trạng quy trình để tuân theo NOP và Mẫu kiểm tra tình trạng. Điều đáng tiếc duy nhất là không phải tất cả các lỗi đều được loại bỏ bằng cách khởi động lại. Trong trường hợp này, k8s cung cấp 2 cách sâu hơn để xác định sự cố với nhóm: Liveness Probe и thăm dò sự sẵn sàng.

thăm dò sự sống

Trong suốt Liveness Probe kubelet thực hiện 3 loại kiểm tra: không chỉ xác định xem pod có đang chạy hay không mà còn xác định xem pod có sẵn sàng nhận và phản hồi đầy đủ các yêu cầu hay không:

  • Thiết lập một yêu cầu HTTP tới nhóm. Phản hồi phải chứa mã phản hồi HTTP trong phạm vi từ 200 đến 399. Do đó, mã 5xx và 4xx báo hiệu rằng nhóm đang gặp sự cố, mặc dù quy trình đang chạy.
  • Để kiểm tra các nhóm có dịch vụ không phải HTTP (ví dụ: máy chủ thư Postfix), bạn cần thiết lập kết nối TCP.
  • Thực thi một lệnh tùy ý cho một nhóm (nội bộ). Việc kiểm tra được coi là thành công nếu mã hoàn thành lệnh là 0.

Một ví dụ về cách thức hoạt động của nó. Định nghĩa nhóm tiếp theo chứa ứng dụng NodeJS đưa ra lỗi 500 đối với các yêu cầu HTTP. Để đảm bảo rằng vùng chứa được khởi động lại khi nhận được lỗi như vậy, chúng tôi sử dụng tham số livenessProbe:

apiVersion: v1
kind: Pod
metadata:
 name: node500
spec:
 containers:
   - image: magalix/node500
     name: node500
     ports:
       - containerPort: 3000
         protocol: TCP
     livenessProbe:
       httpGet:
         path: /
         port: 3000
       initialDelaySeconds: 5

Điều này không khác với bất kỳ định nghĩa nhóm nào khác, nhưng chúng tôi đang thêm một đối tượng .spec.containers.livenessProbe... Tham số httpGet chấp nhận đường dẫn mà yêu cầu HTTP GET được gửi đến (trong ví dụ của chúng tôi đây là /, nhưng trong các tình huống chiến đấu có thể có điều gì đó giống như /api/v1/status). Một livenessProbe khác chấp nhận một tham số initialDelaySeconds, hướng dẫn thao tác xác minh chờ một số giây được chỉ định. Cần có độ trễ vì vùng chứa cần thời gian để khởi động và khi khởi động lại, vùng chứa sẽ không khả dụng trong một thời gian.

Để áp dụng cài đặt này cho một cụm, hãy sử dụng:

kubectl apply -f pod.yaml

Sau vài giây, bạn có thể kiểm tra nội dung của nhóm bằng lệnh sau:

kubectl describe pods node500

Ở cuối đầu ra, tìm đó là những gì.

Như bạn có thể thấy, livenessProbe đã khởi tạo một yêu cầu HTTP GET, vùng chứa đã tạo ra lỗi 500 (đó là lỗi được lập trình để thực hiện) và kubelet đã khởi động lại lỗi đó.

Nếu bạn đang thắc mắc ứng dụng NideJS được lập trình như thế nào thì đây là app.js và Dockerfile đã được sử dụng:

ứng dụng.js

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(500, { "Content-type": "text/plain" });
    res.end("We have run into an errorn");
});

server.listen(3000, function() {
    console.log('Server is running at 3000')
})

Dockerfile

FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]

Điều quan trọng cần lưu ý là: livenessProbe sẽ chỉ khởi động lại vùng chứa nếu thất bại. Nếu khởi động lại không khắc phục được lỗi ngăn container chạy thì kubelet sẽ không thể thực hiện hành động để khắc phục sự cố.

thăm dò sự sẵn sàng

sẵn sàngProbe hoạt động tương tự như livenessProbes (yêu cầu GET, giao tiếp TCP và thực thi lệnh), ngoại trừ các hành động khắc phục sự cố. Vùng chứa được phát hiện lỗi sẽ không được khởi động lại mà bị cô lập với lưu lượng truy cập đến. Hãy tưởng tượng rằng một trong các vùng chứa đang thực hiện nhiều phép tính hoặc đang chịu tải nặng, khiến thời gian phản hồi tăng lên. Trong trường hợp livenessProbe, việc kiểm tra tính khả dụng của phản hồi được kích hoạt (thông qua tham số kiểm tra timeoutSeconds), sau đó kubelet sẽ khởi động lại vùng chứa. Khi được khởi động, vùng chứa bắt đầu thực hiện các tác vụ tiêu tốn nhiều tài nguyên và được khởi động lại. Điều này có thể rất quan trọng đối với các ứng dụng cần tốc độ phản hồi. Ví dụ: một chiếc ô tô đang di chuyển trên đường đang chờ phản hồi từ máy chủ, phản hồi bị chậm - và chiếc ô tô gặp tai nạn.

Hãy viết một định nghĩa redinessProbe sẽ đặt thời gian phản hồi yêu cầu GET không quá hai giây và ứng dụng sẽ phản hồi yêu cầu GET sau 5 giây. Tệp pod.yaml sẽ trông như thế này:

apiVersion: v1
kind: Pod
metadata:
 name: nodedelayed
spec:
 containers:
   - image: afakharany/node_delayed
     name: nodedelayed
     ports:
       - containerPort: 3000
         protocol: TCP
     readinessProbe:
       httpGet:
         path: /
         port: 3000
       timeoutSeconds: 2

Hãy triển khai một nhóm với kubectl:

kubectl apply -f pod.yaml

Hãy đợi vài giây và sau đó xem tính sẵn sàng hoạt động như thế nào:

kubectl describe pods nodedelayed

Ở cuối kết quả đầu ra, bạn có thể thấy một số sự kiện tương tự cái này.

Như bạn có thể thấy, kubectl đã không khởi động lại nhóm khi thời gian kiểm tra vượt quá 2 giây. Thay vào đó, anh ấy đã hủy yêu cầu. Thông tin liên lạc đến được chuyển hướng đến các nhóm đang hoạt động khác.

Lưu ý rằng hiện tại nhóm đã được giảm tải, kubectl sẽ định tuyến lại các yêu cầu đến nhóm đó: phản hồi cho các yêu cầu GET không còn bị trì hoãn nữa.

Để so sánh, bên dưới là tệp app.js đã sửa đổi:

var http = require('http');

var server = http.createServer(function(req, res) {
   const sleep = (milliseconds) => {
       return new Promise(resolve => setTimeout(resolve, milliseconds))
   }
   sleep(5000).then(() => {
       res.writeHead(200, { "Content-type": "text/plain" });
       res.end("Hellon");
   })
});

server.listen(3000, function() {
   console.log('Server is running at 3000')
})

TL; DR
Trước khi các ứng dụng đám mây ra đời, nhật ký là phương tiện chính để theo dõi và kiểm tra tình trạng ứng dụng. Tuy nhiên, không có biện pháp nào để thực hiện bất kỳ hành động khắc phục nào. Nhật ký vẫn còn hữu ích cho đến ngày nay; chúng cần được thu thập và gửi đến hệ thống thu thập nhật ký để phân tích các tình huống khẩn cấp và đưa ra quyết định. [Ví dụ: tất cả điều này có thể được thực hiện mà không cần ứng dụng đám mây sử dụng monit, nhưng với k8s thì mọi việc trở nên dễ dàng hơn nhiều :) – ghi chú của biên tập viên. ]

Ngày nay, việc chỉnh sửa phải được thực hiện gần như theo thời gian thực, do đó các ứng dụng không còn phải là hộp đen nữa. Không, chúng phải hiển thị các điểm cuối cho phép hệ thống giám sát truy vấn và thu thập dữ liệu có giá trị về trạng thái của các quy trình để chúng có thể phản hồi ngay lập tức nếu cần. Đây được gọi là Mẫu thiết kế kiểm tra hiệu suất, tuân theo Nguyên tắc khả năng quan sát cao (HOP).

Kubernetes cung cấp 2 loại kiểm tra tình trạng theo mặc định: sẵn sàngProbe và livenessProbe. Cả hai đều sử dụng các loại kiểm tra giống nhau (yêu cầu HTTP GET, giao tiếp TCP và thực thi lệnh). Họ khác nhau về những quyết định mà họ đưa ra để giải quyết các vấn đề trong nhóm. livenessProbe khởi động lại vùng chứa với hy vọng rằng lỗi sẽ không xảy ra lần nữa và ReadyProbe sẽ cô lập nhóm khỏi lưu lượng truy cập đến cho đến khi nguyên nhân của sự cố được giải quyết.

Thiết kế ứng dụng phù hợp phải bao gồm cả hai loại kiểm tra và đảm bảo rằng chúng thu thập đủ dữ liệu, đặc biệt là khi đưa ra ngoại lệ. Nó cũng phải hiển thị các điểm cuối API cần thiết để cung cấp cho hệ thống giám sát (Prometheus) các số liệu sức khỏe quan trọng.

Nguồn: www.habr.com

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