diff --git a/operators/pkg/controller/elasticsearch/driver/default.go b/operators/pkg/controller/elasticsearch/driver/default.go index e5baa4fe5e..74c4997c74 100644 --- a/operators/pkg/controller/elasticsearch/driver/default.go +++ b/operators/pkg/controller/elasticsearch/driver/default.go @@ -23,6 +23,7 @@ import ( "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/cleanup" esclient "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/client" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/configmap" + "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/initcontainer" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/license" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/migration" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/mutation" @@ -126,8 +127,7 @@ func (d *defaultDriver) Reconcile( return results.WithError(err) } - scriptsConfigMap := prepareScriptsConfigMap(es) - if err := configmap.ReconcileConfigMap(d.Client, d.Scheme, es, scriptsConfigMap); err != nil { + if err := reconcileScriptsConfigMap(d.Client, d.Scheme, es); err != nil { return results.WithError(err) } @@ -535,10 +535,22 @@ func (d *defaultDriver) newElasticsearchClient(service corev1.Service, user user return esclient.NewElasticsearchClient(d.Dialer, url, user.Auth(), v, caCerts) } -func prepareScriptsConfigMap(es v1alpha1.Elasticsearch) corev1.ConfigMap { - return configmap.NewConfigMapWithData( +func reconcileScriptsConfigMap(c k8s.Client, scheme *runtime.Scheme, es v1alpha1.Elasticsearch) error { + fsScript, err := initcontainer.RenderPrepareFsScript() + if err != nil { + return err + } + + scriptsConfigMap := configmap.NewConfigMapWithData( types.NamespacedName{Namespace: es.Namespace, Name: name.ScriptsConfigMap(es.Name)}, map[string]string{ - pod.ReadinessProbeScriptConfigKey: pod.ReadinessProbeScript, + pod.ReadinessProbeScriptConfigKey: pod.ReadinessProbeScript, + initcontainer.PrepareFsScriptConfigKey: fsScript, }) + + if err := configmap.ReconcileConfigMap(c, scheme, es, scriptsConfigMap); err != nil { + return err + } + + return nil } diff --git a/operators/pkg/controller/elasticsearch/initcontainer/initcontainer.go b/operators/pkg/controller/elasticsearch/initcontainer/initcontainer.go index 76bc96e47a..639100a7f5 100644 --- a/operators/pkg/controller/elasticsearch/initcontainer/initcontainer.go +++ b/operators/pkg/controller/elasticsearch/initcontainer/initcontainer.go @@ -25,9 +25,9 @@ const ( func NewInitContainers( elasticsearchImage string, operatorImage string, - linkedFiles LinkedFilesArray, setVMMaxMapCount *bool, transportCertificatesVolume volume.SecretVolume, + clusterName string, ) ([]corev1.Container, error) { var containers []corev1.Container // create the privileged init container if not explicitly disabled by the user @@ -38,7 +38,7 @@ func NewInitContainers( } containers = append(containers, osSettingsContainer) } - prepareFsContainer, err := NewPrepareFSInitContainer(elasticsearchImage, linkedFiles, transportCertificatesVolume) + prepareFsContainer, err := NewPrepareFSInitContainer(elasticsearchImage, transportCertificatesVolume, clusterName) if err != nil { return nil, err } diff --git a/operators/pkg/controller/elasticsearch/initcontainer/initcontainer_test.go b/operators/pkg/controller/elasticsearch/initcontainer/initcontainer_test.go index 4aa79b5d08..e7e7d2d4ad 100644 --- a/operators/pkg/controller/elasticsearch/initcontainer/initcontainer_test.go +++ b/operators/pkg/controller/elasticsearch/initcontainer/initcontainer_test.go @@ -17,7 +17,6 @@ func TestNewInitContainers(t *testing.T) { type args struct { elasticsearchImage string operatorImage string - linkedFiles LinkedFilesArray SetVMMaxMapCount *bool } tests := []struct { @@ -30,7 +29,6 @@ func TestNewInitContainers(t *testing.T) { args: args{ elasticsearchImage: "es-image", operatorImage: "op-image", - linkedFiles: LinkedFilesArray{}, SetVMMaxMapCount: &varTrue, }, expectedNumberOfContainers: 3, @@ -40,7 +38,6 @@ func TestNewInitContainers(t *testing.T) { args: args{ elasticsearchImage: "es-image", operatorImage: "op-image", - linkedFiles: LinkedFilesArray{}, SetVMMaxMapCount: nil, }, expectedNumberOfContainers: 3, @@ -50,7 +47,6 @@ func TestNewInitContainers(t *testing.T) { args: args{ elasticsearchImage: "es-image", operatorImage: "op-image", - linkedFiles: LinkedFilesArray{}, SetVMMaxMapCount: &varFalse, }, expectedNumberOfContainers: 2, @@ -61,9 +57,9 @@ func TestNewInitContainers(t *testing.T) { containers, err := NewInitContainers( tt.args.elasticsearchImage, tt.args.operatorImage, - tt.args.linkedFiles, tt.args.SetVMMaxMapCount, volume.SecretVolume{}, + "clusterName", ) assert.NoError(t, err) assert.Equal(t, tt.expectedNumberOfContainers, len(containers)) diff --git a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs.go b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs.go index 463699ce60..39e583c40f 100644 --- a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs.go +++ b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs.go @@ -6,26 +6,34 @@ package initcontainer import ( "fmt" - - corev1 "k8s.io/api/core/v1" + "path" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/certificates" volume "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/volume" + "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/name" + "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/settings" + "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/user" esvolume "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume" + "github.com/elastic/cloud-on-k8s/operators/pkg/utils/stringsutil" + corev1 "k8s.io/api/core/v1" +) + +const ( + transportCertificatesVolumeMountPath = "/mnt/elastic-internal/transport-certificates" ) // Volumes that are shared between the prepare-fs init container and the ES container var ( DataSharedVolume = SharedVolume{ Name: esvolume.ElasticsearchDataVolumeName, - InitContainerMountPath: "/usr/share/elasticsearch/data", - EsContainerMountPath: "/usr/share/elasticsearch/data", + InitContainerMountPath: esvolume.ElasticsearchDataMountPath, + EsContainerMountPath: esvolume.ElasticsearchDataMountPath, } LogsSharedVolume = SharedVolume{ Name: esvolume.ElasticsearchLogsVolumeName, - InitContainerMountPath: "/usr/share/elasticsearch/logs", - EsContainerMountPath: "/usr/share/elasticsearch/logs", + InitContainerMountPath: esvolume.ElasticsearchLogsMountPath, + EsContainerMountPath: esvolume.ElasticsearchLogsMountPath, } // EsBinSharedVolume contains the ES bin/ directory @@ -58,6 +66,40 @@ var ( LogsSharedVolume, }, } + + PluginVolumes = SharedVolumeArray{ + Array: []SharedVolume{ + EsConfigSharedVolume, + EsPluginsSharedVolume, + EsBinSharedVolume, + }, + } + + // linkedFiles describe how various secrets are mapped into the pod's filesystem. + linkedFiles = LinkedFilesArray{ + Array: []LinkedFile{ + { + Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticUsersFile), + Target: stringsutil.Concat(EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticUsersFile), + }, + { + Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticRolesFile), + Target: stringsutil.Concat(EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticRolesFile), + }, + { + Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticUsersRolesFile), + Target: stringsutil.Concat(EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticUsersRolesFile), + }, + { + Source: stringsutil.Concat(settings.ConfigVolumeMountPath, "/", settings.ConfigFileName), + Target: stringsutil.Concat(EsConfigSharedVolume.EsContainerMountPath, "/", settings.ConfigFileName), + }, + { + Source: stringsutil.Concat(esvolume.UnicastHostsVolumeMountPath, "/", esvolume.UnicastHostsFile), + Target: stringsutil.Concat(EsConfigSharedVolume.EsContainerMountPath, "/", esvolume.UnicastHostsFile), + }, + }, + } ) // NewPrepareFSInitContainer creates an init container to handle things such as: @@ -66,30 +108,21 @@ var ( // This container does not need to be privileged. func NewPrepareFSInitContainer( imageName string, - linkedFiles LinkedFilesArray, transportCertificatesVolume volume.SecretVolume, + clusterName string, ) (corev1.Container, error) { // we mount the certificates to a location outside of the default config directory because the prepare-fs script // will attempt to move all the files under the configuration directory to a different volume, and it should not // be attempting to move files from this secret volume mount (any attempt to do so will be logged as errors). certificatesVolumeMount := transportCertificatesVolume.VolumeMount() - certificatesVolumeMount.MountPath = "/mnt/elastic-internal/transport-certificates" + certificatesVolumeMount.MountPath = transportCertificatesVolumeMountPath - script, err := RenderScriptTemplate(TemplateParams{ - SharedVolumes: PrepareFsSharedVolumes, - LinkedFiles: linkedFiles, - ChownToElasticsearch: []string{ - DataSharedVolume.InitContainerMountPath, - LogsSharedVolume.InitContainerMountPath, - }, - TransportCertificatesKeyPath: fmt.Sprintf( - "%s/%s", certificatesVolumeMount.MountPath, certificates.KeyFileName, - ), - }) - if err != nil { - return corev1.Container{}, err - } + scriptsVolume := volume.NewConfigMapVolumeWithMode( + name.ScriptsConfigMap(clusterName), + esvolume.ScriptsVolumeName, + esvolume.ScriptsVolumeMountPath, + 0755) privileged := false container := corev1.Container{ @@ -99,11 +132,26 @@ func NewPrepareFSInitContainer( SecurityContext: &corev1.SecurityContext{ Privileged: &privileged, }, - Command: []string{"bash", "-c", script}, + Command: []string{"bash", "-c", path.Join(esvolume.ScriptsVolumeMountPath, PrepareFsScriptConfigKey)}, VolumeMounts: append( - PrepareFsSharedVolumes.InitContainerVolumeMounts(), certificatesVolumeMount, + PrepareFsSharedVolumes.InitContainerVolumeMounts(), certificatesVolumeMount, scriptsVolume.VolumeMount(), ), } return container, nil } + +func RenderPrepareFsScript() (string, error) { + return RenderScriptTemplate(TemplateParams{ + PluginVolumes: PluginVolumes, + LinkedFiles: linkedFiles, + ChownToElasticsearch: []string{ + DataSharedVolume.InitContainerMountPath, + LogsSharedVolume.InitContainerMountPath, + }, + TransportCertificatesKeyPath: fmt.Sprintf( + "%s/%s", + transportCertificatesVolumeMountPath, + certificates.KeyFileName), + }) +} diff --git a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script.go b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script.go index 744b35a023..a8c7cc1471 100644 --- a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script.go +++ b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script.go @@ -12,7 +12,7 @@ import ( // TemplateParams are the parameters manipulated in the scriptTemplate type TemplateParams struct { // SharedVolumes are directories to persist in shared volumes - SharedVolumes SharedVolumeArray + PluginVolumes SharedVolumeArray // LinkedFiles are files to link individually LinkedFiles LinkedFilesArray // ChownToElasticsearch are paths that need to be chowned to the Elasticsearch user/group. @@ -30,11 +30,15 @@ func RenderScriptTemplate(params TemplateParams) (string, error) { return tplBuffer.String(), nil } +const PrepareFsScriptConfigKey = "prepare-fs.sh" + // scriptTemplate is the main script to be run // in the prepare-fs init container before ES starts var scriptTemplate = template.Must(template.New("").Parse( - `#!/usr/bin/env bash -eu - + `#!/usr/bin/env bash + + set -eu + # compute time in seconds since the given start time function duration() { local start=$1 @@ -68,10 +72,10 @@ var scriptTemplate = template.Must(template.New("").Parse( # Files persistence # ###################### - # Persist the content of bin/, config/ and plugins/ - # to a volume, to be used by the ES container + # Persist the content of bin/, config/ and plugins/ to a volume, + # so installed plugins files can to be used by the ES container mv_start=$(date +%s) - {{range .SharedVolumes.Array}} + {{range .PluginVolumes.Array}} if [[ -z "$(ls -A {{.EsContainerMountPath}})" ]]; then echo "Empty dir {{.EsContainerMountPath}}" else diff --git a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script_test.go b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script_test.go index 150d9acb72..64609d5864 100644 --- a/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script_test.go +++ b/operators/pkg/controller/elasticsearch/initcontainer/prepare_fs_script_test.go @@ -20,7 +20,7 @@ func TestRenderScriptTemplate(t *testing.T) { { name: "Standard script rendering", params: TemplateParams{ - SharedVolumes: PrepareFsSharedVolumes, + PluginVolumes: PluginVolumes, LinkedFiles: LinkedFilesArray{ Array: []LinkedFile{ LinkedFile{ diff --git a/operators/pkg/controller/elasticsearch/settings/merged_config.go b/operators/pkg/controller/elasticsearch/settings/merged_config.go index a41cb501da..e538742243 100644 --- a/operators/pkg/controller/elasticsearch/settings/merged_config.go +++ b/operators/pkg/controller/elasticsearch/settings/merged_config.go @@ -10,7 +10,6 @@ import ( "github.com/elastic/cloud-on-k8s/operators/pkg/apis/common/v1alpha1" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/certificates" common "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/settings" - "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/initcontainer" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume" ) @@ -47,8 +46,8 @@ func baseConfig(clusterName string) *CanonicalConfig { NetworkPublishHost: "${" + EnvPodIP + "}", NetworkHost: "0.0.0.0", - PathData: initcontainer.DataSharedVolume.EsContainerMountPath, - PathLogs: initcontainer.LogsSharedVolume.EsContainerMountPath, + PathData: volume.ElasticsearchDataMountPath, + PathLogs: volume.ElasticsearchLogsMountPath, } return &CanonicalConfig{common.MustCanonicalConfig(cfg)} } diff --git a/operators/pkg/controller/elasticsearch/version/common.go b/operators/pkg/controller/elasticsearch/version/common.go index a1c2eafb40..41e8cd5094 100644 --- a/operators/pkg/controller/elasticsearch/version/common.go +++ b/operators/pkg/controller/elasticsearch/version/common.go @@ -31,7 +31,7 @@ func NewExpectedPodSpecs( newEnvironmentVarsFn func(p pod.NewPodSpecParams, certs, creds, securecommon volume.SecretVolume) []corev1.EnvVar, newESConfigFn func(clusterName string, config commonv1alpha1.Config) (settings.CanonicalConfig, error), - newInitContainersFn func(imageName string, operatorImage string, setVMMaxMapCount *bool, transportCerts volume.SecretVolume) ([]corev1.Container, error), + newInitContainersFn func(imageName string, operatorImage string, setVMMaxMapCount *bool, transportCerts volume.SecretVolume, clusterName string) ([]corev1.Container, error), operatorImage string, ) ([]pod.PodSpecContext, error) { podSpecs := make([]pod.PodSpecContext, 0, es.Spec.NodeCount()) @@ -81,7 +81,7 @@ func podSpec( operatorImage string, newEnvironmentVarsFn func(p pod.NewPodSpecParams, certs, creds, keystore volume.SecretVolume) []corev1.EnvVar, newESConfigFn func(clusterName string, config commonv1alpha1.Config) (settings.CanonicalConfig, error), - newInitContainersFn func(elasticsearchImage string, operatorImage string, setVMMaxMapCount *bool, transportCerts volume.SecretVolume) ([]corev1.Container, error), + newInitContainersFn func(elasticsearchImage string, operatorImage string, setVMMaxMapCount *bool, transportCerts volume.SecretVolume, clusterName string) ([]corev1.Container, error), ) (corev1.PodSpec, settings.CanonicalConfig, error) { // setup volumes probeSecret := volume.NewSelectiveSecretVolumeWithMountPath( @@ -121,7 +121,13 @@ func podSpec( WithEnv(newEnvironmentVarsFn(p, httpCertificatesVolume, keystoreUserSecret, secureSettingsVolume)...) // setup init containers - initContainers, err := newInitContainersFn(builder.Container.Image, operatorImage, p.SetVMMaxMapCount, transportCertificatesVolume) + initContainers, err := newInitContainersFn( + builder.Container.Image, + operatorImage, + p.SetVMMaxMapCount, + transportCertificatesVolume, + p.ClusterName) + if err != nil { return corev1.PodSpec{}, settings.CanonicalConfig{}, err } diff --git a/operators/pkg/controller/elasticsearch/version/common_test.go b/operators/pkg/controller/elasticsearch/version/common_test.go index 484e0e88f3..bc6fdde7fa 100644 --- a/operators/pkg/controller/elasticsearch/version/common_test.go +++ b/operators/pkg/controller/elasticsearch/version/common_test.go @@ -232,7 +232,7 @@ func Test_podSpec(t *testing.T) { newESConfigFn := func(clusterName string, config commonv1alpha1.Config) (settings.CanonicalConfig, error) { return settings.CanonicalConfig{}, nil } - newInitContainersFn := func(elasticsearchImage string, operatorImage string, setVMMaxMapCount *bool, nodeCertificatesVolume volume.SecretVolume) ([]corev1.Container, error) { + newInitContainersFn := func(elasticsearchImage string, operatorImage string, setVMMaxMapCount *bool, nodeCertificatesVolume volume.SecretVolume, clusterName string) ([]corev1.Container, error) { return []corev1.Container{ { Name: "init-container1", diff --git a/operators/pkg/controller/elasticsearch/version/version6/podspecs.go b/operators/pkg/controller/elasticsearch/version/version6/podspecs.go index 0a2e83cac1..eeb8e91bed 100644 --- a/operators/pkg/controller/elasticsearch/version/version6/podspecs.go +++ b/operators/pkg/controller/elasticsearch/version/version6/podspecs.go @@ -7,8 +7,6 @@ package version6 import ( "path" - corev1 "k8s.io/api/core/v1" - "github.com/elastic/cloud-on-k8s/operators/pkg/apis/elasticsearch/v1alpha1" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/common/volume" @@ -20,35 +18,7 @@ import ( "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/user" "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/version" esvolume "github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume" - "github.com/elastic/cloud-on-k8s/operators/pkg/utils/stringsutil" -) - -var ( - // linkedFiles6 describe how various secrets are mapped into the pod's filesystem. - linkedFiles6 = initcontainer.LinkedFilesArray{ - Array: []initcontainer.LinkedFile{ - { - Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticUsersFile), - Target: stringsutil.Concat(initcontainer.EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticUsersFile), - }, - { - Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticRolesFile), - Target: stringsutil.Concat(initcontainer.EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticRolesFile), - }, - { - Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.ElasticUsersRolesFile), - Target: stringsutil.Concat(initcontainer.EsConfigSharedVolume.EsContainerMountPath, "/", user.ElasticUsersRolesFile), - }, - { - Source: stringsutil.Concat(settings.ConfigVolumeMountPath, "/", settings.ConfigFileName), - Target: stringsutil.Concat(initcontainer.EsConfigSharedVolume.EsContainerMountPath, "/", settings.ConfigFileName), - }, - { - Source: stringsutil.Concat(esvolume.UnicastHostsVolumeMountPath, "/", esvolume.UnicastHostsFile), - Target: stringsutil.Concat(initcontainer.EsConfigSharedVolume.EsContainerMountPath, "/", esvolume.UnicastHostsFile), - }, - }, - } + corev1 "k8s.io/api/core/v1" ) // ExpectedPodSpecs returns a list of pod specs with context that we would expect to find in the Elasticsearch cluster. @@ -69,24 +39,8 @@ func ExpectedPodSpecs( paramsTmpl, newEnvironmentVars, settings.NewMergedESConfig, - newInitContainers, - operatorImage, - ) -} - -// newInitContainers returns a list of init containers -func newInitContainers( - elasticsearchImage string, - operatorImage string, - setVMMaxMapCount *bool, - transportCertificatesVolume volume.SecretVolume, -) ([]corev1.Container, error) { - return initcontainer.NewInitContainers( - elasticsearchImage, + initcontainer.NewInitContainers, operatorImage, - linkedFiles6, - setVMMaxMapCount, - transportCertificatesVolume, ) } diff --git a/operators/pkg/controller/elasticsearch/volume/names.go b/operators/pkg/controller/elasticsearch/volume/names.go index e1fc44a5ee..dd7f27399e 100644 --- a/operators/pkg/controller/elasticsearch/volume/names.go +++ b/operators/pkg/controller/elasticsearch/volume/names.go @@ -31,7 +31,10 @@ const ( ProcessManagerEmptyDirMountPath = "/mnt/elastic-internal/process-manager" ElasticsearchDataVolumeName = "elasticsearch-data" + ElasticsearchDataMountPath = "/usr/share/elasticsearch/data" + ElasticsearchLogsVolumeName = "elasticsearch-logs" + ElasticsearchLogsMountPath = "/usr/share/elasticsearch/logs" ScriptsVolumeName = "elastic-internal-scripts" ScriptsVolumeMountPath = "/mnt/elastic-internal/scripts"