Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

operator changes for managed cluster #2863

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/calico_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ components:
version: master
csi-node-driver-registrar:
version: master
calico/fluentd:
version: master
calico/guardian:
version: master
image: tigera/guardian
16 changes: 16 additions & 0 deletions hack/gen-versions/calico.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,26 @@ var (
Registry: "{{ .Registry }}",
}
{{- end }}
{{ with index .Components "calico/fluentd"}}
ComponentCalicoFluentd = component{
Version: "{{ .Version }}",
Image: "{{ .Image }}",
Registry: "{{ .Registry }}",
}
{{- end }}
{{ with index .Components "csi-node-driver-registrar"}}
ComponentCalicoCSIRegistrarFIPS = component{
Version: "{{ .Version }}-fips",
Image: "{{ .Image }}",
Registry: "{{ .Registry }}",
}
{{- end }}
{{ with index .Components "calico/guardian" }}
ComponentCalicoGuardian = component{
Version: "{{ .Version }}",
Image: "{{ .Image }}",
Registry: "{{ .Registry }}",
}
{{- end }}
ComponentOperatorInit = component{
Version: version.VERSION,
Expand All @@ -155,6 +169,8 @@ var (
ComponentCalicoCSI,
ComponentCalicoCSIFIPS,
ComponentCalicoCSIRegistrar,
ComponentCalicoFluentd,
ComponentCalicoCSIRegistrarFIPS,
ComponentCalicoGuardian,
}
)
2 changes: 2 additions & 0 deletions hack/gen-versions/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ var defaultImages = map[string]string{
"calico/apiserver": "calico/apiserver",
"calico/windows-upgrade": "calico/windows-upgrade",
"tigera/linseed": "tigera/linseed",
"calico/fluentd": "calico/fluentd",
"calico/guardian": "calico/guardian",
}

var ignoredImages = map[string]struct{}{
Expand Down
8 changes: 4 additions & 4 deletions hack/gen-versions/enterprise.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,14 @@ var (
}
{{- end }}
{{ with .Components.fluentd }}
ComponentFluentd = component{
ComponentTigeraFluentd = component{
Version: "{{ .Version }}",
Image: "{{ .Image }}",
Registry: "{{ .Registry }}",
}
{{- end }}
{{ with index .Components "fluentd-windows" }}
ComponentFluentdWindows = component{
ComponentTigeraFluentdWindows = component{
Version: "{{ .Version }}",
Image: "{{ .Image }}",
Registry: "{{ .Registry }}",
Expand Down Expand Up @@ -387,8 +387,8 @@ var (
ComponentElasticsearchOperator,
ComponentEsCurator,
ComponentEsProxy,
ComponentFluentd,
ComponentFluentdWindows,
ComponentTigeraFluentd,
ComponentTigeraFluentdWindows,
ComponentGuardian,
ComponentIntrusionDetectionController,
ComponentAnomalyDetectionJobs,
Expand Down
14 changes: 14 additions & 0 deletions pkg/components/calico.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,23 @@ var (
Registry: "",
}

ComponentCalicoFluentd = component{
Version: "master",
Image: "calico/fluentd",
Registry: "",
}

ComponentCalicoCSIRegistrarFIPS = component{
Version: "master-fips",
Image: "calico/node-driver-registrar",
Registry: "",
}

ComponentCalicoGuardian = component{
Version: "master",
Image: "tigera/guardian",
Registry: "",
}
ComponentOperatorInit = component{
Version: version.VERSION,
Image: "tigera/operator",
Expand All @@ -139,6 +151,8 @@ var (
ComponentCalicoCSI,
ComponentCalicoCSIFIPS,
ComponentCalicoCSIRegistrar,
ComponentCalicoFluentd,
ComponentCalicoCSIRegistrarFIPS,
ComponentCalicoGuardian,
}
)
8 changes: 4 additions & 4 deletions pkg/components/enterprise.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ var (
Registry: "",
}

ComponentFluentd = component{
ComponentTigeraFluentd = component{
Version: "master",
Image: "tigera/fluentd",
Registry: "",
}

ComponentFluentdWindows = component{
ComponentTigeraFluentdWindows = component{
Version: "master",
Image: "tigera/fluentd-windows",
Registry: "",
Expand Down Expand Up @@ -336,8 +336,8 @@ var (
ComponentElasticsearchOperator,
ComponentEsCurator,
ComponentEsProxy,
ComponentFluentd,
ComponentFluentdWindows,
ComponentTigeraFluentd,
ComponentTigeraFluentdWindows,
ComponentGuardian,
ComponentIntrusionDetectionController,
ComponentAnomalyDetectionJobs,
Expand Down
3 changes: 2 additions & 1 deletion pkg/components/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ func GetReference(c component, registry, imagePath, imagePrefix string, is *oper
ComponentCalicoCSI,
ComponentCalicoCSIFIPS,
ComponentCalicoCSIRegistrar,
ComponentCalicoCSIRegistrarFIPS:
ComponentCalicoCSIRegistrarFIPS,
ComponentCalicoFluentd:

registry = CalicoRegistry
case ComponentOperatorInit:
Expand Down
140 changes: 76 additions & 64 deletions pkg/controller/clusterconnection/clusterconnection_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ var log = logf.Log.WithName(controllerName)
// Add creates a new ManagementClusterConnection Controller and adds it to the Manager. The Manager will set fields on the Controller
// and start it when the Manager is started. This controller is meant only for enterprise users.
func Add(mgr manager.Manager, opts options.AddOptions) error {
if !opts.EnterpriseCRDExists {
// No need to start this controller.
return nil
}
statusManager := status.New(mgr.GetClient(), "management-cluster-connection", opts.KubernetesVersion)

// Create the reconciler
Expand All @@ -76,22 +72,24 @@ func Add(mgr manager.Manager, opts options.AddOptions) error {
return fmt.Errorf("failed to create %s: %w", controllerName, err)
}

k8sClient, err := kubernetes.NewForConfig(mgr.GetConfig())
if err != nil {
log.Error(err, "Failed to establish a connection to k8s")
return err
}
if opts.EnterpriseCRDExists {
k8sClient, err := kubernetes.NewForConfig(mgr.GetConfig())
if err != nil {
log.Error(err, "Failed to establish a connection to k8s")
return err
}

// Watch for changes to License and Tier, as their status is used as input to determine whether network policy should be reconciled by this controller.
go utils.WaitToAddLicenseKeyWatch(controller, k8sClient, log, nil)
go utils.WaitToAddTierWatch(networkpolicy.TigeraComponentTierName, controller, k8sClient, log, tierWatchReady)
// Watch for changes to License and Tier, as their status is used as input to determine whether network policy should be reconciled by this controller.
go utils.WaitToAddLicenseKeyWatch(controller, k8sClient, log, nil)
go utils.WaitToAddTierWatch(networkpolicy.TigeraComponentTierName, controller, k8sClient, log, tierWatchReady)

go utils.WaitToAddNetworkPolicyWatches(controller, k8sClient, log, []types.NamespacedName{
{Name: render.GuardianPolicyName, Namespace: render.GuardianNamespace},
{Name: networkpolicy.TigeraComponentDefaultDenyPolicyName, Namespace: render.GuardianNamespace},
})
go utils.WaitToAddNetworkPolicyWatches(controller, k8sClient, log, []types.NamespacedName{
{Name: render.GuardianPolicyName, Namespace: render.GuardianNamespace},
{Name: networkpolicy.TigeraComponentDefaultDenyPolicyName, Namespace: render.GuardianNamespace},
})
}

return add(mgr, controller)
return add(mgr, controller, opts.EnterpriseCRDExists)
}

// newReconciler returns a new reconcile.Reconciler
Expand All @@ -117,15 +115,10 @@ func newReconciler(
}

// add adds a new controller to mgr with r as the reconcile.Reconciler
func add(mgr manager.Manager, c controller.Controller) error {
// Watch for changes to primary resource ManagementCluster
err := c.Watch(&source.Kind{Type: &operatorv1.ManagementCluster{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return fmt.Errorf("%s failed to watch primary resource: %w", controllerName, err)
}
func add(mgr manager.Manager, c controller.Controller, enterpriseCRDExists bool) error {

// Watch for changes to primary resource ManagementClusterConnection
err = c.Watch(&source.Kind{Type: &operatorv1.ManagementClusterConnection{}}, &handler.EnqueueRequestForObject{})
err := c.Watch(&source.Kind{Type: &operatorv1.ManagementClusterConnection{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return fmt.Errorf("%s failed to watch primary resource: %w", controllerName, err)
}
Expand All @@ -135,15 +128,23 @@ func add(mgr manager.Manager, c controller.Controller) error {
return fmt.Errorf("%s failed to watch Secret resource %s: %w", controllerName, render.GuardianSecretName, err)
}

// Watch for changes to the secrets associated with the PacketCapture APIs.
if err = utils.AddSecretsWatch(c, render.PacketCaptureServerCert, common.OperatorNamespace()); err != nil {
return fmt.Errorf("%s failed to watch Secret resource %s: %w", controllerName, render.PacketCaptureServerCert, err)
}
// Watch for changes to the secrets associated with Prometheus.
if err = utils.AddSecretsWatch(c, monitor.PrometheusTLSSecretName, common.OperatorNamespace()); err != nil {
return fmt.Errorf("%s failed to watch Secret resource %s: %w", controllerName, monitor.PrometheusTLSSecretName, err)
}

if enterpriseCRDExists {
// Watch for changes to primary resource ManagementCluster
err := c.Watch(&source.Kind{Type: &operatorv1.ManagementCluster{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return fmt.Errorf("%s failed to watch primary resource: %w", controllerName, err)
}
// Watch for changes to the secrets associated with the PacketCapture APIs.
if err = utils.AddSecretsWatch(c, render.PacketCaptureServerCert, common.OperatorNamespace()); err != nil {
return fmt.Errorf("%s failed to watch Secret resource %s: %w", controllerName, render.PacketCaptureServerCert, err)
}
}

if err = utils.AddSecretsWatch(c, certificatemanagement.CASecretName, common.OperatorNamespace()); err != nil {
return fmt.Errorf("%s failed to watch Secret resource %s: %w", controllerName, certificatemanagement.CASecretName, err)
}
Expand Down Expand Up @@ -192,10 +193,13 @@ func (r *ReconcileConnection) Reconcile(ctx context.Context, request reconcile.R
return result, err
}

managementCluster, err := utils.GetManagementCluster(ctx, r.Client)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error reading ManagementCluster", err, reqLogger)
return reconcile.Result{}, err
var managementCluster *operatorv1.ManagementCluster
if variant == operatorv1.TigeraSecureEnterprise {
managementCluster, err = utils.GetManagementCluster(ctx, r.Client)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error reading ManagementCluster", err, reqLogger)
return reconcile.Result{}, err
}
}

// Fetch the managementClusterConnection.
Expand Down Expand Up @@ -278,7 +282,13 @@ func (r *ReconcileConnection) Reconcile(ctx context.Context, request reconcile.R
trustedCertBundle = certificateManager.CreateTrustedBundle()
}

for _, secretName := range []string{render.PacketCaptureServerCert, monitor.PrometheusTLSSecretName, render.ProjectCalicoAPIServerTLSSecretName(instl.Variant)} {
var certs []string
if variant == operatorv1.TigeraSecureEnterprise {
certs = []string{render.PacketCaptureServerCert, monitor.PrometheusTLSSecretName, render.ProjectCalicoAPIServerTLSSecretName(instl.Variant)}
} else {
certs = []string{render.ProjectCalicoAPIServerTLSSecretName(instl.Variant)}
}
for _, secretName := range certs {
secret, err := certificateManager.GetCertificate(r.Client, secretName, common.OperatorNamespace())
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, fmt.Sprintf("Failed to retrieve %s", secretName), err, reqLogger)
Expand All @@ -291,42 +301,44 @@ func (r *ReconcileConnection) Reconcile(ctx context.Context, request reconcile.R
trustedCertBundle.AddCertificates(secret)
}

// Validate that the tier watch is ready before querying the tier to ensure we utilize the cache.
if !r.tierWatchReady.IsReady() {
r.status.SetDegraded(operatorv1.ResourceNotReady, "Waiting for Tier watch to be established", nil, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}

// Ensure the allow-tigera tier exists, before rendering any network policies within it.
includeV3NetworkPolicy := false
if err := r.Client.Get(ctx, client.ObjectKey{Name: networkpolicy.TigeraComponentTierName}, &v3.Tier{}); err != nil {
// The creation of the Tier depends on this controller to reconcile it's non-NetworkPolicy resources so that the
// License becomes available. Therefore, if we fail to query the Tier, we exclude NetworkPolicy from reconciliation
// and tolerate errors arising from the Tier not being created.
if !k8serrors.IsNotFound(err) {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying allow-tigera tier", err, reqLogger)
return reconcile.Result{}, err
// Validate that the tier watch is ready before querying the tier to ensure we utilize the cache.
if variant == operatorv1.TigeraSecureEnterprise {
if !r.tierWatchReady.IsReady() {
r.status.SetDegraded(operatorv1.ResourceNotReady, "Waiting for Tier watch to be established", nil, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}
} else {
includeV3NetworkPolicy = true

// The Tier has been created, which means that this controller's reconciliation should no longer be a dependency
// of the License being deployed. If NetworkPolicy requires license features, it should now be safe to validate
// License presence and sufficiency.
if networkPolicyRequiresEgressAccessControl(managementClusterConnection, log) {
license, err := utils.FetchLicenseKey(ctx, r.Client)
if err != nil {
if k8serrors.IsNotFound(err) {
r.status.SetDegraded(operatorv1.ResourceNotFound, "License not found", err, reqLogger)

// Ensure the allow-tigera tier exists, before rendering any network policies within it.
if err := r.Client.Get(ctx, client.ObjectKey{Name: networkpolicy.TigeraComponentTierName}, &v3.Tier{}); err != nil {
// The creation of the Tier depends on this controller to reconcile it's non-NetworkPolicy resources so that the
// License becomes available. Therefore, if we fail to query the Tier, we exclude NetworkPolicy from reconciliation
// and tolerate errors arising from the Tier not being created.
if !k8serrors.IsNotFound(err) {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying allow-tigera tier", err, reqLogger)
return reconcile.Result{}, err
}
} else {
includeV3NetworkPolicy = true

// The Tier has been created, which means that this controller's reconciliation should no longer be a dependency
// of the License being deployed. If NetworkPolicy requires license features, it should now be safe to validate
// License presence and sufficiency.
if networkPolicyRequiresEgressAccessControl(managementClusterConnection, log) {
license, err := utils.FetchLicenseKey(ctx, r.Client)
if err != nil {
if k8serrors.IsNotFound(err) {
r.status.SetDegraded(operatorv1.ResourceNotFound, "License not found", err, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying license", err, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying license", err, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}

if !utils.IsFeatureActive(license, common.EgressAccessControlFeature) {
r.status.SetDegraded(operatorv1.ResourceReadError, "Feature is not active - License does not support feature: egress-access-control", nil, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
if !utils.IsFeatureActive(license, common.EgressAccessControlFeature) {
r.status.SetDegraded(operatorv1.ResourceReadError, "Feature is not active - License does not support feature: egress-access-control", nil, reqLogger)
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
}
}
}
}
Expand Down
Loading