关注分享主机优惠活动
国内外VPS云服务器

k8s动态准入控制(k8s准入控制器)

准入控制是k8s中用来提供安全控制的控制器,动态控制是用户自定义的安全策略。

Type

动态访问控制正在变异和变异 验证

更改

更改主要是由于 API 的更改。一旦完成,k8s 将其发送到配置的 Webhook 服务,与 ValidatingWebhookConfiguration 的条件匹配。k 服务根据业务逻辑进行修改。 比如著名的istio Sidecar注入就在这里

验证

验证主要关注是否满足条件集群要求。例如,为了获得高可用性,不允许将副本数设置为 1 并输入部署请求。 style="margin-top: 0px; margin-bottom: 20px; text -align: center;">下图显示了 API 请求流程。

编写 webhook 来创建

创建证书的程序有很多,最著名的是openssl 这里,我们将使用rancher提供的脚本自动生成证书create_self-signed-cert.sh#!/bin/ 保存为 bash -ehelp (){ echo ' ================= =。 ============================================= ' echo ' --ssl-domain:生成 SSL 证书所需的主域名。 如果未指定,则默认为 www.rancher.local。 对于IP 访问服务可以忽略。 ' echo ' --ssl-trusted-ip:SSL 证书通常只信任域名访问请求。 在某些情况下,您可能需要使用 IP 访问服务器,在这种情况下,您需要将扩展​​ IP 添加到 SSL 证书。 使用多个IP。 用逗号分隔。 ' echo ' --ssl-trusted-domain:如果要访问多个域名,请添加扩展域名(SSL_TRUSTED_DOMAIN)。 多个扩展域名以逗号分隔。 ' echo ' --ssl -size:SSL加密位数长度,默认为2048; ' echo ' --ssl-cn:国家代码(两字母代码),默认 CN ; ' echo ' 用法示例: ' echo ' ./create_self[k4 ]signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ ' echo ' [ k4][ k4]ssl-可信-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650' echo ' ====== =============== =================================================== =='}案例“$1” -h|--help) help; exit;;esacif [[ $1 == '' ]];then help; exit;fiCMDOPTS="$*" for OPTS in $CMDOPTS;do key=$ (echo ${OPTS} | awk -F"=" '{print$1}' ) value=$(echo ${OPTS} | awk -F"=" '{print $2}' ) case "$key" in --s sl-domain) SSL_DOMAIN= $值 ;; --ssl-可信-ip) SSL_TRUSTED_IP=$值 ;; --ssl-可信-域) SSL_TRUSTED_DOMAIN=$value ;; --ssl- 大小) SSL_SIZE=$value ;;日期) SSL_DATE=$值 ;; --ca-日期)CA_DATE=$value ;; --ssl-cn) CN=$value ;; CA 相关设置 CA _DATE=${CA_DATE:-3650}CA_KEY=${CA_KEY:-cakey.pem}CA_CERT=${CA_CERT:-cacerts.pem}CA_DOMAIN=cattle- ca# ssl 相关设置 SSL_CONFIG=${SSL_CONFIG:-$PWD/openssl.cnf}SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'}SSL_DATE= ${SSL_DATE:[k 4]3650}SSL_SIZE=${SSL_SIZE :-2048}## 国家/地区代码 (2 字符代码),默认CN。 CN=${CN:-CN}SSL_KEY=$SSL_DOMAIN.keySSL_CSR=$SSL_DOMAIN.csrSSL_CERT=$SSL_DOMAIN.crtecho -e "\0 33[32m ----------------[k4 ]----------- \033[0m"回声 -e "\033[32m  | 生成 SSL 证书 | \033[0m"echo -e "\033[32m --------[k4 ][ k4]----[k 4]-------------\033[0m"如果 [[ [ k4]e ./${CA_KEY} ]]; 然后 echo -e "\ 033[32m ====> 1. CA 可以看到私钥已经存在 如果存在的话,将“${CA_KEY}”备份到“${CA_KEY}”-bak,然后重新创建 \033[0m" mv ${CA_KEY} " ${CA_KEY} “-bak openssl genrsa - out ${CA_KEY} ${SSL_SIZE}else echo -e "\033[32m ====> 1. 生成新的 CA 私钥 ${CA_KEY} \033[0m" &注意: openssl genrsa -out ${CA_KEY} ${SSL_SIZE}fiif [[ -e ./${CA_CERT} ]]; 然后 echo -e "\033[32 m ====> 2原来CA证书已经存在,所以先把“${CA_CERT}”改为“${CA_CERT}”-bak。 \033[0m" mv ${CA_CERT} "${ CA_CERT}"-bak openssl req -x509 重新创建 -sha256 - 新 - 节点 [k4 ]key ${CA_KEY} - ${CA_CERT} 中的 ${CA_DATE} 天 - -subj "/C=${CN}/CN =${CA_DOMAIN}"else echo -e "\033[32m ====> 2. 生成新的 CA 证书 ${CA_CERT} \ 033[ 0米”打开sl req -x509 -sha256 -新 -节点 -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C= ${CN}/CN=${CA_DOMAI N}"fiecho -e "\033[32m ====> 3. 生成 Openssl 配置文件 ${SSL_CONFIG} \033[0m"cat > ${SSL_CONFIG} <> ${SSL_CONFIG} <> ${SSL_CONFIG} 完成 if [[ -n ${SSL_TRUSTED_IP} ]]; 然后 for i in "${!ip[@]}" do ip=(${SSL_TRUSTED_IP});;echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG} Done fiecho -e "\033[32m ====> 4. 生成服务 SSL KEY $ {SS L_KEY} \033[0m"openssl genrsa -out ${SSL_KEY} ${SSL_SIZE}echo -e "\033[32m ====> 5. 生成服务 SSL CSR ${SSL_CSR} \033[0m"openssl req -sha256 -new -key ${SSL_KEY} [k4 ]输出 ${SSL_CSR} -subj "/C=${CN}/CN=${SSL_DOMAIN} " -config ${SSL_CONFIG}echo -e "\033[32m ====> 6. 生成服务 SSL CERT ${SSL_CERT} \ 033[0m"openssl x509 -sha256-req -in ${SSL_CSR} -CA ${CA_CERT} \ -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \ -days ${SSL_DATE} [k 4]扩展 v3_req \ -extfile ${SSL_CONFIG}echo -e "\033[32m ====> 7. 证书创建完成 \033[0m"echeecho -e "\033[32m == ==> 8. YAML 格式输出结果 \033[0m "回声” “------------[ k4]---[ k4]------------ [ k4]---------------- ------------”回显 "ca_key: |"猫 $CA_KEY | sed /^/ /'echoecho "ca_cert: |"cat $CA_CERT | sed /^/ /'echoecho "ssl_key: | "cat $SSL_KEY | sed /^/ /'echoecho "ssl_csr: |"cat $SSL_CSR | sed /^/ /'回声 "ssl_cert: |"cat $SSL_CERT | sed 's/^/ /'echoecho -e "\033[32m ====> 9. 将 CA 证书附加到证书文件 \033[0m" cat ${ CA_C ERT} >> ${SSL_CERT} echo "ssl_cert: |"cat $SSL_CERT | 's/^/ /'回声 -e "\033[32m ====>&nbsp;10。 服务证书 \033[0m"echo "cp ${SSL_DOMAIN}.key tls.key"cp ${SSL_DOMAIN}.key tls.keyecho "cp ${SSL_DOMAIN}.crt tls.crt"cp $ {SSL_DOMAIN} 运行的名称crt tls.crt2。 命令./create_self-signed-cert.sh --ssl-domain=admission-example.admission-example.svc.cluster.local - -ssl-trusted-domain=admission-example,admission-example.admission-example.svc -ssl-trusted-ip=127.0.0.13。将在中生成一组文档和密钥。

.key 是私钥。

.crt。 name

csr文件为证书申请文件

创建一个以ca开头的yaml文件,用于根证书和私钥。

MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration 写入 apiVersion:admissionregistration.k8s.io/v1kind:MutatingWebhookConfigurationmetadata:名称:- 标签更改示例:应用程序:Admission-examplewebhooks:- 名称:Admission-example.naturelr.cc clientConfig:服务:名称:Admission- 示例命名空间:admission-示例路径:“/mutate”端口:8080#证书是 Base64 编码的 caBundle:{{CA}} 规则:- 操作ns:[“CREATE”] apiGroups:[“apps”,“”] apiVersions:[“v1”]资源:[“Deployment”,“Service”]admissionReviewVersions:[“v1”,“v1beta1”]副作用:无# 这是admission-webhook-示例:已启用 ns namespaceSelector: matchLabels: 仅在可用时启用。 准入-webhook-示例:启用---api版本:admissionregistration.k8s。io/v1kind:ValidatingWebhookConfiguration元数据:名称:validation-examplelabels:app:admission-examplewebhooks:-名称:admission-example.naturelr.cc clientConfig:service:name:admission-示例命名空间:接待处- 示例路径:“/validate” 端口:8080 caBundle: {{CA}} 规则: - 操作: [ "CREATE" ] apiGroups: ["apps", ""] apiVersions: ["v1"] 资源: ["deployments","services"] attendReviewVersions: ["v1", "v1beta1"] SideEffects: None 命名空间选择器: matchLabels: 入场-webhook-示例:开发启用的 webhook

开发、验证和修改上面定义的两个接口。

听 端口与上面配置的端口相同,将使用创建的证书

... http.HandleFunc("/validate" , validate) http.HandleFunc("/mutate", mutate) http .HandleFunc( "/ping", func(w http.Respo nseWriter, r *http.Request) { fmt.Fprintln(w, "pong") }) svr := http.Server{ 地址: ":8080", ReadTimeout: time.Minute, WriteTimeout: time.Minute, } go func() { if *key == "" || *cert == "" { fmt.Println("http 服务启动成功") if err := svr. != nil { log.Fatalln(err) } } } fmt.Println("https 服务启动成功") if err := svr.Li stenAndServeTLS(*cert, *key); err != nil { log.Fatalln(err) }() }

要实现 mutate,您必须将名为admission-example.naturelr.cc/status 的文件添加到合格的部署和服务中。":“test”注释非常好。 它与使用 kubectl 类似,只不过代码将其返回给 k8s。

func mutate(w http.ResponseWriter, r *http.Request) { // 请求结构 qar :=admissionv1.AdmissionReview {} _, _, err :=serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer ().Decode(body, nil, &qar) checkErr(err) type patchOperation struct { Op 字符串 `json: "op"` 路径字符串 `json:"path"`  值接口 {} `json:"value,omitempty"` } p := patchOperation{ Op: "add", 路径: "/metadata/annotations", value: map[string]string{"admission-example .naturelr .cc/status": "test t"}, } 补丁,错误 := json.Marshal([]patchOperation{p}) checkErr(err) // 返回给k8s的消息为:= &admiss ionv1.AdmissionReview{ TypeMeta: apimetav1.TypeMeta{ APIVersion: qar.APIVersion, Kind:   qar.Kind, }, 响应: &admissionv1.AdmissionResponse{ 权限: true, patch: patch, PatchType: func() *admissionv1.PatchType { pt := a Commissionv1.PatchTypeJSONPatch return &pt }(), UID: qar.Request .UID , }, } resp, err := json.Marshal(are) checkErr(err) fmt.Println("响应:", string(resp))w.WriteHeader(200) w.Write(resp)}

验证主要适用于服务和部署标签中的准入字段。有。 否则,访问将被拒绝。

func validate(w http.ResponseWriter, r *ht tp.Request) { // 请求结构 qar := attendv1.AdmissionReview{} _, _, err :=serializer.NewCodecFactory(runtime .NewScheme()). UniversalDeserializer().Decode(body, nil, &qar) checkErr(err // 处理逻辑 从请求的结构中判断是否满足条件 var avai lableLabels map[string]string requiredLabels := "admission" var errMsg error switch qar.Request.Kind.Kind {case "Deployment": vardeploy appsv1.Deployment if err := json.Unmarshal(qar.Request.O bject.Raw, &deploy); err != nil { log.Println("无法解析格式:", err) errMsg = err } a availableLabels =deploy.Labels case "Service": var service corev1.Service if err := json.Unmarshal(qar.Request.Object.Raw, &service); err != nil { log.Println("无法解析格式:", err)  errMsg = err } availableLabels = service.Labels 默认: msg := fmt.Sprint ln("无法处理的类型:", qar.Request.Kind.Kind) log.Println(msg) errMsg =errors.New(msg) } var status *apimetav1.Status var allowed bool if _, ok := 可用标签 [必需标签]; ok || errMsg != nil { msg := "条件不满足" if err != nil { msg = fmt.Sprintln(errMsg) &注意: } } status = &apimetav1.Status{ 消息: msg, 原因: apimetav1.StatusReason(msg), 代码: 304, } allowed = false } el se { 消息: "通过", status = &apimetav1.Status{ 原因: "通过" , 代码: 200, } allowed = true } // k8s 返回的消息是:= &admissionv1。AdmissionReview{ TypeMeta: apimetav1.TypeMeta{ APIVersion: qar.APIVersion, Kind: qar.Kind, }, Response: &admissionv1.AdmissionResponse{Allowed: allowed, Result: status, UID: qar.Request.UID, }, } resp, err := json.Marshal (是) checkErr(err) fmt.Println("响应:", string(resp)) w.WriteHeader(200) w.Write(resp)

完整的项目为 https://github.com/NatureLR/admission-example

测试验证

按后承认-webhook[ k4]示例:如果你在ns中随机创建一个应用程序在有效标签下,你会看到它会被拒绝。

如果你添加了你设置的标签,你就可以创建它。 其他注释已添加到部署中。

未经允许不得转载:主机频道 » k8s动态准入控制(k8s准入控制器)

评论 抢沙发

评论前必须登录!