Xác thực Kubernetes YAML để có phương pháp và chính sách tốt nhất
Trong bài viết này, Bizfly Cloud sẽ so sánh 6 công cụ tĩnh để xác thực và ghi điểm các tệp Kubernetes YAML về các phương pháp và chính sách tốt nhất. Hãy cùng tìm hiểu nhé!
Các Kubernetes workload thường được định nghĩa là tài liệu được định dạng YAML.
Một trong những thách thức với YAML là khá khó để thể hiện các ràng buộc hoặc mối quan hệ giữa các tệp manifest.
Điều gì sẽ xảy ra nếu bạn muốn kiểm tra xem tất cả các image được triển khai vào cluster đều được lấy từ một registry đáng tin cậy? Làm cách nào bạn có thể ngăn các Deployment không có PodDisruptBudgets được gửi đến cluster?
Tích hợp kiểm tra tĩnh cho phép bắt lỗi và vi phạm chính sách gần hơn với vòng đời phát triển. Và vì đảm bảo xung quanh tính hợp lệ và an toàn của các định nghĩa tài nguyên được cải thiện, bạn có thể tin tưởng rằng việc sản xuất các workload đang tuân theo các phương pháp tốt nhất.
Hệ sinh thái kiểm tra tĩnh của các tệp Kubernetes YAML có thể được nhóm lại theo các danh mục sau:
- Trình xác thực API - Các công cụ trong danh mục này xác thực một tệp manifest YAML nhất định dựa trên máy chủ Kubernetes API.
- Công cụ kiểm tra tích hợp - Các công cụ trong danh mục này bao gồm các công cụ kiểm tra xác nhận tính bảo mật, các phương pháp tốt nhất, v.v.
- Trình xác thực tùy chỉnh - Các công cụ trong danh mục này cho phép viết kiểm tra tùy chỉnh bằng một số ngôn ngữ như Rego và Javascript.
Trong bài viết này, bạn sẽ tìm hiểu và so sánh 6 công cụ khác nhau:
1. Kubeval
2. Kuber-score
3. Config-lint
4. Copper
5. Conftest
6. Polaris
Xác thực một deployment
Trước khi bắt đầu so sánh các công cụ, bạn nên đặt đường cơ sở (baseline).
Tệp manifest dưới đây có một số vấn đề và không tuân theo các phương pháp hay nhất - bạn có thể phát hiện ra bao nhiêu vấn đề?
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
Bạn sẽ sử dụng tệp YAML này để so sánh các công cụ khác nhau. Tệp manifest mô tả một ứng dụng web luôn trả lời bằng thông báo "Hello World" trên cổng 5678.
Bạn có thể triển khai ứng dụng với:
kubectl apply -f hello-world.yaml
Bạn có thể kiểm tra nó bằng:
kubectl port-forward svc/http-echo 8080:5678
Bạn có thể truy cập http: // localhost: 8080 và xác nhận rằng ứng dụng hoạt động như mong đợi.
1. Kubeval
Tiền đề của kubeval là bất kỳ tương tác nào với Kubernetes đều thông qua API REST của nó. Do đó, bạn có thể sử dụng lược đồ API để xác thực xem một đầu vào YAML nhất định có phù hợp với lược đồ hay không.
Hãy xem một ví dụ.
Sau khi cài đặt, hãy chạy nó với tệp manifest đã đề cập trước đó:
kubeval base-valid.yaml
PASS - base-valid.yaml contains a valid Deployment (http-echo)
PASS - base-valid.yaml contains a valid Service (http-echo)
Khi thành công, kubeval thoát với exit code là 0. Bạn có thể xác minh exit code bằng:
echo $?
0
Bây giờ hãy thử kubeval với một tệp manifest khác:
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
Bạn có thể phát hiện ra vấn đề không?
Hãy chạy kubeval:
kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contains an invalid Deployment (http-echo) - selector: selector is required
PASS - kubeval-invalid.yaml contains a valid Service (http-echo)
# let's check the return value
echo $?
1
Tài nguyên không vượt qua xác thực.
Các Deployment sử dụng phiên bản app/v1 API phải bao gồm một selector phù hợp với nhãn Pod. Tệp manifest ở trên không bao gồm selector và chạy kubeval đối với tệp manifest đã báo cáo lỗi và exit code khác 0.
Bạn có thể tự hỏi điều gì sẽ xảy ra khi bạn chạy kubectl apply -f với tệp manifest trên?
Hãy thử:
kubectl apply -f kubeval-invalid.yaml
error: error validating "kubeval-invalid.yaml": error validating data: ValidationError(Deployment.spec):
missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors,
turn validation off with --validate=false
Chính xác là lỗi mà kubeval đã cảnh báo cho bạn.
Bạn có thể sửa tài nguyên bằng cách thêm selector như sau:
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
Ưu điểm của một công cụ như kubeval là bạn có thể phát hiện sớm các lỗi như vậy trong chu kỳ triển khai của mình.
Ngoài ra, bạn không cần truy cập vào một cluster để chạy kiểm tra - chúng có thể chạy ngoại tuyến. Theo mặc định, kubeval xác thực tài nguyên dựa trên lược đồ API Kubernetes mới nhất chưa được phát hành. Tuy nhiên, trong hầu hết các trường hợp, bạn có thể muốn chạy xác thực đối với một bản phát hành Kubernetes cụ thể.
Bạn có thể kiểm tra một phiên bản API cụ thể bằng cách sử dụng flag --kubernetes-version:
kubeval --kubernetes-version 1.16.1 base-valid.yaml
Hãy lưu ý rằng phiên bản phát hành phải có dạng Major.Minor.Patch. Nếu bạn cần chạy kubeval ngoại tuyến, bạn có thể tải xuống các lược đồ và sau đó sử dụng flag --schema-location để sử dụng thư mục cục bộ. Ngoài các tệp YAML riêng lẻ, bạn có thể chạy kubeval đối với các thư mục cũng như đầu vào tiêu chuẩn.
Bạn cũng nên biết rằng Kubeval giúp tích hợp dễ dàng với Continuous Integration pipeline.
Nếu bạn muốn bao gồm các kiểm tra trước khi gửi các manifest của mình đến cluster, bạn sẽ rất vui khi biết rằng kubeval hỗ trợ 3 định dạng đầu ra:
- Văn bản thô
- JSON
- Kiểm tra mọi thứ Giao thức (Test Anything Protocol - TAP)
Và bạn có thể sử dụng một trong các định dạng để phân tích cú pháp đầu ra hơn nữa nhằm tạo một bản tóm tắt kết quả tùy chỉnh.
Một hạn chế của kubeval là nó hiện không thể xác thực theo Custom Resource Definitions (CRD).
Tuy nhiên, bạn có thể bảo kubeval bỏ qua chúng.
Kubeval là một lựa chọn tuyệt vời để kiểm tra và xác thực tài nguyên, nhưng hãy lưu ý rằng tài nguyên vượt qua bài kiểm tra không được đảm bảo tuân theo các phương pháp hay nhất.
Ví dụ: sử dụng thẻ mới nhất trong container image không được coi là phương pháp hay nhất.
Tuy nhiên, Kubeval không báo cáo đó là lỗi và nó sẽ xác thực YAML mà không có cảnh báo.
Điều gì sẽ xảy ra nếu bạn muốn ghi điểm YAML và bắt các lỗi vi phạm, chẳng hạn như thẻ mới nhất? Làm cách nào để bạn có thể kiểm tra các tệp YAML của mình theo các phương pháp hay nhất?
2. Kube-score
Kube-score phân tích các YAML manifest và ghi điểm chúng so với các lần kiểm tra tích hợp sẵn. Các kiểm tra này được chọn dựa trên các khuyến nghị bảo mật và các phương pháp tốt nhất, chẳng hạn như:
- Chạy container với tư cách là non-root user.
- Chỉ định kiểm tra sức khỏe cho các pod.
- Xác định các yêu cầu và giới hạn tài nguyên.
Kết quả của việc kiểm tra có thể là OK, WARNING hoặc CRITICAL.
Hãy thử và chạy nó với tệp manifest trước đó base-valid.yaml:
kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITICAL] Container Image Tag
· http-echo -> Image with latest tag
Using a fixed tag is recommended to avoid accidental upgrades
[CRITICAL] Pod NetworkPolicy
· The pod does not have a matching network policy
Create a NetworkPolicy that targets this pod
[CRITICAL] Pod Probes
· Container is missing a readinessProbe
A readinessProbe should be used to indicate when the service is ready to receive traffic.
Without it, the Pod is risking to receive traffic before it has booted. It is also used during
rollouts, and can prevent downtime if a new version of the application is failing.
More information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container Security Context
· http-echo -> Container has no configured security context
Set securityContext to run the container in a more secure context.
[CRITICAL] Container Resources
· http-echo -> CPU limit is not set
Resource limits are recommended to avoid resource DDOS. Set resources.limits.cpu
· http-echo -> Memory limit is not set
Resource limits are recommended to avoid resource DDOS. Set resources.limits.memory
· http-echo -> CPU request is not set
Resource requests are recommended to make sure that the application can start and run without
crashing. Set resources.requests.cpu
· http-echo -> Memory request is not set
Resource requests are recommended to make sure that the application can start and run without crashing.
Set resources.requests.memory
[CRITICAL] Deployment has PodDisruptionBudget
· No matching PodDisruptionBudget was found
It is recommended to define a PodDisruptionBudget to avoid unexpected downtime during Kubernetes
maintenance operations, such as when draining a node.
[WARNING] Deployment has host PodAntiAffinity
· Deployment does not have a host podAntiAffinity set
It is recommended to set a podAntiAffinity that stops multiple pods from a deployment from
being scheduled on the same node. This increases availability in case the node becomes unavailable.
Tệp YAML vượt qua kiểm tra kubeval, nhưng kube-score chỉ ra một số thiếu sót:
- Thiếu các readiness probe.
- Thiếu bộ nhớ và yêu cầu CPU và giới hạn.
- Thiếu ngân sách gián đoạn Pod.
- Thiếu quy tắc anti-affinity để tối đa hóa tính khả dụng.
- Container chạy dưới dạng root.
Đó là tất cả những điểm hợp lệ mà bạn nên giải quyết để làm cho việc triển khai của bạn mạnh mẽ và đáng tin cậy hơn.
Các lệnh kube-score in một đầu ra chứa tất cả các vi phạm WARNING và CRITICAL. Nếu bạn định sử dụng nó như một phần của Continuous Integration pipeline, bạn có thể sử dụng đầu ra ngắn gọn hơn với flag --output-format ci cũng cho ra các kiểm tra với mức OK:
kube-score score base-valid.yaml --output-format ci
[OK] http-echo apps/v1/Deployment
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Image with latest tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: The pod does not have a matching network policy
[CRITICAL] http-echo apps/v1/Deployment: Container is missing a readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container has no configured security context
[CRITICAL] http-echo apps/v1/Deployment: No matching PodDisruptionBudget was found
[WARNING] http-echo apps/v1/Deployment: Deployment does not have a host podAntiAffinity set
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
Tương tự như kubeval, kube-score trả về exit code khác 0 khi có kiểm tra CRITICAL không thành công, nhưng bạn đã định cấu hình nó không thành công ngay cả trên WARNINGs. Ngoài ra còn có một kiểm tra tích hợp để xác thực tài nguyên so với các phiên bản API khác nhau - tương tự như kubeval. Tuy nhiên, thông tin này được mã hóa cứng trong chính kube-score và bạn không thể chọn một phiên bản Kubernetes khác.
Do đó, nếu bạn nâng cấp cluster của mình hoặc bạn có một số cluster khác nhau đang chạy các phiên bản khác nhau, điều này có thể chứng tỏ là một hạn chế nghiêm trọng.
Kiểm tra Kube-score là một công cụ tuyệt vời để thực thi các phương pháp tốt nhất, nhưng nếu bạn muốn tùy chỉnh một hoặc thêm các quy tắc của riêng mình thì sao? Câu trả lời là không thể.
Kube-score không được thiết kế để có thể mở rộng và bạn không thể thêm hoặc chỉnh sửa các chính sách.
Nếu bạn muốn viết kiểm tra tùy chỉnh để tuân thủ các chính sách tổ chức của mình, bạn có thể sử dụng một trong bốn tùy chọn tiếp theo: config-lint, copper, conftest hoặc polaris.
3. Config-lint
Config-lint là một công cụ được thiết kế để xác thực các tệp cấu hình được viết trong tệp manifest YAML, JSON, Terraform, CSV và Kubernetes.
Config-lint không có kiểm tra tích hợp sẵn cho các tệp manifest Kubernetes.
Bạn phải viết các quy tắc của riêng mình để thực hiện bất kỳ xác nhận nào. Các quy tắc được viết dưới dạng tệp YAML, được gọi là bộ quy tắc và có cấu trúc sau:
version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
- "*.yaml"
rules:
# list of rules
Hãy xem xét chi tiết hơn:
- Các trường type chỉ ra loại cấu hình bạn sẽ được kiểm tra với config-lint - nó luôn luôn là Kubernetes đối với các Kubernetes manifest.
- Các trường files chấp nhận một thư mục như là đầu vào, thêm vào tập tin cá nhân.
- Các trường rule là nơi bạn có thể xác định kiểm tra tùy chỉnh.
Giả sử bạn muốn kiểm tra xem các image trong Deployment có luôn được lấy từ một kho lưu trữ đáng tin cậy chẳng hạn như my-company.com/myapp:1.0. Một quy tắc config-lint thực hiện một kiểm tra như vậy có thể trông như thế này:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Deployment must use a valid image tag
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"
Mỗi quy tắc phải có các thuộc tính sau:
- id - Điều này xác định duy nhất quy tắc.
- severity- Nó phải là một trong những FAILURE, WARNING, và NON_COMPLIANT.
- message - Nếu một quy tắc bị vi phạm, nội dung của chuỗi này sẽ được hiển thị.
- resource - Loại tài nguyên bạn muốn áp dụng quy tắc này.
- assertions - Danh sách các điều kiện sẽ được đánh giá dựa trên tài nguyên được chỉ định.
Trong quy tắc trên, xác nhận every kiểm tra rằng mỗi container trong một Deployment (key: spec.templates.spec.containers) sử dụng một image đáng tin cậy (tức là image bắt đầu bằng "my-company.com/").
Bộ quy tắc hoàn chỉnh trông như thế này:
version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY
severity: FAILURE
message: Deployment must use a valid image repository
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"
Nếu bạn muốn kiểm thử check, bạn có thể lưu bộ quy tắc dưới dạng check_image_repo.yaml.
Bây giờ hãy chạy xác thực đối với tệp base-valid.yaml:
config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Every expression fails: And expression fails: image does not start with my-company.com/",
"Category": "",
"CreatedAt": "2020-06-04T01:29:25Z",
"Filename": "test-data/base-valid.yaml",
"LineNumber": 0,
"ResourceID": "http-echo",
"ResourceType": "Deployment",
"RuleID": "DEPLOYMENT_IMAGE_REPOSITORY",
"RuleMessage": "Deployment must use a valid image repository",
"Status": "FAILURE"
}
]
Nó thất bại.
Bây giờ, hãy xem xét tệp manifest sau với một kho lưu trữ image hợp lệ:
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: my-company.com/http-echo:1.0
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
Chạy kiểm tra tương tự với tệp manifest ở trên và sẽ không có vi phạm nào được báo cáo:
config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]
Config-lint là một framework đầy hứa hẹn cho phép bạn viết các kiểm tra tùy chỉnh cho các Kubernetes YAML manifest bằng cách sử dụng YAML DSL.
Nhưng nếu bạn muốn diễn đạt logic và kiểm tra phức tạp hơn thì sao? Không phải YAML quá hạn chế cho điều đó? Điều gì sẽ xảy ra nếu bạn có thể diễn đạt những kiểm tra đó bằng một ngôn ngữ lập trình thực?
4. Copper
Copper V2 là một framework xác thực các tệp manifest bằng cách sử dụng các kiểm tra tùy chỉnh - giống như config-lint. Tuy nhiên, Copper không sử dụng YAML để xác định các kiểm tra.
Thay vào đó, các kiểm thử được viết bằng JavaScript và Copper cung cấp một thư viện với một vài trình trợ giúp cơ bản để hỗ trợ việc đọc các đối tượng Kubernetes và báo cáo lỗi.
Tương tự như config-lint, Copper không có kiểm tra tích hợp sẵn.
Hãy viết kiểm tra để đảm bảo rằng các triển khai chỉ có thể kéo container image từ một kho lưu trữ đáng tin cậy chẳng hạn như my-company.com.
Tạo một tệp mới, check_image_repo.js với nội dung sau:
$$.forEach(function($){
if ($.kind === 'Deployment') {
$.spec.template.spec.containers.forEach(function(container) {
var image = new DockerImage(container.image);
if (image.registry.lastIndexOf('my-company.com/') != 0) {
errors.add_error('no_company_repo',"Image " + $.metadata.name + " is not from my-company.com repo", 1)
}
});
}
});
Bây giờ, để chạy kiểm tra này đối với manifest base-valid.yaml, bạn có thể sử dụng lệnh copper validate:
copper validate --in=base-valid.yaml --validator=check_image_tag.js
Check no_company_repo failed with severity 1 due to Image http-echo is not from my-company.com repo
Validation failed
Như bạn có thể tưởng tượng, bạn có thể viết các kiểm tra phức tạp hơn như xác thực tên miền cho các tệp Ingress manifest hoặc từ chối bất kỳ Pod nào chạy dưới dạng đặc quyền.
Copper có một số trình trợ giúp tích hợp:
- Các hàm DockerImage đọc các tập tin đầu vào cụ thể và tạo ra một đối tượng chứa các thuộc tính sau:
+ name chứa tên image
+ tag chứa thẻ image
+ registry chứa image registry
+ registry_url chứa giao thức và image registry
+ fqin đại diện cho toàn bộ vị trí image đủ điều kiện.
- Các hàm findByName giúp tìm một nguồn cung cấp một kind và name từ một tập tin đầu vào
- Các hàm findByLabels giúp tìm một nguồn cung cấp kind và labels.
Theo mặc định, nó tải toàn bộ tệp đầu vào YAML vào biến $$ và làm cho nó có sẵn trong các tập lệnh của bạn (nếu trước đây bạn đã sử dụng jQuery, bạn có thể thấy mẫu này quen thuộc).
Ngoài việc không phải học một ngôn ngữ tùy chỉnh, bạn có quyền truy cập vào toàn bộ ngôn ngữ JavaScript để viết các kiểm tra của mình, chẳng hạn như string interpolation, các hàm, v.v.
Cần lưu ý rằng bản phát hành copper hiện tại nhúng phiên bản ES5 của JavaScript engine chứ không phải ES6.
Nếu Javascript không phải là ngôn ngữ ưa thích của bạn và bạn thích ngôn ngữ được thiết kế để truy vấn và mô tả các chính sách, bạn nên kiểm tra kỹ lưỡng.
5. Conftest
Conftest là một framework thử nghiệm cho dữ liệu cấu hình có thể được sử dụng để kiểm tra và xác minh các Kubernetes manifest.
Các kiểm thử được viết bằng ngôn ngữ truy vấn được xây dựng có mục đích - Rego.
Tương tự như config-lint và copper, conftest không đi kèm với bất kỳ kiểm tra tích hợp nào.
Vì vậy, chúng ta hãy thử nó, bằng cách viết một chính sách. Đối với ví dụ trước, bạn sẽ kiểm tra xem container có đến từ một nguồn đáng tin cậy hay không.
Tạo một thư mục mới conftest-checks và một tệp có tên check_image_registry.rego với nội dung sau:
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "my-company.com/")
msg := sprintf("image '%v' doesn't come from my-company.com repository", [image])
}
Bây giờ hãy chạy conftest để xác thực tệp manifest base-valid.yaml:
conftest test --policy ./conftest-checks base-valid.yaml
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
1 tests, 1 passed, 0 warnings, 1 failure
Tất nhiên, nó không thành công vì image không đáng tin cậy.
Tệp Rego ở trên chỉ định một khối deny đánh giá vi phạm khi đúng.
Khi bạn có nhiều hơn một khối deny, conftest sẽ kiểm tra chúng một cách độc lập và kết quả tổng thể là sự vi phạm của bất kỳ khối nào trong số các khối đó dẫn đến vi phạm.
Khác với định dạng đầu ra mặc định, conftest hỗ trợ JSON, TAP và định dạng bảng thông qua flag --output, điều này rất tuyệt nếu bạn muốn tích hợp các báo cáo với Continuous Integration pipeline.
Để giúp debug các chính sách, conftest có một flag --trace in một dấu vết về cách conftest phân tích cú pháp các tệp chính sách được chỉ định. Chính sách Conftest có thể được xuất bản và chia sẻ dưới dạng các artefact trong các OCI registry(Open Container Initiative).
Các lệnh push và pull cho phép xuất bản một artefact và kéo một artefact hiện có từ một sổ registry từ xa.
Chúng ta hãy xem demo về việc xuất bản chính sách trên lên một docker registry cục bộ bằng cách sử dụng conftest push.
Bắt đầu một docker registry cục bộ bằng cách sử dụng:
docker run -it --rm -p 5000:5000 registry
Từ một terminal khác, điều hướng đến thư mục conftest-checks được tạo ở trên và chạy lệnh sau:
conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest
Lệnh sẽ hoàn tất thành công với thông báo sau:
2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609c
Bây giờ, hãy tạo một thư mục tạm thời và chạy lệnh conftest pull sẽ tải xuống gói ở trên vào thư mục tạm thời:
cd $(mktemp -d)
conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest
Bạn sẽ thấy rằng có một thư mục con mới policy trong thư mục tạm thời chứa tệp chính sách đã đẩy trước đó:
tree
.
└── policy
└── check_image_registry.rego
Bạn thậm chí có thể chạy các kiểm thử trực tiếp từ kho lưu trữ:
conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
2 tests, 1 passed, 0 warnings, 1 failure
Thật không may, DockerHub vẫn chưa phải là một trong những hệ thống đăng ký được hỗ trợ.
Tuy nhiên, nếu bạn đang sử dụng Azure Container Registry (ACR) hoặc chạy đăng ký vùng chứa của mình, bạn có thể gặp may. Các định dạng artefact giống như được sử dụng bởi các Open Policy Agent (OPA) bundle, làm cho nó có thể sử dụng conftest để chạy thử nghiệm từ các OPA bundle hiện có.
6. Polaris
Công cụ cuối cùng bạn sẽ khám phá trong bài viết này là polaris.
Polaris có thể được cài đặt bên trong một cluster hoặc như một công cụ dòng lệnh để phân tích các biểu hiện Kubernetes tĩnh.
Khi chạy như một công cụ dòng lệnh, nó bao gồm một số kiểm tra tích hợp bao gồm các trường như bảo mật và các phương pháp tốt nhất - tương tự như kube-score. Ngoài ra, bạn có thể sử dụng nó để viết các kiểm tra tùy chỉnh tương tự như config-lint, copper và conftest.
Nói cách khác, polaris kết hợp tốt nhất của hai loại: bộ kiểm tra tích hợp và bộ kiểm tra tùy chỉnh. Sau khi cài đặt, bạn có thể chạy polaris với tệp manifest base-valid.yaml với:
polaris audit --audit-path base-valid.yaml
Lệnh trên sẽ in ra một chuỗi có định dạng JSON trình bày chi tiết các lần kiểm tra đã được chạy và kết quả của mỗi lần kiểm tra. Đầu ra sẽ có cấu trúc như sau:
{
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "test-data/base-valid.yaml",
"DisplayName": "test-data/base-valid.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 2,
"Namespaces": 0,
"Controllers": 2
},
"Results": [
/* long list */
]
}
Tương tự như kube-score, polaris xác định một số trường hợp trong đó tệp manifest thiếu các phương pháp hay nhất được đề xuất, bao gồm:
- Thiếu kiểm tra sức khỏe cho các pod.
- Container image không có thẻ được chỉ định.
- Container chạy dưới dạng root.
- Yêu cầu và giới hạn cho CPU và memory không được đặt.
Mỗi kiểm tra đều được phân loại với mức độ nghiêm trọng của warning hoặc danger.
Nếu bạn không quan tâm đến kết quả chi tiết, việc chuyển flag --format score in một số trong phạm vi 1-100 mà polaris dùng làm score:
polaris audit --audit-path test-data/base-valid.yaml --format score
68
Điểm càng gần 100, mức độ phù hợp càng cao.
Nếu bạn kiểm tra exit code của lệnh polaris audit, bạn sẽ thấy rằng nó là 0.
Để polaris audit thoát bằng mã khác 0, bạn có thể sử dụng hai flag khác. Các flag --set-exit-code-below-score chấp nhận một số điểm ngưỡng trong khoảng 1-100 và sẽ thoát ra với một exit code của 4 khi score là dưới ngưỡng.
Điều này rất hữu ích trong trường hợp điểm cơ bản của bạn là 75 và bạn muốn được cảnh báo khi nó thấp hơn. Các flag --set-exit-code-on-danger sẽ thoát ra với một exit code của 3 khi bất kỳ danger kiểm tra thất bại.
Bây giờ chúng ta hãy xem cách bạn có thể xác định kiểm tra tùy chỉnh polaris để kiểm tra xem container image trong Deployment có phải từ một registry đáng tin cậy hay không.
Kiểm tra tùy chỉnh được xác định ở định dạng YAML với chính kiểm tra được mô tả bằng cách sử dụng Lược đồ JSON.
Đoạn mã YAML sau đây xác định một check-called checkImageRepo:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
Chúng ta hãy xem xét kỹ hơn nó:
- successMessage là một chuỗi sẽ được hiển thị khi kiểm tra thành công.
- failureMessage được hiển thị khi kiểm tra không thành công.
- Category đề cập đến một trong các loại - Images, Health Checks, Security, Networking và Resources.
- Target là một chuỗi xác định spec object nào mà việc kiểm tra được áp dụng - và nên là một trong Container, Pod hoặc Controller.
- Bản thân việc kiểm thử được định nghĩa trong object schema bằng lược đồ JSON. Ở đây kiểm tra sử dụng từ khóa pattern để đối sánh xem image có phải từ một registry được phép hay không.
Để chạy kiểm tra được xác định ở trên, bạn sẽ cần tạo tệp cấu hình Polaris như sau:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
Hãy chia nhỏ tệp:
- Các trường checks xác định kiểm tra và mức độ nghiêm trọng của nó. Vì bạn muốn được cảnh báo khi image không đáng tin cậy, nên checkImageRepo được chỉ định một mức độ nghiêm trọng danger.
- Các checkImageRepo tuwj kiểm tra nó sau đó được xác định trong đối tượng customChecks.
Bạn có thể lưu tệp ở trên dưới dạng custom_check.yaml và chạy polaris audit với tệp YAML manifest mà bạn muốn xác thực.
Bạn có thể kiểm tra nó bằng tệp manifest base-valid.yaml:
polaris audit --config custom_check.yaml --audit-path base-valid.yaml
Bạn sẽ thấy rằng polaris audit chỉ chạy kiểm tra tùy chỉnh không thành công được xác định ở trên. Nếu bạn sửa đổi container image thành my-company.com/http-echo:1.0, polaris sẽ báo thành công.
Kho lưu trữ Github chứa tệp manifest đã sửa đổi, vì vậy bạn có thể kiểm tra lệnh trước đó đối với tệp manifest image-valid-mycompany.yaml.
Nhưng làm thế nào để bạn chạy cả kiểm tra tích hợp và kiểm tra tùy chỉnh?
Tệp cấu hình ở trên phải được cập nhật với tất cả các số nhận dạng kiểm tra được tích hợp sẵn và sẽ như sau:
checks:
cpuRequestsMissing: warning
cpuLimitsMissing: warning
# Other inbuilt checks..
# ..
# custom checks
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
Bạn có thể kiểm tra tệp manifest base-valid.yaml bằng kiểm tra tùy chỉnh và kiểm tra tích hợp với:
polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yaml
Polaris tăng cường kiểm tra tích hợp với kiểm tra tùy chỉnh của bạn, do đó kết hợp tốt nhất của cả hai thế giới. Tuy nhiên, không có quyền truy cập vào các ngôn ngữ mạnh mẽ hơn như Rego hoặc JavaScript có thể là một hạn chế để viết các kiểm tra phức tạp hơn.
Tóm lược
Mặc dù có rất nhiều công cụ để xác thực, ghi điểm và xác định các tệp Kubernetes YAML, nhưng điều quan trọng là phải có một mental model về cách bạn sẽ thiết kế và thực hiện kiểm tra.
Ví dụ: nếu bạn nghĩ về các tệp Kubernetes manifest đi qua một đường ống (pipeline), kubeval có thể là bước đầu tiên trong một pipeline như vậy vì nó xác thực nếu các định nghĩa đối tượng tuân theo lược đồ API Kubernetes.
Khi quá trình kiểm tra này thành công, có lẽ bạn có thể chuyển sang các bài kiểm tra phức tạp hơn, chẳng hạn như các phương pháp hay nhất tiêu chuẩn và chính sách tùy chỉnh.
Kube-score và polaris là những lựa chọn tuyệt vời ở đây.
Nếu bạn có yêu cầu phức tạp và muốn tùy chỉnh kiểm tra đến chi tiết, bạn nên xem xét copper, config-lint và conftest.
Trong khi cả conftest và config-lint sử dụng nhiều YAML hơn để xác định các quy tắc xác thực tùy chỉnh, thì copper cung cấp cho bạn quyền truy cập vào một ngôn ngữ lập trình thực khiến nó trở nên khá hấp dẫn.
Nhưng bạn có nên sử dụng một trong những thứ này và viết tất cả các kiểm tra từ đầu hay thay vào đó bạn nên sử dụng Polaris và chỉ viết các kiểm tra tùy chỉnh bổ sung? Điều này còn tùy.
Vì các công cụ này không dựa vào quyền truy cập vào một Kubernetes cluster, chúng dễ dàng thiết lập và cho phép bạn thực thi kiểm soát cũng như đưa ra phản hồi nhanh chóng để lấy các yêu cầu author cho các project.
Bizfly Kubernetes Engine với những tính năng ưu việt và vượt trội sẽ mang lại những tác động tích cực đến các Dev team/DevOps cũng như toàn bộ doanh nghiệp. Nếu bạn đang muốn bắt đầu với Kubernetes, truy cập: https://bizflycloud.vn/kubernetes-engine để trải nghiệm miễn phí ngay hôm nay.
>> Có thể bạn quan tâm: Cách triển khai Nginx Ingress với Cert-Manager trên Bizfly Kubernetes Engine