pkg/controller/elasticsearch/initcontainer/prepare_fs.go (120 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package initcontainer import ( "path" "strings" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/defaults" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/volume" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/elasticsearch/settings" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/elasticsearch/user" "github.com/elastic/cloud-on-k8s/v3/pkg/controller/elasticsearch/user/filerealm" esvolume "github.com/elastic/cloud-on-k8s/v3/pkg/controller/elasticsearch/volume" "github.com/elastic/cloud-on-k8s/v3/pkg/utils/stringsutil" ) const ( initContainerTransportCertificatesVolumeMountPath = "/mnt/elastic-internal/transport-certificates" ) // Volumes that are shared between the prepare-fs init container and the ES container var ( // EsBinSharedVolume contains the ES bin/ directory EsBinSharedVolume = volume.SharedVolume{ VolumeName: "elastic-internal-elasticsearch-bin-local", InitContainerMountPath: "/mnt/elastic-internal/elasticsearch-bin-local", ContainerMountPath: "/usr/share/elasticsearch/bin", } // EsConfigSharedVolume contains the ES config/ directory EsConfigSharedVolume = volume.SharedVolume{ VolumeName: "elastic-internal-elasticsearch-config-local", InitContainerMountPath: "/mnt/elastic-internal/elasticsearch-config-local", ContainerMountPath: esvolume.ConfigVolumeMountPath, } // EsPluginsSharedVolume contains the ES plugins/ directory EsPluginsSharedVolume = volume.SharedVolume{ VolumeName: "elastic-internal-elasticsearch-plugins-local", InitContainerMountPath: "/mnt/elastic-internal/elasticsearch-plugins-local", ContainerMountPath: "/usr/share/elasticsearch/plugins", } PluginVolumes = volume.SharedVolumeArray{ Array: []volume.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, "/", filerealm.UsersFile), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", filerealm.UsersFile), }, { Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", user.RolesFile), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", user.RolesFile), }, { Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", filerealm.UsersRolesFile), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", filerealm.UsersRolesFile), }, { Source: stringsutil.Concat(settings.ConfigVolumeMountPath, "/", settings.ConfigFileName), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", settings.ConfigFileName), }, { Source: stringsutil.Concat(esvolume.UnicastHostsVolumeMountPath, "/", esvolume.UnicastHostsFile), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", esvolume.UnicastHostsFile), }, { Source: stringsutil.Concat(esvolume.XPackFileRealmVolumeMountPath, "/", esvolume.ServiceAccountsFile), Target: stringsutil.Concat(EsConfigSharedVolume.InitContainerMountPath, "/", esvolume.ServiceAccountsFile), }, }, } // defaultResources are the default request and limits for the init container. defaultResources = corev1.ResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceMemory: resource.MustParse("50Mi"), corev1.ResourceCPU: resource.MustParse("0.1"), }, Limits: map[corev1.ResourceName]resource.Quantity{ // Memory limit should be at least 12582912 when running with CRI-O corev1.ResourceMemory: resource.MustParse("50Mi"), corev1.ResourceCPU: resource.MustParse("0.1"), }, } ) // NewPrepareFSInitContainer creates an init container to handle things such as: // - configuration changes // Modified directories and files are meant to be persisted for reuse in the actual ES container. // This container does not need to be privileged. func NewPrepareFSInitContainer(transportCertificatesVolume volume.SecretVolume, nodeLabelsAsAnnotations []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 = initContainerTransportCertificatesVolumeMountPath volumeMounts := append( // we will also inherit all volume mounts from the main container later on in the pod template builder PluginVolumes.InitContainerVolumeMounts(), certificatesVolumeMount, ) if len(nodeLabelsAsAnnotations) > 0 { volumeMounts = append(volumeMounts, corev1.VolumeMount{ Name: esvolume.DownwardAPIVolumeName, ReadOnly: true, MountPath: esvolume.DownwardAPIMountPath, }) } container := corev1.Container{ ImagePullPolicy: corev1.PullIfNotPresent, Name: PrepareFilesystemContainerName, Env: defaults.PodDownwardEnvVars(), Command: []string{"bash", "-c", path.Join(esvolume.ScriptsVolumeMountPath, PrepareFsScriptConfigKey)}, VolumeMounts: volumeMounts, Resources: defaultResources, } return container, nil } func RenderPrepareFsScript(expectedAnnotations []string) (string, error) { templateParams := TemplateParams{ PluginVolumes: PluginVolumes, LinkedFiles: linkedFiles, ChownToElasticsearch: []string{ esvolume.ElasticsearchDataMountPath, esvolume.ElasticsearchLogsMountPath, }, InitContainerTransportCertificatesSecretVolumeMountPath: initContainerTransportCertificatesVolumeMountPath, TransportCertificatesSecretVolumeMountPath: esvolume.TransportCertificatesSecretVolumeMountPath, } if len(expectedAnnotations) > 0 { expectedAnnotationsAsString := strings.Join(expectedAnnotations, " ") templateParams.ExpectedAnnotations = &expectedAnnotationsAsString } return RenderScriptTemplate(templateParams) }