def set_image_for_stateful_set(self, sts_name, container_name, service_name, image): stateful_set_spec_template_spec_containers = [ client.V1Container(name=container_name, image=image) ] stateful_set_spec_template_spec = client.V1PodSpec( containers=stateful_set_spec_template_spec_containers) stateful_set_spec_template = client.V1PodTemplateSpec( spec=stateful_set_spec_template_spec) stateful_set_spec = client.V1beta1StatefulSetSpec( template=stateful_set_spec_template, service_name=service_name) stateful_set = client.V1beta1StatefulSet(spec=stateful_set_spec) self.appsv1betaapi.patch_namespaced_stateful_set( name=sts_name, namespace=self.namespace, body=stateful_set)
def createStatefulSet(cls, cluster_object: V1MongoClusterConfiguration) -> client.V1beta1StatefulSet: """ Creates a the stateful set configuration for the given cluster. :param cluster_object: The cluster object from the YAML file. :return: The stateful set object. """ # Parse cluster data object. name = cluster_object.metadata.name namespace = cluster_object.metadata.namespace replicas = cluster_object.spec.mongodb.replicas storage_mount_path = cluster_object.spec.mongodb.host_path or cls.DEFAULT_STORAGE_MOUNT_PATH host_path = cluster_object.spec.mongodb.host_path cpu_limit = cluster_object.spec.mongodb.cpu_limit or cls.DEFAULT_CPU_LIMIT memory_limit = cluster_object.spec.mongodb.memory_limit or cls.DEFAULT_MEMORY_LIMIT run_as_user = cluster_object.spec.mongodb.run_as_user or cls.DEFAULT_RUN_AS_USER service_account = cluster_object.spec.mongodb.service_account or cls.DEFAULT_SERVICE_ACCOUNT wired_tiger_cache_size = cluster_object.spec.mongodb.wired_tiger_cache_size or cls.DEFAULT_CACHE_SIZE secret_name = cls.ADMIN_SECRET_NAME_FORMAT.format(name) # create container mongo_container = client.V1Container( name=name, env=[client.V1EnvVar( name="POD_IP", value_from=client.V1EnvVarSource( field_ref = client.V1ObjectFieldSelector( api_version = "v1", field_path = "status.podIP" ) ) ), client.V1EnvVar( name="MONGODB_PASSWORD", value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector( key="database-password", name=secret_name ) ) ), client.V1EnvVar( name="MONGODB_USER", value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector( key="database-user", name=secret_name ) ) ), client.V1EnvVar( name="MONGODB_DATABASE", value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector( key="database-name", name=secret_name ) ) ), client.V1EnvVar( name="MONGODB_ADMIN_PASSWORD", value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector( key="database-admin-password", name=secret_name ) ) ), client.V1EnvVar( name="WIREDTIGER_CACHE_SIZE", value=wired_tiger_cache_size ), client.V1EnvVar( name="MONGODB_REPLICA_NAME", value=name ), client.V1EnvVar( name="MONGODB_SERVICE_NAME", value="svc-" + name + "-internal" ), client.V1EnvVar( name="MONGODB_KEYFILE_VALUE", value="supersecretkeyfile123" )], liveness_probe=client.V1Probe(failure_threshold=3, initial_delay_seconds=30, period_seconds=30, success_threshold=1, tcp_socket=client.V1TCPSocketAction(port=cls.MONGO_PORT), timeout_seconds=1 ), command=cls.MONGO_COMMAND.split(), image=cls.MONGO_IMAGE, image_pull_policy="Always", ports=[client.V1ContainerPort( name="mongodb", container_port=cls.MONGO_PORT, protocol="TCP" )], readiness_probe=client.V1Probe(_exec=client.V1ExecAction(command=["/bin/sh", "-i", "-c", "mongo 127.0.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD --eval=\"quit()\""]), failure_threshold=3, initial_delay_seconds=10, period_seconds=10, success_threshold=1, timeout_seconds=1 ), security_context=client.V1SecurityContext( run_as_user=int(run_as_user), se_linux_options=client.V1SELinuxOptions( level="s0", type="spc_t" ) ), termination_message_path="/dev/termination-log", volume_mounts=[client.V1VolumeMount( name="mongo-data", read_only=False, mount_path=storage_mount_path )], resources=client.V1ResourceRequirements( limits={"cpu": cpu_limit, "memory": memory_limit}, requests={"cpu": cpu_limit, "memory": memory_limit} ) ) #create affinity rules affinity = client.V1Affinity( pod_anti_affinity=client.V1PodAntiAffinity( required_during_scheduling_ignored_during_execution=[ client.V1PodAffinityTerm(label_selector=client.V1LabelSelector( match_expressions=[client.V1LabelSelectorRequirement( key="app", operator="In", values=[name] )] ), topology_key="kubernetes.io/hostname") ] ) ) volumes = [client.V1Volume( name="mongo-data", host_path=client.V1HostPathVolumeSource(path=host_path) )] # Create stateful set. return client.V1beta1StatefulSet( metadata = client.V1ObjectMeta(annotations={"service.alpha.kubernetes.io/tolerate-unready-endpoints": "true"}, name=name, namespace=namespace, labels=cls.createDefaultLabels(name)), spec = client.V1beta1StatefulSetSpec( replicas = replicas, service_name = "svc-" + name + "-internal", template = client.V1PodTemplateSpec( metadata = client.V1ObjectMeta(labels=cls.createDefaultLabels(name)), spec = client.V1PodSpec(affinity = affinity, containers=[mongo_container], node_selector={"compute":"mongodb"}, service_account=service_account, #restart_policy="Never", volumes=volumes ) ), ), )
def generate_stateful_set(self): volume_claim_spec = client.V1PersistentVolumeClaimSpec(**self.volume_claim_spec) if not volume_claim_spec.access_modes: volume_claim_spec.access_modes = ["ReadWriteOnce"] if not volume_claim_spec.resources: volume_claim_spec.resources = client.V1ResourceRequirements( requests={"storage": "20Gi"} ) stateful_set = client.V1beta1StatefulSet( metadata=self.metadata, spec=client.V1beta1StatefulSetSpec( # we can't update service name or pod management policy service_name=self.full_name + "-headless", pod_management_policy="Parallel", # we can't update volume claim templates volume_claim_templates=[client.V1PersistentVolumeClaim( metadata=client.V1ObjectMeta( name="image-store", ), spec=volume_claim_spec, )] ) ) stateful_set.spec.replicas = 2 pod_labels = {'component': 'registry'} pod_labels.update(self.labels) volumes = [] if self.ca_certificate_bundle: volumes = [ client.V1Volume( name=self.ca_certificate_bundle, config_map=client.V1ConfigMapVolumeSource( name=self.ca_certificate_bundle ) ) ] volumes.append( client.V1Volume( name="tls", secret=client.V1SecretVolumeSource( secret_name=self.docker_certificate_secret ), ) ) volumes_to_mount = [ client.V1VolumeMount( name="image-store", mount_path="/var/lib/registry" ), client.V1VolumeMount( name="tls", mount_path="/etc/registry-certs", read_only=True ) ] if self.ca_certificate_bundle: volumes_to_mount.append( client.V1VolumeMount( name=self.ca_certificate_bundle, mount_path="/etc/ssl/certs", read_only=True ) ) env = [client.V1EnvVar(name="REGISTRY_PROXY_REMOTEURL", value="https://" + self.upstreamUrl), client.V1EnvVar(name="REGISTRY_HTTP_ADDR", value=":5000"), client.V1EnvVar(name="REGISTRY_HTTP_DEBUG_ADDR", value="localhost:6000"), client.V1EnvVar(name="REGISTRY_HTTP_TLS_CERTIFICATE", value="/etc/registry-certs/tls.crt"), client.V1EnvVar(name="REGISTRY_HTTP_TLS_KEY", value="/etc/registry-certs/tls.key"), client.V1EnvVar(name="REGISTRY_LOG_ACCESSLOG_DISABLED", value="true"), client.V1EnvVar(name="REGISTRY_LOG_FORMATTER", value="logstash"), client.V1EnvVar(name="REGISTRY_STORAGE_DELETE_ENABLED", value="true"), client.V1EnvVar(name="REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY", value="/var/lib/registry") ] env = self.handle_proxy_credentials(env) stateful_set.spec.template = client.V1PodTemplateSpec( metadata=client.V1ObjectMeta( labels=pod_labels ), spec=client.V1PodSpec( init_containers=[ client.V1Container( name="validate-state-file", image="python:3.6-alpine", env=[ client.V1EnvVar( name="STATE_FILE", value="/var/lib/registry/scheduler-state.json" ), client.V1EnvVar( name="LOWER_LIMIT", value="1024" ), ], volume_mounts=[ client.V1VolumeMount( name="image-store", mount_path="/var/lib/registry" ) ], command=[ "sh", "-e", "-c", "touch $STATE_FILE; if [[ $(stat -c \"%s\" $STATE_FILE) -lt $LOWER_LIMIT ]]; then rm -f $STATE_FILE; else cat $STATE_FILE | python -m json.tool > /dev/null 2>&1 || rm -f $STATE_FILE; fi" # noqa ] ) ], containers=[ client.V1Container( name="registry", image="registry:2.6.0", env=env, readiness_probe=client.V1Probe( http_get=client.V1HTTPGetAction( path="/", port=5000, scheme="HTTPS" ), initial_delay_seconds=3, period_seconds=3 ), ports=[client.V1ContainerPort( container_port=5000, name="https" )], resources=client.V1ResourceRequirements( requests={"cpu": "0.1", "memory": "500Mi"}, limits={"cpu": "0.5", "memory": "500Mi"} ), volume_mounts=volumes_to_mount, ) ], termination_grace_period_seconds=10, volumes=volumes, ) ) stateful_set.spec.update_strategy = client.V1beta1StatefulSetUpdateStrategy(type="RollingUpdate",) return stateful_set
def createStatefulSet( cls, cluster_object: V1MongoClusterConfiguration ) -> client.V1beta1StatefulSet: """ Creates a the stateful set configuration for the given cluster. :param cluster_object: The cluster object from the YAML file. :return: The stateful set object. """ # Parse cluster data object. name = cluster_object.metadata.name storage_name = cluster_object.spec.mongodb.storage_name or cls.DEFAULT_STORAGE_NAME storage_size = cluster_object.spec.mongodb.storage_size or cls.DEFAULT_STORAGE_SIZE storage_mount_path = cluster_object.spec.mongodb.storage_data_path or cls.DEFAULT_STORAGE_MOUNT_PATH storage_class_name = cluster_object.spec.mongodb.storage_class_name or cls.DEFAULT_STORAGE_CLASS_NAME cpu_limit = cluster_object.spec.mongodb.cpu_limit or cls.DEFAULT_CPU_LIMIT cpu_request = cluster_object.spec.mongodb.cpu_request or cls.DEFAULT_CPU_REQUEST memory_limit = cluster_object.spec.mongodb.memory_limit or cls.DEFAULT_MEMORY_LIMIT memory_request = cluster_object.spec.mongodb.memory_request or cls.DEFAULT_MEMORY_REQUEST wired_tiger_cache_size = cluster_object.spec.mongodb.wired_tiger_cache_size or cls.DEFAULT_CACHE_SIZE # create container mongo_container = client.V1Container( name=cls.MONGO_NAME, env=[ client.V1EnvVar( name="POD_IP", value_from=client.V1EnvVarSource( field_ref=client.V1ObjectFieldSelector( api_version="v1", field_path="status.podIP"))) ], command=cls.MONGO_COMMAND.format( name=name, cache_size=wired_tiger_cache_size).split(), image=cls.MONGO_IMAGE, ports=[ client.V1ContainerPort(name=cls.MONGO_NAME, container_port=cls.MONGO_PORT, protocol="TCP") ], volume_mounts=[ client.V1VolumeMount(name=storage_name, read_only=False, mount_path=storage_mount_path) ], resources=client.V1ResourceRequirements(limits={ "cpu": cpu_limit, "memory": memory_limit }, requests={ "cpu": cpu_request, "memory": memory_request })) # Create stateful set. return client.V1beta1StatefulSet( metadata=client.V1ObjectMeta( name=name, namespace=cluster_object.metadata.namespace, labels=cls.createDefaultLabels(name)), spec=client.V1beta1StatefulSetSpec( replicas=cluster_object.spec.mongodb.replicas, service_name=name, template=client.V1PodTemplateSpec( metadata=client.V1ObjectMeta( labels=cls.createDefaultLabels(name)), spec=client.V1PodSpec(containers=[mongo_container]), ), volume_claim_templates=[ client.V1PersistentVolumeClaim( metadata=client.V1ObjectMeta(name=storage_name), spec=client.V1PersistentVolumeClaimSpec( access_modes=["ReadWriteOnce"], resources=client.V1ResourceRequirements( requests={"storage": storage_size}), storage_class_name=storage_class_name), ) ], ), )
def get_statefulset_object(cluster_object): name = cluster_object['metadata']['name'] namespace = cluster_object['metadata']['namespace'] try: replicas = cluster_object['spec']['mongodb']['replicas'] except KeyError: replicas = 3 try: mongodb_limit_cpu = \ cluster_object['spec']['mongodb']['mongodb_limit_cpu'] except KeyError: mongodb_limit_cpu = '100m' try: mongodb_limit_memory = \ cluster_object['spec']['mongodb']['mongodb_limit_memory'] except KeyError: mongodb_limit_memory = '64Mi' statefulset = client.V1beta1StatefulSet() # Metadata statefulset.metadata = client.V1ObjectMeta( name=name, namespace=namespace, labels=get_default_labels(name=name)) # Spec statefulset.spec = client.V1beta1StatefulSetSpec(replicas=replicas, service_name=name) statefulset.spec.template = client.V1PodTemplateSpec() statefulset.spec.template.metadata = client.V1ObjectMeta( labels=get_default_labels(name=name)) statefulset.spec.template.spec = client.V1PodSpec() statefulset.spec.template.spec.affinity = client.V1Affinity( pod_anti_affinity=client.V1PodAntiAffinity( required_during_scheduling_ignored_during_execution=[ client.V1PodAffinityTerm( topology_key='kubernetes.io/hostname', label_selector=client.V1LabelSelector(match_expressions=[ client.V1LabelSelectorRequirement( key='cluster', operator='In', values=[name]) ])) ])) # MongoDB container mongodb_port = client.V1ContainerPort(name='mongodb', container_port=27017, protocol='TCP') mongodb_tls_volumemount = client.V1VolumeMount( name='mongo-tls', read_only=True, mount_path='/etc/ssl/mongod') mongodb_data_volumemount = client.V1VolumeMount(name='mongo-data', read_only=False, mount_path='/data/db') mongodb_resources = client.V1ResourceRequirements(limits={ 'cpu': mongodb_limit_cpu, 'memory': mongodb_limit_memory }, requests={ 'cpu': mongodb_limit_cpu, 'memory': mongodb_limit_memory }) mongodb_container = client.V1Container( name='mongod', command=[ 'mongod', '--auth', '--replSet', name, '--sslMode', 'requireSSL', '--clusterAuthMode', 'x509', '--sslPEMKeyFile', '/etc/ssl/mongod/mongod.pem', '--sslCAFile', '/etc/ssl/mongod/ca.pem' ], image='mongo:3.4.1', ports=[mongodb_port], volume_mounts=[mongodb_tls_volumemount, mongodb_data_volumemount], resources=mongodb_resources) # Metrics container metrics_port = client.V1ContainerPort(name='metrics', container_port=9001, protocol='TCP') metrics_resources = client.V1ResourceRequirements(limits={ 'cpu': '50m', 'memory': '16Mi' }, requests={ 'cpu': '50m', 'memory': '16Mi' }) metrics_secret_name = '{}-monitoring-credentials'.format(name) metrics_username_env_var = client.V1EnvVar( name='MONGODB_MONITORING_USERNAME', value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector(name=metrics_secret_name, key='username'))) metrics_password_env_var = client.V1EnvVar( name='MONGODB_MONITORING_PASSWORD', value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector(name=metrics_secret_name, key='password'))) metrics_container = client.V1Container( name='prometheus-exporter', image='quay.io/kubestack/prometheus-mongodb-exporter:latest', command=[ '/bin/sh', '-c', '/bin/mongodb_exporter --mongodb.uri mongodb://${MONGODB_MONITORING_USERNAME}:${MONGODB_MONITORING_PASSWORD}@127.0.0.1:27017/admin --mongodb.tls-cert /etc/ssl/mongod/mongod.pem --mongodb.tls-ca /etc/ssl/mongod/ca.pem' ], # flake8: noqa ports=[metrics_port], resources=metrics_resources, volume_mounts=[mongodb_tls_volumemount], env=[metrics_username_env_var, metrics_password_env_var]) statefulset.spec.template.spec.containers = [ mongodb_container, metrics_container ] ca_volume = client.V1Volume(name='mongo-ca', secret=client.V1SecretVolumeSource( secret_name='{}-ca'.format(name), items=[ client.V1KeyToPath(key='ca.pem', path='ca.pem'), client.V1KeyToPath(key='ca-key.pem', path='ca-key.pem') ])) tls_volume = client.V1Volume(name='mongo-tls', empty_dir=client.V1EmptyDirVolumeSource()) data_volume = client.V1Volume(name='mongo-data', empty_dir=client.V1EmptyDirVolumeSource()) statefulset.spec.template.spec.volumes = [ ca_volume, tls_volume, data_volume ] # Init container # For now use annotation format for init_container to support K8s >= 1.5 statefulset.spec.template.metadata.annotations = { 'pod.beta.kubernetes.io/init-containers': '[{"name": "cert-init","image": "quay.io/kubestack/mongodb-init:latest","volumeMounts": [{"readOnly": true,"mountPath": "/etc/ssl/mongod-ca","name": "mongo-ca"}, {"mountPath": "/etc/ssl/mongod","name": "mongo-tls"}],"env": [{"name": "METADATA_NAME","valueFrom": {"fieldRef": {"apiVersion": "v1","fieldPath": "metadata.name"}}}, {"name": "NAMESPACE","valueFrom": {"fieldRef": {"apiVersion": "v1","fieldPath": "metadata.namespace"}}}],"command": ["ansible-playbook","member-cert.yml"],"imagePullPolicy": "Always"}]' } # flake8: noqa # tls_init_ca_volumemount = client.V1VolumeMount( # name='mongo-ca', # read_only=True, # mount_path='/etc/ssl/mongod-ca') # tls_init_container = client.V1Container( # name="cert-init", # image="quay.io/kubestack/mongodb-init:latest", # volume_mounts=[tls_init_ca_volumemount, mongodb_tls_volumemount], # env=[ # client.V1EnvVar( # name='METADATA_NAME', # value_from=client.V1EnvVarSource( # field_ref=client.V1ObjectFieldSelector( # api_version='v1', # field_path='metadata.name'))), # client.V1EnvVar( # name='NAMESPACE', # value_from=client.V1EnvVarSource( # field_ref=client.V1ObjectFieldSelector( # api_version='v1', # field_path='metadata.namespace')))], # command=["ansible-playbook", "member-cert.yml"]) # # statefulset.spec.template.spec.init_containers = [tls_init_container] return statefulset
def create_stateful_set(self, replicas=3, volumeSize=10, namespace=None): """ Create the StatefulSet for the Mongo cluster within a namespace. :param replicas: Number of replicas for the StatefulSet. :params volumeSize: The size of the volume to be generated via PVC and attached to pods within the statefulSet. :param namespace: Namespace to deploy to. :return: N/A """ self._create_mongo_configmap(namespace=namespace) stateful_set = client.V1beta1StatefulSet( metadata=client.V1ObjectMeta(name='mongo', namespace=namespace, labels={"app": "MongoStatefulSet"}), status=client.V1beta1StatefulSetStatus(replicas=replicas), spec=client.V1beta1StatefulSetSpec( volume_claim_templates=[ client.V1PersistentVolumeClaim( spec=client.V1PersistentVolumeClaimSpec( access_modes=['ReadWriteOnce'], resources=client.V1ResourceRequirements( requests={ "storage": '{0}Gi'.format(volumeSize) }))) ], replicas=replicas, selector=client.V1LabelSelector( match_labels={"app": "MongoStatefulSet"}), service_name="mongo-service", template=client.V1PodTemplateSpec( metadata=client.V1ObjectMeta( name='mongo-pod', namespace=namespace, labels={"app": "MongoStatefulSet"}), spec=client.V1PodSpec( containers=[ client.V1Container( name='mongo-container', image=Config.MONGO_IMAGE, image_pull_policy='Always', ports=[ client.V1ContainerPort( name='mongo', container_port=27017, protocol='TCP') ], volume_mounts=[ client.V1VolumeMount( name='mongo-config-volume', mount_path='/etc/mongo') ], command=[ "mongod", "-f", "/etc/mongo/mongod.conf" ]) ], volumes=[ client.V1Volume( name='mongo-config-volume', config_map=client.V1ConfigMapVolumeSource( default_mode=0o555, name='mongo-configmap')) ])))) try: self.apps_v1_api.create_namespaced_stateful_set( namespace=namespace, body=stateful_set) except ApiException as E: if E.status == 409: print('Stateful Set already exists.') else: raise E
def get_statefulset_object(cluster_object): name = cluster_object['metadata']['name'] namespace = cluster_object['metadata']['namespace'] try: replicas = cluster_object['spec']['mongodb']['replicas'] except KeyError: replicas = 3 try: mongodb_limit_cpu = \ cluster_object['spec']['mongodb']['mongodb_limit_cpu'] except KeyError: mongodb_limit_cpu = '100m' try: mongodb_limit_memory = \ cluster_object['spec']['mongodb']['mongodb_limit_memory'] except KeyError: mongodb_limit_memory = '64Mi' try: hard_pod_anti_affinity = \ cluster_object['spec']['mongodb']['hard_pod_anti_affinity'] except KeyError: hard_pod_anti_affinity = True statefulset = client.V1beta1StatefulSet() # Metadata statefulset.metadata = client.V1ObjectMeta( name=name, namespace=namespace, labels=get_default_labels(name=name)) # Spec statefulset.spec = client.V1beta1StatefulSetSpec( replicas=replicas, service_name=name, template=client.V1PodTemplateSpec()) statefulset.spec.template.metadata = client.V1ObjectMeta( labels=get_default_labels(name=name)) statefulset.spec.template.spec = client.V1PodSpec(containers=[]) pod_affinity_term = client.V1PodAffinityTerm( topology_key='kubernetes.io/hostname', label_selector=client.V1LabelSelector(match_expressions=[ client.V1LabelSelectorRequirement( key='cluster', operator='In', values=[name]) ])) pod_anti_affinity = client.V1PodAntiAffinity( required_during_scheduling_ignored_during_execution=[ pod_affinity_term ]) if not hard_pod_anti_affinity: pod_anti_affinity = client.V1PodAntiAffinity( preferred_during_scheduling_ignored_during_execution=[ client.V1WeightedPodAffinityTerm( weight=100, pod_affinity_term=pod_affinity_term) ]) statefulset.spec.template.spec.affinity = client.V1Affinity( pod_anti_affinity=pod_anti_affinity) # MongoDB container mongodb_port = client.V1ContainerPort(name='mongodb', container_port=27017, protocol='TCP') mongodb_tls_volumemount = client.V1VolumeMount( name='mongo-tls', read_only=True, mount_path='/etc/ssl/mongod') mongodb_data_volumemount = client.V1VolumeMount(name='mongo-data', read_only=False, mount_path='/data/db') mongodb_resources = client.V1ResourceRequirements(limits={ 'cpu': mongodb_limit_cpu, 'memory': mongodb_limit_memory }, requests={ 'cpu': mongodb_limit_cpu, 'memory': mongodb_limit_memory }) mongodb_container = client.V1Container( name='mongod', env=[ client.V1EnvVar( name='POD_IP', value_from=client.V1EnvVarSource( field_ref=client.V1ObjectFieldSelector( api_version='v1', field_path='status.podIP'))) ], command=[ 'mongod', '--auth', '--replSet', name, '--sslMode', 'requireSSL', '--clusterAuthMode', 'x509', '--sslPEMKeyFile', '/etc/ssl/mongod/mongod.pem', '--sslCAFile', '/etc/ssl/mongod/ca.pem', '--bind_ip', '127.0.0.1,$(POD_IP)' ], image='mongo:3.6.4', ports=[mongodb_port], volume_mounts=[mongodb_tls_volumemount, mongodb_data_volumemount], resources=mongodb_resources) # Metrics container metrics_port = client.V1ContainerPort(name='metrics', container_port=9001, protocol='TCP') metrics_resources = client.V1ResourceRequirements(limits={ 'cpu': '50m', 'memory': '16Mi' }, requests={ 'cpu': '50m', 'memory': '16Mi' }) metrics_secret_name = '{}-monitoring-credentials'.format(name) metrics_username_env_var = client.V1EnvVar( name='MONGODB_MONITORING_USERNAME', value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector(name=metrics_secret_name, key='username'))) metrics_password_env_var = client.V1EnvVar( name='MONGODB_MONITORING_PASSWORD', value_from=client.V1EnvVarSource( secret_key_ref=client.V1SecretKeySelector(name=metrics_secret_name, key='password'))) metrics_container = client.V1Container( name='prometheus-exporter', image='quay.io/kubestack/prometheus-mongodb-exporter:latest', command=[ '/bin/sh', '-c', '/bin/mongodb_exporter --mongodb.uri mongodb://${MONGODB_MONITORING_USERNAME}:${MONGODB_MONITORING_PASSWORD}@127.0.0.1:27017/admin --mongodb.tls-cert /etc/ssl/mongod/mongod.pem --mongodb.tls-ca /etc/ssl/mongod/ca.pem' ], # flake8: noqa ports=[metrics_port], resources=metrics_resources, volume_mounts=[mongodb_tls_volumemount], env=[metrics_username_env_var, metrics_password_env_var]) statefulset.spec.template.spec.containers = [ mongodb_container, metrics_container ] ca_volume = client.V1Volume(name='mongo-ca', secret=client.V1SecretVolumeSource( secret_name='{}-ca'.format(name), items=[ client.V1KeyToPath(key='ca.pem', path='ca.pem'), client.V1KeyToPath(key='ca-key.pem', path='ca-key.pem') ])) tls_volume = client.V1Volume(name='mongo-tls', empty_dir=client.V1EmptyDirVolumeSource()) data_volume = client.V1Volume(name='mongo-data', empty_dir=client.V1EmptyDirVolumeSource()) statefulset.spec.template.spec.volumes = [ ca_volume, tls_volume, data_volume ] # Init container tls_init_ca_volumemount = client.V1VolumeMount( name='mongo-ca', read_only=True, mount_path='/etc/ssl/mongod-ca') tls_init_mongodb_tls_volumemount = client.V1VolumeMount( name='mongo-tls', read_only=False, mount_path='/etc/ssl/mongod') tls_init_container = client.V1Container( name="cert-init", image="quay.io/kubestack/mongodb-init:latest", volume_mounts=[ tls_init_ca_volumemount, tls_init_mongodb_tls_volumemount ], env=[ client.V1EnvVar( name='METADATA_NAME', value_from=client.V1EnvVarSource( field_ref=client.V1ObjectFieldSelector( api_version='v1', field_path='metadata.name'))), client.V1EnvVar( name='NAMESPACE', value_from=client.V1EnvVarSource( field_ref=client.V1ObjectFieldSelector( api_version='v1', field_path='metadata.namespace'))) ], command=["ansible-playbook", "member-cert.yml"]) statefulset.spec.template.spec.init_containers = [tls_init_container] return statefulset