Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Ngày 8 tháng XNUMX tại hội nghị Thánh HighLoad++ 2019, như một phần của phần “DevOps và Hoạt động”, một báo cáo “Mở rộng và bổ sung Kubernetes” đã được đưa ra, với sự tham gia của ba nhân viên của công ty Flant. Trong đó, chúng tôi nói về nhiều tình huống mà chúng tôi muốn mở rộng và bổ sung khả năng của Kubernetes, nhưng chúng tôi không tìm thấy giải pháp đơn giản và sẵn có. Chúng tôi có các giải pháp cần thiết dưới dạng các dự án Nguồn mở và bài phát biểu này cũng dành riêng cho chúng.

Theo truyền thống, chúng tôi xin hân hạnh giới thiệu video báo cáo (50 phút, nhiều thông tin hơn bài viết) và phần tóm tắt chính ở dạng văn bản. Đi!

Cốt lõi và bổ sung trong K8s

Kubernetes đang thay đổi ngành công nghiệp và các phương pháp quản trị đã được thiết lập từ lâu:

  • Cảm ơn anh ấy sự trừu tượng, chúng tôi không còn hoạt động với các khái niệm như thiết lập cấu hình hoặc chạy lệnh (Chef, Ansible...), mà sử dụng việc nhóm các container, dịch vụ, v.v.
  • Chúng ta có thể chuẩn bị đơn đăng ký mà không cần suy nghĩ về các sắc thái của trang web cụ thể, trên đó nó sẽ được tung ra: kim loại trần, đám mây của một trong những nhà cung cấp, v.v.
  • Với K8, bạn chưa bao giờ dễ tiếp cận hơn thế thực tiễn tốt nhất về tổ chức cơ sở hạ tầng: kỹ thuật mở rộng quy mô, khả năng tự phục hồi, khả năng chịu lỗi, v.v.

Tuy nhiên, tất nhiên mọi thứ không hề suôn sẻ: Kubernetes cũng mang đến những thách thức mới cho riêng mình.

Kubernetes không là sự kết hợp giải quyết mọi vấn đề của mọi người dùng. Hạt nhân Kubernetes chỉ chịu trách nhiệm về một tập hợp các chức năng cần thiết tối thiểu có trong mỗi cụm:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Lõi Kubernetes xác định một tập hợp nguyên thủy cơ bản để nhóm các container, quản lý lưu lượng, v.v. Chúng tôi đã nói về chúng chi tiết hơn trong báo cáo 2 năm trước.

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Mặt khác, K8s mang đến những cơ hội tuyệt vời để mở rộng các chức năng sẵn có, giúp đóng các chức năng khác - cụ thể - nhu cầu của người dùng. Việc bổ sung Kubernetes là trách nhiệm của quản trị viên cụm, những người phải cài đặt và định cấu hình mọi thứ cần thiết để cụm của họ “ở đúng hình dạng” [để giải quyết các vấn đề cụ thể của họ]. Những loại bổ sung này là gì? Hãy xem xét một số ví dụ.

Ví dụ về tiện ích bổ sung

Sau khi cài đặt Kubernetes, chúng tôi có thể ngạc nhiên rằng mạng rất cần thiết cho sự tương tác của các nhóm cả trong một nút và giữa các nút không tự hoạt động. Hạt nhân Kubernetes không đảm bảo các kết nối cần thiết; thay vào đó, nó xác định mạng giao diện (CNI) cho các tiện ích bổ sung của bên thứ ba. Chúng ta phải cài đặt một trong những tiện ích bổ sung này, tiện ích này sẽ chịu trách nhiệm về cấu hình mạng.

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Một ví dụ gần gũi là các giải pháp lưu trữ dữ liệu (đĩa cục bộ, thiết bị khối mạng, Ceph...). Ban đầu họ ở vị trí cốt lõi, nhưng với sự ra đời CSI tình huống thay đổi thành một điều tương tự như đã được mô tả: giao diện nằm trong Kubernetes và việc triển khai nó nằm trong các mô-đun của bên thứ ba.

Các ví dụ khác bao gồm:

  • Sự đi vào-bộ điều khiển (xem đánh giá của họ trong bài viết gần đây của chúng tôi).
  • quản lý chứng chỉ:

    Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

  • Người vận hành là một nhóm toàn bộ các tiện ích bổ sung (bao gồm trình quản lý chứng chỉ đã đề cập), chúng xác định (các) nguyên thủy và (các) bộ điều khiển. Logic công việc của họ chỉ bị giới hạn bởi trí tưởng tượng của chúng tôi và cho phép chúng tôi biến các thành phần cơ sở hạ tầng làm sẵn (ví dụ: DBMS) thành nguyên thủy, dễ làm việc hơn nhiều (so với một bộ vùng chứa và cài đặt của chúng). Một số lượng lớn các toán tử đã được viết - ngay cả khi nhiều toán tử trong số đó chưa sẵn sàng để đưa vào sản xuất thì đó chỉ là vấn đề thời gian:

    Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

  • Số liệu - một minh họa khác về cách Kubernetes tách giao diện (API số liệu) khỏi quá trình triển khai (các tiện ích bổ sung của bên thứ ba như bộ điều hợp Prometheus, tác nhân cụm Datadog...).
  • giám sát và thống kê, trong thực tế không chỉ cần thiết Prometheus và Grafana, mà còn cả kube-state-metrics, node-exporter, v.v.

Và đây không phải là danh sách bổ sung đầy đủ... Ví dụ: tại công ty Flant, chúng tôi hiện đang cài đặt 29 bổ sung (tất cả đều tạo ra tổng cộng 249 đối tượng Kubernetes). Nói một cách đơn giản, chúng ta không thể nhìn thấy cuộc sống của một cụm nếu không có sự bổ sung.

Tự động hóa

Các toán tử được thiết kế để tự động hóa các hoạt động thường ngày mà chúng ta gặp phải hàng ngày. Dưới đây là những ví dụ thực tế mà việc viết một toán tử sẽ là một giải pháp tuyệt vời:

  1. Có một sổ đăng ký riêng tư (tức là yêu cầu đăng nhập) có hình ảnh cho ứng dụng. Người ta giả định rằng mỗi nhóm được gán một bí mật đặc biệt cho phép xác thực trong sổ đăng ký. Nhiệm vụ của chúng tôi là đảm bảo rằng bí mật này được tìm thấy trong không gian tên để các nhóm có thể tải xuống hình ảnh. Có thể có rất nhiều ứng dụng (mỗi ứng dụng cần có một bí mật) và việc cập nhật các bí mật đó thường xuyên sẽ rất hữu ích, do đó tùy chọn sắp xếp các bí mật bằng tay sẽ bị loại bỏ. Đây là lúc người vận hành đến giải cứu: chúng tôi tạo một bộ điều khiển sẽ đợi không gian tên xuất hiện và dựa trên sự kiện này, sẽ thêm một bí mật vào không gian tên.
  2. Theo mặc định, quyền truy cập từ nhóm vào Internet bị cấm. Nhưng đôi khi nó có thể được yêu cầu: điều hợp lý là cơ chế cấp phép truy cập hoạt động đơn giản, không yêu cầu các kỹ năng cụ thể, chẳng hạn như sự hiện diện của một nhãn nhất định trong không gian tên. Nhà điều hành có thể giúp chúng tôi như thế nào ở đây? Một bộ điều khiển được tạo để chờ nhãn xuất hiện trong không gian tên và thêm chính sách thích hợp để truy cập Internet.
  3. Một tình huống tương tự: giả sử chúng ta cần thêm một số vết bẩn, nếu nó có nhãn tương tự (với một số loại tiền tố). Các hành động với người điều hành là rõ ràng...

Trong bất kỳ cụm nào, các nhiệm vụ thông thường phải được giải quyết và một cách chính xác điều này có thể được thực hiện bằng cách sử dụng các toán tử.

Tổng hợp tất cả những câu chuyện được mô tả, chúng tôi đi đến kết luận rằng để làm việc thoải mái với Kubernetes, bạn cần: MỘT) cài đặt tiện ích bổ sung, b) phát triển toán tử (để giải quyết các công việc quản trị hàng ngày).

Làm cách nào để viết tuyên bố cho Kubernetes?

Nói chung, sơ đồ rất đơn giản:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

... nhưng sau đó hóa ra là:

  • API Kubernetes là một thứ không hề tầm thường và cần rất nhiều thời gian để thành thạo;
  • lập trình cũng không dành cho tất cả mọi người (ngôn ngữ Go được chọn làm ngôn ngữ ưa thích vì có một khuôn khổ đặc biệt cho nó - SDK nhà điều hành);
  • Tình hình cũng tương tự với chính khuôn khổ đó.

Điểm mấu chốt: viết bộ điều khiển (người điều hành) phải dành nguồn lực đáng kể để nghiên cứu tài liệu. Điều này sẽ hợp lý đối với các nhà khai thác “lớn” - chẳng hạn như đối với MySQL DBMS. Nhưng nếu chúng ta nhớ các ví dụ được mô tả ở trên (tiết lộ bí mật, truy cập nhóm vào Internet...), điều mà chúng ta cũng muốn thực hiện một cách chính xác, thì chúng ta sẽ hiểu rằng nỗ lực bỏ ra sẽ lớn hơn kết quả mà chúng ta cần bây giờ:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Nói chung, nảy sinh một vấn đề nan giải: tốn nhiều nguồn lực và tìm công cụ phù hợp để viết báo cáo, hoặc làm theo cách cũ (nhưng nhanh chóng). Để giải quyết nó - để tìm ra sự thỏa hiệp giữa những thái cực này - chúng tôi đã tạo dự án của riêng mình: người điều hành shell (xem thêm của anh ấy thông báo gần đây trên trung tâm).

Người vận hành vỏ

Anh ấy làm việc như thế nào? Cụm có một nhóm chứa nhị phân Go với toán tử shell. Bên cạnh anh là một bộ móc (thêm chi tiết về họ - xem bên dưới). Bản thân toán tử shell đăng ký một số phát triển trong API Kubernetes, khi xảy ra sự cố, nó sẽ khởi chạy các hook tương ứng.

Làm thế nào để người vận hành shell biết nên gọi hook nào trong sự kiện nào? Thông tin này được truyền đến trình điều khiển shell bằng chính các hook và chúng thực hiện việc đó rất đơn giản.

Hook là tập lệnh Bash hoặc bất kỳ tệp thực thi nào khác chấp nhận một đối số duy nhất --config và phản hồi bằng JSON. Cái sau xác định đối tượng nào được nó quan tâm và sự kiện nào (đối với những đối tượng này) sẽ được phản hồi:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Tôi sẽ minh họa cách triển khai trên trình điều khiển shell của một trong các ví dụ của chúng tôi - phân tách các bí mật để truy cập vào sổ đăng ký riêng tư bằng hình ảnh ứng dụng. Nó bao gồm hai giai đoạn.

Thực hành: 1. Viết hook

Trước hết, trong hook chúng ta sẽ xử lý --config, cho biết rằng chúng tôi quan tâm đến không gian tên và cụ thể là thời điểm tạo ra chúng:

[[ $1 == "--config" ]] ; then
  cat << EOF
{
  "onKubernetesEvent": [
    {
      "kind": "namespace",
      "event": ["add"]
    }
  ]
}
EOF
…

Logic sẽ trông như thế nào? Cũng khá đơn giản:

…
else
  createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
  kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi

Bước đầu tiên là tìm ra không gian tên nào đã được tạo và bước thứ hai là tạo nó bằng cách sử dụng kubectl bí mật cho không gian tên này.

Thực hành: 2. Lắp ráp hình ảnh

Tất cả những gì còn lại là chuyển hook đã tạo cho toán tử shell - thực hiện việc này như thế nào? Bản thân shell-operator xuất hiện dưới dạng hình ảnh Docker, vì vậy nhiệm vụ của chúng ta là thêm hook vào một thư mục đặc biệt trong hình ảnh này:

FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooks

Tất cả những gì còn lại là lắp ráp nó và đẩy nó:

$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1

Bước cuối cùng là triển khai hình ảnh vào cụm. Để làm điều này, hãy viết Triển khai:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-operator
spec:
  template:
    spec:
      containers:
      - name: my-operator
        image: registry.example.com/my-operator:v1 # 1
      serviceAccountName: my-operator              # 2

Có hai điểm cần chú ý:

  1. dấu hiệu của hình ảnh mới được tạo;
  2. Đây là thành phần hệ thống (tối thiểu) cần có quyền đăng ký các sự kiện trong Kubernetes và phân bổ bí mật cho các không gian tên, vì vậy chúng tôi tạo ServiceAccount (và một bộ quy tắc) cho hook.

Kết quả - chúng tôi đã giải quyết được vấn đề của mình họ hàng cho Kubernetes theo cách tạo ra toán tử để phân tách bí mật.

Các tính năng vận hành shell khác

Để giới hạn các đối tượng thuộc loại bạn đã chọn mà hook sẽ hoạt động, chúng có thể được lọc, chọn theo nhãn nhất định (hoặc sử dụng matchExpressions):

"onKubernetesEvent": [
  {
    "selector": {
      "matchLabels": {
        "foo": "bar",
       },
       "matchExpressions": [
         {
           "key": "allow",
           "operation": "In",
           "values": ["wan", "warehouse"],
         },
       ],
     }
     …
  }
]

Cung cấp cơ chế chống trùng lặp, - sử dụng bộ lọc jq - cho phép bạn chuyển đổi các đối tượng JSON lớn thành các đối tượng nhỏ, trong đó chỉ còn lại những tham số mà chúng tôi muốn theo dõi các thay đổi.

Khi một hook được gọi, toán tử shell sẽ chuyển nó dữ liệu đối tượng, có thể được sử dụng cho bất kỳ nhu cầu nào.

Các sự kiện kích hoạt hook không chỉ giới hạn ở các sự kiện Kubernetes: shell-operator cung cấp hỗ trợ cho gọi hook theo thời gian (tương tự như crontab trong bộ lập lịch truyền thống), cũng như một sự kiện đặc biệt onStartup. Tất cả những sự kiện này có thể được kết hợp và gán cho cùng một hook.

Và hai tính năng nữa của shell-operator:

  1. anh ấy làm việc không đồng bộ. Vì một sự kiện Kubernetes (chẳng hạn như một đối tượng đang được tạo) đã được nhận nên các sự kiện khác (chẳng hạn như cùng một đối tượng bị xóa) có thể đã xảy ra trong cụm và các hook cần phải tính đến điều này. Nếu hook được thực thi có lỗi thì theo mặc định nó sẽ là nhớ lại cho đến khi hoàn thành thành công (hành vi này có thể được thay đổi).
  2. Nó xuất khẩu số liệu đối với Prometheus, nhờ đó bạn có thể hiểu liệu toán tử shell có hoạt động hay không, tìm ra số lỗi cho mỗi hook và kích thước hàng đợi hiện tại.

Để tóm tắt phần này của báo cáo:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Cài đặt tiện ích

Để làm việc thoải mái với Kubernetes, nhu cầu cài đặt các tiện ích bổ sung cũng đã được đề cập. Tôi sẽ kể cho bạn nghe về điều đó bằng cách sử dụng ví dụ về lộ trình của công ty chúng tôi đến cách chúng tôi thực hiện điều đó hiện nay.

Chúng tôi bắt đầu làm việc với Kubernetes với một số cụm, cụm bổ sung duy nhất là Ingress. Nó cần được cài đặt khác nhau trong mỗi cụm và chúng tôi đã tạo một số cấu hình YAML cho các môi trường khác nhau: bare metal, AWS...

Vì có nhiều cụm hơn nên có nhiều cấu hình hơn. Ngoài ra, chúng tôi đã tự cải thiện các cấu hình này, do đó chúng trở nên khá không đồng nhất:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Để sắp xếp mọi thứ theo thứ tự, chúng tôi bắt đầu với một tập lệnh (install-ingress.sh), lấy đối số là loại cụm mà chúng ta sẽ triển khai, tạo cấu hình YAML cần thiết và triển khai nó cho Kubernetes.

Nói tóm lại, con đường xa hơn của chúng tôi và lý do liên quan đến nó như sau:

  • để làm việc với các cấu hình YAML, cần có một công cụ mẫu (ở giai đoạn đầu, đây là sed đơn giản);
  • với sự gia tăng số lượng cụm, nhu cầu cập nhật tự động xuất hiện (giải pháp sớm nhất là đưa tập lệnh vào Git, cập nhật bằng cron và chạy nó);
  • một tập lệnh tương tự được yêu cầu cho Prometheus (install-prometheus.sh), tuy nhiên, điều đáng chú ý là nó yêu cầu nhiều dữ liệu đầu vào hơn, cũng như bộ lưu trữ của chúng (theo cách tốt - tập trung và trong một cụm) và một số dữ liệu (mật khẩu) có thể được tạo tự động:

    Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

  • nguy cơ triển khai sai điều gì đó cho số lượng cụm ngày càng tăng không ngừng tăng lên, vì vậy chúng tôi nhận thấy rằng trình cài đặt (tức là hai tập lệnh: dành cho Ingress và Prometheus) cần phải dàn dựng (một số nhánh trong Git, một số cron để cập nhật chúng trong các cụm tương ứng: ổn định hoặc thử nghiệm);
  • с kubectl apply nó trở nên khó làm việc vì nó không mang tính khai báo và chỉ có thể tạo các đối tượng chứ không thể đưa ra quyết định về trạng thái/xóa chúng;
  • Chúng tôi thiếu một số chức năng mà chúng tôi chưa triển khai vào thời điểm đó:
    • toàn quyền kiểm soát kết quả cập nhật cụm,
    • tự động xác định một số tham số (đầu vào cho tập lệnh cài đặt) dựa trên dữ liệu có thể lấy từ cụm (khám phá),
    • sự phát triển logic của nó dưới hình thức khám phá liên tục.

Chúng tôi đã triển khai tất cả kinh nghiệm tích lũy này trong khuôn khổ dự án khác của mình - toán tử bổ sung.

Toán tử bổ sung

Nó dựa trên toán tử shell đã được đề cập. Toàn bộ hệ thống trông như thế này:

Phần sau đây được thêm vào hook toán tử shell:

  • lưu trữ giá trị,
  • Biểu đồ mũ lái,
  • thành phần đó giám sát việc lưu trữ giá trị và - trong trường hợp có bất kỳ thay đổi nào - yêu cầu Helm cuộn lại biểu đồ.

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Do đó, chúng ta có thể phản ứng với một sự kiện trong Kubernetes, khởi chạy một hook và từ hook này, chúng ta có thể thực hiện các thay đổi đối với bộ lưu trữ, sau đó biểu đồ sẽ được tải xuống lại. Trong sơ đồ kết quả, chúng tôi tách tập hợp các móc và biểu đồ thành một thành phần mà chúng tôi gọi là mô-đun:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Có thể có nhiều mô-đun và với chúng, chúng tôi thêm các móc nối toàn cầu, kho lưu trữ giá trị toàn cầu và thành phần giám sát cửa hàng toàn cầu này.

Bây giờ, khi có điều gì đó xảy ra trong Kubernetes, chúng ta có thể phản ứng lại bằng cách sử dụng Global Hook và thay đổi thứ gì đó trong Global Store. Thay đổi này sẽ được chú ý và sẽ khiến tất cả các mô-đun trong cụm được triển khai:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Lược đồ này đáp ứng tất cả các yêu cầu để cài đặt các tiện ích bổ sung đã nêu ở trên:

  • Helm chịu trách nhiệm tạo khuôn mẫu và khai báo.
  • Vấn đề tự động cập nhật đã được giải quyết bằng cách sử dụng một móc toàn cục, nó sẽ đi tới sổ đăng ký theo lịch trình và nếu nó nhìn thấy hình ảnh hệ thống mới ở đó, nó sẽ xuất hiện (tức là "chính nó").
  • Lưu trữ cài đặt trong cụm được thực hiện bằng cách sử dụng Bản đồ cấu hình, chứa dữ liệu chính cho kho lưu trữ (khi khởi động, chúng được tải vào kho lưu trữ).
  • Các vấn đề về tạo, phát hiện và phát hiện liên tục mật khẩu đã được giải quyết bằng cách sử dụng hook.
  • Việc dàn dựng đạt được nhờ vào các thẻ mà Docker hỗ trợ ngay lập tức.
  • Kết quả được theo dõi bằng các số liệu mà chúng tôi có thể hiểu được trạng thái.

Toàn bộ hệ thống này được triển khai dưới dạng một nhị phân duy nhất trong Go, được gọi là toán tử addon. Điều này làm cho sơ đồ trông đơn giản hơn:

Mở rộng và bổ sung Kubernetes (tổng quan và báo cáo video)

Thành phần chính trong sơ đồ này là một tập hợp các mô-đun (được đánh dấu màu xám bên dưới). Bây giờ chúng ta có thể viết một mô-đun cho tiện ích bổ sung cần thiết với một chút nỗ lực và đảm bảo rằng nó sẽ được cài đặt trong mỗi cụm, sẽ được cập nhật và phản hồi các sự kiện mà nó cần trong cụm.

Công dụng của "Flant" toán tử bổ sung trên hơn 70 cụm Kubernetes. Tình trạng hiện tại - phiên bản alpha. Bây giờ chúng tôi đang chuẩn bị tài liệu để phát hành bản beta, nhưng hiện tại trong kho ví dụ có sẵn, trên cơ sở đó bạn có thể tạo addon của riêng mình.

Tôi có thể lấy mô-đun cho toán tử bổ trợ ở đâu? Xuất bản thư viện của chúng tôi là giai đoạn tiếp theo đối với chúng tôi; chúng tôi dự định thực hiện việc này vào mùa hè.

Video và slide

Video màn trình diễn (~50 phút):

Trình bày báo cáo:

PS

Các báo cáo khác trên blog của chúng tôi:

Bạn cũng có thể quan tâm đến các ấn phẩm sau:

Nguồn: www.habr.com

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