You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ho...@apache.org on 2021/11/03 22:39:21 UTC

[solr-operator] branch main updated: Add support for more ZK Pod options. (#361)

This is an automated email from the ASF dual-hosted git repository.

houston pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-operator.git


The following commit(s) were added to refs/heads/main by this push:
     new b908801  Add support for more ZK Pod options. (#361)
b908801 is described below

commit b908801b36b82cda72cc885040d85f9234aae761
Author: Houston Putman <ho...@apache.org>
AuthorDate: Wed Nov 3 18:39:14 2021 -0400

    Add support for more ZK Pod options. (#361)
---
 api/v1beta1/solrcloud_types.go                   |  28 +++++-
 api/v1beta1/zz_generated.deepcopy.go             |  24 +++++
 config/crd/bases/solr.apache.org_solrclouds.yaml | 112 ++++++++++++++++++++++-
 controllers/controller_utils_test.go             |   3 +-
 controllers/solrcloud_controller_zk_test.go      |  25 +++--
 controllers/util/zk_util.go                      |  50 +++++++++-
 docs/solr-cloud/solr-cloud-crd.md                |   5 +
 helm/solr-operator/Chart.yaml                    |   7 ++
 helm/solr-operator/crds/crds.yaml                | 112 ++++++++++++++++++++++-
 helm/solr/README.md                              |   5 +
 10 files changed, 359 insertions(+), 12 deletions(-)

diff --git a/api/v1beta1/solrcloud_types.go b/api/v1beta1/solrcloud_types.go
index e61aa76..692afd4 100644
--- a/api/v1beta1/solrcloud_types.go
+++ b/api/v1beta1/solrcloud_types.go
@@ -764,7 +764,7 @@ type ZookeeperSpec struct {
 	// +optional
 	Ephemeral *ZKEphemeral `json:"ephemeral,omitempty"`
 
-	// Pod resources for zookeeper pod
+	// Customization options for the Zookeeper Pod
 	// +optional
 	ZookeeperPod ZookeeperPodPolicy `json:"zookeeperPodPolicy,omitempty"`
 
@@ -980,6 +980,32 @@ type ZookeeperPodPolicy struct {
 	// Optional Service Account to run the zookeeper pods under.
 	// +optional
 	ServiceAccountName string `json:"serviceAccountName,omitempty"`
+
+	// Labels specifies the labels to attach to pods the operator creates for
+	// the zookeeper cluster.
+	// +optional
+	Labels map[string]string `json:"labels,omitempty"`
+
+	// Annotations specifies the annotations to attach to zookeeper pods
+	// creates.
+	// +optional
+	Annotations map[string]string `json:"annotations,omitempty"`
+
+	// SecurityContext specifies the security context for the entire zookeeper pod
+	// More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context
+	// +optional
+	SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`
+
+	// TerminationGracePeriodSeconds is the amount of time that kubernetes will
+	// give for a zookeeper pod instance to shutdown normally.
+	// The default value is 30.
+	// +optional
+	// +kubebuilder:validation:Minimum=0
+	TerminationGracePeriodSeconds int64 `json:"terminationGracePeriodSeconds,omitempty"`
+
+	// ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images
+	// +optional
+	ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
 }
 
 // SolrCloudStatus defines the observed state of SolrCloud
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index 439ca53..79d356a 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -1551,6 +1551,30 @@ func (in *ZookeeperPodPolicy) DeepCopyInto(out *ZookeeperPodPolicy) {
 		}
 	}
 	in.Resources.DeepCopyInto(&out.Resources)
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Annotations != nil {
+		in, out := &in.Annotations, &out.Annotations
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.SecurityContext != nil {
+		in, out := &in.SecurityContext, &out.SecurityContext
+		*out = new(v1.PodSecurityContext)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ImagePullSecrets != nil {
+		in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
+		*out = make([]v1.LocalObjectReference, len(*in))
+		copy(*out, *in)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZookeeperPodPolicy.
diff --git a/config/crd/bases/solr.apache.org_solrclouds.yaml b/config/crd/bases/solr.apache.org_solrclouds.yaml
index ec403d2..4af3461 100644
--- a/config/crd/bases/solr.apache.org_solrclouds.yaml
+++ b/config/crd/bases/solr.apache.org_solrclouds.yaml
@@ -6334,7 +6334,7 @@ spec:
                         format: int32
                         type: integer
                       zookeeperPodPolicy:
-                        description: Pod resources for zookeeper pod
+                        description: Customization options for the Zookeeper Pod
                         properties:
                           affinity:
                             description: The scheduling constraints on pods.
@@ -6677,6 +6677,11 @@ spec:
                                     type: array
                                 type: object
                             type: object
+                          annotations:
+                            additionalProperties:
+                              type: string
+                            description: Annotations specifies the annotations to attach to zookeeper pods creates.
+                            type: object
                           env:
                             description: List of environment variables to set in the main ZK container.
                             items:
@@ -6757,6 +6762,21 @@ spec:
                               - name
                               type: object
                             type: array
+                          imagePullSecrets:
+                            description: ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images
+                            items:
+                              description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.
+                              properties:
+                                name:
+                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
+                                  type: string
+                              type: object
+                            type: array
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Labels specifies the labels to attach to pods the operator creates for the zookeeper cluster.
+                            type: object
                           nodeSelector:
                             additionalProperties:
                               type: string
@@ -6784,9 +6804,99 @@ spec:
                                 description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                                 type: object
                             type: object
+                          securityContext:
+                            description: 'SecurityContext specifies the security context for the entire zookeeper pod More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context'
+                            properties:
+                              fsGroup:
+                                description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume."
+                                format: int64
+                                type: integer
+                              fsGroupChangePolicy:
+                                description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used.'
+                                type: string
+                              runAsGroup:
+                                description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                format: int64
+                                type: integer
+                              runAsNonRoot:
+                                description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                type: boolean
+                              runAsUser:
+                                description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                format: int64
+                                type: integer
+                              seLinuxOptions:
+                                description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container.  May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                properties:
+                                  level:
+                                    description: Level is SELinux level label that applies to the container.
+                                    type: string
+                                  role:
+                                    description: Role is a SELinux role label that applies to the container.
+                                    type: string
+                                  type:
+                                    description: Type is a SELinux type label that applies to the container.
+                                    type: string
+                                  user:
+                                    description: User is a SELinux user label that applies to the container.
+                                    type: string
+                                type: object
+                              seccompProfile:
+                                description: The seccomp options to use by the containers in this pod.
+                                properties:
+                                  localhostProfile:
+                                    description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must only be set if type is "Localhost".
+                                    type: string
+                                  type:
+                                    description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied."
+                                    type: string
+                                required:
+                                - type
+                                type: object
+                              supplementalGroups:
+                                description: A list of groups applied to the first process run in each container, in addition to the container's primary GID.  If unspecified, no groups will be added to any container.
+                                items:
+                                  format: int64
+                                  type: integer
+                                type: array
+                              sysctls:
+                                description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.
+                                items:
+                                  description: Sysctl defines a kernel parameter to be set
+                                  properties:
+                                    name:
+                                      description: Name of a property to set
+                                      type: string
+                                    value:
+                                      description: Value of a property to set
+                                      type: string
+                                  required:
+                                  - name
+                                  - value
+                                  type: object
+                                type: array
+                              windowsOptions:
+                                description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                properties:
+                                  gmsaCredentialSpec:
+                                    description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field.
+                                    type: string
+                                  gmsaCredentialSpecName:
+                                    description: GMSACredentialSpecName is the name of the GMSA credential spec to use.
+                                    type: string
+                                  runAsUserName:
+                                    description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                    type: string
+                                type: object
+                            type: object
                           serviceAccountName:
                             description: Optional Service Account to run the zookeeper pods under.
                             type: string
+                          terminationGracePeriodSeconds:
+                            description: TerminationGracePeriodSeconds is the amount of time that kubernetes will give for a zookeeper pod instance to shutdown normally. The default value is 30.
+                            format: int64
+                            minimum: 0
+                            type: integer
                           tolerations:
                             description: Tolerations to be added on pods.
                             items:
diff --git a/controllers/controller_utils_test.go b/controllers/controller_utils_test.go
index 72b10d8..d7e7299 100644
--- a/controllers/controller_utils_test.go
+++ b/controllers/controller_utils_test.go
@@ -26,7 +26,6 @@ import (
 	zk_api "github.com/apache/solr-operator/controllers/zk_api"
 	"golang.org/x/net/context"
 	appsv1 "k8s.io/api/apps/v1"
-	batchv1 "k8s.io/api/batch/v1"
 	corev1 "k8s.io/api/core/v1"
 	netv1 "k8s.io/api/networking/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
@@ -638,7 +637,7 @@ func cleanupTest(ctx context.Context, parentResource client.Object) {
 		&zk_api.ZookeeperCluster{},
 
 		// All dependent Kubernetes types, in order of dependence (deployment then replicaSet then pod)
-		&corev1.ConfigMap{}, &batchv1.Job{}, &netv1.Ingress{},
+		&corev1.ConfigMap{}, &netv1.Ingress{},
 		&corev1.PersistentVolumeClaim{}, &corev1.PersistentVolume{},
 		&appsv1.StatefulSet{}, &appsv1.Deployment{}, &appsv1.ReplicaSet{}, &corev1.Pod{}, &corev1.PersistentVolumeClaim{},
 		&corev1.Secret{},
diff --git a/controllers/solrcloud_controller_zk_test.go b/controllers/solrcloud_controller_zk_test.go
index fcd8511..898a5f8 100644
--- a/controllers/solrcloud_controller_zk_test.go
+++ b/controllers/solrcloud_controller_zk_test.go
@@ -48,6 +48,8 @@ var _ = FDescribe("SolrCloud controller - Zookeeper", func() {
 			},
 			Spec: solrv1beta1.SolrCloudSpec{},
 		}
+
+		cleanupTest(ctx, solrCloud)
 	})
 
 	JustBeforeEach(func() {
@@ -194,18 +196,24 @@ var _ = FDescribe("SolrCloud controller - Zookeeper", func() {
 				ZookeeperRef: &solrv1beta1.ZookeeperRef{
 					ProvidedZookeeper: &solrv1beta1.ZookeeperSpec{
 						Replicas: &four,
+						Image:    &solrv1beta1.ContainerImage{ImagePullSecret: testImagePullSecretName},
 						Ephemeral: &solrv1beta1.ZKEphemeral{
 							EmptyDirVolumeSource: corev1.EmptyDirVolumeSource{
 								Medium: "Memory",
 							},
 						},
 						ZookeeperPod: solrv1beta1.ZookeeperPodPolicy{
-							Affinity:           testAffinity,
-							NodeSelector:       testNodeSelectors,
-							Tolerations:        testTolerations,
-							Env:                extraVars,
-							Resources:          testResources,
-							ServiceAccountName: testServiceAccountName,
+							Affinity:                      testAffinity,
+							NodeSelector:                  testNodeSelectors,
+							Tolerations:                   testTolerations,
+							Env:                           extraVars,
+							Resources:                     testResources,
+							ServiceAccountName:            testServiceAccountName,
+							Labels:                        testSSLabels,
+							Annotations:                   testSSAnnotations,
+							SecurityContext:               &testPodSecurityContext,
+							TerminationGracePeriodSeconds: testTerminationGracePeriodSeconds,
+							ImagePullSecrets:              testAdditionalImagePullSecrets,
 						},
 						Config: zkConf,
 						ChRoot: "a-ch/root",
@@ -272,6 +280,11 @@ var _ = FDescribe("SolrCloud controller - Zookeeper", func() {
 			Expect(zkCluster.Spec.Pod.Resources).To(Equal(testResources), "Incorrect zkCluster resources")
 			Expect(zkCluster.Spec.Pod.Env).To(Equal(extraVars), "Incorrect zkCluster env vars")
 			Expect(zkCluster.Spec.Pod.ServiceAccountName).To(Equal(testServiceAccountName), "Incorrect zkCluster serviceAccountName")
+			Expect(zkCluster.Spec.Pod.Labels).To(Equal(util.MergeLabelsOrAnnotations(testSSLabels, map[string]string{"app": "foo-solrcloud-zookeeper", "release": "foo-solrcloud-zookeeper"})), "Incorrect zkCluster pod labels")
+			Expect(zkCluster.Spec.Pod.Annotations).To(Equal(testSSAnnotations), "Incorrect zkCluster pod annotations")
+			Expect(zkCluster.Spec.Pod.SecurityContext).To(Equal(&testPodSecurityContext), "Incorrect zkCluster pod securityContext")
+			Expect(zkCluster.Spec.Pod.TerminationGracePeriodSeconds).To(Equal(testTerminationGracePeriodSeconds), "Incorrect zkCluster pod terminationGracePeriodSeconds")
+			Expect(zkCluster.Spec.Pod.ImagePullSecrets).To(Equal(append(append(make([]corev1.LocalObjectReference, 0), testAdditionalImagePullSecrets...), corev1.LocalObjectReference{Name: testImagePullSecretName})), "Incorrect zkCluster imagePullSecrets")
 
 			// Check ZK Config Options
 			Expect(zkCluster.Spec.Conf.InitLimit).To(Equal(zkConf.InitLimit), "Incorrect zkCluster Config InitLimit")
diff --git a/controllers/util/zk_util.go b/controllers/util/zk_util.go
index 01fefd8..980a42f 100644
--- a/controllers/util/zk_util.go
+++ b/controllers/util/zk_util.go
@@ -123,8 +123,32 @@ func GenerateZookeeperCluster(solrCloud *solrv1beta1.SolrCloud, zkSpec *solrv1be
 		zkCluster.Spec.Pod.ServiceAccountName = zkSpec.ZookeeperPod.ServiceAccountName
 	}
 
+	if len(zkSpec.ZookeeperPod.Labels) > 0 {
+		zkCluster.Spec.Pod.Labels = zkSpec.ZookeeperPod.Labels
+	}
+
+	if len(zkSpec.ZookeeperPod.Annotations) > 0 {
+		zkCluster.Spec.Pod.Annotations = zkSpec.ZookeeperPod.Annotations
+	}
+
+	if zkSpec.ZookeeperPod.SecurityContext != nil {
+		zkCluster.Spec.Pod.SecurityContext = zkSpec.ZookeeperPod.SecurityContext
+	}
+
+	if zkSpec.ZookeeperPod.TerminationGracePeriodSeconds != 0 {
+		zkCluster.Spec.Pod.TerminationGracePeriodSeconds = zkSpec.ZookeeperPod.TerminationGracePeriodSeconds
+	}
+
+	if len(zkSpec.ZookeeperPod.ImagePullSecrets) > 0 {
+		zkCluster.Spec.Pod.ImagePullSecrets = zkSpec.ZookeeperPod.ImagePullSecrets
+	}
+
 	if zkSpec.Image.ImagePullSecret != "" {
-		zkCluster.Spec.Pod.ImagePullSecrets = []corev1.LocalObjectReference{{Name: zkSpec.Image.ImagePullSecret}}
+		if len(zkSpec.ZookeeperPod.ImagePullSecrets) > 0 {
+			zkCluster.Spec.Pod.ImagePullSecrets = append(zkCluster.Spec.Pod.ImagePullSecrets, corev1.LocalObjectReference{Name: zkSpec.Image.ImagePullSecret})
+		} else {
+			zkCluster.Spec.Pod.ImagePullSecrets = []corev1.LocalObjectReference{{Name: zkSpec.Image.ImagePullSecret}}
+		}
 	}
 
 	// Add defaults that the ZK Operator should set itself, otherwise we will have problems with reconcile loops.
@@ -295,6 +319,30 @@ func CopyZookeeperClusterFields(from, to *zk_api.ZookeeperCluster, logger logr.L
 		to.Spec.Pod.ServiceAccountName = from.Spec.Pod.ServiceAccountName
 	}
 
+	if !DeepEqualWithNils(to.Spec.Pod.Labels, from.Spec.Pod.Labels) {
+		logger.Info("Update required because field changed", "field", "Spec.Pod.Labels", "from", to.Spec.Pod.Labels, "to", from.Spec.Pod.Labels)
+		requireUpdate = true
+		to.Spec.Pod.Labels = from.Spec.Pod.Labels
+	}
+
+	if !DeepEqualWithNils(to.Spec.Pod.Annotations, from.Spec.Pod.Annotations) {
+		logger.Info("Update required because field changed", "field", "Spec.Pod.Annotations", "from", to.Spec.Pod.Annotations, "to", from.Spec.Pod.Annotations)
+		requireUpdate = true
+		to.Spec.Pod.Annotations = from.Spec.Pod.Annotations
+	}
+
+	if !DeepEqualWithNils(to.Spec.Pod.SecurityContext, from.Spec.Pod.SecurityContext) {
+		logger.Info("Update required because field changed", "field", "Spec.Pod.SecurityContext", "from", to.Spec.Pod.SecurityContext, "to", from.Spec.Pod.SecurityContext)
+		requireUpdate = true
+		to.Spec.Pod.SecurityContext = from.Spec.Pod.SecurityContext
+	}
+
+	if !DeepEqualWithNils(to.Spec.Pod.TerminationGracePeriodSeconds, from.Spec.Pod.TerminationGracePeriodSeconds) {
+		logger.Info("Update required because field changed", "field", "Spec.Pod.TerminationGracePeriodSeconds", "from", to.Spec.Pod.TerminationGracePeriodSeconds, "to", from.Spec.Pod.TerminationGracePeriodSeconds)
+		requireUpdate = true
+		to.Spec.Pod.TerminationGracePeriodSeconds = from.Spec.Pod.TerminationGracePeriodSeconds
+	}
+
 	if !DeepEqualWithNils(to.Spec.Pod.ImagePullSecrets, from.Spec.Pod.ImagePullSecrets) {
 		logger.Info("Update required because field changed", "field", "Spec.Pod.ImagePullSecrets", "from", to.Spec.Pod.ImagePullSecrets, "to", from.Spec.Pod.ImagePullSecrets)
 		requireUpdate = true
diff --git a/docs/solr-cloud/solr-cloud-crd.md b/docs/solr-cloud/solr-cloud-crd.md
index 20c108b..6d9c7a0 100644
--- a/docs/solr-cloud/solr-cloud-crd.md
+++ b/docs/solr-cloud/solr-cloud-crd.md
@@ -187,6 +187,11 @@ each solrCloud that has this option specified.
 
 The startup parameter `zookeeper-operator` must be provided on startup of the solr-operator for this parameter to be available.
 
+To find all Provided zookeeper options, run `kubectl explain solrcloud.spec.zookeeperRef.provided`.
+Zookeeper Conf and PodOptions provided in the linked Zookeeper Operator version should be supported in the SolrCloud CRD.
+However, this is a manual task, so not all options might be available.
+If there is an option available in the ZookeeperCluster CRD that is not exposed via the SolrCloud CRD, please create a Github Issue.
+
 #### Zookeeper Storage Options
 _Since v0.4.0_
 
diff --git a/helm/solr-operator/Chart.yaml b/helm/solr-operator/Chart.yaml
index ae80f5b..4f9bd1b 100644
--- a/helm/solr-operator/Chart.yaml
+++ b/helm/solr-operator/Chart.yaml
@@ -169,6 +169,13 @@ annotations:
           url: https://github.com/apache/solr-operator/issues/347
         - name: Github PR
           url: https://github.com/apache/solr-operator/pull/357
+    - kind: added
+      description: Support for more Zookeeper Pod customization options
+      links:
+        - name: Github Issue
+          url: https://github.com/apache/solr-operator/issues/352
+        - name: Github PR
+          url: https://github.com/apache/solr-operator/pull/361
   artifacthub.io/images: |
     - name: solr-operator
       image: apache/solr-operator:v0.5.0-prerelease
diff --git a/helm/solr-operator/crds/crds.yaml b/helm/solr-operator/crds/crds.yaml
index 409fca0..a2d4ccd 100644
--- a/helm/solr-operator/crds/crds.yaml
+++ b/helm/solr-operator/crds/crds.yaml
@@ -7468,7 +7468,7 @@ spec:
                         format: int32
                         type: integer
                       zookeeperPodPolicy:
-                        description: Pod resources for zookeeper pod
+                        description: Customization options for the Zookeeper Pod
                         properties:
                           affinity:
                             description: The scheduling constraints on pods.
@@ -7811,6 +7811,11 @@ spec:
                                     type: array
                                 type: object
                             type: object
+                          annotations:
+                            additionalProperties:
+                              type: string
+                            description: Annotations specifies the annotations to attach to zookeeper pods creates.
+                            type: object
                           env:
                             description: List of environment variables to set in the main ZK container.
                             items:
@@ -7891,6 +7896,21 @@ spec:
                               - name
                               type: object
                             type: array
+                          imagePullSecrets:
+                            description: ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images
+                            items:
+                              description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.
+                              properties:
+                                name:
+                                  description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
+                                  type: string
+                              type: object
+                            type: array
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Labels specifies the labels to attach to pods the operator creates for the zookeeper cluster.
+                            type: object
                           nodeSelector:
                             additionalProperties:
                               type: string
@@ -7918,9 +7938,99 @@ spec:
                                 description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                                 type: object
                             type: object
+                          securityContext:
+                            description: 'SecurityContext specifies the security context for the entire zookeeper pod More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context'
+                            properties:
+                              fsGroup:
+                                description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume."
+                                format: int64
+                                type: integer
+                              fsGroupChangePolicy:
+                                description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used.'
+                                type: string
+                              runAsGroup:
+                                description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                format: int64
+                                type: integer
+                              runAsNonRoot:
+                                description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                type: boolean
+                              runAsUser:
+                                description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                format: int64
+                                type: integer
+                              seLinuxOptions:
+                                description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container.  May also be set in SecurityContext.  If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.
+                                properties:
+                                  level:
+                                    description: Level is SELinux level label that applies to the container.
+                                    type: string
+                                  role:
+                                    description: Role is a SELinux role label that applies to the container.
+                                    type: string
+                                  type:
+                                    description: Type is a SELinux type label that applies to the container.
+                                    type: string
+                                  user:
+                                    description: User is a SELinux user label that applies to the container.
+                                    type: string
+                                type: object
+                              seccompProfile:
+                                description: The seccomp options to use by the containers in this pod.
+                                properties:
+                                  localhostProfile:
+                                    description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must only be set if type is "Localhost".
+                                    type: string
+                                  type:
+                                    description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied."
+                                    type: string
+                                required:
+                                - type
+                                type: object
+                              supplementalGroups:
+                                description: A list of groups applied to the first process run in each container, in addition to the container's primary GID.  If unspecified, no groups will be added to any container.
+                                items:
+                                  format: int64
+                                  type: integer
+                                type: array
+                              sysctls:
+                                description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch.
+                                items:
+                                  description: Sysctl defines a kernel parameter to be set
+                                  properties:
+                                    name:
+                                      description: Name of a property to set
+                                      type: string
+                                    value:
+                                      description: Value of a property to set
+                                      type: string
+                                  required:
+                                  - name
+                                  - value
+                                  type: object
+                                type: array
+                              windowsOptions:
+                                description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                properties:
+                                  gmsaCredentialSpec:
+                                    description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field.
+                                    type: string
+                                  gmsaCredentialSpecName:
+                                    description: GMSACredentialSpecName is the name of the GMSA credential spec to use.
+                                    type: string
+                                  runAsUserName:
+                                    description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
+                                    type: string
+                                type: object
+                            type: object
                           serviceAccountName:
                             description: Optional Service Account to run the zookeeper pods under.
                             type: string
+                          terminationGracePeriodSeconds:
+                            description: TerminationGracePeriodSeconds is the amount of time that kubernetes will give for a zookeeper pod instance to shutdown normally. The default value is 30.
+                            format: int64
+                            minimum: 0
+                            type: integer
                           tolerations:
                             description: Tolerations to be added on pods.
                             items:
diff --git a/helm/solr/README.md b/helm/solr/README.md
index 07edb9a..0871e66 100644
--- a/helm/solr/README.md
+++ b/helm/solr/README.md
@@ -174,6 +174,8 @@ Currently the Zookeeper Operator does not support ACLs, so do not use the provid
 | zk.provided.persistence.annotations | object | | Annotations to use for the ZooKeeper PVC(s) |
 | zk.provided.ephemeral.emptydirvolumesource | object | | An emptyDir volume source for the ZooKeeper Storage on each pod. |
 | zk.provided.config | object | | Zookeeper Config Options to set for the provided cluster. For all possible options, run: `kubectl explain solrcloud.spec.zookeeperRef.provided.config` |
+| zk.provided.zookeeperPodPolicy.labels | map[string]string |  | List of additional labels to add to the Zookeeper pod |
+| zk.provided.zookeeperPodPolicy.annotations | map[string]string |  | List of additional annotations to add to the Zookeeper pod |
 | zk.provided.zookeeperPodPolicy.serviceAccountName | string |  | Optional serviceAccount to run the ZK Pod under |
 | zk.provided.zookeeperPodPolicy.affinity | string |  | PullSecret for the ZooKeeper image |
 | zk.provided.zookeeperPodPolicy.resources.limits | map[string]string |  | Provide Resource limits for the ZooKeeper containers |
@@ -182,6 +184,9 @@ Currently the Zookeeper Operator does not support ACLs, so do not use the provid
 | zk.provided.zookeeperPodPolicy.affinity | object |  | Add Kubernetes affinity information for the ZooKeeper pod |
 | zk.provided.zookeeperPodPolicy.tolerations | []object |  | Specify a list of Kubernetes tolerations for the ZooKeeper pod |
 | zk.provided.zookeeperPodPolicy.envVars | []object |  | List of additional environment variables for the ZooKeeper container |
+| zk.provided.zookeeperPodPolicy.securityContext | object |  | Security context for the entire ZooKeeper pod. More information can be found in the [Kubernetes docs](More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context). |
+| zk.provided.zookeeperPodPolicy.terminationGracePeriodSeconds | int | `30` | The amount of time that Kubernetes will give for a zookeeper pod instance to shutdown normally. |
+| zk.provided.zookeeperPodPolicy.imagePullSecrets | []object |  | List of image pull secrets to inject into the Zookeeper pod. |
 | zk.acl.secret | string |  | Name of a secret in the same namespace as the Solr cloud that stores the ZK admin ACL information |
 | zk.acl.usernameKey | string |  | Key in the Admin ACL Secret that stores the ACL username |
 | zk.acl.passwordKey | string |  | Key in the Admin ACL Secret that stores the ACL password |