Kubernetes YAML最佳实践和策略
Kubernetes工作负载最常用YAML格式的文件来定义。
YAML的问题之一就是很难描述清单文件之间的约束或关系。
如果你希望检查是否已从受信任的注册表中提取部署到群集中的所有映像,该怎么办?
如何防止没有Pod安全策略的工作负载提交到集群?
集成静态检查可以在更接近开发生命周期的时间内捕获错误和违反策略的行为。
并且由于改善了资源定义的有效性和安全性,因此你可以相信生产工作负载遵循最佳实践。
Kubernetes YAML文件的静态检查生态系统可以分为以下几类:
- API验证程序:此类工具针对Kubernetes API服务器验证给定的YAML清单。
- 内置检查器:此类工具捆绑了针对安全性,最佳实践等的自觉检查。
- 自定义验证器:此类工具允许使用多种语言(例如python和Javascript)编写自定义检查。
在本文中,你将学习到六个不同的工具:
Kubeval
Kube-score
Config-lint
Copper
Conftest
Polaris
Let's Go ~~~
基准服务
首先部署一个基准服务,以便后面测试对比
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
部署完成并验证如下:
[root@k8s-node001 Test]# kubectl get po
NAME READY STATUS RESTARTS AGE
http-echo-57dd74545-rtxzm 1/1 Running 0 65s
http-echo-57dd74545-trst7 1/1 Running 0 65s
[root@k8s-node001 Test]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
http-echo ClusterIP 10.102.221.64 <none> 5678/TCP 70s
[root@k8s-node001 Test]# curl 10.102.221.64:5678
hello-world
以上YAML文件能部署成功,但是,它遵循最佳做法吗?
Let's start.
kubeval
kubeval的前提是与Kubernetes的任何交互都通过其REST API进行。
因此,可以使用API模式来验证给定的YAML输入是否符合该模式。
安装kubeval
wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz
tar xf kubeval-linux-amd64.tar.gz
cp kubeval /usr/local/bin
现在我们来改下base.yaml,删除
selector:
matchLabels:
app: http-echo
然后使用kubeval对base.yaml检查
[root@k8s-node001 Test]# kubeval base.yaml
WARN - base.yaml contains an invalid Deployment (http-echo) - selector: selector is required
PASS - base.yaml contains a valid Service (http-echo)
输出看到一个WARN,提示selector是必须的字段
然后恢复selector,再次检查
[root@k8s-node001 Test]# kubeval base.yaml
PASS - base.yaml contains a valid Deployment (http-echo)
PASS - base.yaml contains a valid Service (http-echo)
检查PASS
kubeval之类的工具的优势在于,咱们可以在部署周期的早期发现此类错误。
另外,您不需要访问集群即可运行检查-它们可以脱机运行。
默认情况下,kubeval会根据最新的未发布的Kubernetes API模式验证资源。
更多用法详情请参见官网
kube-score
kube-score会对你提供的YAML清单进行分析,并针对集群的内置检查对其进行评分。
kube-score提供在线版和离线版
本文偷懒就用在线版了
首先打开https://kube-score.com/ ,然后在输入框贴入写好的YAML清单,这里以上文base.yaml来分析
解析结果如下
从如上可以看到针对这个文件给出的建议,比如资源限制、镜像TAG、Pod网络策略等。不错吧,非常好用的工具。。。
当然,kube-score并不可扩展,并且您不能添加或调整策略。
如果要编写自定义检查以符合组织策略,则可以使用以下四个工具之一:config-lint,copper,conftest或Polaris。
Config-lint
Config-lint是用于验证以YAML,JSON,Terraform,CSV和Kubernetes清单编写的配置文件的工具。
安装Config-lint
wget https://github.com/stelligent/config-lint/releases/download/v1.6.0/config-lint_Linux_x86_64.tar.gz
tar -zxf config-lint_Linux_x86_64.tar.gz
mv config-lint /usr/local/bin/
Config-lint并没有对Kubernetes清单进行内置检查。你必须编写自己的规则才能执行任何验证。
规则被写为YAML文件,称为规则集,并具有以下结构:
version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
- "*.yaml"
rules:
# list of rules
假设咱们希望检查部署中的镜像是否总是从可信任的仓库(例如kubeops.net/app:1.0 )中提取。
实施此类检查的config-lint规则如下所示:
- 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: "kubeops.net/"
一个完整的规则集如下所示:
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: "kubeops.net/"
如果要测试检查,可以将规则集另存为check_image_repo.yaml。
然后使用config-lint执行检查
[root@k8s-node001 Test]# config-lint -rules check_image_repo.yaml base.yaml
[
{
"AssertionMessage": "Every expression fails: And expression fails: image does not start with kubeops.net/",
"Category": "",
"CreatedAt": "2020-11-02T08:28:43Z",
"Filename": "base.yaml",
"LineNumber": 0,
"ResourceID": "http-echo",
"ResourceType": "Deployment",
"RuleID": "DEPLOYMENT_IMAGE_REPOSITORY",
"RuleMessage": "Deployment must use a valid image repository",
"Status": "FAILURE"
}
]
可以看到Every expression fails,检测不通过。
现在我们来改下images地址为image: kubeops.net/http-echo
,再来检查一次
[root@k8s-node001 Test]# config-lint -rules check_image_repo.yaml base.yaml
[]
输出不报错即为成功。
Config-lint是一个很有前途的框架,可以让你使用YAML DSL为Kubernetes YAML清单编写自定义检查。
但是,如果您想表达更复杂的逻辑和检查该怎么办?
YAML对此是否也有限制?
如果您可以使用真正的编程语言来表达这些检查,该怎么办?接下来看Copper
Copper
Copper V2是一个使用自定义检查来验证清单的框架,就像config-lint一样。
但是,Copper不使用YAML定义检查。
相反,测试是用JavaScript编写的,而Copper提供了一个包含一些基本帮助程序的库,以帮助读取Kubernetes对象和报告错误。
安装Copper
https://github.com/cloud66-oss/copper/releases/download/2.0.1/linux_amd64_2.0.1
mv linux_amd64_2.0.1 copper
chmod + x copper
mv copper /usr/local/bin/
与config-lint相似,Copper并没有提供内置检查。
让我们自定义一个检查,以确保部署镜像tag必须非latest。
check_image_repo.js
$$.forEach(function($){
if ($.kind === 'Deployment') {
$.spec.template.spec.containers.forEach(function(container) {
var image = new DockerImage(container.image);
if (image.tag === 'latest') {
errors.add_error('no_latest',"latest is used in " + $.metadata.name, 1)
}
});
}
});
执行检查
[root@k8s-node001 Test]# copper validate --in=base.yaml --validator=check_image_tag.js
Check no_latest failed with severity 1 due to latest is used in http-echo
Validation failed
现在修改为image: kubeops.net/http-echo:v1.0.0
[root@k8s-node001 Test]# copper validate --in=base.yaml --validator=check_image_tag.js
Validation successful
更多用法参见
Conftest
Conftest是用于配置数据的测试框架,可用于检查和验证Kubernetes清单。
测试使用专用查询语言Rego编写的。
安装Conftest
wget https://github.com/open-policy-agent/conftest/releases/download/v0.21.0/conftest_0.21.0_Linux_x86_64.tar.gz
tar -xzf conftest_0.21.0_Linux_x86_64.tar.gz
mv conftest /usr/local/bin
与config-lint和copper类似,conftest没有任何内置检查。
首先创建一个新目录conftest-checks和一个名为check_image_registry.rego的文件,其内容如下:
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "kubeops.net/")
msg := sprintf("image '%v' doesn't come from kubeops.net repository", [image])
}
先修改base.yaml,image: docker.io/http-echo
使用conftest执行检测
[root@k8s-node001 Test]# conftest test --policy ./conftest-checks base.yaml
FAIL - base.yaml - image 'docker.io/http-echo:v1.0.0' doesn't come from kubeops.net repository
2 tests, 1 passed, 0 warnings, 1 failure, 0 exceptions
再次修改为base.yaml,image: kubeops.net/http-echo
[root@k8s-node001 Test]# conftest test --policy ./conftest-checks base.yaml
2 tests, 2 passed, 0 warnings, 0 failures, 0 exceptions
更多用法参见
Polaris
最后一个工具了,Polaris既可以安装在集群内部,也可以作为命令行工具来静态分析Kubernetes清单。
作为命令行工具运行时,它包含多个内置检查,涉及诸如安全性和最佳实践等方面,类似于kube-score。
另外,你可以使用它来编写类似于config-lint,copper和conftest的自定义检查。
换句话说,Polaris结合了两类的优点:内置和自定义检查器。
安装Polaris,这里只安装命令行模式
wget https://github.com/FairwindsOps/polaris/releases/download/1.2.1/polaris_1.2.1_linux_amd64.tar.gz
tar -zxf polaris_1.2.1_linux_amd64.tar.gz
mv polaris /usr/local/bin/
安装完成后,就可以使用Polaris对base.yaml进行检查
[root@k8s-node001 Test]# polaris audit --audit-path base.yaml
结果如下,信息比较多,这里只截取部分信息,自己可以仔细看看分析出来的结果。
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "base.yaml",
"DisplayName": "base.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 1,
"Namespaces": 0,
"Controllers": 1
},
"Results": [
{
"Name": "http-echo",
"Namespace": "",
"Kind": "Deployment",
"Results": {},
"PodResult": {
"Name": "",
"Results": {
"hostIPCSet": {
"ID": "hostIPCSet",
"Message": "Host IPC is not configured",
"Success": true,
"Severity": "danger",
"Category": "Security"
..............
"tagNotSpecified": {
"ID": "tagNotSpecified",
"Message": "Image tag is specified",
"Success": true,
"Severity": "danger",
"Category": "Images"
}
}
}
]
},
"CreatedTime": "0001-01-01T00:00:00Z"
}
]
}
另外,可以只输出评分
[root@k8s-node001 Test]# polaris audit --audit-path base.yaml --format score
66
下面使用YAML代码段定义了一个称为checkImageRepo的新检查:
config_with_custom_check.yaml
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: ^kubeops.net/.+$
现在base.yaml的image为:image: docker.io/http-echo:v1.0.0
我们来使用自定义的规则执行检查
[root@k8s-node001 Test]# polaris audit --config config_with_custom_check.yaml --audit-path base.yaml
{
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "base.yaml",
"DisplayName": "base.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 1,
"Namespaces": 0,
"Controllers": 1
},
"Results": [
{
"Name": "http-echo",
"Namespace": "",
"Kind": "Deployment",
"Results": {},
"PodResult": {
"Name": "",
"Results": {},
"ContainerResults": [
{
"Name": "http-echo",
"Results": {
"checkImageRepo": {
"ID": "checkImageRepo",
"Message": "Image registry is not valid",
"Success": false,
"Severity": "danger",
"Category": "Images"
}
}
}
]
},
"CreatedTime": "0001-01-01T00:00:00Z"
}
]
}
结果显示"Message": "Image registry is not valid", "Success": false,
然后修改base.yaml的image为:image: kubeops.net/http-echo:v1.0.0
再次执行检查
[root@k8s-node001 Test]# polaris audit --config config_with_custom_check.yaml --audit-path base.yaml
{
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "base.yaml",
"DisplayName": "base.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 1,
"Namespaces": 0,
"Controllers": 1
},
"Results": [
{
"Name": "http-echo",
"Namespace": "",
"Kind": "Deployment",
"Results": {},
"PodResult": {
"Name": "",
"Results": {},
"ContainerResults": [
{
"Name": "http-echo",
"Results": {
"checkImageRepo": {
"ID": "checkImageRepo",
"Message": "Image registry is valid",
"Success": true,
"Severity": "danger",
"Category": "Images"
}
}
}
]
},
"CreatedTime": "0001-01-01T00:00:00Z"
}
]
}
从输出看到 "Message": "Image registry is valid","Success": true,,检查通过。。。
更多用法参见
总结
尽管有很多工具可以对Kubernetes YAML文件进行验证,评分和整理,但重要的是要有一个健康的模型来设计和执行检查。
例如,如果你要考虑通过管道的Kubernetes清单,则kubeval可能是该管道中的第一步,因为它可以验证对象定义是否符合Kubernetes API模式。一旦此检查成功,你可以继续进行更详尽的测试,例如标准最佳实践和自定义策略。
Kube-score和Polaris是比较好的选择。
如果你有复杂的要求,并且想要自定义检查的细节,则应考虑使用copper ,config-lint和conftest。
尽管conftest和config-lint都使用更多的YAML来定义自定义验证规则,但是Copper允许访问一种真正的编程语言,这使其颇具吸引力。
但是,你应该使用其中之一并从头开始编写所有检查吗?还是应该使用Polaris并仅编写其他自定义检查?
这都取决于你自己,合适自己的才是最好的。。。
Kubernetes YAML最佳实践和策略的更多相关文章
- 验证Kubernetes YAML的最佳实践和策略
本文来自Rancher Labs Kubernetes工作负载最常见的定义是YAML格式的文件.使用YAML所面临的挑战之一是,它相当难以表达manifest文件之间的约束或关系. 如果你想检查所有部 ...
- Kubernetes Deployment 最佳实践
零.示例 首先给出一个 Deployment+HPA+ PodDisruptionBudget 的完整 demo,后面再详细介绍其中的每一个部分: apiVersion: apps/v1 kind: ...
- Kubernetes生产环境最佳实践
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 众所周知,Kubernetes很难! 以下是在生产中使用 ...
- 生产环境容器落地最佳实践 --JFrog 内部K8s落地旅程
引言 Kubernetes已经成为市场上事实上领先的编配工具,不仅对技术公司如此,对所有公司都是如此,因为它允许您快速且可预测地部署应用程序.动态地伸缩应用程序.无缝地推出新特性,同时有效地利用硬件资 ...
- Kubernetes集群的监控报警策略最佳实践
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/79652064 本文为Kub ...
- 可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践
写在前面 为了不违反广告法,我竭尽全力,不过"最佳实践"确是标题党无疑,如果硬要说的话 只能是个人最佳实践. 问题引出 可能很多新手都会遇到同样的问题:我要我的Asp.net ...
- Kubernetes 服务部署最佳实践(二) ——如何提高服务可用性
引言 上一篇文章我们围绕如何合理利用资源的主题做了一些最佳实践的分享,这一次我们就如何提高服务可用性的主题来展开探讨. 怎样提高我们部署服务的可用性呢?K8S 设计本身就考虑到了各种故障的可能性,并提 ...
- 在CentOS 7.6 以 kubeadm 安装 Kubernetes 1.15 最佳实践
前言 Kubernetes作为容器编排工具,简化容器管理,提升工作效率而颇受青睐.很多新手部署Kubernetes由于"scientifically上网"问题举步维艰,本文以实战经 ...
- Kubernetes 微服务最佳实践
本文由个人笔记 ryan4yin/knowledge 整理而来 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes 配置」,是我个人的「最佳实践」. 其中大部 ...
随机推荐
- sping cloud入门
可以参考原文 https://www.cnblogs.com/sam-uncle/archive/2018/04/25/8943471.html 注册服务 https://www.cnblogs.co ...
- Electron安装过程深入解析(读完此文解决Electron应用无法启动,无法打包的问题)
1. 安装Electron依赖包 开发者往往通过npm install(或 yarn add)指令完成为Node.js工程安装依赖包的工作, 安装Electron也不例外,下面是npm和yarn的安装 ...
- Effective C++ 读书笔记 名博客
https://www.cnblogs.com/harlanc/tag/effective%20c%2B%2B/default.html?page=3
- 04 Storage and Calculation C语言中的存储和计算
文章内容来源于Programming Hub的学习记录,本人整理添加了中文翻译,如有侵权,联系本人删除 Variables C语言中的变量 Let's extend our mainfunction ...
- matlab中fft快速傅里叶变换
视频来源:https://www.bilibili.com/video/av51932171?t=628. 博文来源:https://ww2.mathworks.cn/help/matlab/ref/ ...
- 《C++primerplus》第8章练习题
1.(简单用一下引用变量,没有采用书中的题目)定义一个替身结构体,存储名字(char[])和力量值(int).使用结构体引用作为形参写两个函数,一个不加const,使得能对定义的结构体做修改,另一个加 ...
- JavaScript倒计时效果
实现思路: 输入的时间减去现在的时间就是剩余的时间,但是不能拿着时分秒相减,比如05分减去25分,结果会是负的. 可以用时间戳来做,用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的 ...
- MySQL中事务和事务的隔离级别
本文主要是帮助理解相关知识,没有具体的操作和代码. 事务 事务就是一组操作,这组操作要么全部成功,要么全部失败. 最经典的例子就是银行转账: 张三给李四转账100,对用户来说,就是一个操作.但对应到数 ...
- java安全编码指南之:输入注入injection
目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下ja ...
- 《流畅的Python》第三部分 把函数视作对象 【一等函数】【使用一等函数实现设计模式】【函数装饰器和闭包】
第三部分 第5章 一等函数 一等对象 在运行时创建 能赋值给变量或数据结构中的元素 能作为参数传递给函数 能作为函数的返回结果 在Python中,所有函数都是一等对象 函数是对象 函数本身是 func ...