func BuildPodTemplateSpec()

in pkg/controller/elasticsearch/nodespec/podspec.go [54:148]


func BuildPodTemplateSpec(
	ctx context.Context,
	client k8s.Client,
	es esv1.Elasticsearch,
	nodeSet esv1.NodeSet,
	cfg settings.CanonicalConfig,
	keystoreResources *keystore.Resources,
	setDefaultSecurityContext bool,
	policyConfig PolicyConfig,
) (corev1.PodTemplateSpec, error) {
	ver, err := version.Parse(es.Spec.Version)
	if err != nil {
		return corev1.PodTemplateSpec{}, err
	}

	downwardAPIVolume := volume.DownwardAPI{}.WithAnnotations(es.HasDownwardNodeLabels())
	volumes, volumeMounts := buildVolumes(es.Name, ver, nodeSet, keystoreResources, downwardAPIVolume, policyConfig.AdditionalVolumes)

	labels, err := buildLabels(es, cfg, nodeSet)
	if err != nil {
		return corev1.PodTemplateSpec{}, err
	}

	defaultContainerPorts := getDefaultContainerPorts(es)

	// now build the initContainers using the effective main container resources as an input
	initContainers, err := initcontainer.NewInitContainers(
		transportCertificatesVolume(esv1.StatefulSet(es.Name, nodeSet.Name)),
		keystoreResources,
		es.DownwardNodeLabels(),
	)
	if err != nil {
		return corev1.PodTemplateSpec{}, err
	}

	builder := defaults.NewPodTemplateBuilder(nodeSet.PodTemplate, esv1.ElasticsearchContainerName)

	if ver.GTE(minDefaultSecurityContextVersion) && setDefaultSecurityContext {
		builder = builder.WithPodSecurityContext(corev1.PodSecurityContext{
			FSGroup: ptr.To[int64](defaultFsGroup),
		})
	}

	headlessServiceName := HeadlessServiceName(esv1.StatefulSet(es.Name, nodeSet.Name))

	// We retrieve the ConfigMap that holds the scripts to trigger a Pod restart if it is updated.
	esScripts := &corev1.ConfigMap{}
	if err := client.Get(context.Background(), types.NamespacedName{Namespace: es.Namespace, Name: esv1.ScriptsConfigMap(es.Name)}, esScripts); err != nil {
		return corev1.PodTemplateSpec{}, err
	}
	annotations := buildAnnotations(es, cfg, keystoreResources, getScriptsConfigMapContent(esScripts), policyConfig.PolicyAnnotations)

	// Attempt to detect if the default data directory is mounted in a volume.
	// If not, it could be a bug, a misconfiguration, or a custom storage configuration that requires the user to
	// explicitly set ReadOnlyRootFilesystem to true.
	enableReadOnlyRootFilesystem := false
	for _, volumeMount := range volumeMounts {
		if volumeMount.Name == esvolume.ElasticsearchDataVolumeName {
			enableReadOnlyRootFilesystem = true
			break
		}
	}

	// build the podTemplate until we have the effective resources configured
	builder = builder.
		WithLabels(labels).
		WithAnnotations(annotations).
		WithDockerImage(es.Spec.Image, container.ImageRepository(container.ElasticsearchImage, ver)).
		WithResources(DefaultResources).
		WithTerminationGracePeriod(DefaultTerminationGracePeriodSeconds).
		WithPorts(defaultContainerPorts).
		WithReadinessProbe(*NewReadinessProbe(ver)).
		WithAffinity(DefaultAffinity(es.Name)).
		WithEnv(DefaultEnvVars(ver, es.Spec.HTTP, headlessServiceName)...).
		WithVolumes(volumes...).
		WithVolumeMounts(volumeMounts...).
		WithInitContainers(initContainers...).
		// inherit all env vars from main containers to allow Elasticsearch tools that read ES config to work in initContainers
		WithInitContainerDefaults(builder.MainContainer().Env...).
		// set a default security context for both the Containers and the InitContainers
		WithContainersSecurityContext(securitycontext.For(ver, enableReadOnlyRootFilesystem)).
		WithPreStopHook(*NewPreStopHook())

	builder, err = stackmon.WithMonitoring(ctx, client, builder, es)
	if err != nil {
		return corev1.PodTemplateSpec{}, err
	}

	if ver.LT(version.From(7, 2, 0)) {
		// mitigate CVE-2021-44228
		enableLog4JFormatMsgNoLookups(builder)
	}

	return builder.PodTemplate, nil
}