예제 #1
0
    def get_sidecar_containers(
            self,
            system_paasta_config: SystemPaastaConfig) -> List[V1Container]:
        registrations = " ".join(self.get_registrations())
        # s_m_j currently asserts that services are healthy in smartstack before
        # continuing a bounce. this readiness check lets us achieve the same thing
        readiness_probe: Optional[V1Probe]
        if system_paasta_config.get_enable_nerve_readiness_check():
            readiness_probe = V1Probe(
                _exec=V1ExecAction(command=[
                    system_paasta_config.get_nerve_readiness_check_script(),
                ] + self.get_registrations(), ),
                initial_delay_seconds=10,
                period_seconds=10,
            )
        else:
            readiness_probe = None

        hacheck_sidecar = V1Container(
            image=system_paasta_config.get_hacheck_sidecar_image_url(),
            lifecycle=V1Lifecycle(pre_stop=V1Handler(_exec=V1ExecAction(
                command=[
                    "/bin/sh",
                    "-c",
                    f"/usr/bin/hadown {registrations}; sleep 31",
                ], ), ), ),
            name="hacheck",
            env=self.get_kubernetes_environment(),
            ports=[
                V1ContainerPort(container_port=6666, ),
            ],
            readiness_probe=readiness_probe,
        )
        return [hacheck_sidecar]
예제 #2
0
def generate_delaying_proxy_deployment(concourse_cfg: ConcourseConfig):
    ensure_not_none(concourse_cfg)

    external_url = concourse_cfg.external_url()
    label = {'app': 'delaying-proxy'}

    return V1Deployment(
        kind='Deployment',
        metadata=V1ObjectMeta(name='delaying-proxy'),
        spec=V1DeploymentSpec(
            replicas=1,
            selector=V1LabelSelector(match_labels=label),
            template=V1PodTemplateSpec(
                metadata=V1ObjectMeta(labels=label),
                spec=V1PodSpec(containers=[
                    V1Container(
                        image=
                        'eu.gcr.io/gardener-project/cc/github-enterprise-proxy:0.1.0',
                        image_pull_policy='IfNotPresent',
                        name='delaying-proxy',
                        ports=[
                            V1ContainerPort(container_port=8080),
                        ],
                        liveness_probe=V1Probe(
                            tcp_socket=V1TCPSocketAction(port=8080),
                            initial_delay_seconds=10,
                            period_seconds=10,
                        ),
                        env=[
                            V1EnvVar(name='CONCOURSE_URL', value=external_url),
                        ],
                    ),
                ], ))))
예제 #3
0
 def get_kubernetes_containers(
     self,
     volumes: Sequence[DockerVolume],
     system_paasta_config: SystemPaastaConfig,
 ) -> Sequence[V1Container]:
     service_container = V1Container(
         image=self.get_docker_url(),
         command=self.get_cmd(),
         args=self.get_args(),
         env=self.get_container_env(),
         lifecycle=V1Lifecycle(
             pre_stop=V1Handler(
                 _exec=V1ExecAction(
                     command=[
                         "/bin/sh",
                         "-c",
                         "sleep 30",
                     ],
                 ),
             ),
         ),
         name="{service}-{instance}".format(
             service=self.get_sanitised_service_name(),
             instance=self.get_sanitised_instance_name(),
         ),
         liveness_probe=V1Probe(
             failure_threshold=10,
             http_get=V1HTTPGetAction(
                 path="/status",
                 port=8888,
             ),
             initial_delay_seconds=15,
             period_seconds=10,
             timeout_seconds=5,
         ),
         ports=[
             V1ContainerPort(
                 container_port=8888,
             ),
         ],
         volume_mounts=self.get_volume_mounts(volumes=volumes),
     )
     containers = [service_container] + self.get_sidecar_containers(system_paasta_config=system_paasta_config)
     return containers
    def _create_containers(self, service_name: str, deployment_name: str, container_config, mounts,
                           core_container=False):
        cores = container_config.cpu_cores
        memory = container_config.ram_mb
        min_memory = min(container_config.ram_mb_min, container_config.ram_mb)
        environment_variables: list[V1EnvVar] = []

        # Use custom health check located in service base
        health_probe = V1Probe(
            _exec=V1ExecAction(command=["python3", "-m", "assemblyline_v4_service.healthz"]),
            timeout_seconds=SERVICE_LIVENESS_TIMEOUT,
            period_seconds=SERVICE_LIVENESS_PERIOD)

        # If we are launching a core container, include environment variables related to authentication for DBs
        if core_container:
            environment_variables += [V1EnvVar(name=_n, value=_v) for _n, _v in self.core_env.items()]
            environment_variables.append(V1EnvVar(name='PRIVILEGED', value='true'))
        # Overwrite them with configured special environment variables
        environment_variables += [V1EnvVar(name=_e.name, value=_e.value) for _e in container_config.environment]
        # Overwrite those with special hard coded variables
        environment_variables += [
            V1EnvVar(name='AL_SERVICE_NAME', value=service_name),
            V1EnvVar(name='LOG_LEVEL', value=self.log_level)
        ]
        # Overwrite ones defined dynamically by dependency container launches
        for name, value in self._service_limited_env[service_name].items():
            environment_variables.append(V1EnvVar(name=name, value=value))
        image_pull_policy = 'Always' if DEV_MODE else 'IfNotPresent'
        return [V1Container(
            name=deployment_name,
            image=container_config.image,
            command=container_config.command,
            env=environment_variables,
            image_pull_policy=image_pull_policy,
            volume_mounts=mounts,
            resources=V1ResourceRequirements(
                limits={'cpu': cores, 'memory': f'{memory}Mi'},
                requests={'cpu': cores*self.cpu_reservation, 'memory': f'{min_memory}Mi'},
            ),
            liveness_probe=health_probe,
            readiness_probe=health_probe
        )]
예제 #5
0
    def get_liveness_probe(
        self,
        service_namespace_config: ServiceNamespaceConfig,
    ) -> Optional[V1Probe]:
        mode = self.get_healthcheck_mode(service_namespace_config)
        if mode is None:
            return None

        initial_delay_seconds = self.get_healthcheck_grace_period_seconds()
        period_seconds = self.get_healthcheck_interval_seconds()
        timeout_seconds = self.get_healthcheck_timeout_seconds()
        failure_threshold = self.get_healthcheck_max_consecutive_failures()
        probe = V1Probe(
            failure_threshold=failure_threshold,
            initial_delay_seconds=initial_delay_seconds,
            period_seconds=period_seconds,
            timeout_seconds=timeout_seconds,
        )

        if mode == 'http' or mode == 'https':
            path = self.get_healthcheck_uri(service_namespace_config)
            probe.http_get = V1HTTPGetAction(
                path=path,
                port=self.get_container_port(),
                scheme=mode.upper(),
            )
        elif mode == 'tcp':
            probe.tcp_socket = V1TCPSocketAction(
                port=self.get_container_port(), )
        elif mode == 'cmd':
            probe._exec = V1ExecAction(command=[
                "/bin/sh",
                "-c",
                self.get_healthcheck_cmd(),
            ], )
        else:
            raise InvalidHealthcheckMode(
                "Unknown mode: %s. Only acceptable healthcheck modes are http/https/tcp"
                % mode, )

        return probe
예제 #6
0
 def send_create_pod_request(self,
                             namespace,
                             name,
                             image,
                             args,
                             ports={},
                             requests={},
                             limits={},
                             probe="",
                             probe_idelay=3,
                             probe_period=3,
                             node_selector=None,
                             node_name=None,
                             labels=None):
     metadata = V1ObjectMeta(name=name, namespace=namespace, labels=labels)
     ports = [
         V1ContainerPort(container_port=p, name=n)
         for p, n in ports.items()
     ]
     probe_object = None
     if probe:
         probe_action = V1ExecAction(re.split(r" +", probe))
         probe_object = V1Probe(probe_action,
                                initial_delay_seconds=probe_idelay,
                                period_seconds=probe_period)
     container = V1Container(args=args.split(),
                             image=image,
                             name=name,
                             ports=ports,
                             resources=V1ResourceRequirements(
                                 requests=requests, limits=limits),
                             liveness_probe=probe_object)
     spec = V1PodSpec(containers=[container],
                      node_selector=node_selector,
                      node_name=node_name,
                      restart_policy="Never")
     # {"kubernetes.io/hostname": "10.19.137.148"})
     pod = V1Pod(spec=spec, metadata=metadata)
     return self.apiV1.create_namespaced_pod(namespace, body=pod)
예제 #7
0
 def add_container(self,
                   name,
                   image,
                   image_pull_policy="IfNotPresent",
                   args=None,
                   requests={},
                   limits={},
                   probe="",
                   volumes=[],
                   ports=[],
                   **envs):
     ports = [p.pod_port for p in ports]
     probe_object = None
     if probe:
         probe_action = V1ExecAction(re.split(r" +", probe))
         probe_object = V1Probe(probe_action,
                                initial_delay_seconds=5,
                                period_seconds=3)
     if args is not None:
         args = re.split(r" +", args)
     self.volumes.extend(
         [v.volume for v in volumes if v.volume not in self.volumes])
     volume_mounts = [v.mount for v in volumes]
     container_env = [
         V1EnvVar(name=k, value=str(v)) for k, v in envs.items()
     ]
     container = V1Container(
         args=args,
         image=image,
         image_pull_policy=image_pull_policy,
         name=name,
         ports=ports,
         resources=V1ResourceRequirements(requests=requests, limits=limits),
         liveness_probe=probe_object,
         volume_mounts=volume_mounts,
         env=container_env,
     )
     self.containers.append(container)
     return self
예제 #8
0
 def test_get_kubernetes_containers(self):
     with mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_docker_url',
             autospec=True,
     ) as mock_get_docker_url, mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_cmd',
             autospec=True,
     ) as mock_get_cmd, mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_args',
             autospec=True,
     ) as mock_get_args, mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_container_env',
             autospec=True,
     ) as mock_get_container_env, mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_sanitised_service_name',
             autospec=True,
             return_value='kurupt',
     ), mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_sanitised_instance_name',
             autospec=True,
             return_value='fm',
     ), mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_volume_mounts',
             autospec=True,
     ) as mock_get_volume_mounts, mock.patch(
             'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_sidecar_containers',
             autospec=True,
             return_value=['mock_sidecar'],
     ):
         mock_system_config = mock.Mock()
         mock_docker_volumes: Sequence[DockerVolume] = []
         mock_aws_ebs_volumes: Sequence[AwsEbsVolume] = []
         expected = [
             V1Container(
                 args=mock_get_args.return_value,
                 command=mock_get_cmd.return_value,
                 env=mock_get_container_env.return_value,
                 image=mock_get_docker_url.return_value,
                 lifecycle=V1Lifecycle(pre_stop=V1Handler(
                     _exec=V1ExecAction(command=[
                         '/bin/sh',
                         '-c',
                         'sleep 30',
                     ], ), ), ),
                 liveness_probe=V1Probe(
                     failure_threshold=10,
                     http_get=V1HTTPGetAction(
                         path='/status',
                         port=8888,
                     ),
                     initial_delay_seconds=15,
                     period_seconds=10,
                     timeout_seconds=5,
                 ),
                 name='kurupt-fm',
                 ports=[V1ContainerPort(container_port=8888)],
                 volume_mounts=mock_get_volume_mounts.return_value,
             ),
             'mock_sidecar',
         ]
         assert self.deployment.get_kubernetes_containers(
             docker_volumes=mock_docker_volumes,
             system_paasta_config=mock_system_config,
             aws_ebs_volumes=mock_aws_ebs_volumes,
         ) == expected
예제 #9
0
    def test_get_sidecar_containers(self):
        with mock.patch(
                'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_registrations',
                autospec=True,
                return_value=['universal.credit'],
        ), mock.patch(
                'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_kubernetes_environment',
                autospec=True,
                return_value={},
        ), mock.patch(
                'paasta_tools.kubernetes_tools.KubernetesDeploymentConfig.get_sanitised_volume_name',
                autospec=True,
                return_value='sane-name',
        ):
            mock_system_config = mock.Mock(
                get_enable_nerve_readiness_check=mock.Mock(return_value=False),
                get_nerve_readiness_check_script=mock.Mock(
                    return_value='/nail/blah.sh'),
                get_hacheck_sidecar_image_url=mock.Mock(
                    return_value='some-docker-image'),
            )
            ret = self.deployment.get_sidecar_containers(mock_system_config)
            expected = [
                V1Container(
                    env={},
                    image='some-docker-image',
                    lifecycle=V1Lifecycle(pre_stop=V1Handler(
                        _exec=V1ExecAction(command=[
                            '/bin/sh',
                            '-c',
                            '/usr/bin/hadown '
                            'universal.credit; sleep '
                            '31',
                        ], ), ), ),
                    name='hacheck',
                    ports=[V1ContainerPort(container_port=6666)],
                ),
            ]
            assert ret == expected

            mock_system_config = mock.Mock(
                get_enable_nerve_readiness_check=mock.Mock(return_value=True),
                get_nerve_readiness_check_script=mock.Mock(
                    return_value='/nail/blah.sh'),
                get_hacheck_sidecar_image_url=mock.Mock(
                    return_value='some-docker-image'),
            )
            ret = self.deployment.get_sidecar_containers(mock_system_config)
            expected = [
                V1Container(
                    env={},
                    image='some-docker-image',
                    lifecycle=V1Lifecycle(pre_stop=V1Handler(
                        _exec=V1ExecAction(command=[
                            '/bin/sh',
                            '-c',
                            '/usr/bin/hadown '
                            'universal.credit; sleep '
                            '31',
                        ], ), ), ),
                    name='hacheck',
                    ports=[V1ContainerPort(container_port=6666)],
                    readiness_probe=V1Probe(
                        _exec=V1ExecAction(
                            command=['/nail/blah.sh', 'universal.credit'], ),
                        initial_delay_seconds=10,
                        period_seconds=10,
                    ),
                ),
            ]
            assert ret == expected
예제 #10
0
def generate_secrets_server_deployment(
    secrets_server_config: SecretsServerConfig, ):
    service_name = secrets_server_config.service_name()
    secret_name = secrets_server_config.secrets().concourse_secret_name()
    # We need to ensure that the labels and selectors match for both the deployment and the service,
    # therefore we base them on the configured service name.
    labels = {'app': service_name}

    return V1Deployment(
        kind='Deployment',
        metadata=V1ObjectMeta(name=service_name, labels=labels),
        spec=V1DeploymentSpec(
            replicas=1,
            selector=V1LabelSelector(match_labels=labels),
            template=V1PodTemplateSpec(
                metadata=V1ObjectMeta(labels=labels),
                spec=V1PodSpec(containers=[
                    V1Container(
                        image='eu.gcr.io/gardener-project/cc/job-image:latest',
                        image_pull_policy='IfNotPresent',
                        name='secrets-server',
                        resources=V1ResourceRequirements(
                            requests={
                                'cpu': '50m',
                                'memory': '50Mi'
                            },
                            limits={
                                'cpu': '50m',
                                'memory': '50Mi'
                            },
                        ),
                        command=['bash'],
                        args=[
                            '-c', '''
                                # chdir to secrets dir; create if absent
                                mkdir -p /secrets && cd /secrets
                                # make Kubernetes serviceaccount secrets available by default
                                cp -r /var/run/secrets/kubernetes.io/serviceaccount serviceaccount
                                # store Kubernetes service endpoint env as file for consumer
                                env | grep KUBERNETES_SERVICE > serviceaccount/env
                                # launch secrets server serving secrets dir contents on all IFs
                                python3 -m http.server 8080
                                '''
                        ],
                        ports=[
                            V1ContainerPort(container_port=8080),
                        ],
                        liveness_probe=V1Probe(
                            tcp_socket=V1TCPSocketAction(port=8080),
                            initial_delay_seconds=10,
                            period_seconds=10,
                        ),
                        volume_mounts=[
                            V1VolumeMount(
                                name=secret_name,
                                mount_path='/secrets/concourse-secrets',
                                read_only=True,
                            ),
                        ],
                    ),
                ],
                               node_selector={
                                   "worker.garden.sapcloud.io/group":
                                   "cc-control"
                               },
                               volumes=[
                                   V1Volume(name=secret_name,
                                            secret=V1SecretVolumeSource(
                                                secret_name=secret_name, ))
                               ]))))