Location>code7788 >text

Developing a MutatingWebhook

Popularity:937 ℃/2024-08-22 10:15:37

present (sb for a job etc)

Webhook is a kind of HTTP callback, used to perform certain actions in a certain situation, Webhook is not unique to K8S, a lot of scenarios can be carried out Webhook, such as in the submission of the code after the invocation of a Webhook automatically build docker image

An Admission Webhook is an HTTP callback mechanism for receiving and processing admission requests. There are two types of Admission Webhooks that can be defined, Admission Webhooks that validate and Admission Webhooks that change. Admission Webhooks that change are called first. They can modify the objects sent to the API server to perform customized set-default operations.

After all object modifications have been made and the API server has validated the incoming objects, the validation Webhook is called and enforces the custom policy by rejecting the request.

The Admission Webhook is used in the following scenarios

  1. Mutating Webhooks before resources are persisted to ETCD, e.g. adding init Container or sidecar Container.
  2. Validating Webhook before resources are persisted to ETCD, resources that do not meet the conditions are rejected and a message is given.

make up

  1. webhook service
  2. webhook configuration
  3. webhook certificate

Creating a Webhook for the Core Component Pod

Using kubebuilder to create a new webhook project

kubebuilder init --domain  --repo /test-operator
(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder init --domain  --repo /test-operator
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Get controller runtime:
$ go get sigs./[email protected]
INFO Update dependencies:
$ go mod tidy
go:  file indicates go 1.21, but maximum version supported by tidy is 1.19
Error: failed to initialize project: unable to run post-scaffold tasks of "/v4": exit status 1

Because my default is go1.19 so the version does not meet the requirements, here are two ways to deal with it

  1. specify --plugins go/v3 --project-version 3
  2. Switching to a higher version of golang, here I switched to go1.22.
(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder init --domain  --repo /test-operator                                    
INFO Writing kustomize manifests for you to edit... 
INFO Writing scaffold for you to edit...          
INFO Get controller runtime:
$ go get sigs./[email protected] 
INFO Update dependencies:
$ go mod tidy           
Next: define a resource with:
$ kubebuilder create api

API for generating the core component Pod

(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder create api --group core --version v1 --kind Pod                                                    
INFO Create Resource [y/n]                        
n
INFO Create Controller [y/n]                      
n
INFO Writing kustomize manifests for you to edit... 
INFO Writing scaffold for you to edit...          
INFO Update dependencies:
$ go mod tidy        

There are two options here, Create Resource and Create Controller
Because it's a built-in resource Pod there's no need to create a resource and no need for a controller
If it is a custom resource, you need to create the resource and create the controller.

Creating a webhook

(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder create webhook --group core --version v1 --kind Pod --defaulting --programmatic-validation
INFO Writing kustomize manifests for you to edit... 
ERRO Unable to find the target(s) #- path: patches/webhook/* to uncomment in the file config/crd/. 
ERRO Unable to find the target(s) #configurations:
#-  to uncomment in the file config/crd/. 
INFO Writing scaffold for you to edit...          
INFO api/v1/pod_webhook.go                        
INFO api/v1/pod_webhook_test.go                   
INFO api/v1/webhook_suite_test.go                 
INFO Update dependencies:
$ go mod tidy           
INFO Running make:
$ make generate                
mkdir -p /Users/xxxx/test-operator/bin
Downloading sigs./controller-tools/cmd/[email protected]
/Users/xxxx/test-operator/bin/controller-gen-v0.14.0 object:headerFile="hack/" paths="./..."
Next: implement your new Webhook and generate the manifests with:
$ make manifests

code structure

.
├── Dockerfile
├── Makefile
├── PROJECT
├── 
├── api
│   └── v1
│       ├── pod_webhook.go
│       ├── pod_webhook_test.go
│       └── webhook_suite_test.go
├── bin
│   └── controller-gen-v0.14.0
├── cmd
│   └── 
├── config
│   ├── certmanager
│   │   ├── 
│   │   ├── 
│   │   └── 
│   ├── crd
│   │   └── patches
│   │       ├── cainjection_in_pods.yaml
│   │       └── webhook_in_pods.yaml
│   ├── default
│   │   ├── 
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_config_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── 
│   │   └── 
│   ├── prometheus
│   │   ├── 
│   │   └── 
│   ├── rbac
│   │   ├── auth_proxy_client_clusterrole.yaml
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── 
│   │   ├── leader_election_role.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   ├── 
│   │   ├── role_binding.yaml
│   │   └── service_account.yaml
│   └── webhook
│       ├── 
│       ├── 
│       ├── 
│       └── 
├── 
├── 
├── hack
│   └── 
└── test
├── e2e
│   ├── e2e_suite_test.go
│   └── e2e_test.go
└── utils
└── 

Implementation of Webhook related code

Because there is only Webhook, there is no Controller so you only need to implement the Webhook related code can be, at the same time you need to comment out some code such as:
Dockerfile in the

# COPY internal/controller/ internal/controller/

Modify api/v1/xxx_suite_test.go
Because the core component Pod's webhook is not the same as the normal CRD's webhook, the generated pod_webhook.go here only has the Default() function, so we need to rewrite the whole code directly, most importantly the Handle() method.

/*
Copyright 2024.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    /licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1

import (
	"fmt"
	"net/http"
	"sigs./controller-runtime/pkg/client"
	logf "sigs./controller-runtime/pkg/log"
	"sigs./controller-runtime/pkg/webhook/admission"
)

// log is for logging in this package.
var podlog = ("pod-resource")

// Defining Core Componentspod(used form a nominal expression)webhook(used form a nominal expression)主struct,alikejava(used form a nominal expression)Class
type PodWebhookMutate struct {
	Client
	decoder *
}

// +kubebuilder:webhook:path=/mutate-core-v1-pod,mutating=true,failurePolicy=fail,sideEffects=None,groups=core,resources=pods,verbs=create;update,versions=v1,name=,admissionReviewVersions=v1
func (a *PodWebhookMutate) Handle(ctx , req ) {
	pod := &{}
	err := (req, pod)
	if err != nil {
		return (, err)
	}

	// TODO: variantmarshaledPodanMap,Can be modified directlypod(used form a nominal expression)一些属性
	marshaledPod, err := (pod)
	if err != nil {
		return (, err)
	}
	// printable
	("======================================================")
	(string(marshaledPod))
	return (, marshaledPod)
}

func (a *PodWebhookMutate) InjectDecoder(d *) error {
	 = d
	return nil
}

Modify the file:

if ("ENABLE_WEBHOOKS") != "false" {
    //if err = (&{}).SetupWebhookWithManager(mgr); err != nil {
    //	(err, "unable to create webhook", "webhook", "Pod")
    //	(1)
    //}
    ().Register("/mutate-core-v1-pod", &{Handler: &{Client: ()}})
}

Generate mainfests

make manifests generate

certificates

Manual certificate issuance

/2020/07/kubernetes/admission-webhook/

Automatic issuance of certificates

The webhook service automatically generates certificates when it starts, and the authorization certificate

  1. Create CA root certificates and certificates for services
  2. Write server and CA certificates to k8s secret and support find or create
  3. Local Write Certificates
  4. Get MutatingWebhookConfiguration and ValidatingWebhookConfiguration to write the caCert to the webhook config (one problem here is that the webhook needs to be created in advance, the CABundle can be written as a temporary value, etc.). The CABundle can be written as a temporary value to be overwritten when the webhook server starts)

Automatic issuance of certificate reference items:/koordinator-sh/koordinator/blob/main/pkg/webhook/util/controller/webhook_controller.go#L187