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

add k8s events logging to alloy #263

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b276673
add k8s events logging to alloy
QuantumEnigmaa Nov 12, 2024
d1ecc0e
changelog
QuantumEnigmaa Nov 12, 2024
73c3a71
create the events-logger resource : either alloy or grafana-agent
QuantumEnigmaa Nov 14, 2024
c39115a
handle secret for authentication
QuantumEnigmaa Nov 14, 2024
3cfb909
merge with main and resolve conflicts
QuantumEnigmaa Nov 14, 2024
33cce97
fix alloy config property name
QuantumEnigmaa Nov 14, 2024
dedd9ad
merge with main
QuantumEnigmaa Nov 18, 2024
f49f6f3
merge with main
QuantumEnigmaa Nov 18, 2024
2e6c67f
merge with main
QuantumEnigmaa Nov 18, 2024
f09f504
fix build errors
QuantumEnigmaa Nov 18, 2024
9a8454c
rename k8s-events-config package to events-logger-config
QuantumEnigmaa Nov 19, 2024
a62b968
Apply suggestions from code review
QuantumEnigmaa Nov 19, 2024
8e78389
fix error log
QuantumEnigmaa Nov 19, 2024
6776f50
return correct configmap name depending on the events logger
QuantumEnigmaa Nov 19, 2024
27f1aef
return correct secret name depending on the events logger
QuantumEnigmaa Nov 19, 2024
83c572b
add scrapedNamespaces to alloy config create related function in common
QuantumEnigmaa Nov 19, 2024
ab44bc4
add tls config for alloy
QuantumEnigmaa Nov 19, 2024
ad0e906
fix formating in grafana-agent template
QuantumEnigmaa Nov 19, 2024
1469dff
hardcode controller.type and controller.replicas in alloyEvents template
QuantumEnigmaa Nov 19, 2024
25c8cb4
remove unused observabilityBundleVersion parameters and variable in e…
QuantumEnigmaa Nov 19, 2024
e0cb4a7
remove grafanaAgentSecretName and eventsLoggerSecretName from securit…
QuantumEnigmaa Nov 19, 2024
aa6917a
rename variables in events-logger-config's reconciler to a neutral name
QuantumEnigmaa Nov 19, 2024
049d2cc
make several functions private
QuantumEnigmaa Nov 19, 2024
ec83211
hardcode several fields in grafana-agent config template
QuantumEnigmaa Nov 19, 2024
ad971d0
rename comments and logs in agents-toggle's reconciler
QuantumEnigmaa Nov 19, 2024
194d1cc
enable events logger in main.go
QuantumEnigmaa Nov 20, 2024
b3e196e
fix formating in events-logger templates
QuantumEnigmaa Nov 20, 2024
cdc361c
remove unused field in alloy generateAlloyConfig
QuantumEnigmaa Nov 20, 2024
df3a66e
fix alloy-events secret name
QuantumEnigmaa Nov 20, 2024
5d04402
merge with main
QuantumEnigmaa Nov 20, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add kubernetes events logging in Alloy.
- Add support for Private CAs in alloy logs.
- Add KubeEventsLogger option and related methods in loggedCLuster package.
- Add `events-logger` flag in the operator.
Expand Down
11 changes: 6 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import (
loggingreconciler "github.com/giantswarm/logging-operator/pkg/logging-reconciler"
"github.com/giantswarm/logging-operator/pkg/reconciler"
agentstoggle "github.com/giantswarm/logging-operator/pkg/resource/agents-toggle"
eventsloggerconfig "github.com/giantswarm/logging-operator/pkg/resource/grafana-agent-config"
eventsloggersecret "github.com/giantswarm/logging-operator/pkg/resource/grafana-agent-secret"
eventsloggersecret "github.com/giantswarm/logging-operator/pkg/resource/events-logger-secret"
grafanadatasource "github.com/giantswarm/logging-operator/pkg/resource/grafana-datasource"
eventsloggerconfig "github.com/giantswarm/logging-operator/pkg/resource/k8s-events-config"
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
loggingconfig "github.com/giantswarm/logging-operator/pkg/resource/logging-config"
loggingcredentials "github.com/giantswarm/logging-operator/pkg/resource/logging-credentials"
loggingsecret "github.com/giantswarm/logging-operator/pkg/resource/logging-secret"
Expand Down Expand Up @@ -167,11 +167,12 @@ func main() {
DefaultWorkloadClusterNamespaces: defaultNamespaces,
}

eventsLoggerSecret := eventsloggersecret.Reconciler{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this change I guess :D

Client: mgr.GetClient(),
eventsLoggerConfig := eventsloggerconfig.Reconciler{
Client: mgr.GetClient(),
DefaultWorkloadClusterNamespaces: defaultNamespaces,
QuentinBisson marked this conversation as resolved.
Show resolved Hide resolved
}

eventsLoggerConfig := eventsloggerconfig.Reconciler{
eventsLoggerSecret := eventsloggersecret.Reconciler{
Client: mgr.GetClient(),
}

Expand Down
60 changes: 60 additions & 0 deletions pkg/resource/events-logger-secret/events-logger-secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package eventsloggersecret

import (
"fmt"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/pkg/errors"

"github.com/giantswarm/logging-operator/pkg/common"
loggedcluster "github.com/giantswarm/logging-operator/pkg/logged-cluster"
loggingsecret "github.com/giantswarm/logging-operator/pkg/resource/logging-secret"
)

const eventsLoggerSecretName = "events-logger-secret"

func GenerateEventsLoggerSecret(lc loggedcluster.Interface, loggingCredentialsSecret *v1.Secret, lokiURL string) (v1.Secret, error) {
var data map[string][]byte
var err error

switch lc.GetKubeEventsLogger() {
case common.EventsLoggerGrafanaAgent:
data, err = GenerateGrafanaAgentSecret(lc, loggingCredentialsSecret, lokiURL)
if err != nil {
return v1.Secret{}, err
}
case common.EventsLoggerAlloy:
// In the case of Alloy being the events logger, we reuse the secret generation from the logging-secret package
data, err = loggingsecret.GenerateAlloyLoggingSecret(lc, loggingCredentialsSecret, lokiURL)
QuentinBisson marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return v1.Secret{}, err
}
default:
return v1.Secret{}, errors.Errorf("unsupported logging agent %q", lc.GetLoggingAgent())
}

secret := v1.Secret{
ObjectMeta: SecretMeta(lc),
Data: data,
}

return secret, nil
}

// SecretMeta returns metadata for the events-logger-secret
func SecretMeta(lc loggedcluster.Interface) metav1.ObjectMeta {
metadata := metav1.ObjectMeta{
Name: GetEventsLoggerSecretName(lc),
Namespace: lc.GetAppsNamespace(),
Labels: map[string]string{},
}

common.AddCommonLabels(metadata.Labels)
return metadata
}

func GetEventsLoggerSecretName(lc loggedcluster.Interface) string {
QuentinBisson marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Sprintf("%s-%s", lc.GetClusterName(), eventsLoggerSecretName)
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package grafanaagentsecret
package eventsloggersecret

import (
"fmt"

"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"

"github.com/giantswarm/logging-operator/pkg/common"
Expand All @@ -22,26 +21,14 @@ type extraSecret struct {
Data map[string]string `yaml:"data" json:"data"`
}

// SecretMeta returns metadata for the grafana-agent-secret
func SecretMeta(lc loggedcluster.Interface) metav1.ObjectMeta {
metadata := metav1.ObjectMeta{
Name: getGrafanaAgentSecretName(lc),
Namespace: lc.GetAppsNamespace(),
Labels: map[string]string{},
}

common.AddCommonLabels(metadata.Labels)
return metadata
}

// GenerateGrafanaAgentSecret returns a secret for
// the Loki-multi-tenant-proxy config
func GenerateGrafanaAgentSecret(lc loggedcluster.Interface, credentialsSecret *v1.Secret, lokiURL string) (v1.Secret, error) {
func GenerateGrafanaAgentSecret(lc loggedcluster.Interface, credentialsSecret *v1.Secret, lokiURL string) (map[string][]byte, error) {
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
clusterName := lc.GetClusterName()
writeUser := clusterName
writePassword, err := loggingcredentials.GetPassword(lc, credentialsSecret, clusterName)
if err != nil {
return v1.Secret{}, errors.WithStack(err)
return nil, errors.WithStack(err)
}

values := values{
Expand All @@ -58,19 +45,11 @@ func GenerateGrafanaAgentSecret(lc loggedcluster.Interface, credentialsSecret *v

v, err := yaml.Marshal(values)
if err != nil {
return v1.Secret{}, errors.WithStack(err)
return nil, errors.WithStack(err)
}

secret := v1.Secret{
ObjectMeta: SecretMeta(lc),
Data: map[string][]byte{
"values": []byte(v),
},
}

return secret, nil
}
data := make(map[string][]byte)
data["values"] = []byte(v)

func getGrafanaAgentSecretName(lc loggedcluster.Interface) string {
return fmt.Sprintf("%s-%s", lc.GetClusterName(), common.GrafanaAgentExtraSecretName())
return data, nil
}
120 changes: 120 additions & 0 deletions pkg/resource/events-logger-secret/reconciler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package eventsloggersecret

import (
"context"
"reflect"

"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
apimachineryerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"

"github.com/giantswarm/logging-operator/pkg/common"
loggedcluster "github.com/giantswarm/logging-operator/pkg/logged-cluster"
loggingcredentials "github.com/giantswarm/logging-operator/pkg/resource/logging-credentials"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

// Reconciler implements a reconciler.Interface to handle
// Events-logger secret: extra events-logger secret about where and how to send logs (in this case : k8S events)
type Reconciler struct {
client.Client
}

// ReconcileCreate ensures events-logger-secret is created with the right credentials
func (r *Reconciler) ReconcileCreate(ctx context.Context, lc loggedcluster.Interface) (ctrl.Result, error) {
logger := log.FromContext(ctx)
logger.Info("events-logger-secret create")

// Retrieve secret containing credentials
var eventsLoggerCredentialsSecret v1.Secret
err := r.Client.Get(ctx, types.NamespacedName{Name: loggingcredentials.LoggingCredentialsSecretMeta(lc).Name, Namespace: loggingcredentials.LoggingCredentialsSecretMeta(lc).Namespace},
QuentinBisson marked this conversation as resolved.
Show resolved Hide resolved
&eventsLoggerCredentialsSecret)
if err != nil {
return ctrl.Result{}, errors.WithStack(err)
}

// Retrieve Loki ingress name
lokiURL, err := common.ReadProxyIngressURL(ctx, lc, r.Client)
if err != nil {
return ctrl.Result{}, errors.WithStack(err)
}

// Get desired secret
desiredEventsLoggerSecret, err := GenerateEventsLoggerSecret(lc, &eventsLoggerCredentialsSecret, lokiURL)
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Info("logging-secret - failed generating auth config!", "error", err)
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
return ctrl.Result{}, errors.WithStack(err)
}

// Check if secret already exists.
logger.Info("events-logger-secret - getting", "namespace", desiredEventsLoggerSecret.GetNamespace(), "name", desiredEventsLoggerSecret.GetName())
var currentEventsLoggerSecret v1.Secret
err = r.Client.Get(ctx, types.NamespacedName{Name: desiredEventsLoggerSecret.GetName(), Namespace: desiredEventsLoggerSecret.GetNamespace()}, &currentEventsLoggerSecret)
if err != nil {
if apimachineryerrors.IsNotFound(err) {
logger.Info("events-logger-secret not found, creating")
err = r.Client.Create(ctx, &desiredEventsLoggerSecret)
if err != nil {
return ctrl.Result{}, errors.WithStack(err)
}
} else {
return ctrl.Result{}, errors.WithStack(err)
}
}

if !needUpdate(currentEventsLoggerSecret, desiredEventsLoggerSecret) {
logger.Info("events-logger-secret up to date")
return ctrl.Result{}, nil
}

logger.Info("events-logger-secret - updating")
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
err = r.Client.Update(ctx, &desiredEventsLoggerSecret)
if err != nil {
return ctrl.Result{}, errors.WithStack(err)
}

logger.Info("events-logger-secret - done")
QuantumEnigmaa marked this conversation as resolved.
Show resolved Hide resolved
return ctrl.Result{}, nil
}

// ReconcileDelete - Not much to do here when a cluster is deleted
func (r *Reconciler) ReconcileDelete(ctx context.Context, lc loggedcluster.Interface) (ctrl.Result, error) {
logger := log.FromContext(ctx)
logger.Info("events-logger-secret delete")

// Get expected secret.
var currentEventsLoggerSecret v1.Secret
err := r.Client.Get(ctx, types.NamespacedName{Name: GetEventsLoggerSecretName(lc), Namespace: lc.GetAppsNamespace()}, &currentEventsLoggerSecret)
if err != nil {
if apimachineryerrors.IsNotFound(err) {
logger.Info("events-logger-secret not found, stop here")
return ctrl.Result{}, nil
}
return ctrl.Result{}, errors.WithStack(err)
}

// Delete secret.
logger.Info("events-logger-secret deleting", "namespace", currentEventsLoggerSecret.GetNamespace(), "name", currentEventsLoggerSecret.GetName())
err = r.Client.Delete(ctx, &currentEventsLoggerSecret)
if err != nil {
if apimachineryerrors.IsNotFound(err) {
// Do no throw error in case it was not found, as this means
// it was already deleted.
logger.Info("events-logger-secret already deleted")
return ctrl.Result{}, nil
}
return ctrl.Result{}, errors.WithStack(err)
}
logger.Info("events-logger-secret deleted")

return ctrl.Result{}, nil
}

// needUpdate return true if current.Data and desired.Data do not match.
func needUpdate(current, desired v1.Secret) bool {
return !reflect.DeepEqual(current.Data, desired.Data)
}
Loading