Sửa các lỗ hổng trong cụm Kubernetes. Báo cáo và bảng ghi từ DevOpsConf

Pavel Selivanov, kiến ​​trúc sư giải pháp Southbridge và giáo viên Slurm, đã có bài thuyết trình tại DevOpsConf 2019. Buổi nói chuyện này là một trong những chủ đề của khóa học chuyên sâu về Kubernetes “Slurm Mega”.

Slurm Basic: Giới thiệu về Kubernetes diễn ra tại Moscow vào ngày 18-20 tháng XNUMX.
Slurm Mega: nhìn sâu hơn vào Kubernetes – Mátxcơva, ngày 22-24 tháng XNUMX.
Slurm Online: cả hai khóa học Kubernetes luôn luôn sẵn sàng.

Bên dưới phần cắt là bản ghi của báo cáo.

Xin chào các đồng nghiệp và những ai thông cảm cho họ. Hôm nay tôi sẽ nói về sự an toàn.

Tôi thấy hôm nay có rất nhiều nhân viên bảo vệ ở hội trường. Tôi xin lỗi bạn trước nếu tôi sử dụng các thuật ngữ từ thế giới bảo mật không chính xác như thông lệ của bạn.

Chuyện xảy ra là khoảng sáu tháng trước, tôi tình cờ gặp một cụm Kubernetes công khai. Công khai có nghĩa là có số lượng không gian tên thứ n; trong những không gian tên này có những người dùng bị cô lập trong không gian tên của họ. Tất cả những người dùng này thuộc về các công ty khác nhau. Chà, người ta cho rằng cụm này nên được sử dụng làm CDN. Nghĩa là, họ cung cấp cho bạn một cụm, họ cung cấp cho bạn người dùng ở đó, bạn đến đó vào không gian tên của mình, triển khai mặt trận của bạn.

Công ty trước đây của tôi đã cố gắng bán một dịch vụ như vậy. Và tôi được yêu cầu chọc cụm để xem giải pháp này có phù hợp hay không.

Tôi đã đến cụm này. Tôi được cấp quyền hạn chế, không gian tên hạn chế. Những người ở đó hiểu an toàn là gì. Họ đọc về Kiểm soát truy cập dựa trên vai trò (RBAC) trong Kubernetes - và họ đã vặn vẹo nó để tôi không thể khởi chạy các nhóm riêng biệt với quá trình triển khai. Tôi không nhớ vấn đề mà tôi đang cố gắng giải quyết bằng cách khởi chạy một nhóm mà không cần triển khai, nhưng tôi thực sự chỉ muốn khởi chạy một nhóm. Để may mắn, tôi quyết định xem mình có những quyền gì trong cụm, tôi có thể làm gì, không thể làm gì và họ đã làm gì sai sót ở đó. Đồng thời, tôi sẽ cho bạn biết họ đã cấu hình sai những gì trong RBAC.

Tình cờ là trong hai phút, tôi nhận được một quản trị viên cho cụm của họ, nhìn vào tất cả các không gian tên lân cận, thấy ở đó mặt trận sản xuất đang hoạt động của các công ty đã mua dịch vụ và triển khai. Tôi hầu như không thể ngăn mình đi đến trước mặt ai đó và viết vài lời chửi thề lên trang chính.

Tôi sẽ cho bạn biết bằng các ví dụ về cách tôi đã làm điều này và cách bảo vệ bạn khỏi điều này.

Nhưng trước tiên, hãy để tôi giới thiệu bản thân mình. Tên tôi là Pavel Selivanov. Tôi là kiến ​​trúc sư ở Southbridge. Tôi hiểu Kubernetes, DevOps và tất cả những thứ lạ mắt. Các kỹ sư của Southbridge và tôi đang xây dựng tất cả những thứ này và tôi đang tư vấn.

Ngoài các hoạt động chính của mình, gần đây chúng tôi còn triển khai các dự án mang tên Slurms. Chúng tôi đang cố gắng mang khả năng làm việc với Kubernetes của mình đến với đại chúng một chút, để dạy những người khác cũng làm việc với K8.

Hôm nay tôi sẽ nói về điều gì? Chủ đề của báo cáo rất rõ ràng - về tính bảo mật của cụm Kubernetes. Nhưng tôi muốn nói ngay rằng chủ đề này rất lớn - và do đó tôi muốn làm rõ ngay những gì tôi chắc chắn sẽ không nói đến. Tôi sẽ không nói về những thuật ngữ nhàm chán đã được sử dụng hàng trăm lần trên Internet. Tất cả các loại RBAC và chứng chỉ.

Tôi sẽ nói về điều khiến tôi và các đồng nghiệp của tôi lo lắng về vấn đề bảo mật trong cụm Kubernetes. Chúng tôi nhận thấy những vấn đề này ở cả các nhà cung cấp cung cấp cụm Kubernetes và giữa các khách hàng đến với chúng tôi. Và thậm chí từ những khách hàng đến với chúng tôi từ các công ty quản trị tư vấn khác. Tức là quy mô của thảm kịch thực sự rất lớn.

Thực sự có ba điểm mà tôi sẽ nói đến hôm nay:

  1. Quyền của người dùng so với quyền của nhóm. Quyền của người dùng và quyền của nhóm không giống nhau.
  2. Thu thập thông tin về cụm. Tôi sẽ chỉ ra rằng bạn có thể thu thập tất cả thông tin bạn cần từ một cụm mà không cần có các quyền đặc biệt trong cụm này.
  3. Tấn công DoS vào cụm. Nếu chúng tôi không thể thu thập thông tin, chúng tôi sẽ có thể đặt một cụm trong mọi trường hợp. Tôi sẽ nói về các cuộc tấn công DoS vào các phần tử điều khiển cụm.

Một điều tổng quát khác mà tôi sẽ đề cập đến là những gì tôi đã thử nghiệm tất cả những thứ này, trên đó tôi có thể nói chắc chắn rằng tất cả đều hoạt động.

Chúng tôi lấy việc cài đặt cụm Kubernetes bằng Kubespray làm cơ sở. Nếu ai chưa biết thì đây thực chất là một tập hợp các vai trò dành cho Ansible. Chúng tôi sử dụng nó liên tục trong công việc của chúng tôi. Điều tốt là bạn có thể cuộn nó ở bất cứ đâu - bạn có thể cuộn nó lên những miếng sắt hoặc thành một đám mây ở đâu đó. Về nguyên tắc, một phương pháp cài đặt hoạt động cho mọi thứ.

Trong cụm này tôi sẽ có Kubernetes v1.14.5. Toàn bộ cụm Cube mà chúng ta sẽ xem xét được chia thành các không gian tên, mỗi không gian tên thuộc về một nhóm riêng biệt và các thành viên của nhóm này có quyền truy cập vào từng không gian tên. Họ không thể đi đến các không gian tên khác nhau, chỉ đi đến không gian tên của riêng họ. Nhưng có một tài khoản quản trị viên nhất định có quyền đối với toàn bộ cụm.

Sửa các lỗ hổng trong cụm Kubernetes. Báo cáo và bảng ghi từ DevOpsConf

Tôi đã hứa rằng điều đầu tiên chúng ta sẽ làm là giành được quyền quản trị cho cụm. Chúng ta cần một nhóm được chuẩn bị đặc biệt để phá vỡ cụm Kubernetes. Tất cả những gì chúng ta cần làm là áp dụng nó cho cụm Kubernetes.

kubectl apply -f pod.yaml

Nhóm này sẽ đến một trong những bậc thầy của cụm Kubernetes. Và sau đó, cụm sẽ vui vẻ trả lại cho chúng ta một tệp có tên admin.conf. Trong Cube, tệp này lưu trữ tất cả các chứng chỉ của quản trị viên, đồng thời định cấu hình API cụm. Tôi nghĩ đây là cách dễ dàng để quản trị viên có quyền truy cập vào 98% cụm Kubernetes.

Tôi nhắc lại, nhóm này được tạo bởi một nhà phát triển trong cụm của bạn, người có quyền truy cập để triển khai các đề xuất của anh ấy vào một không gian tên nhỏ, tất cả đều được RBAC kiểm soát. Anh ta không có quyền. Nhưng tuy nhiên giấy chứng nhận đã được trả lại.

Và bây giờ về một cái kén được chuẩn bị đặc biệt. Chúng tôi chạy nó trên bất kỳ hình ảnh nào. Hãy lấy debian:jessie làm ví dụ.

Chúng tôi có điều này:

tolerations:
-   effect: NoSchedule 
    operator: Exists 
nodeSelector: 
    node-role.kubernetes.io/master: "" 

Khoan dung là gì? Các bậc thầy trong cụm Kubernetes thường được đánh dấu bằng thứ gọi là vết bẩn. Và bản chất của sự “lây nhiễm” này là nó nói rằng các nhóm không thể được gán cho các nút chính. Nhưng không ai bận tâm chỉ ra trong bất kỳ nhóm nào rằng nó có khả năng chịu được “sự lây nhiễm”. Phần Dung sai chỉ nói rằng nếu một số nút có NoSchedule thì nút của chúng tôi có khả năng chịu được sự lây nhiễm như vậy - và không có vấn đề gì.

Hơn nữa, chúng tôi nói rằng cấp dưới của chúng tôi không chỉ khoan dung mà còn muốn nhắm mục tiêu cụ thể vào chủ nhân. Bởi vì các bậc thầy có thứ ngon nhất mà chúng ta cần - tất cả các chứng chỉ. Do đó, chúng tôi nói nodeSelector - và chúng tôi có nhãn tiêu chuẩn trên các nút chính, cho phép bạn chọn từ tất cả các nút trong cụm chính xác các nút là nút chính.

Với hai phần này chắc chắn anh ta sẽ đến với chủ nhân. Và anh ta sẽ được phép sống ở đó.

Nhưng chỉ đến với thầy thôi thì chưa đủ đối với chúng ta. Điều này sẽ không mang lại cho chúng tôi bất cứ điều gì. Vì vậy, tiếp theo chúng ta có hai điều sau:

hostNetwork: true 
hostPID: true 

Chúng tôi chỉ định rằng nhóm mà chúng tôi khởi chạy sẽ nằm trong không gian tên kernel, trong không gian tên mạng và trong không gian tên PID. Sau khi nhóm được khởi chạy trên máy chủ, nó sẽ có thể xem tất cả các giao diện thực, trực tiếp của nút này, lắng nghe tất cả lưu lượng truy cập và xem PID của tất cả các quy trình.

Sau đó, đó là vấn đề của những điều nhỏ nhặt. Lấy etcd và đọc những gì bạn muốn.

Điều thú vị nhất là tính năng Kubernetes này, được mặc định có ở đó.

volumeMounts:
- mountPath: /host 
  name: host 
volumes:
- hostPath: 
    path: / 
    type: Directory 
  name: host 

Và bản chất của nó là chúng ta có thể nói trong nhóm mà chúng ta khởi chạy, ngay cả khi không có quyền đối với cụm này, rằng chúng ta muốn tạo một tập thuộc loại hostingPath. Điều này có nghĩa là lấy đường dẫn từ máy chủ mà chúng tôi sẽ khởi chạy - và lấy đường dẫn đó làm ổ đĩa. Và sau đó chúng tôi gọi nó là tên: máy chủ. Chúng tôi gắn toàn bộ HostPath này vào bên trong nhóm. Trong ví dụ này, vào thư mục /host.

Tôi sẽ lặp lại nó một lần nữa. Chúng tôi đã yêu cầu nhóm đến với nhóm chính, lấy HostNetwork và HostPID ở đó - và gắn toàn bộ thư mục gốc của nhóm chính vào trong nhóm này.

Bạn hiểu rằng trong Debian chúng tôi có bash đang chạy và bash này chạy dưới quyền root. Tức là chúng ta vừa nhận được quyền root trên bản gốc mà không có bất kỳ quyền nào trong cụm Kubernetes.

Sau đó, toàn bộ nhiệm vụ là đi đến thư mục con /host /etc/kubernetes/pki, nếu tôi không nhầm, hãy lấy tất cả các chứng chỉ chính của cụm ở đó và theo đó, trở thành quản trị viên cụm.

Nếu bạn nhìn nhận theo cách này, đây là một số quyền nguy hiểm nhất trong nhóm - bất kể người dùng có quyền gì:
Sửa các lỗ hổng trong cụm Kubernetes. Báo cáo và bảng ghi từ DevOpsConf

Nếu tôi có quyền chạy một nhóm trong một số không gian tên của cụm thì nhóm này có các quyền này theo mặc định. Tôi có thể chạy các nhóm đặc quyền và nhìn chung đây là tất cả các quyền, thực tế là root trên nút.

Yêu thích của tôi là người dùng Root. Và Kubernetes có tùy chọn Run As Non-Root này. Đây là một loại bảo vệ khỏi hacker. Bạn có biết “virus Moldavian” là gì không? Nếu bạn đột nhiên là một hacker và đến với cụm Kubernetes của tôi, thì chúng tôi, những quản trị viên kém cỏi, sẽ hỏi: “Vui lòng cho biết trong nhóm của bạn mà bạn sẽ hack cụm của tôi, chạy với tư cách không phải root. Nếu không, bạn sẽ chạy tiến trình này trong nhóm của mình dưới quyền root và bạn sẽ rất dễ dàng hack tôi. Hãy tự bảo vệ mình khỏi chính mình."

Theo tôi, khối lượng đường dẫn máy chủ là cách nhanh nhất để nhận được kết quả mong muốn từ cụm Kubernetes.

Nhưng phải làm gì với tất cả điều này?

Suy nghĩ sẽ đến với bất kỳ quản trị viên bình thường nào gặp Kubernetes là: “Ừ, tôi đã nói với bạn rồi, Kubernetes không hoạt động. Có những lỗ hổng trong đó. Và toàn bộ Cube là thứ nhảm nhí.” Trên thực tế, có một thứ gọi là tài liệu, và nếu bạn nhìn vào đó, có một phần Chính sách bảo mật nhóm.

Đây là một đối tượng yaml - chúng ta có thể tạo nó trong cụm Kubernetes - kiểm soát các khía cạnh bảo mật cụ thể trong phần mô tả của nhóm. Trên thực tế, nghĩa là nó kiểm soát quyền sử dụng bất kỳ HostNetwork, HostPID, một số loại ổ đĩa nhất định có trong nhóm khi khởi động. Với sự trợ giúp của Chính sách bảo mật Pod, tất cả điều này có thể được mô tả.

Điều thú vị nhất về Chính sách bảo mật Pod là trong cụm Kubernetes, tất cả các trình cài đặt PSP không chỉ không được mô tả dưới bất kỳ hình thức nào mà chúng còn bị tắt theo mặc định. Chính sách bảo mật Pod được kích hoạt bằng cách sử dụng plugin đăng ký.

Được rồi, hãy triển khai Chính sách bảo mật Pod vào cụm, giả sử rằng chúng ta có một số nhóm dịch vụ trong không gian tên mà chỉ quản trị viên mới có quyền truy cập. Giả sử, trong tất cả các trường hợp khác, nhóm có quyền hạn chế. Bởi vì rất có thể các nhà phát triển không cần chạy các nhóm đặc quyền trong cụm của bạn.

Và mọi thứ dường như đều ổn với chúng tôi. Và cụm Kubernetes của chúng tôi không thể bị hack trong hai phút.

Có một vấn đề. Rất có thể, nếu bạn có cụm Kubernetes thì tính năng giám sát sẽ được cài đặt trên cụm của bạn. Tôi thậm chí còn đi xa hơn khi dự đoán rằng nếu cụm của bạn có tính năng giám sát thì nó sẽ được gọi là Prometheus.

Những gì tôi sắp nói với bạn sẽ có giá trị đối với cả toán tử Prometheus và Prometheus được phân phối ở dạng nguyên chất. Câu hỏi đặt ra là nếu tôi không thể đưa quản trị viên vào cụm nhanh như vậy thì điều này có nghĩa là tôi cần phải xem xét nhiều hơn. Và tôi có thể tìm kiếm với sự giúp đỡ của việc theo dõi của bạn.

Có lẽ mọi người đều đọc những bài viết giống nhau trên Habré và tính năng giám sát nằm trong không gian tên giám sát. Biểu đồ Helm được gọi là gần giống nhau đối với tất cả mọi người. Tôi đoán rằng nếu bạn thực hiện helm install stable/prometheus, bạn sẽ có những cái tên gần giống nhau. Và rất có thể tôi thậm chí sẽ không phải đoán tên DNS trong cụm của bạn. Bởi vì nó là tiêu chuẩn.

Sửa các lỗ hổng trong cụm Kubernetes. Báo cáo và bảng ghi từ DevOpsConf

Tiếp theo, chúng tôi có một số nhà phát triển nhất định, trong đó bạn có thể chạy một nhóm nhất định. Và từ nhóm này, thật dễ dàng để làm những việc như thế này:

$ curl http://prometheus-kube-state-metrics.monitoring 

prometheus-kube-state-metrics là một trong những nhà xuất khẩu Prometheus thu thập số liệu từ chính API Kubernetes. Có rất nhiều dữ liệu ở đó, cái gì đang chạy trong cụm của bạn, nó là gì, bạn gặp vấn đề gì với nó.

Như một ví dụ đơn giản:

kube_pod_container_info{namespace=“kube-system”,pod=”kube-apiserver-k8s- 1″,container=”kube-apiserver”,image=

"gcr.io/google-containers/kube-apiserver:v1.14.5"

,image_id=»docker-pullable://gcr.io/google-containers/kube- apiserver@sha256:e29561119a52adad9edc72bfe0e7fcab308501313b09bf99df4a96 38ee634989″,container_id=»docker://7cbe7b1fea33f811fdd8f7e0e079191110268f2 853397d7daf08e72c22d3cf8b»} 1

Bằng cách thực hiện một yêu cầu cuộn tròn đơn giản từ một nhóm không có đặc quyền, bạn có thể nhận được thông tin sau. Nếu bạn không biết mình đang chạy phiên bản Kubernetes nào, nó sẽ dễ dàng cho bạn biết.

Và điều thú vị nhất là ngoài việc truy cập kube-state-metrics, bạn có thể dễ dàng truy cập trực tiếp vào chính Prometheus. Bạn có thể thu thập số liệu từ đó. Bạn thậm chí có thể xây dựng số liệu từ đó. Thậm chí về mặt lý thuyết, bạn có thể xây dựng một truy vấn như vậy từ một cụm trong Prometheus, thao tác này sẽ đơn giản tắt nó đi. Và việc giám sát của bạn sẽ ngừng hoạt động hoàn toàn từ cụm.

Và ở đây câu hỏi đặt ra là liệu có giám sát bên ngoài nào giám sát việc giám sát của bạn hay không. Tôi vừa có cơ hội hoạt động trong cụm Kubernetes mà không gây bất kỳ hậu quả nào cho bản thân. Bạn thậm chí sẽ không biết rằng tôi đang hoạt động ở đó vì không còn bất kỳ sự giám sát nào nữa.

Cũng giống như PSP, có vẻ như vấn đề là tất cả các công nghệ ưa thích này - Kubernetes, Prometheus - chúng không hoạt động và đầy lỗ hổng. Không thực sự.

Có một điều như vậy - Chính sách mạng.

Nếu bạn là một quản trị viên bình thường, thì rất có thể bạn biết về Network Policy rằng đây chỉ là một yaml khác, trong đó đã có rất nhiều trong số đó trong cụm. Và một số Network Policies chắc chắn là không cần thiết. Và ngay cả khi bạn đọc Chính sách mạng là gì, rằng đó là tường lửa yaml của Kubernetes, nó cho phép bạn giới hạn quyền truy cập giữa các không gian tên, giữa các nhóm, thì bạn chắc chắn đã quyết định rằng tường lửa ở định dạng yaml trong Kubernetes dựa trên các phần tóm tắt tiếp theo ... Không, không. Điều này chắc chắn là không cần thiết.

Ngay cả khi bạn không nói với các chuyên gia bảo mật của mình rằng bằng cách sử dụng Kubernetes, bạn vẫn có thể xây dựng một tường lửa rất dễ dàng và đơn giản cũng như một tường lửa rất chi tiết. Nếu họ chưa biết điều này và không làm phiền bạn: “Chà, đưa tôi, đưa tôi…” Sau đó, trong mọi trường hợp, bạn cần Chính sách mạng để chặn quyền truy cập vào một số địa điểm dịch vụ có thể được lấy từ cụm của bạn mà không có bất kỳ sự cho phép nào.

Như trong ví dụ tôi đã đưa ra, bạn có thể lấy số liệu trạng thái kube từ bất kỳ không gian tên nào trong cụm Kubernetes mà không có bất kỳ quyền nào để làm như vậy. Các chính sách mạng đã đóng quyền truy cập từ tất cả các không gian tên khác vào không gian tên giám sát và chỉ có vậy: không có quyền truy cập, không có vấn đề gì. Trong tất cả các biểu đồ tồn tại, cả Prometheus tiêu chuẩn và Prometheus nằm trong nhà điều hành, chỉ có một tùy chọn trong các giá trị điều khiển để chỉ cần kích hoạt các chính sách mạng cho chúng. Bạn chỉ cần bật nó lên và chúng sẽ hoạt động.

Thực sự có một vấn đề ở đây. Là một quản trị viên có râu bình thường, rất có thể bạn đã quyết định rằng không cần các chính sách mạng. Và sau khi đọc tất cả các loại bài viết về các tài nguyên như Habr, bạn đã quyết định rằng flannel, đặc biệt là với chế độ cổng máy chủ, là thứ tốt nhất bạn có thể chọn.

Phải làm gì?

Bạn có thể thử triển khai lại giải pháp mạng mà bạn có trong cụm Kubernetes, thử thay thế nó bằng giải pháp nào đó có nhiều chức năng hơn. Đối với Calico tương tự, ví dụ. Nhưng tôi muốn nói ngay rằng nhiệm vụ thay đổi giải pháp mạng trong cụm làm việc Kubernetes là khá không hề nhỏ. Tôi đã giải được nó hai lần (tuy nhiên, cả hai lần đều là về mặt lý thuyết), nhưng chúng tôi thậm chí còn chỉ ra cách thực hiện điều đó tại Slurms. Đối với các sinh viên của mình, chúng tôi đã chỉ ra cách thay đổi giải pháp mạng trong cụm Kubernetes. Về nguyên tắc, bạn có thể cố gắng đảm bảo rằng không có thời gian ngừng hoạt động trên cụm sản xuất. Nhưng có lẽ bạn sẽ không thành công.

Và vấn đề thực sự được giải quyết rất đơn giản. Có các chứng chỉ trong cụm và bạn biết rằng chứng chỉ của mình sẽ hết hạn sau một năm. Chà, và thường là một giải pháp bình thường với các chứng chỉ trong cụm - tại sao chúng ta lại lo lắng, chúng ta sẽ xây dựng một cụm mới gần đó, để cụm cũ mục nát và triển khai lại mọi thứ. Đúng là khi nó thối rữa, chúng ta sẽ phải ngồi cả ngày, nhưng đây là cụm mới.

Khi nâng cụm mới, đồng thời chèn Calico thay vì flannel.

Phải làm gì nếu chứng chỉ của bạn được cấp trong một trăm năm và bạn sẽ không triển khai lại cụm? Có một thứ như Kube-RBAC-Proxy. Đây là một sự phát triển rất thú vị, nó cho phép bạn nhúng chính nó như một thùng chứa sidecar vào bất kỳ nhóm nào trong cụm Kubernetes. Và nó thực sự bổ sung quyền cho nhóm này thông qua RBAC của chính Kubernetes.

Có một vấn đề. Trước đây, giải pháp Kube-RBAC-Proxy này đã được tích hợp vào Prometheus của nhà điều hành. Nhưng sau đó anh ấy đã biến mất. Giờ đây, các phiên bản hiện đại dựa vào thực tế là bạn có chính sách mạng và đóng nó bằng cách sử dụng chúng. Và do đó chúng ta sẽ phải viết lại biểu đồ một chút. Trong thực tế, nếu bạn đi đến kho lưu trữ này, có những ví dụ về cách sử dụng nó làm sidecar và các biểu đồ sẽ phải được viết lại ở mức tối thiểu.

Có một vấn đề nhỏ nữa. Prometheus không phải là người duy nhất cung cấp các số liệu của mình cho bất kỳ ai. Tất cả các thành phần cụm Kubernetes của chúng tôi cũng có thể trả về số liệu của riêng chúng.

Nhưng như tôi đã nói, nếu bạn không thể truy cập vào cụm và thu thập thông tin thì ít nhất bạn cũng có thể gây ra một số tác hại.

Vì vậy, tôi sẽ nhanh chóng chỉ ra hai cách mà cụm Kubernetes có thể bị phá hủy.

Bạn sẽ cười khi tôi kể cho bạn điều này, đây là hai trường hợp có thật trong đời thực.

Phương pháp một. Cạn kiệt tài nguyên.

Hãy khởi động một nhóm đặc biệt khác. Nó sẽ có một phần như thế này.

resources: 
    requests: 
        cpu: 4 
        memory: 4Gi 

Như bạn đã biết, yêu cầu là lượng CPU và bộ nhớ được dành riêng trên máy chủ cho các nhóm cụ thể có yêu cầu. Nếu chúng ta có một máy chủ bốn lõi trong cụm Kubernetes và bốn nhóm CPU đến đó cùng với các yêu cầu, điều đó có nghĩa là sẽ không có thêm nhóm nào có yêu cầu có thể đến máy chủ này.

Nếu tôi chạy một nhóm như vậy thì tôi sẽ chạy lệnh:

$ kubectl scale special-pod --replicas=...

Sau đó, không ai khác có thể triển khai vào cụm Kubernetes. Bởi vì tất cả các nút sẽ hết yêu cầu. Và do đó tôi sẽ dừng cụm Kubernetes của bạn. Nếu tôi làm việc này vào buổi tối, tôi có thể dừng việc triển khai trong một thời gian khá dài.

Nếu xem lại tài liệu Kubernetes, chúng ta sẽ thấy thứ này được gọi là Phạm vi giới hạn. Nó đặt tài nguyên cho các đối tượng cụm. Bạn có thể viết một đối tượng Phạm vi giới hạn trong yaml, áp dụng nó cho một số không gian tên nhất định - và sau đó trong không gian tên này, bạn có thể nói rằng bạn có tài nguyên mặc định, tối đa và tối thiểu cho các nhóm.

Với sự trợ giúp của thứ như vậy, chúng tôi có thể hạn chế người dùng trong không gian tên sản phẩm cụ thể của các nhóm ở khả năng chỉ ra tất cả các loại điều khó chịu trên nhóm của họ. Nhưng thật không may, ngay cả khi bạn nói với người dùng rằng họ không thể khởi chạy các nhóm có yêu cầu nhiều CPU, thì vẫn có một lệnh chia tỷ lệ tuyệt vời như vậy hoặc họ có thể mở rộng quy mô thông qua bảng điều khiển.

Và đây là nơi bắt nguồn của phương pháp số hai. Chúng tôi ra mắt 11 nhóm. Đó là mười một tỷ. Đây không phải là do tôi nghĩ ra con số như vậy mà là do chính tôi nhìn thấy.

Câu chuyện có thật. Vào buổi tối muộn, tôi chuẩn bị rời khỏi văn phòng. Tôi thấy một nhóm nhà phát triển đang ngồi trong góc, điên cuồng làm gì đó với máy tính xách tay của họ. Tôi đến gần các chàng trai và hỏi: "Chuyện gì đã xảy ra với các bạn vậy?"

Trước đó một chút, khoảng chín giờ tối, một trong những nhà phát triển đã chuẩn bị về nhà. Và tôi quyết định: “Bây giờ tôi sẽ thu nhỏ ứng dụng của mình xuống còn một.” Tôi nhấn một nút, nhưng Internet chậm lại một chút. Anh nhấn lại một lần nữa, nhấn một lần và nhấn Enter. Tôi chọc vào mọi thứ tôi có thể. Sau đó, Internet ra đời - và mọi thứ bắt đầu thu nhỏ lại ở con số này.

Đúng là câu chuyện này không diễn ra trên Kubernetes, lúc đó là Nomad. Nó kết thúc với thực tế là sau một giờ chúng tôi cố gắng ngăn chặn Nomad cố gắng mở rộng quy mô, Nomad trả lời rằng anh ấy sẽ không ngừng mở rộng quy mô và sẽ không làm bất cứ điều gì khác. "Tôi mệt rồi, tôi đi đây." Và anh cuộn tròn.

Đương nhiên, tôi đã cố gắng làm điều tương tự trên Kubernetes. Kubernetes không hài lòng với 1 tỷ nhóm, anh ấy nói: “Tôi không thể. Vượt quá mức bảo vệ miệng bên trong." Nhưng 000 quả thì có thể.

Để đáp lại một tỷ, Cube không rút vào chính nó. Anh ấy thực sự bắt đầu mở rộng quy mô. Quá trình càng tiến xa, anh ấy càng mất nhiều thời gian để tạo ra các nhóm mới. Nhưng quá trình vẫn tiếp tục. Vấn đề duy nhất là nếu tôi có thể khởi chạy các nhóm không giới hạn trong không gian tên của mình, thì ngay cả khi không có yêu cầu và giới hạn, tôi vẫn có thể khởi chạy rất nhiều nhóm với một số tác vụ mà với sự trợ giúp của các tác vụ này, các nút sẽ bắt đầu tích lũy trong bộ nhớ, trong CPU. Khi tôi khởi chạy nhiều nhóm như vậy, thông tin từ chúng sẽ được lưu trữ, tức là, v.v. Và khi có quá nhiều thông tin đến đó, bộ lưu trữ bắt đầu quay trở lại quá chậm - và Kubernetes bắt đầu trở nên buồn tẻ.

Và một vấn đề nữa... Như bạn đã biết, các phần tử điều khiển Kubernetes không phải là một phần tử trung tâm mà là một số thành phần. Đặc biệt, có trình quản lý bộ điều khiển, bộ lập lịch, v.v. Tất cả những người này sẽ bắt đầu làm những công việc ngu ngốc, không cần thiết cùng một lúc, công việc này sẽ ngày càng tốn nhiều thời gian hơn theo thời gian. Trình quản lý bộ điều khiển sẽ tạo các nhóm mới. Người lập lịch sẽ cố gắng tìm một nút mới cho họ. Rất có thể bạn sẽ sớm hết nút mới trong cụm của mình. Cụm Kubernetes sẽ bắt đầu hoạt động ngày càng chậm hơn.

Nhưng tôi quyết định đi xa hơn nữa. Như bạn đã biết, trong Kubernetes có một thứ gọi là dịch vụ. Chà, theo mặc định trong các cụm của bạn, rất có thể, dịch vụ này hoạt động bằng cách sử dụng bảng IP.

Ví dụ: nếu bạn chạy một tỷ nhóm, sau đó sử dụng tập lệnh để buộc Kubernetis tạo dịch vụ mới:

for i in {1..1111111}; do
    kubectl expose deployment test --port 80  
        --overrides="{"apiVersion": "v1", 
           "metadata": {"name": "nginx$i"}}"; 
done 

Trên tất cả các nút của cụm, ngày càng nhiều quy tắc iptables mới sẽ được tạo ra gần như đồng thời. Hơn nữa, một tỷ quy tắc iptables sẽ được tạo cho mỗi dịch vụ.

Tôi đã kiểm tra toàn bộ điều này trên vài nghìn, có thể lên tới mười. Và vấn đề là đã ở ngưỡng này thì việc thực hiện ssh tới nút là khá khó khăn. Bởi vì các gói, trải qua rất nhiều chuỗi, bắt đầu có cảm giác không tốt lắm.

Và tất cả điều này cũng được giải quyết với sự trợ giúp của Kubernetes. Có một đối tượng hạn ngạch tài nguyên như vậy. Đặt số lượng tài nguyên và đối tượng có sẵn cho không gian tên trong cụm. Chúng ta có thể tạo một đối tượng yaml trong mỗi namespace của cụm Kubernetes. Khi sử dụng đối tượng này, chúng ta có thể nói rằng chúng ta có một số lượng yêu cầu và giới hạn nhất định được phân bổ cho không gian tên này, sau đó chúng ta có thể nói rằng trong không gian tên này có thể tạo 10 dịch vụ và 10 nhóm. Và một nhà phát triển ít nhất có thể tự bóp cổ mình vào buổi tối. Kubernetes sẽ nói với anh ta: “Bạn không thể mở rộng quy mô nhóm của mình đến số lượng đó vì tài nguyên vượt quá hạn ngạch”. Thế là xong, vấn đề đã được giải quyết. Tài liệu ở đây.

Một điểm có vấn đề nảy sinh về vấn đề này. Bạn cảm thấy việc tạo một không gian tên trong Kubernetes trở nên khó khăn như thế nào. Để tạo ra nó, chúng ta cần phải tính đến rất nhiều thứ.

Hạn ngạch tài nguyên + Phạm vi giới hạn + RBAC
• Tạo một không gian tên
• Tạo phạm vi giới hạn bên trong
• Tạo hạn ngạch tài nguyên bên trong
• Tạo tài khoản dịch vụ cho CI
• Tạo ràng buộc vai trò cho CI và người dùng
• Tùy chọn khởi chạy các nhóm dịch vụ cần thiết

Vì vậy, tôi muốn nhân cơ hội này để chia sẻ những phát triển của mình. Có một thứ gọi là toán tử SDK. Đây là một cách để cụm Kubernetes viết các toán tử cho nó. Bạn có thể viết báo cáo bằng Ansible.

Lúc đầu nó được viết bằng Ansible, sau đó tôi thấy có một toán tử SDK và viết lại vai trò Ansible thành một toán tử. Câu lệnh này cho phép bạn tạo một đối tượng trong cụm Kubernetes được gọi là lệnh. Bên trong một lệnh, nó cho phép bạn mô tả môi trường cho lệnh này trong yaml. Và trong môi trường nhóm, nó cho phép chúng tôi mô tả rằng chúng tôi đang phân bổ rất nhiều nguồn lực.

Ít làm cho toàn bộ quá trình phức tạp này trở nên dễ dàng hơn.

Và kết luận lại. Phải làm gì với tất cả điều này?
Đầu tiên. Chính sách bảo mật của Pod rất tốt. Và mặc dù thực tế là cho đến nay không có trình cài đặt Kubernetes nào sử dụng chúng, bạn vẫn cần sử dụng chúng trong cụm của mình.

Chính sách mạng không chỉ là một tính năng không cần thiết khác. Đây là những gì thực sự cần thiết trong một cụm.

LimitRange/ResourceQuota - đã đến lúc sử dụng nó. Chúng tôi đã bắt đầu sử dụng tính năng này từ lâu và trong một thời gian dài tôi chắc chắn rằng mọi người đều đang sử dụng nó. Hóa ra điều này rất hiếm.

Ngoài những gì tôi đã đề cập trong báo cáo, còn có những tính năng không có giấy tờ cho phép bạn tấn công cụm. Được phát hành gần đây phân tích sâu rộng các lỗ hổng Kubernetes.

Có những điều thật buồn và đau đớn. Ví dụ: trong một số điều kiện nhất định, các khối nhỏ trong cụm Kubernetes có thể cung cấp nội dung của thư mục warlocks cho người dùng trái phép.

Đây Có hướng dẫn về cách tái tạo mọi thứ tôi đã nói với bạn. Có các tệp chứa ví dụ sản xuất về Chính sách bảo mật ResourceQuota và Pod trông như thế nào. Và bạn có thể chạm vào tất cả điều này.

Cảm ơn tất cả các bạn.

Nguồn: www.habr.com

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