github.com/projectcontour/contour@v1.28.2/cmd/contour/gatewayprovisioner.go (about) 1 // Copyright Project Contour Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package main 15 16 import ( 17 "fmt" 18 "os" 19 20 "github.com/projectcontour/contour/internal/k8s" 21 "github.com/projectcontour/contour/internal/provisioner" 22 "github.com/projectcontour/contour/internal/provisioner/controller" 23 "github.com/projectcontour/contour/pkg/config" 24 25 "github.com/alecthomas/kingpin/v2" 26 "github.com/distribution/reference" 27 _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 28 "k8s.io/client-go/rest" 29 ctrl "sigs.k8s.io/controller-runtime" 30 "sigs.k8s.io/controller-runtime/pkg/manager" 31 controller_runtime_metrics_server "sigs.k8s.io/controller-runtime/pkg/metrics/server" 32 ) 33 34 func registerGatewayProvisioner(app *kingpin.Application) (*kingpin.CmdClause, *gatewayProvisionerConfig) { 35 cmd := app.Command("gateway-provisioner", "Run contour gateway provisioner.") 36 37 provisionerConfig := &gatewayProvisionerConfig{ 38 contourImage: "ghcr.io/projectcontour/contour:v1.28.2", 39 envoyImage: "docker.io/envoyproxy/envoy:v1.29.2", 40 metricsBindAddress: ":8080", 41 leaderElection: false, 42 leaderElectionID: "0d879e31.projectcontour.io", 43 gatewayControllerName: "projectcontour.io/gateway-controller", 44 } 45 46 cmd.Flag("contour-image", "The container image used for the managed Contour."). 47 Default(provisionerConfig.contourImage). 48 StringVar(&provisionerConfig.contourImage) 49 50 cmd.Flag("enable-leader-election", "Enable leader election for the gateway provisioner."). 51 BoolVar(&provisionerConfig.leaderElection) 52 53 cmd.Flag("envoy-image", "The container image used for the managed Envoy."). 54 Default(provisionerConfig.envoyImage). 55 StringVar(&provisionerConfig.envoyImage) 56 57 cmd.Flag("gateway-controller-name", "The controller string to process GatewayClasses and Gateways for."). 58 Default(provisionerConfig.gatewayControllerName). 59 StringVar(&provisionerConfig.gatewayControllerName) 60 61 cmd.Flag("incluster", "Use in cluster configuration."). 62 Default("true"). 63 BoolVar(&provisionerConfig.inCluster) 64 cmd.Flag("kubeconfig", "Path to kubeconfig (if not in running inside a cluster)."). 65 PlaceHolder("/path/to/file"). 66 StringVar(&provisionerConfig.kubeconfig) 67 68 cmd.Flag("leader-election-namespace", "The namespace in which the leader election resource will be created."). 69 Default(config.GetenvOr("CONTOUR_PROVISIONER_NAMESPACE", "projectcontour")). 70 StringVar(&provisionerConfig.leaderElectionNamespace) 71 72 cmd.Flag("metrics-addr", "The address the metric endpoint binds to. It can be set to 0 to disable serving metrics."). 73 Default(provisionerConfig.metricsBindAddress). 74 StringVar(&provisionerConfig.metricsBindAddress) 75 76 return cmd, provisionerConfig 77 } 78 79 type gatewayProvisionerConfig struct { 80 // contourImage is the container image for the Contour container(s) managed 81 // by the gateway provisioner. 82 contourImage string 83 84 // envoyImage is the container image for the Envoy container(s) managed 85 // by the gateway provisioner. 86 envoyImage string 87 88 // metricsBindAddress is the TCP address that the gateway provisioner should bind to for 89 // serving prometheus metrics. It can be set to "0" to disable the metrics serving. 90 metricsBindAddress string 91 92 // leaderElection determines whether or not to use leader election when starting 93 // the gateway provisioner. 94 leaderElection bool 95 96 // leaderElectionID determines the name of the configmap that leader election will 97 // use for holding the leader lock. 98 leaderElectionID string 99 100 // leaderElectionNamespace determines the namespace in which the leader 101 // election resource will be created. 102 leaderElectionNamespace string 103 104 // gatewayControllerName defines the controller string that this gateway provisioner instance 105 // will process GatewayClasses and Gateways for. 106 gatewayControllerName string 107 108 // Kubernetes client parameters. 109 inCluster bool 110 kubeconfig string 111 } 112 113 func runGatewayProvisioner(config *gatewayProvisionerConfig) { 114 setupLog := ctrl.Log.WithName("setup") 115 116 for _, image := range []string{config.contourImage, config.envoyImage} { 117 // Parse will not handle short digests. 118 if _, err := reference.Parse(image); err != nil { 119 setupLog.Error(err, "invalid image reference", "value", image) 120 os.Exit(1) 121 } 122 } 123 124 setupLog.Info("using contour", "image", config.contourImage) 125 setupLog.Info("using envoy", "image", config.envoyImage) 126 127 // Establish k8s core client connection. 128 restConfig, err := k8s.NewRestConfig(config.kubeconfig, config.inCluster) 129 if err != nil { 130 setupLog.Error(err, "failed to create REST config for Kubernetes clients") 131 os.Exit(1) 132 } 133 134 mgr, err := createManager(restConfig, config) 135 if err != nil { 136 setupLog.Error(err, "failed to create contour gateway provisioner") 137 os.Exit(1) 138 } 139 140 setupLog.Info("starting contour gateway provisioner") 141 if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 142 setupLog.Error(err, "failed to start contour gateway provisioner") 143 os.Exit(1) 144 } 145 } 146 147 // createManager creates a new manager from restConfig and provisionerConfig. 148 func createManager(restConfig *rest.Config, provisionerConfig *gatewayProvisionerConfig) (manager.Manager, error) { 149 scheme, err := provisioner.CreateScheme() 150 if err != nil { 151 return nil, fmt.Errorf("error creating runtime scheme: %w", err) 152 } 153 154 mgr, err := ctrl.NewManager(restConfig, manager.Options{ 155 Scheme: scheme, 156 LeaderElection: provisionerConfig.leaderElection, 157 LeaderElectionResourceLock: "leases", 158 LeaderElectionID: provisionerConfig.leaderElectionID, 159 LeaderElectionNamespace: provisionerConfig.leaderElectionNamespace, 160 LeaderElectionReleaseOnCancel: true, 161 Metrics: controller_runtime_metrics_server.Options{ 162 BindAddress: provisionerConfig.metricsBindAddress, 163 }, 164 Logger: ctrl.Log.WithName("contour-gateway-provisioner"), 165 }) 166 if err != nil { 167 return nil, fmt.Errorf("failed to create manager: %w", err) 168 } 169 170 // Create and register the controllers with the manager. 171 if _, err := controller.NewGatewayClassController(mgr, provisionerConfig.gatewayControllerName); err != nil { 172 return nil, fmt.Errorf("failed to create gatewayclass controller: %w", err) 173 } 174 if _, err := controller.NewGatewayController(mgr, provisionerConfig.gatewayControllerName, provisionerConfig.contourImage, provisionerConfig.envoyImage); err != nil { 175 return nil, fmt.Errorf("failed to create gateway controller: %w", err) 176 } 177 return mgr, nil 178 }