github.com/cilium/cilium@v1.16.2/pkg/ciliumenvoyconfig/cell.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ciliumenvoyconfig
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/cilium/hive/cell"
    11  	"github.com/cilium/hive/job"
    12  	"github.com/sirupsen/logrus"
    13  	"github.com/spf13/pflag"
    14  
    15  	"github.com/cilium/cilium/pkg/envoy"
    16  	"github.com/cilium/cilium/pkg/k8s"
    17  	ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
    18  	"github.com/cilium/cilium/pkg/k8s/resource"
    19  	slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1"
    20  	"github.com/cilium/cilium/pkg/k8s/synced"
    21  	"github.com/cilium/cilium/pkg/logging/logfields"
    22  	"github.com/cilium/cilium/pkg/node"
    23  	"github.com/cilium/cilium/pkg/option"
    24  	"github.com/cilium/cilium/pkg/policy"
    25  	"github.com/cilium/cilium/pkg/service"
    26  	"github.com/cilium/cilium/pkg/time"
    27  )
    28  
    29  // Cell provides support for the CRD CiliumEnvoyConfig that backs Ingress, Gateway API
    30  // and L7 loadbalancing.
    31  var Cell = cell.Module(
    32  	"ciliumenvoyconfig",
    33  	"CiliumEnvoyConfig",
    34  
    35  	cell.Invoke(registerCECK8sReconciler),
    36  	cell.ProvidePrivate(newCECManager),
    37  	cell.ProvidePrivate(newCECResourceParser),
    38  	cell.ProvidePrivate(newEnvoyServiceBackendSyncer),
    39  	cell.Config(cecConfig{}),
    40  )
    41  
    42  type cecConfig struct {
    43  	EnvoyConfigRetryInterval time.Duration
    44  	EnvoyConfigTimeout       time.Duration
    45  }
    46  
    47  func (r cecConfig) Flags(flags *pflag.FlagSet) {
    48  	flags.Duration("envoy-config-retry-interval", 15*time.Second, "Interval in which an attempt is made to reconcile failed EnvoyConfigs. If the duration is zero, the retry is deactivated.")
    49  	flags.Duration("envoy-config-timeout", 2*time.Minute, "Timeout that determines how long to wait for Envoy to N/ACK CiliumEnvoyConfig resources")
    50  }
    51  
    52  type reconcilerParams struct {
    53  	cell.In
    54  
    55  	Logger    logrus.FieldLogger
    56  	Lifecycle cell.Lifecycle
    57  	JobGroup  job.Group
    58  	Health    cell.Health
    59  
    60  	K8sResourceSynced *synced.Resources
    61  	K8sAPIGroups      *synced.APIGroups
    62  
    63  	Config  cecConfig
    64  	Manager ciliumEnvoyConfigManager
    65  
    66  	CECResources   resource.Resource[*ciliumv2.CiliumEnvoyConfig]
    67  	CCECResources  resource.Resource[*ciliumv2.CiliumClusterwideEnvoyConfig]
    68  	LocalNodeStore *node.LocalNodeStore
    69  }
    70  
    71  func registerCECK8sReconciler(params reconcilerParams) {
    72  	if !option.Config.EnableL7Proxy || !option.Config.EnableEnvoyConfig {
    73  		return
    74  	}
    75  
    76  	ctx, cancel := context.WithCancel(context.Background())
    77  
    78  	reconciler := newCiliumEnvoyConfigReconciler(params)
    79  
    80  	params.Lifecycle.Append(cell.Hook{
    81  		OnStart: func(startCtx cell.HookContext) error {
    82  			localNode, err := params.LocalNodeStore.Get(startCtx)
    83  			if err != nil {
    84  				return fmt.Errorf("failed to get LocalNodeStore: %w", err)
    85  			}
    86  
    87  			reconciler.localNodeLabels = localNode.Labels
    88  
    89  			params.Logger.
    90  				WithField(logfields.Labels, reconciler.localNodeLabels).
    91  				Debug("Retrieved initial labels from local Node")
    92  
    93  			return nil
    94  		},
    95  		OnStop: func(cell.HookContext) error {
    96  			if cancel != nil {
    97  				cancel()
    98  			}
    99  			return nil
   100  		},
   101  	})
   102  
   103  	reconciler.registerResourceWithSyncFn(ctx, k8sAPIGroupCiliumEnvoyConfigV2, func() bool {
   104  		return reconciler.cecSynced.Load()
   105  	})
   106  	reconciler.registerResourceWithSyncFn(ctx, k8sAPIGroupCiliumClusterwideEnvoyConfigV2, func() bool {
   107  		return reconciler.ccecSynced.Load()
   108  	})
   109  
   110  	params.JobGroup.Add(job.Observer("cec-resource-events", reconciler.handleCECEvent, params.CECResources))
   111  	params.JobGroup.Add(job.Observer("ccec-resource-events", reconciler.handleCCECEvent, params.CCECResources))
   112  
   113  	// Observing local node events for changed labels
   114  	// Note: LocalNodeStore (in comparison to `resource.Resource`) doesn't provide a retry mechanism
   115  	params.JobGroup.Add(job.Observer("local-node-events", reconciler.handleLocalNodeEvent, params.LocalNodeStore))
   116  
   117  	// TimerJob periodically reconciles all existing configs.
   118  	// This covers the cases were the reconciliation fails after changing the labels of a node.
   119  	if params.Config.EnvoyConfigRetryInterval > 0 {
   120  		params.JobGroup.Add(job.Timer("reconcile-existing-configs", reconciler.reconcileExistingConfigs, params.Config.EnvoyConfigRetryInterval))
   121  		params.JobGroup.Add(job.Timer("sync-headless-service", reconciler.syncHeadlessService, params.Config.EnvoyConfigRetryInterval))
   122  	}
   123  }
   124  
   125  type managerParams struct {
   126  	cell.In
   127  
   128  	Logger logrus.FieldLogger
   129  
   130  	Config cecConfig
   131  
   132  	PolicyUpdater  *policy.Updater
   133  	ServiceManager service.ServiceManager
   134  
   135  	XdsServer      envoy.XDSServer
   136  	BackendSyncer  *envoyServiceBackendSyncer
   137  	ResourceParser *cecResourceParser
   138  
   139  	Services  resource.Resource[*slim_corev1.Service]
   140  	Endpoints resource.Resource[*k8s.Endpoints]
   141  }
   142  
   143  func newCECManager(params managerParams) ciliumEnvoyConfigManager {
   144  	return newCiliumEnvoyConfigManager(params.Logger, params.PolicyUpdater, params.ServiceManager, params.XdsServer,
   145  		params.BackendSyncer, params.ResourceParser, params.Config.EnvoyConfigTimeout, params.Services, params.Endpoints)
   146  }