Skip to content

Commit

Permalink
Init container updates for persisting kibana plugins. (elastic#8389)
Browse files Browse the repository at this point in the history
* Init container for persisting kibana plugins.
---------
Signed-off-by: Michael Montgomery <[email protected]>
(cherry picked from commit 0efeb94)
  • Loading branch information
naemono committed Jan 15, 2025
1 parent 33caea2 commit 061a050
Show file tree
Hide file tree
Showing 24 changed files with 840 additions and 246 deletions.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
run:
timeout: 360s
timeout: 420s

linters-settings:
exhaustive:
Expand Down
2 changes: 2 additions & 0 deletions docs/release-notes/highlights-2.16.0.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ securityContext:
readOnlyRootFilesystem: true
----

Also note that this change will cause the Kibana pod(s) to be restarted as this change is applied during the upgrade.

[float]
[id="{p}-2160-breaking-changes"]
=== eck-fleet-server Helm chart breaking changes
Expand Down
16 changes: 15 additions & 1 deletion pkg/apis/kibana/v1/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import (
common_name "github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/name"
)

const httpServiceSuffix = "http"
const (
httpServiceSuffix = "http"
scriptsConfigMapSuffix = "scripts"
configSecretSuffix = "config"
)

// KBNamer is a KBNamer that is configured with the defaults for resources related to a Kibana resource.
var KBNamer = common_name.NewNamer("kb")
Expand All @@ -20,3 +24,13 @@ func HTTPService(kbName string) string {
func Deployment(kbName string) string {
return KBNamer.Suffix(kbName)
}

// ScriptsConfigMap returns the name of the ConfigMap containing scripts for the given Kibana resource.
func ScriptsConfigMap(kbName string) string {
return KBNamer.Suffix(kbName, scriptsConfigMapSuffix)
}

// ConfigSecret returns the name of the Secret containing the Kibana configuration for the given Kibana resource.
func ConfigSecret(kbName string) string {
return KBNamer.Suffix(kbName, configSecretSuffix)
}
41 changes: 29 additions & 12 deletions pkg/apis/kibana/v1/name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,42 @@ import (
"testing"
)

func TestHTTPService(t *testing.T) {
type args struct {
kbName string
}
func TestNamers(t *testing.T) {
tests := []struct {
name string
args args
want string
name string
namer func(string) string
arg string
want string
}{
{
name: "sample",
args: args{kbName: "sample"},
want: "sample-kb-http",
name: "test httpService namer",
namer: HTTPService,
arg: "sample",
want: "sample-kb-http",
},
{
name: "test deployment namer",
namer: Deployment,
arg: "sample",
want: "sample-kb",
},
{
name: "test scripts configmap namer",
namer: ScriptsConfigMap,
arg: "sample",
want: "sample-kb-scripts",
},
{
name: "test ConfigSecret namer",
namer: ConfigSecret,
arg: "sample",
want: "sample-kb-config",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := HTTPService(tt.args.kbName); got != tt.want {
t.Errorf("HTTPService() = %v, want %v", got, tt.want)
if got := tt.namer(tt.arg); got != tt.want {
t.Errorf("%s = %v, want %v", tt.name, got, tt.want)
}
})
}
Expand Down
40 changes: 2 additions & 38 deletions pkg/controller/kibana/config_reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,51 +18,15 @@ import (
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/labels"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/reconciler"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/tracing"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/volume"
kblabel "github.com/elastic/cloud-on-k8s/v2/pkg/controller/kibana/label"
"github.com/elastic/cloud-on-k8s/v2/pkg/utils/k8s"
)

// Constants to use for the config files in a Kibana pod.
const (
ConfigVolumeName = "elastic-internal-kibana-config-local"
ConfigVolumeMountPath = "/usr/share/kibana/config"
InitContainerConfigVolumeMountPath = "/mnt/elastic-internal/kibana-config-local"

// InternalConfigVolumeName is a volume which contains the generated configuration.
InternalConfigVolumeName = "elastic-internal-kibana-config"
InternalConfigVolumeMountPath = "/mnt/elastic-internal/kibana-config"

TelemetryFilename = "telemetry.yml"
)

var (
// ConfigSharedVolume contains the Kibana config/ directory, it's an empty volume where the required configuration
// is initialized by the elastic-internal-init-config init container. Its content is then shared by the init container
// that creates the keystore and the main Kibana container.
// This is needed in order to have in a same directory both the generated configuration and the keystore file which
// is created in /usr/share/kibana/config since Kibana 7.9
ConfigSharedVolume = volume.SharedVolume{
VolumeName: ConfigVolumeName,
InitContainerMountPath: InitContainerConfigVolumeMountPath,
ContainerMountPath: ConfigVolumeMountPath,
}
)

// ConfigVolume returns a SecretVolume to hold the Kibana config of the given Kibana resource.
func ConfigVolume(kb kbv1.Kibana) volume.SecretVolume {
return volume.NewSecretVolumeWithMountPath(
SecretName(kb),
InternalConfigVolumeName,
InternalConfigVolumeMountPath,
)
}

// SecretName is the name of the secret that holds the Kibana config for the given Kibana resource.
func SecretName(kb kbv1.Kibana) string {
return kb.Name + "-kb-config"
}

// ReconcileConfigSecret reconciles the expected Kibana config secret for the given Kibana resource.
// This managed secret is mounted into each pod of the Kibana deployment.
func ReconcileConfigSecret(
Expand Down Expand Up @@ -95,7 +59,7 @@ func ReconcileConfigSecret(
expected := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: kb.Namespace,
Name: SecretName(kb),
Name: kbv1.ConfigSecret(kb.Name),
Labels: labels.AddCredentialsLabel(map[string]string{
kblabel.KibanaNameLabelName: kb.Name,
}),
Expand All @@ -111,7 +75,7 @@ func ReconcileConfigSecret(
// if the Secret or usage key doesn't exist yet.
func getTelemetryYamlBytes(client k8s.Client, kb kbv1.Kibana) ([]byte, error) {
var secret corev1.Secret
if err := client.Get(context.Background(), types.NamespacedName{Namespace: kb.Namespace, Name: SecretName(kb)}, &secret); err != nil {
if err := client.Get(context.Background(), types.NamespacedName{Namespace: kb.Namespace, Name: kbv1.ConfigSecret(kb.Name)}, &secret); err != nil {
if apierrors.IsNotFound(err) {
// this secret is just about to be created, we don't know usage yet
return nil, nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/kibana/config_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ type reusableSettings struct {
func getExistingConfig(ctx context.Context, client k8s.Client, kb kbv1.Kibana) (*settings.CanonicalConfig, error) {
log := ulog.FromContext(ctx)
var secret corev1.Secret
err := client.Get(context.Background(), types.NamespacedName{Name: SecretName(kb), Namespace: kb.Namespace}, &secret)
err := client.Get(context.Background(), types.NamespacedName{Name: kbv1.ConfigSecret(kb.Name), Namespace: kb.Namespace}, &secret)
if err != nil && apierrors.IsNotFound(err) {
log.V(1).Info("Kibana config secret does not exist", "namespace", kb.Namespace, "kibana_name", kb.Name)
return nil, nil
Expand Down
20 changes: 10 additions & 10 deletions pkg/controller/kibana/config_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func Test_reuseOrGenerateSecrets(t *testing.T) {
args: args{
c: k8s.NewFakeClient(
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: SecretName(defaultKb)},
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: kbv1.ConfigSecret(defaultKb.Name)},
Data: map[string][]byte{
SettingsFilename: defaultConfig,
},
Expand All @@ -127,7 +127,7 @@ func Test_reuseOrGenerateSecrets(t *testing.T) {
args: args{
c: k8s.NewFakeClient(
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: SecretName(defaultKb)},
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: kbv1.ConfigSecret(defaultKb.Name)},
Data: map[string][]byte{
SettingsFilename: esAssociationConfig,
},
Expand All @@ -151,7 +151,7 @@ func Test_reuseOrGenerateSecrets(t *testing.T) {
args: args{
c: k8s.NewFakeClient(
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: SecretName(defaultKb)},
ObjectMeta: metav1.ObjectMeta{Namespace: defaultKb.Namespace, Name: kbv1.ConfigSecret(defaultKb.Name)},
Data: map[string][]byte{
SettingsFilename: esAssociationConfig,
},
Expand Down Expand Up @@ -186,7 +186,7 @@ func TestNewConfigSettings(t *testing.T) {
defaultKb := mkKibana()
existingSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(defaultKb),
Name: kbv1.ConfigSecret(defaultKb.Name),
Namespace: defaultKb.Namespace,
},
Data: map[string][]byte{
Expand Down Expand Up @@ -519,7 +519,7 @@ func TestNewConfigSettings(t *testing.T) {
args: args{
client: k8s.NewFakeClient(&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(defaultKb),
Name: kbv1.ConfigSecret(defaultKb.Name),
Namespace: defaultKb.Namespace,
},
Data: map[string][]byte{
Expand All @@ -544,7 +544,7 @@ func TestNewConfigSettings(t *testing.T) {
args: args{
client: k8s.NewFakeClient(&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(defaultKb),
Name: kbv1.ConfigSecret(defaultKb.Name),
Namespace: defaultKb.Namespace,
},
Data: map[string][]byte{
Expand Down Expand Up @@ -607,7 +607,7 @@ func TestNewConfigSettingsExistingEncryptionKey(t *testing.T) {
savedObjsKey := "savedObjsKey"
existingSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(kb),
Name: kbv1.ConfigSecret(kb.Name),
Namespace: kb.Namespace,
},
Data: map[string][]byte{
Expand Down Expand Up @@ -686,7 +686,7 @@ func Test_getExistingConfig(t *testing.T) {
}
testValidSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(testKb),
Name: kbv1.ConfigSecret(testKb.Name),
Namespace: testKb.Namespace,
},
Data: map[string][]byte{
Expand All @@ -695,7 +695,7 @@ func Test_getExistingConfig(t *testing.T) {
}
testNoYaml := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(testKb),
Name: kbv1.ConfigSecret(testKb.Name),
Namespace: testKb.Namespace,
},
Data: map[string][]byte{
Expand All @@ -704,7 +704,7 @@ func Test_getExistingConfig(t *testing.T) {
}
testInvalidYaml := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: SecretName(testKb),
Name: kbv1.ConfigSecret(testKb.Name),
Namespace: testKb.Namespace,
},
Data: map[string][]byte{
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/kibana/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ func addWatches(mgr manager.Manager, c controller.Controller, r *ReconcileKibana
return err
}

// Watch configmaps
if err := c.Watch(source.Kind(mgr.GetCache(), &corev1.ConfigMap{}, handler.TypedEnqueueRequestForOwner[*corev1.ConfigMap](
mgr.GetScheme(), mgr.GetRESTMapper(),
&kbv1.Kibana{}, handler.OnlyControllerOwner(),
))); err != nil {
return err
}

// dynamically watch referenced secrets to connect to Elasticsearch
return c.Watch(source.Kind(mgr.GetCache(), &corev1.Secret{}, r.dynamicWatches.Secrets))
}
Expand Down
17 changes: 10 additions & 7 deletions pkg/controller/kibana/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/version"
commonvolume "github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/volume"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/common/watches"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/kibana/initcontainer"
kblabel "github.com/elastic/cloud-on-k8s/v2/pkg/controller/kibana/label"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/kibana/network"
"github.com/elastic/cloud-on-k8s/v2/pkg/controller/kibana/stackmon"
Expand Down Expand Up @@ -160,8 +161,7 @@ func (d *driver) Reconcile(
return results.WithError(err)
}

err = ReconcileConfigSecret(ctx, d.client, *kb, kbSettings)
if err != nil {
if err = ReconcileConfigSecret(ctx, d.client, *kb, kbSettings); err != nil {
return results.WithError(err)
}

Expand All @@ -170,8 +170,11 @@ func (d *driver) Reconcile(
return results.WithError(err)
}

err = stackmon.ReconcileConfigSecrets(ctx, d.client, *kb, basePath)
if err != nil {
if err = stackmon.ReconcileConfigSecrets(ctx, d.client, *kb, basePath); err != nil {
return results.WithError(err)
}

if err = initcontainer.ReconcileScriptsConfigMap(ctx, d.client, *kb); err != nil {
return results.WithError(err)
}

Expand Down Expand Up @@ -226,7 +229,7 @@ func (d *driver) getStrategyType(kb *kbv1.Kibana) (appsv1.DeploymentStrategyType
}

func (d *driver) deploymentParams(ctx context.Context, kb *kbv1.Kibana, policyAnnotations map[string]string, basePath string, setDefaultSecurityContext bool) (deployment.Params, error) {
initContainersParameters, err := newInitContainersParameters(kb)
initContainersParameters, err := initcontainer.NewInitContainersParameters(kb)
if err != nil {
return deployment.Params{}, err
}
Expand Down Expand Up @@ -282,7 +285,7 @@ func (d *driver) deploymentParams(ctx context.Context, kb *kbv1.Kibana, policyAn

// get config secret to add its content to the config checksum
configSecret := corev1.Secret{}
err = d.client.Get(ctx, types.NamespacedName{Name: SecretName(*kb), Namespace: kb.Namespace}, &configSecret)
err = d.client.Get(ctx, types.NamespacedName{Name: kbv1.ConfigSecret(kb.Name), Namespace: kb.Namespace}, &configSecret)
if err != nil {
return deployment.Params{}, err
}
Expand Down Expand Up @@ -314,7 +317,7 @@ func (d *driver) deploymentParams(ctx context.Context, kb *kbv1.Kibana, policyAn
}

func (d *driver) buildVolumes(kb *kbv1.Kibana) ([]commonvolume.VolumeLike, error) {
volumes := []commonvolume.VolumeLike{DataVolume, ConfigSharedVolume, ConfigVolume(*kb)}
volumes := []commonvolume.VolumeLike{DataVolume, initcontainer.ConfigSharedVolume, initcontainer.ConfigVolume(*kb)}

esAssocConf, err := kb.EsAssociation().AssociationConf()
if err != nil {
Expand Down
Loading

0 comments on commit 061a050

Please sign in to comment.