go - 使用 Mutate 准入控制器修改 deploymnet 中的 ImagePullPolicy
问题描述
我正在构建一个用于部署的 Mutate 准入控制器,以确保 Pod 上的 imagePullPolicy 设置为 Always 并带有相应的验证准入控制器。我注意到我可以在部署(创建时)或副本集上设置它。
代码如下所示:
package main
import (
"net/http"
"fmt"
"io/ioutil"
"encoding/json"
"os"
// "github.com/golang/glog"
"strconv"
"k8s.io/api/admission/v1"
// corev1 "k8s.io/api/core/v1"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
admissionv1 "k8s.io/api/admission/v1"
)
func isKubeNamespace(ns string) bool {
return ns == metav1.NamespacePublic || ns == metav1.NamespaceSystem
}
type patchOperation struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value,omitempty"`
}
func (mr *myServerHandler) mutserve(w http.ResponseWriter, r *http.Request) {
var Body []byte
if r.Body != nil {
if data , err := ioutil.ReadAll(r.Body); err == nil {
Body = data
}
}
if len(Body) == 0 {
fmt.Fprintf(os.Stderr, "Unable to retrieve Body from API")
http.Error(w,"Empty Body", http.StatusBadRequest)
}
fmt.Fprintf(os.Stdout,"Received Request")
if r.URL.Path != "/mutate" {
fmt.Fprintf(os.Stderr, "Not a Validate URL Path")
http.Error(w, "Not A Validate URL Path", http.StatusBadRequest)
}
// Read the Response from the Kubernetes API and place it in the Request
arRequest := &v1.AdmissionReview{}
if err := json.Unmarshal(Body, arRequest); err != nil {
fmt.Fprintf(os.Stderr, "Error Unmarsheling the Body request")
http.Error(w, "Error Unmarsheling the Body request", http.StatusBadRequest)
return
}
// if arRequest.Request.Resource.Resource != "pods" {
// fmt.Fprintf(os.Stderr, "Handling the wrong resource")
// http.Error(w, "Handling the wrong resource", http.StatusBadRequest)
// return
// }
raw := arRequest.Request.Object.Raw
replicaset := appsv1.ReplicaSet{}
if !isKubeNamespace(arRequest.Request.Namespace) {
if err := json.Unmarshal(raw, &replicaset); err != nil {
fmt.Fprintf(os.Stderr, "Error , unable to Deserializing Pod")
http.Error(w,"Error , unable to Deserializing Pod", http.StatusBadRequest)
return
}
} else {
fmt.Fprintf(os.Stderr, "Error , unauthorized Namespace")
http.Error(w,"Error , unauthorized Namespace", http.StatusBadRequest)
return
}
containers := replicaset.Spec.Template.Spec.Containers
arResponse := v1.AdmissionReview{
Response: &v1.AdmissionResponse{
UID: arRequest.Request.UID,
},
}
var patches []patchOperation
for i , container := range containers {
fmt.Fprintf(os.Stdout, "container[%d]= %s imagePullPolicy=%s", i, container.Name , container.ImagePullPolicy)
if containers[i].ImagePullPolicy != "Always" {
if containers[i].ImagePullPolicy == "Never" || containers[i].ImagePullPolicy == "IfNotPresent" {
patches = append(patches, patchOperation{
Op: "replace",
Path: "spec/template/spec/containers/[" + strconv.Itoa(i) + "]/ImagePullPolicy",
Value: "Always",
})
} else {
patches = append(patches, patchOperation{
Op: "Add",
Path: "/spec/template/spec/containers/[" + strconv.Itoa(i) + "]/ImagePullPolicy",
Value: "Always",
})
arResponse.Response.Allowed = true
}
}
}
// if pullPolicy != "Always" {
patchBytes, err := json.Marshal(patches)
if err != nil {
fmt.Fprintf(os.Stderr, "Can't encode Patches: %v", err)
http.Error(w, fmt.Sprintf("couldn't encode Patches: %v", err), http.StatusInternalServerError)
return
}
v1JSONPatch := admissionv1.PatchTypeJSONPatch
arResponse.APIVersion = "admission.k8s.io/v1"
arResponse.Kind = arRequest.Kind
arResponse.Response.Allowed = true
arResponse.Response.Patch = patchBytes
arResponse.Response.PatchType = &v1JSONPatch
resp, rErr := json.Marshal(arResponse)
if rErr != nil {
fmt.Fprintf(os.Stderr, "Can't encode response: %v", rErr)
http.Error(w, fmt.Sprintf("couldn't encode response: %v", rErr), http.StatusInternalServerError)
}
if _ , wErr := w.Write(resp); wErr != nil {
fmt.Fprintf(os.Stderr, "Can't write response: %v", wErr)
http.Error(w, fmt.Sprintf("cloud not write response: %v", wErr), http.StatusInternalServerError)
}
}
如果我运行“添加”补丁,它最终会始终添加 imagePullPolicy,但如果我想替换它,我会收到以下错误:
“无法创建新的副本集“ubi-kuku-547654586”:发生内部错误:替换操作不适用:文档缺少路径:/spec/template/spec/containers/[0]/ImagePullPolicy:缺少值”
我在创建部署时尝试过它仍然是同样的错误
我尝试使用 core/v1 包为单个 pod(/spec/containers/[0]/ImagePullPolicy)使用相同的结构(不同的路径)并且它有效。
解决方案
推荐阅读
- string - Powershell - 从字符串中提取句子的最佳方法是什么
- python - 如何同时运行 python flask 应用程序和 webview
- etl - 如何使用 Talend 从 CSV 中提取键值对
- algorithm - 在扑克中分配边底池
- optimization - Julia:NLsolve 函数内部函数
- vue.js - 安装异步 axios 时未更新存储副本
- python - 从数据框中创建逗号分隔列表以传递到 SQL 查询时出错
- docker - Dockerfile 环境变量
- mysql - 从远程机器通过 SSH 的 Docker 命令
- mysql - 如何从 MySQL 中的比较和空检查中指定 ORDER BY?