1 背景
运维新同学在预发环境操作删除pod的时候,不知道什么原因把kubectl delete pod命令敲成了kubectl delete ns pre把预发环境删了,几十个模块,将近一个小时才恢复。幸亏是测试环境啊,如果是生产可以可以跑路了。
2 解决方案
通过kubectl操作k8s资源把数据发给apiserver,在apiserver把数据持久化到etcd之前我们可以通过MutatingWebhook修改、拦截相关资源的变更。
所以我们可以通过实现MutatingWebhook
机制,控制高危的操作。
方案一:自己实现MutatingWebhook
保护k8s资源不被删除,这个具体实现大家参考作者之前写的文章实现。
方案二:阿里开源的OpenKruise
已经帮我们实现相关资源的删除保护。他的实现原理也是基于webhook
实现。
下面我们重点实践基于OpenKruise
资源删除保护。
2.1 OpenKruise 删除保护实践
2.1.1 OpenKruise架构
-
**API:**所有 OpenKruise 的功能都是通过 Kubernetes API 来提供
-
Manager: Kruise-manager 是一个运行 controller 和 webhook 中心组件,它通过 Deployment 部署在 kruise-system 命名空间中。资源保护主要是
kruise-controller-manager
的实现的webhook
功能。 -
**Daemon:**DaemonSet 部署到每个 Node 节点上,提供镜像预热、容器重启等功能。
2.1.2 k8s集群在线部署OpenKruise
建议采用 helm v3.5+ 来安装 Kruise,,helm 是一个简单的命令行工具可以从 这里 获取。
# Firstly add openkruise charts repository if you haven't do this.
$ helm repo add openkruise https://openkruise.github.io/charts/
# [Optional]
$ helm repo update
# Install the latest version.
$ helm install kruise openkruise/kruise --version 1.5.0
通过上述办法可以在线部署OpenKruise
。
大部分同学的线上环境是没有外网的,下面我们看看离线部署方式。
2.1.3 k8s集群离线部署OpenKruise
下载最新稳定版OpenKruise,作者没有大家helm仓库,这里使用gitlab管理kruise
# Firstly add openkruise charts repository if you haven't do this.
$ helm repo add openkruise https://openkruise.github.io/charts/
# [Optional]
$ helm repo update
# download the latest version.
$ helm pull openkruise/kruise --version 1.5.0
在当前目录下有kruise-1.5.0.tgz
解压缩,并修改镜像地址为你仓库地址
tar kruise-1.5.0.tgz
cd kruise
vim values.yaml
image:
repository: yourharbor.domain.com/openkruise/kruise-manager
tag: v1.5.0
注意:作者这里kruise
上传到gitlab管理,如果你有helm仓库可以放到自己的helm仓库。
下载镜像,并上传自己的harbor仓库
docker pull openkruise/kruise-manager:v1.5.0
docker tag openkruise/kruise-manager:v1.5.0 yourharbor.domain.com/openkruise/kruise-manager:v1.5.0
docker push yourharbor.domain.com/openkruise/kruise-manager:v1.5.0
在master节点上部署OpenKruise
git clone yourgit.domain.com/kruise.git
helm install kruise kruise/
至此,离线版安装OpenKruise
就完成了。
部署完后,效果如下有kruise-controller-manager
和kruise-daemon
kubectl get pod -n kruise-system
NAME READY STATUS RESTARTS AGE
kruise-controller-manager-6d7bfd75wf-4s6jk 1/1 Running 0 4h23m
kruise-controller-manager-6d7bfd75wf-dstl5 1/1 Running 0 6h21m
kruise-daemon-tnfd8 1/1 Running 0 6h21m
2.2 保护的资源类型
2.2.1 保护的资源都有哪些?
目前支持的资源如下:
Kind | Group | Version | Cascading judgement |
---|---|---|---|
Namespace | core | v1 | namespace |
CustomResourceDefinition | apiextensions.k8s.io | v1beta1, v1 | CRD下是否还有存量的 CR |
Deployment | apps | v1 | replicas 是否为 0 |
StatefulSet | apps | v1 | replicas 是否为 0 |
ReplicaSet | apps | v1 | replicas 是否为 0 |
CloneSet | apps.kruise.io | v1alpha1 | replicas 是否为 0 |
StatefulSet | apps.kruise.io | v1alpha1, v1beta1 | replicas 是否为 0 |
UnitedDeployment | apps.kruise.io | v1alpha1 | replicas 是否为 0 |
2.2.2 怎么开启资源保护?
在以上资源上加上标签policy.kruise.io/delete-protection=Always
或 policy.kruise.io/delete-protection=Cascading
,即实现了对相应资源的的保护.
Always: 这个对象禁止被删除,除非上述 label 被去掉
Cascading: 这个对象如果还有可用的下属资源,则禁止被删除
2.2.3 案例实战
2.2.3.1 Always(对象禁止被删除)
test
namespace 打上label policy.kruise.io/delete-protection=Cascading
后,不管test
namespace下是否有资源都不允许删除test
,除非把标签去掉。
kubectl label ns nohost policy.kruise.io/delete-protection=Always
kubectl delete ns test
Error from server: admission webhook "vnamespace.kb.io" denied the req
2.2.4 Cascading(当删除对象还有其他资源是不让删)
test
namespace下还有一个pod,所以当设置label是policy.kruise.io/delete-protection=Cascading
,删除test
不允许删除,这样就对test
namespace 起到保护的作用。
kubect label ns test policy.kruise.io/delete-protection=Cascading --overwrite
kubectl delete ns test
Error from server: admission webhook "vnamespace.kb.io" denied the request: forbidden by ResourcesProtectionDeletion for policy.kruise.io/delete-protection=Cascading and active pods 1>0
如果把test
namespace 下的所有pod都删掉,test
可以被delete
掉。
2.3 OpenKruise 资源保护缺点
支持的资源有限,通过 webhook configuration 的 objectSelector 字段, Kruise webhook 只会拦截处理带有 policy.kruise.io/delete-protection
标签的 Namespace/CustomResourceDefinition/Deployment/StatefulSet/ReplicaSet
资源。