volcano.sh/volcano@v1.9.0/cmd/webhook-manager/app/server.go (about)

     1  /*
     2  Copyright 2018 The Volcano Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package app
    18  
    19  import (
    20  	"fmt"
    21  	"net/http"
    22  	"os"
    23  	"os/signal"
    24  	"strconv"
    25  	"syscall"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
    29  	"k8s.io/client-go/tools/record"
    30  	"k8s.io/klog/v2"
    31  
    32  	"volcano.sh/apis/pkg/apis/helpers"
    33  	"volcano.sh/apis/pkg/apis/scheduling/scheme"
    34  	"volcano.sh/volcano/cmd/webhook-manager/app/options"
    35  	"volcano.sh/volcano/pkg/kube"
    36  	commonutil "volcano.sh/volcano/pkg/util"
    37  	"volcano.sh/volcano/pkg/version"
    38  	wkconfig "volcano.sh/volcano/pkg/webhooks/config"
    39  	"volcano.sh/volcano/pkg/webhooks/router"
    40  )
    41  
    42  // Run start the service of admission controller.
    43  func Run(config *options.Config) error {
    44  	if config.PrintVersion {
    45  		version.PrintVersionAndExit()
    46  		return nil
    47  	}
    48  
    49  	if config.EnableHealthz {
    50  		if err := helpers.StartHealthz(config.HealthzBindAddress, "volcano-admission", config.CaCertData, config.CertData, config.KeyData); err != nil {
    51  			return err
    52  		}
    53  	}
    54  
    55  	if config.WebhookURL == "" && config.WebhookNamespace == "" && config.WebhookName == "" {
    56  		return fmt.Errorf("failed to start webhooks as both 'url' and 'namespace/name' of webhook are empty")
    57  	}
    58  
    59  	restConfig, err := kube.BuildConfig(config.KubeClientOptions)
    60  	if err != nil {
    61  		return fmt.Errorf("unable to build k8s config: %v", err)
    62  	}
    63  
    64  	admissionConf := wkconfig.LoadAdmissionConf(config.ConfigPath)
    65  	if admissionConf == nil {
    66  		klog.Errorf("loadAdmissionConf failed.")
    67  	} else {
    68  		klog.V(2).Infof("loadAdmissionConf:%v", admissionConf.ResGroupsConfig)
    69  	}
    70  
    71  	vClient := getVolcanoClient(restConfig)
    72  	kubeClient := getKubeClient(restConfig)
    73  
    74  	broadcaster := record.NewBroadcaster()
    75  	broadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
    76  	recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: commonutil.GenerateComponentName(config.SchedulerNames)})
    77  	if err := router.ForEachAdmission(config, func(service *router.AdmissionService) error {
    78  		if service.Config != nil {
    79  			service.Config.VolcanoClient = vClient
    80  			service.Config.KubeClient = kubeClient
    81  			service.Config.SchedulerNames = config.SchedulerNames
    82  			service.Config.Recorder = recorder
    83  			service.Config.ConfigData = admissionConf
    84  		}
    85  
    86  		klog.V(3).Infof("Registered '%s' as webhook.", service.Path)
    87  		http.HandleFunc(service.Path, service.Handler)
    88  
    89  		klog.V(3).Infof("Add CaCert for webhook <%s>", service.Path)
    90  		if err = addCaCertForWebhook(kubeClient, service, config.CaCertData); err != nil {
    91  			return fmt.Errorf("failed to add caCert for webhook %v", err)
    92  		}
    93  		return nil
    94  	}); err != nil {
    95  		return err
    96  	}
    97  
    98  	klog.V(3).Infof("Successfully added caCert for all webhooks")
    99  
   100  	webhookServeError := make(chan struct{})
   101  	stopChannel := make(chan os.Signal, 1)
   102  	signal.Notify(stopChannel, syscall.SIGTERM, syscall.SIGINT)
   103  
   104  	server := &http.Server{
   105  		Addr:      config.ListenAddress + ":" + strconv.Itoa(config.Port),
   106  		TLSConfig: configTLS(config, restConfig),
   107  	}
   108  	go func() {
   109  		err = server.ListenAndServeTLS("", "")
   110  		if err != nil && err != http.ErrServerClosed {
   111  			klog.Fatalf("ListenAndServeTLS for admission webhook failed: %v", err)
   112  			close(webhookServeError)
   113  		}
   114  
   115  		klog.Info("Volcano Webhook manager started.")
   116  	}()
   117  
   118  	if config.ConfigPath != "" {
   119  		go wkconfig.WatchAdmissionConf(config.ConfigPath, stopChannel)
   120  	}
   121  
   122  	select {
   123  	case <-stopChannel:
   124  		if err := server.Close(); err != nil {
   125  			return fmt.Errorf("close admission server failed: %v", err)
   126  		}
   127  		return nil
   128  	case <-webhookServeError:
   129  		return fmt.Errorf("unknown webhook server error")
   130  	}
   131  }