github.com/cilium/cilium@v1.16.2/operator/pkg/ingress/cell.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package ingress 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/cilium/hive/cell" 11 "github.com/sirupsen/logrus" 12 "github.com/spf13/pflag" 13 networkingv1 "k8s.io/api/networking/v1" 14 ctrlRuntime "sigs.k8s.io/controller-runtime" 15 "sigs.k8s.io/controller-runtime/pkg/builder" 16 "sigs.k8s.io/controller-runtime/pkg/predicate" 17 18 operatorOption "github.com/cilium/cilium/operator/option" 19 "github.com/cilium/cilium/operator/pkg/model/translation" 20 ingressTranslation "github.com/cilium/cilium/operator/pkg/model/translation/ingress" 21 "github.com/cilium/cilium/operator/pkg/secretsync" 22 "github.com/cilium/cilium/pkg/option" 23 ) 24 25 // Cell manages the Kubernetes Ingress related controllers. 26 var Cell = cell.Module( 27 "ingress", 28 "Manages the Kubernetes Ingress controllers", 29 30 cell.Config(ingressConfig{ 31 EnableIngressController: false, 32 EnforceIngressHTTPS: true, 33 EnableIngressProxyProtocol: false, 34 EnableIngressSecretsSync: true, 35 IngressSecretsNamespace: "cilium-secrets", 36 IngressDefaultRequestTimeout: time.Duration(0), 37 IngressLBAnnotationPrefixes: []string{"lbipam.cilium.io", "service.beta.kubernetes.io", "service.kubernetes.io", "cloud.google.com"}, 38 IngressSharedLBServiceName: "cilium-ingress", 39 IngressDefaultLBMode: "dedicated", 40 41 IngressHostnetworkEnabled: false, 42 IngressHostnetworkSharedListenerPort: 0, 43 IngressHostnetworkNodelabelselector: "", 44 }), 45 cell.Invoke(registerReconciler), 46 cell.Provide(registerSecretSync), 47 ) 48 49 type ingressConfig struct { 50 KubeProxyReplacement string 51 EnableNodePort bool 52 EnableIngressController bool 53 EnforceIngressHTTPS bool 54 EnableIngressProxyProtocol bool 55 EnableIngressSecretsSync bool 56 IngressSecretsNamespace string 57 IngressLBAnnotationPrefixes []string 58 IngressSharedLBServiceName string 59 IngressDefaultLBMode string 60 IngressDefaultSecretNamespace string 61 IngressDefaultSecretName string 62 IngressDefaultRequestTimeout time.Duration 63 IngressHostnetworkEnabled bool 64 IngressHostnetworkSharedListenerPort uint32 65 IngressHostnetworkNodelabelselector string 66 IngressDefaultXffNumTrustedHops uint32 67 } 68 69 func (r ingressConfig) Flags(flags *pflag.FlagSet) { 70 flags.String("kube-proxy-replacement", r.KubeProxyReplacement, "Enable only selected features (will panic if any selected feature cannot be enabled) (\"false\"), or enable all features (will panic if any feature cannot be enabled) (\"true\") (default \"false\")") 71 flags.Bool("enable-node-port", r.EnableNodePort, "Enable NodePort type services by Cilium") 72 flags.Bool("enable-ingress-controller", r.EnableIngressController, "Enables cilium ingress controller. This must be enabled along with enable-envoy-config in cilium agent.") 73 flags.Bool("enforce-ingress-https", r.EnforceIngressHTTPS, "Enforces https for host having matching TLS host in Ingress. Incoming traffic to http listener will return 308 http error code with respective location in header.") 74 flags.Bool("enable-ingress-proxy-protocol", r.EnableIngressProxyProtocol, "Enable proxy protocol for all Ingress listeners. Note that _only_ Proxy protocol traffic will be accepted once this is enabled.") 75 flags.Bool("enable-ingress-secrets-sync", r.EnableIngressSecretsSync, "Enables fan-in TLS secrets from multiple namespaces to singular namespace (specified by ingress-secrets-namespace flag)") 76 flags.String("ingress-secrets-namespace", r.IngressSecretsNamespace, "Namespace having tls secrets used by Ingress and CEC.") 77 flags.StringSlice("ingress-lb-annotation-prefixes", r.IngressLBAnnotationPrefixes, "Annotations and labels which are needed to propagate from Ingress to the Load Balancer.") 78 flags.String("ingress-shared-lb-service-name", r.IngressSharedLBServiceName, "Name of shared LB service name for Ingress.") 79 flags.String("ingress-default-lb-mode", r.IngressDefaultLBMode, "Default loadbalancer mode for Ingress. Applicable values: dedicated, shared") 80 flags.String("ingress-default-secret-namespace", r.IngressDefaultSecretNamespace, "Default secret namespace for Ingress.") 81 flags.String("ingress-default-secret-name", r.IngressDefaultSecretName, "Default secret name for Ingress.") 82 flags.Duration("ingress-default-request-timeout", r.IngressDefaultRequestTimeout, "Default request timeout for Ingress.") 83 flags.Bool("ingress-hostnetwork-enabled", r.IngressHostnetworkEnabled, "Exposes ingress listeners on the host network.") 84 flags.Uint32("ingress-hostnetwork-shared-listener-port", r.IngressHostnetworkSharedListenerPort, "Port on the host network that gets used for the shared listener (HTTP, HTTPS & TLS passthrough)") 85 flags.String("ingress-hostnetwork-nodelabelselector", r.IngressHostnetworkNodelabelselector, "Label selector that matches the nodes where the ingress listeners should be exposed. It's a list of comma-separated key-value label pairs. e.g. 'kubernetes.io/os=linux,kubernetes.io/hostname=kind-worker'") 86 flags.Uint32("ingress-default-xff-num-trusted-hops", r.IngressDefaultXffNumTrustedHops, "The number of additional ingress proxy hops from the right side of the HTTP header to trust when determining the origin client's IP address.") 87 } 88 89 type ingressParams struct { 90 cell.In 91 92 Logger logrus.FieldLogger 93 CtrlRuntimeManager ctrlRuntime.Manager 94 AgentConfig *option.DaemonConfig 95 OperatorConfig *operatorOption.OperatorConfig 96 IngressConfig ingressConfig 97 } 98 99 func registerReconciler(params ingressParams) error { 100 if !params.IngressConfig.EnableIngressController { 101 return nil 102 } 103 104 if params.IngressConfig.KubeProxyReplacement != option.KubeProxyReplacementTrue && 105 !params.IngressConfig.EnableNodePort { 106 params.Logger.Warn("Ingress Controller support requires either kube-proxy-replacement or enable-node-port enabled") 107 return nil 108 } 109 110 cecTranslator := translation.NewCECTranslator( 111 params.IngressConfig.IngressSecretsNamespace, 112 params.IngressConfig.EnableIngressProxyProtocol, 113 false, 114 false, // hostNameSuffixMatch 115 params.OperatorConfig.ProxyIdleTimeoutSeconds, 116 params.IngressConfig.IngressHostnetworkEnabled, 117 translation.ParseNodeLabelSelector(params.IngressConfig.IngressHostnetworkNodelabelselector), 118 params.AgentConfig.EnableIPv4, 119 params.AgentConfig.EnableIPv6, 120 params.IngressConfig.IngressDefaultXffNumTrustedHops, 121 ) 122 123 dedicatedIngressTranslator := ingressTranslation.NewDedicatedIngressTranslator(cecTranslator, params.IngressConfig.IngressHostnetworkEnabled) 124 125 reconciler := newIngressReconciler( 126 params.Logger, 127 params.CtrlRuntimeManager.GetClient(), 128 129 cecTranslator, 130 dedicatedIngressTranslator, 131 132 operatorOption.Config.CiliumK8sNamespace, 133 params.IngressConfig.IngressLBAnnotationPrefixes, 134 params.IngressConfig.IngressSharedLBServiceName, 135 params.IngressConfig.IngressDefaultLBMode, 136 params.IngressConfig.IngressDefaultSecretNamespace, 137 params.IngressConfig.IngressDefaultSecretName, 138 params.IngressConfig.EnforceIngressHTTPS, 139 params.IngressConfig.IngressDefaultRequestTimeout, 140 141 params.IngressConfig.IngressHostnetworkEnabled, 142 params.IngressConfig.IngressHostnetworkSharedListenerPort, 143 ) 144 145 if err := reconciler.SetupWithManager(params.CtrlRuntimeManager); err != nil { 146 return fmt.Errorf("failed to setup ingress reconciler: %w", err) 147 } 148 149 return nil 150 } 151 152 // registerSecretSync registers the Ingress Controller for secret synchronization based on TLS secrets referenced 153 // by a Cilium Ingress resource. 154 func registerSecretSync(params ingressParams) secretsync.SecretSyncRegistrationOut { 155 if !params.IngressConfig.EnableIngressController || !params.IngressConfig.EnableIngressSecretsSync { 156 return secretsync.SecretSyncRegistrationOut{} 157 } 158 159 registration := secretsync.SecretSyncRegistrationOut{ 160 SecretSyncRegistration: &secretsync.SecretSyncRegistration{ 161 RefObject: &networkingv1.Ingress{}, 162 RefObjectEnqueueFunc: EnqueueReferencedTLSSecrets(params.CtrlRuntimeManager.GetClient(), params.Logger), 163 RefObjectCheckFunc: IsReferencedByCiliumIngress, 164 SecretsNamespace: params.IngressConfig.IngressSecretsNamespace, 165 // In addition to changed Ingresses an additional watch on IngressClass gets added. 166 // Its purpose is to detect any changes regarding the default IngressClass 167 // (that is marked via annotation). 168 AdditionalWatches: []secretsync.AdditionalWatch{ 169 { 170 RefObject: &networkingv1.IngressClass{}, 171 RefObjectEnqueueFunc: enqueueAllSecrets(params.CtrlRuntimeManager.GetClient()), 172 RefObjectWatchOptions: []builder.WatchesOption{ 173 builder.WithPredicates(predicate.AnnotationChangedPredicate{}), 174 }, 175 }, 176 }, 177 }, 178 } 179 180 if params.IngressConfig.IngressDefaultSecretName != "" && params.IngressConfig.IngressDefaultSecretNamespace != "" { 181 registration.SecretSyncRegistration.DefaultSecret = &secretsync.DefaultSecret{ 182 Namespace: params.IngressConfig.IngressDefaultSecretNamespace, 183 Name: params.IngressConfig.IngressDefaultSecretName, 184 } 185 } 186 187 return registration 188 }