Skip to content

Commit

Permalink
Merge pull request #1584 from OverOrion/extract-fluentd-crd
Browse files Browse the repository at this point in the history
Standalone FluentdConfig resource
  • Loading branch information
pepov authored Dec 6, 2023
2 parents b05c49e + dbf3b28 commit 2149f37
Show file tree
Hide file tree
Showing 40 changed files with 7,370 additions and 500 deletions.
2,918 changes: 2,918 additions & 0 deletions charts/logging-operator/crds/logging.banzaicloud.io_fluentdconfigs.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18679,6 +18679,8 @@ spec:
additionalProperties:
type: boolean
type: object
fluentdConfigName:
type: string
problems:
items:
type: string
Expand Down
2 changes: 2 additions & 0 deletions charts/logging-operator/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ rules:
- clusteroutputs
- flows
- fluentbitagents
- fluentdconfigs
- loggings
- nodeagents
- outputs
Expand All @@ -259,6 +260,7 @@ rules:
- clusteroutputs/status
- flows/status
- fluentbitagents/status
- fluentdconfigs/status
- loggings/status
- nodeagents/status
- outputs/status
Expand Down
2,918 changes: 2,918 additions & 0 deletions config/crd/bases/logging.banzaicloud.io_fluentdconfigs.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions config/crd/bases/logging.banzaicloud.io_loggings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18679,6 +18679,8 @@ spec:
additionalProperties:
type: boolean
type: object
fluentdConfigName:
type: string
problems:
items:
type: string
Expand Down
2 changes: 2 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ rules:
- clusteroutputs
- flows
- fluentbitagents
- fluentdconfigs
- loggings
- nodeagents
- outputs
Expand All @@ -259,6 +260,7 @@ rules:
- clusteroutputs/status
- flows/status
- fluentbitagents/status
- fluentdconfigs/status
- loggings/status
- nodeagents/status
- outputs/status
Expand Down
36 changes: 28 additions & 8 deletions controllers/logging/logging_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ type LoggingReconciler struct {
Log logr.Logger
}

// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents;fluentdconfigs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status;fluentdconfigs/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows;syslogngclusterflows;syslogngoutputs;syslogngclusteroutputs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows/status;syslogngclusterflows/status;syslogngoutputs/status;syslogngclusteroutputs/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -169,13 +169,14 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
),
}

if logging.Spec.FluentdSpec != nil && logging.Spec.SyslogNGSpec != nil {
if logging.AreMultipleAggregatorsSet() {
return ctrl.Result{}, errors.New("fluentd and syslogNG cannot be enabled simultaneously")
}

var loggingDataProvider loggingdataprovider.LoggingDataProvider

if logging.Spec.FluentdSpec != nil {
fluentdSpec := loggingResources.GetFluentdSpec()
if fluentdSpec != nil {
fluentdConfig, secretList, err := r.clusterConfigurationFluentd(loggingResources)
if err != nil {
// TODO: move config generation into Fluentd reconciler
Expand All @@ -185,9 +186,9 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
} else {
log.V(1).Info("flow configuration", "config", fluentdConfig)

reconcilers = append(reconcilers, fluentd.New(r.Client, r.Log, &logging, &fluentdConfig, secretList, reconcilerOpts).Reconcile)
reconcilers = append(reconcilers, fluentd.New(r.Client, r.Log, &logging, fluentdSpec, &fluentdConfig, secretList, reconcilerOpts).Reconcile)
}
loggingDataProvider = fluentd.NewDataProvider(r.Client, &logging)
loggingDataProvider = fluentd.NewDataProvider(r.Client, &logging, fluentdSpec)
}

if logging.Spec.SyslogNGSpec != nil {
Expand Down Expand Up @@ -215,6 +216,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
r.Client,
log.WithName("fluentbit-legacy"),
&logging,
fluentdSpec,
reconcilerOpts,
logging.Spec.FluentbitSpec,
loggingDataProvider,
Expand All @@ -233,6 +235,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
r.Client,
l.WithValues("fluentbitagent", f.Name),
&logging,
fluentdSpec,
reconcilerOpts,
&f.Spec,
loggingDataProvider,
Expand All @@ -257,7 +260,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
log.Error(errors.New("nodeagent definition conflict"), problem)
}
}
reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging)).Reconcile)
reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, fluentdSpec, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging, fluentdSpec)).Reconcile)
}

for _, rec := range reconcilers {
Expand Down Expand Up @@ -433,6 +436,8 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder
return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.LoggingRef)
case *loggingv1beta1.LoggingRoute:
return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.Source)
case *loggingv1beta1.FluentdConfig:
return reconcileRequestsForMatchingControlNamespace(loggingList.Items, o.Namespace)
case *corev1.Secret:
r := regexp.MustCompile(`^logging\.banzaicloud\.io/(.*)`)
var requestList []reconcile.Request
Expand Down Expand Up @@ -482,7 +487,8 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder
Watches(&loggingv1beta1.SyslogNGOutput{}, requestMapper).
Watches(&loggingv1beta1.SyslogNGFlow{}, requestMapper).
Watches(&corev1.Secret{}, requestMapper).
Watches(&loggingv1beta1.LoggingRoute{}, requestMapper)
Watches(&loggingv1beta1.LoggingRoute{}, requestMapper).
Watches(&loggingv1beta1.FluentdConfig{}, requestMapper)

// TODO remove with the next major release
if os.Getenv("ENABLE_NODEAGENT_CRD") != "" {
Expand Down Expand Up @@ -514,6 +520,20 @@ func reconcileRequestsForLoggingRef(loggings []loggingv1beta1.Logging, loggingRe
return
}

func reconcileRequestsForMatchingControlNamespace(loggings []loggingv1beta1.Logging, ControlNamespace string) (reqs []reconcile.Request) {
for _, l := range loggings {
if l.Spec.ControlNamespace == ControlNamespace {
reqs = append(reqs, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: l.Namespace, // this happens to be empty as long as Logging is cluster scoped
Name: l.Name,
},
})
}
}
return
}

func min(a, b int) int {
if a < b {
return a
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/crds/v1beta1/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ For more information please click on the name
| **[](conversion/)** | | v1beta1 |
| **[FlowSpec](flow_types/)** | FlowSpec is the Kubernetes spec for Flows | v1beta1 |
| **[FluentbitSpec](fluentbit_types/)** | FluentbitSpec defines the desired state of FluentbitAgent | v1beta1 |
| **[FluentdSpec](fluentd_types/)** | FluentdSpec defines the desired state of Fluentd | v1beta1 |
| **[Fluent](fluentd_types/)** | FluentdConfig is a reference to the desired Fluentd state | v1beta1 |
| **[Logging](logging_types/)** | Logging system configuration | v1beta1 |
| **[LoggingRouteSpec](loggingroute_types/)** | LoggingRouteSpec defines the desired state of LoggingRoute | v1beta1 |
| **[_hugoNodeAgent](node_agent_types/)** | | v1beta1 |
Expand Down
54 changes: 54 additions & 0 deletions docs/configuration/crds/v1beta1/fluentd_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,60 @@ Fluentd port inside the container (24240 by default). The headless service port



---
title: FluentdConfig
weight: 200
generated_file: true
---

## FluentdConfig

FluentdConfig

### (metav1.TypeMeta, required) {#fluentdconfig-}


### metadata (metav1.ObjectMeta, optional) {#fluentdconfig-metadata}


### spec (FluentdSpec, optional) {#fluentdconfig-spec}


### status (FluentdConfigStatus, optional) {#fluentdconfig-status}



## FluentdConfigStatus

FluentdConfigStatus

### active (*bool, optional) {#fluentdconfigstatus-active}


### logging (string, optional) {#fluentdconfigstatus-logging}


### problems ([]string, optional) {#fluentdconfigstatus-problems}


### problemsCount (int, optional) {#fluentdconfigstatus-problemscount}



## FluentdConfigList

FluentdConfigList

### (metav1.TypeMeta, required) {#fluentdconfiglist-}


### metadata (metav1.ListMeta, optional) {#fluentdconfiglist-metadata}


### items ([]FluentdConfig, required) {#fluentdconfiglist-items}



## FluentOutLogrotate

### age (string, optional) {#fluentoutlogrotate-age}
Expand Down
5 changes: 5 additions & 0 deletions docs/configuration/crds/v1beta1/logging_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ LoggingStatus defines the observed state of Logging
Result of the config check. Under normal conditions there is a single item in the map with a bool value.


### fluentdConfigName (string, optional) {#loggingstatus-fluentdconfigname}

Name of the matched detached fluentd configuration object


### problems ([]string, optional) {#loggingstatus-problems}

Problems with the logging resource
Expand Down
120 changes: 120 additions & 0 deletions docs/standalone-aggregator-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
## Standalone Fluentd config

The standalone `FluentdConfig` is a namespaced resource that allows the configuration of the Fluentd / SyslogNG
aggregator component in the control namespace separately from the Logging resource.

The primary benefit of this behaviour is that it enables a multi-tenant model, where tenant owners are responsible
for operating their own aggregator, while the Logging resource is in control of the central operations team.
For more information about the multi-tenancy model where the collector is capable of routing logs based on namespaces
to individual aggregators and where aggregators are fully isolated, please see [Multi-tenancy](multi-tenancy.md)

Traditional configuration of fluentd within the logging resource:
```
apiVersion: logging.banzaicloud.io/v1beta1
kind: Logging
metadata:
name: example
spec:
controlNamespace: logging
fluentd:
scaling:
replicas: 2
```

The alternative configuration is as follows:
```
apiVersion: logging.banzaicloud.io/v1beta1
kind: Logging
metadata:
name: example
spec:
controlNamespace: logging
---
apiVersion: logging.banzaicloud.io/v1beta1
kind: FluentdConfig
metadata:
name: example
namespace: logging
spec:
scaling:
replicas: 2
```

### Schema and migration

The schema for `FluentdConfig.spec` is the same as it was withing `Logging.spec.fluentd`, so the migration should be a trivial lift and shift
exercise.

### Restrictions and status

There can only be one active `FluentdConfig` for a single `Logging` resource at a time. The controller will make
sure to register the active `FluentdConfig` resource into the `Logging` resource's status under `fluentdConfigName`,
while registering the `Logging` resource name under `logging` in the `FluentdConfig` resource's status.

```
kubectl get logging example -o jsonpath='{.status}' | jq .
{
"configCheckResults": {
"ac2d4553": true
},
"fluentdConfigName": "example"
}
```

```
kubectl get fluentdconfig example -o jsonpath='{.status}' | jq .
{
"active": true,
"logging": "example"
}
```

If there is a conflict, then the controller will add a problem to both resources so that both operations and tenant users can be aware of it.
For example add another `FluentdConfig` resource on top of the existing one:

```
apiVersion: logging.banzaicloud.io/v1beta1
kind: FluentdConfig
metadata:
name: example2
namespace: logging
spec: {}
```

The first `FluentdConfig` should be left intact, while the second one should have the following status:
```
kubectl get fluentdconfig example2 -o jsonpath='{.status}' | jq .
{
"active": false,
"problems": [
"logging already has a detached fluentd configuration, remove excess configuration objects"
],
"problemsCount": 1
}
```

The `Logging` resource will also highlight the issue
```
kubectl get logging example -o jsonpath='{.status}' | jq .
{
"configCheckResults": {
"ac2d4553": true
},
"fluentdConfigName": "example",
"problems": [
"multiple fluentd configurations found, couldn't associate it with logging"
],
"problemsCount": 1
}
```

Once the extra `FluentdConfig` resource is removed the `Logging` resource status should return back to normal:
```
kubectl get logging example -o jsonpath='{.status}' | jq .
{
"configCheckResults": {
"ac2d4553": true
},
"fluentdConfigName": "example"
}
```
Loading

0 comments on commit 2149f37

Please sign in to comment.