Exemple #1
0
    def test_image_pull_secrets_correctly_set(self, mock_client, monitor_mock,
                                              start_mock):
        from airflow.utils.state import State

        fake_pull_secrets = "fakeSecret"
        k = KubernetesPodOperator(
            namespace='default',
            image="ubuntu:16.04",
            cmds=["bash", "-cx"],
            arguments=["echo 10"],
            labels={"foo": "bar"},
            name="test",
            task_id="task",
            in_cluster=False,
            do_xcom_push=False,
            image_pull_secrets=[k8s.V1LocalObjectReference(fake_pull_secrets)],
            cluster_context='default',
        )
        monitor_mock.return_value = (State.SUCCESS, None)
        context = self.create_context(k)
        k.execute(context=context)
        self.assertEqual(
            start_mock.call_args[0][0].spec.image_pull_secrets,
            [k8s.V1LocalObjectReference(name=fake_pull_secrets)],
        )
 def test_image_pull_secrets_correctly_set(self, mock_client,
                                           await_pod_completion_mock,
                                           create_mock):
     fake_pull_secrets = "fakeSecret"
     k = KubernetesPodOperator(
         namespace='default',
         image="ubuntu:16.04",
         cmds=["bash", "-cx"],
         arguments=["echo 10"],
         labels={"foo": "bar"},
         name="test",
         task_id="task",
         in_cluster=False,
         do_xcom_push=False,
         image_pull_secrets=fake_pull_secrets,
         cluster_context='default',
     )
     mock_pod = MagicMock()
     mock_pod.status.phase = 'Succeeded'
     await_pod_completion_mock.return_value = mock_pod
     context = create_context(k)
     k.execute(context=context)
     assert create_mock.call_args[1]['pod'].spec.image_pull_secrets == [
         k8s.V1LocalObjectReference(name=fake_pull_secrets)
     ]
 def _get_image_pull_secrets(self):
     """Extracts any image pull secrets for fetching container(s)"""
     if not self.kube_config.image_pull_secrets:
         return []
     pull_secrets = self.kube_config.image_pull_secrets.split(',')
     return list(
         map(lambda name: k8s.V1LocalObjectReference(name), pull_secrets))
 def test_image_pull_secrets_correctly_set(self):
     fake_pull_secrets = "fakeSecret"
     k = KubernetesPodOperator(
         namespace="default",
         image="ubuntu:16.04",
         cmds=["bash", "-cx"],
         arguments=["echo 10"],
         labels={"foo": "bar"},
         name="test",
         task_id="task",
         in_cluster=False,
         do_xcom_push=False,
         image_pull_secrets=[k8s.V1LocalObjectReference(fake_pull_secrets)],
         cluster_context="default",
     )
     pod = k.create_pod_request_obj()
     assert pod.spec.image_pull_secrets == [k8s.V1LocalObjectReference(name=fake_pull_secrets)]
def convert_image_pull_secrets(image_pull_secrets) -> List[k8s.V1LocalObjectReference]:
    """
    Converts a PodRuntimeInfoEnv into an k8s.V1EnvVar

    :param image_pull_secrets:
    :return:
    """
    if isinstance(image_pull_secrets, str):
        secrets = image_pull_secrets.split(",")
        return [k8s.V1LocalObjectReference(name=secret) for secret in secrets]
    else:
        return image_pull_secrets
    def setUp(self):
        self.static_uuid = uuid.UUID('cf4a56d2-8101-4217-b027-2af6216feb48')
        self.deserialize_result = {
            'apiVersion': 'v1',
            'kind': 'Pod',
            'metadata': {'name': 'memory-demo', 'namespace': 'mem-example'},
            'spec': {
                'containers': [
                    {
                        'args': ['--vm', '1', '--vm-bytes', '150M', '--vm-hang', '1'],
                        'command': ['stress'],
                        'image': 'apache/airflow:stress-2020.07.10-1.0.4',
                        'name': 'memory-demo-ctr',
                        'resources': {'limits': {'memory': '200Mi'}, 'requests': {'memory': '100Mi'}},
                    }
                ]
            },
        }

        self.envs = {'ENVIRONMENT': 'prod', 'LOG_LEVEL': 'warning'}
        self.secrets = [
            # This should be a secretRef
            Secret('env', None, 'secret_a'),
            # This should be a single secret mounted in volumeMounts
            Secret('volume', '/etc/foo', 'secret_b'),
            # This should produce a single secret mounted in env
            Secret('env', 'TARGET', 'secret_b', 'source_b'),
        ]

        self.execution_date = parser.parse('2020-08-24 00:00:00.000000')
        self.execution_date_label = datetime_to_label_safe_datestring(self.execution_date)
        self.dag_id = 'dag_id'
        self.task_id = 'task_id'
        self.try_number = 3
        self.labels = {
            'airflow-worker': 'uuid',
            'dag_id': self.dag_id,
            'execution_date': self.execution_date_label,
            'task_id': self.task_id,
            'try_number': str(self.try_number),
            'airflow_version': __version__.replace('+', '-'),
            'kubernetes_executor': 'True',
        }
        self.annotations = {
            'dag_id': self.dag_id,
            'task_id': self.task_id,
            'execution_date': self.execution_date.isoformat(),
            'try_number': str(self.try_number),
        }
        self.metadata = {
            'labels': self.labels,
            'name': 'pod_id-' + self.static_uuid.hex,
            'namespace': 'namespace',
            'annotations': self.annotations,
        }

        self.resources = k8s.V1ResourceRequirements(
            requests={
                "cpu": 1,
                "memory": "1Gi",
                "ephemeral-storage": "2Gi",
            },
            limits={"cpu": 2, "memory": "2Gi", "ephemeral-storage": "4Gi", 'nvidia.com/gpu': 1},
        )

        self.k8s_client = ApiClient()
        self.expected = k8s.V1Pod(
            api_version="v1",
            kind="Pod",
            metadata=k8s.V1ObjectMeta(
                namespace="default",
                name='myapp-pod-' + self.static_uuid.hex,
                labels={'app': 'myapp'},
            ),
            spec=k8s.V1PodSpec(
                containers=[
                    k8s.V1Container(
                        name='base',
                        image='busybox',
                        command=['sh', '-c', 'echo Hello Kubernetes!'],
                        env=[
                            k8s.V1EnvVar(name='ENVIRONMENT', value='prod'),
                            k8s.V1EnvVar(
                                name="LOG_LEVEL",
                                value='warning',
                            ),
                            k8s.V1EnvVar(
                                name='TARGET',
                                value_from=k8s.V1EnvVarSource(
                                    secret_key_ref=k8s.V1SecretKeySelector(name='secret_b', key='source_b')
                                ),
                            ),
                        ],
                        env_from=[
                            k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name='configmap_a')),
                            k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(name='configmap_b')),
                            k8s.V1EnvFromSource(secret_ref=k8s.V1SecretEnvSource(name='secret_a')),
                        ],
                        ports=[k8s.V1ContainerPort(name="foo", container_port=1234)],
                        resources=k8s.V1ResourceRequirements(
                            requests={'memory': '100Mi'},
                            limits={
                                'memory': '200Mi',
                            },
                        ),
                    )
                ],
                security_context=k8s.V1PodSecurityContext(
                    fs_group=2000,
                    run_as_user=1000,
                ),
                host_network=True,
                image_pull_secrets=[
                    k8s.V1LocalObjectReference(name="pull_secret_a"),
                    k8s.V1LocalObjectReference(name="pull_secret_b"),
                ],
            ),
        )
    def __init__(
        self,
        image: Optional[str] = None,
        name: Optional[str] = None,
        namespace: Optional[str] = None,
        volume_mounts: Optional[List[Union[k8s.V1VolumeMount, dict]]] = None,
        envs: Optional[Dict[str, str]] = None,
        cmds: Optional[List[str]] = None,
        args: Optional[List[str]] = None,
        labels: Optional[Dict[str, str]] = None,
        node_selectors: Optional[Dict[str, str]] = None,
        ports: Optional[List[Union[k8s.V1ContainerPort, dict]]] = None,
        volumes: Optional[List[Union[k8s.V1Volume, dict]]] = None,
        image_pull_policy: Optional[str] = None,
        restart_policy: Optional[str] = None,
        image_pull_secrets: Optional[str] = None,
        init_containers: Optional[List[k8s.V1Container]] = None,
        service_account_name: Optional[str] = None,
        resources: Optional[Union[k8s.V1ResourceRequirements, dict]] = None,
        annotations: Optional[Dict[str, str]] = None,
        affinity: Optional[dict] = None,
        hostnetwork: bool = False,
        tolerations: Optional[list] = None,
        security_context: Optional[Union[k8s.V1PodSecurityContext,
                                         dict]] = None,
        configmaps: Optional[List[str]] = None,
        dnspolicy: Optional[str] = None,
        schedulername: Optional[str] = None,
        extract_xcom: bool = False,
        priority_class_name: Optional[str] = None,
    ):

        self.pod = k8s.V1Pod()
        self.pod.api_version = 'v1'
        self.pod.kind = 'Pod'

        # Pod Metadata
        self.metadata = k8s.V1ObjectMeta()
        self.metadata.labels = labels
        self.metadata.name = name
        self.metadata.namespace = namespace
        self.metadata.annotations = annotations

        # Pod Container
        self.container = k8s.V1Container(name='base')
        self.container.image = image
        self.container.env = []

        if envs:
            if isinstance(envs, dict):
                for key, val in envs.items():
                    self.container.env.append(k8s.V1EnvVar(name=key,
                                                           value=val))
            elif isinstance(envs, list):
                self.container.env.extend(envs)

        configmaps = configmaps or []
        self.container.env_from = []
        for configmap in configmaps:
            self.container.env_from.append(
                k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(
                    name=configmap)))

        self.container.command = cmds or []
        self.container.args = args or []
        if image_pull_policy:
            self.container.image_pull_policy = image_pull_policy
        self.container.ports = ports or []
        self.container.resources = resources
        self.container.volume_mounts = volume_mounts or []

        # Pod Spec
        self.spec = k8s.V1PodSpec(containers=[])
        self.spec.security_context = security_context
        self.spec.tolerations = tolerations
        if dnspolicy:
            self.spec.dns_policy = dnspolicy
        self.spec.scheduler_name = schedulername
        self.spec.host_network = hostnetwork
        self.spec.affinity = affinity
        self.spec.service_account_name = service_account_name
        self.spec.init_containers = init_containers
        self.spec.volumes = volumes or []
        self.spec.node_selector = node_selectors
        if restart_policy:
            self.spec.restart_policy = restart_policy
        self.spec.priority_class_name = priority_class_name

        self.spec.image_pull_secrets = []

        if image_pull_secrets:
            for image_pull_secret in image_pull_secrets.split(','):
                self.spec.image_pull_secrets.append(
                    k8s.V1LocalObjectReference(name=image_pull_secret))

        # Attach sidecar
        self.extract_xcom = extract_xcom
Exemple #8
0
    def test_pod_template_file_override_in_executor_config(
            self, mock_get_kube_client, mock_run_pod_async):
        current_folder = pathlib.Path(__file__).parent.absolute()
        template_file = str(
            (current_folder / "kubernetes_executor_template_files" /
             "basic_template.yaml").absolute())

        mock_kube_client = mock.patch('kubernetes.client.CoreV1Api',
                                      autospec=True)
        mock_get_kube_client.return_value = mock_kube_client

        with conf_vars({('kubernetes', 'pod_template_file'): ''}):
            executor = self.kubernetes_executor
            executor.start()

            assert executor.event_buffer == {}
            assert executor.task_queue.empty()

            execution_date = datetime.utcnow()

            executor.execute_async(
                key=('dag', 'task', execution_date, 1),
                queue=None,
                command=['airflow', 'tasks', 'run', 'true', 'some_parameter'],
                executor_config={
                    "pod_template_file":
                    template_file,
                    "pod_override":
                    k8s.V1Pod(
                        metadata=k8s.V1ObjectMeta(
                            labels={"release": "stable"}),
                        spec=k8s.V1PodSpec(containers=[
                            k8s.V1Container(name="base", image="airflow:3.6")
                        ], ),
                    ),
                },
            )

            assert not executor.task_queue.empty()
            task = executor.task_queue.get_nowait()
            _, _, expected_executor_config, expected_pod_template_file = task

            # Test that the correct values have been put to queue
            assert expected_executor_config.metadata.labels == {
                'release': 'stable'
            }
            assert expected_pod_template_file == template_file

            self.kubernetes_executor.kube_scheduler.run_next(task)
            mock_run_pod_async.assert_called_once_with(
                k8s.V1Pod(
                    api_version="v1",
                    kind="Pod",
                    metadata=k8s.V1ObjectMeta(
                        name=mock.ANY,
                        namespace="default",
                        annotations={
                            'dag_id': 'dag',
                            'execution_date': execution_date.isoformat(),
                            'task_id': 'task',
                            'try_number': '1',
                        },
                        labels={
                            'airflow-worker':
                            '5',
                            'airflow_version':
                            mock.ANY,
                            'dag_id':
                            'dag',
                            'execution_date':
                            datetime_to_label_safe_datestring(execution_date),
                            'kubernetes_executor':
                            'True',
                            'mylabel':
                            'foo',
                            'release':
                            'stable',
                            'task_id':
                            'task',
                            'try_number':
                            '1',
                        },
                    ),
                    spec=k8s.V1PodSpec(
                        containers=[
                            k8s.V1Container(
                                name="base",
                                image="airflow:3.6",
                                args=[
                                    'airflow', 'tasks', 'run', 'true',
                                    'some_parameter'
                                ],
                                env=[
                                    k8s.V1EnvVar(
                                        name='AIRFLOW_IS_K8S_EXECUTOR_POD',
                                        value='True')
                                ],
                            )
                        ],
                        image_pull_secrets=[
                            k8s.V1LocalObjectReference(name='airflow-registry')
                        ],
                        scheduler_name='default-scheduler',
                        security_context=k8s.V1PodSecurityContext(
                            fs_group=50000, run_as_user=50000),
                    ),
                ))
Exemple #9
0
    def __init__(  # pylint: disable=too-many-arguments,too-many-locals
        self,
        image,
        name=None,
        namespace=None,
        volume_mounts=None,
        envs=None,
        cmds=None,
        args=None,
        labels=None,
        node_selectors=None,
        ports=None,
        volumes=None,
        image_pull_policy='IfNotPresent',
        restart_policy='Never',
        image_pull_secrets=None,
        init_containers=None,
        service_account_name=None,
        resources=None,
        annotations=None,
        affinity=None,
        hostnetwork=False,
        tolerations=None,
        security_context=None,
        configmaps=None,
        dnspolicy=None,
        pod=None,
        extract_xcom=False,
    ):
        self.ud_pod = pod
        self.pod = k8s.V1Pod()
        self.pod.api_version = 'v1'
        self.pod.kind = 'Pod'

        # Pod Metadata
        self.metadata = k8s.V1ObjectMeta()
        self.metadata.labels = labels
        self.metadata.name = name + "-" + str(uuid.uuid4())[:8] if name else None
        self.metadata.namespace = namespace
        self.metadata.annotations = annotations

        # Pod Container
        self.container = k8s.V1Container(name='base')
        self.container.image = image
        self.container.env = []

        if envs:
            if isinstance(envs, dict):
                for key, val in envs.items():
                    self.container.env.append(k8s.V1EnvVar(
                        name=key,
                        value=val
                    ))
            elif isinstance(envs, list):
                self.container.env.extend(envs)

        configmaps = configmaps or []
        self.container.env_from = []
        for configmap in configmaps:
            self.container.env_from.append(k8s.V1EnvFromSource(
                config_map_ref=k8s.V1ConfigMapEnvSource(
                    name=configmap
                )
            ))

        self.container.command = cmds or []
        self.container.args = args or []
        self.container.image_pull_policy = image_pull_policy
        self.container.ports = ports or []
        self.container.resources = resources
        self.container.volume_mounts = volume_mounts or []

        # Pod Spec
        self.spec = k8s.V1PodSpec(containers=[])
        self.spec.security_context = security_context
        self.spec.tolerations = tolerations
        self.spec.dns_policy = dnspolicy
        self.spec.host_network = hostnetwork
        self.spec.affinity = affinity
        self.spec.service_account_name = service_account_name
        self.spec.init_containers = init_containers
        self.spec.volumes = volumes or []
        self.spec.node_selector = node_selectors
        self.spec.restart_policy = restart_policy

        self.spec.image_pull_secrets = []

        if image_pull_secrets:
            for image_pull_secret in image_pull_secrets.split(','):
                self.spec.image_pull_secrets.append(k8s.V1LocalObjectReference(
                    name=image_pull_secret
                ))

        # Attach sidecar
        self.extract_xcom = extract_xcom
Exemple #10
0
        env_from=configmaps,
        name="airflow-test-pod",
        task_id="task",
        affinity=affinity,
        is_delete_operator_pod=True,
        hostnetwork=False,
        tolerations=tolerations,
        init_containers=[init_container],
        priority_class_name="medium",
    )

    # [START howto_operator_k8s_private_image]
    quay_k8s = KubernetesPodOperator(
        namespace="default",
        image="quay.io/apache/bash",
        image_pull_secrets=[k8s.V1LocalObjectReference("testquay")],
        cmds=["bash", "-cx"],
        arguments=["echo", "10", "echo pwd"],
        labels={"foo": "bar"},
        name="airflow-private-image-pod",
        is_delete_operator_pod=True,
        in_cluster=True,
        task_id="task-two",
        get_logs=True,
    )
    # [END howto_operator_k8s_private_image]

    # [START howto_operator_k8s_write_xcom]
    write_xcom = KubernetesPodOperator(
        namespace="default",
        image="alpine",
Exemple #11
0
default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime.utcnow()
}

with DAG('dataload-01',
         default_args=default_args,
         schedule_interval=None,
         max_active_tasks=10,
         max_active_runs=10) as dag:
    load_resources = V1ResourceRequirements(requests={"memory": "18Gi"},
                                            limits={"memory": "18Gi"})
    node_selector = {"loader-node": "true"}
    image_pull_secrets = [k8s.V1LocalObjectReference('falkonry-pull-secret')]

    envs = list()
    load_file = "{{ dag_run.conf['load_file'] }}"
    compact_file = "{{ dag_run.conf['compact_file'] }}"
    task_id = "{{ dag_run.conf['task_id'] }}"

    envs.append(
        k8s.V1EnvVar(name="AWS_SECRET_ACCESS_KEY",
                     value_from=k8s.V1EnvVarSource(
                         secret_key_ref=k8s.V1SecretKeySelector(
                             key="secret-id", name="aws-key-prod"))))
    envs.append(
        k8s.V1EnvVar(name="AWS_DEFAULT_REGION",
                     value_from=k8s.V1EnvVarSource(
                         secret_key_ref=k8s.V1SecretKeySelector(
Exemple #12
0
    def to_v1_kubernetes_pod(self):
        """
        Convert to support k8s V1Pod

        :return: k8s.V1Pod
        """
        import kubernetes.client.models as k8s
        meta = k8s.V1ObjectMeta(
            labels=self.labels,
            name=self.name,
            namespace=self.namespace,
            annotations=self.annotations,
        )
        if self.image_pull_secrets:
            image_pull_secrets = [
                k8s.V1LocalObjectReference(i)
                for i in self.image_pull_secrets.split(",")
            ]
        else:
            image_pull_secrets = []
        spec = k8s.V1PodSpec(
            init_containers=self.init_containers,
            containers=[
                k8s.V1Container(
                    image=self.image,
                    command=self.cmds,
                    env_from=[],
                    name="base",
                    env=[
                        k8s.V1EnvVar(name=key, value=val)
                        for key, val in self.envs.items()
                    ],
                    args=self.args,
                    image_pull_policy=self.image_pull_policy,
                )
            ],
            image_pull_secrets=image_pull_secrets,
            service_account_name=self.service_account_name,
            node_selector=self.node_selectors,
            dns_policy=self.dnspolicy,
            host_network=self.hostnetwork,
            tolerations=self.tolerations,
            affinity=self.affinity,
            security_context=self.security_context,
        )

        pod = k8s.V1Pod(
            spec=spec,
            metadata=meta,
        )
        for configmap_name in self.configmaps:
            env_var = k8s.V1EnvFromSource(
                config_map_ref=k8s.V1ConfigMapEnvSource(name=configmap_name, ))
            pod.spec.containers[0].env_from.append(env_var)

        for port in _extract_ports(self.ports):
            pod = port.attach_to_pod(pod)
        volumes = _extract_volumes(self.volumes)
        for volume in volumes:
            pod = volume.attach_to_pod(pod)
        for volume_mount in _extract_volume_mounts(self.volume_mounts):
            pod = volume_mount.attach_to_pod(pod)
        for secret in self.secrets:
            pod = secret.attach_to_pod(pod)
        for runtime_info in self.pod_runtime_info_envs:
            pod = runtime_info.attach_to_pod(pod)
        pod = _extract_resources(self.resources).attach_to_pod(pod)
        return pod
Exemple #13
0
    def __init__(
        self,
        image=None,
        name=None,
        namespace=None,
        volume_mounts=None,
        envs=None,
        cmds=None,
        args=None,
        labels=None,
        node_selectors=None,
        ports=None,
        volumes=None,
        image_pull_policy=None,
        restart_policy=None,
        image_pull_secrets=None,
        init_containers=None,
        service_account_name=None,
        resources=None,
        annotations=None,
        affinity=None,
        hostnetwork=False,
        tolerations=None,
        security_context=None,
        configmaps=None,
        dnspolicy=None,
        schedulername=None,
        priority_class_name=None,
        pod=None,
        pod_template_file=None,
        extract_xcom=False,
    ):

        if pod_template_file:
            self.ud_pod = self.deserialize_model_file(pod_template_file)
        else:
            self.ud_pod = pod

        self.pod = k8s.V1Pod()
        self.pod.api_version = 'v1'
        self.pod.kind = 'Pod'

        # Pod Metadata
        self.metadata = k8s.V1ObjectMeta()
        self.metadata.labels = labels
        self.metadata.name = name
        self.metadata.namespace = namespace
        self.metadata.annotations = annotations

        # Pod Container
        self.container = k8s.V1Container(name='base')
        self.container.image = image
        self.container.env = []

        if envs:
            if isinstance(envs, dict):
                for key, val in envs.items():
                    self.container.env.append(k8s.V1EnvVar(name=key,
                                                           value=val))
            elif isinstance(envs, list):
                self.container.env.extend(envs)

        configmaps = configmaps or []
        self.container.env_from = []
        for configmap in configmaps:
            self.container.env_from.append(
                k8s.V1EnvFromSource(config_map_ref=k8s.V1ConfigMapEnvSource(
                    name=configmap)))

        self.container.command = cmds or []
        self.container.args = args or []
        self.container.image_pull_policy = image_pull_policy
        self.container.ports = ports or []
        self.container.resources = resources
        self.container.volume_mounts = [
            v.to_k8s_client_obj()
            for v in _extract_volume_mounts(volume_mounts)
        ]

        # Pod Spec
        self.spec = k8s.V1PodSpec(containers=[])
        self.spec.security_context = security_context
        self.spec.tolerations = tolerations
        self.spec.dns_policy = dnspolicy
        self.spec.scheduler_name = schedulername
        self.spec.host_network = hostnetwork
        self.spec.affinity = affinity
        self.spec.service_account_name = service_account_name
        self.spec.init_containers = init_containers
        self.spec.volumes = volumes or []
        self.spec.node_selector = node_selectors
        self.spec.restart_policy = restart_policy
        self.spec.priority_class_name = priority_class_name
        self.spec.image_pull_secrets = []

        if image_pull_secrets:
            for image_pull_secret in image_pull_secrets.split(','):
                self.spec.image_pull_secrets.append(
                    k8s.V1LocalObjectReference(name=image_pull_secret))

        # Attach sidecar
        self.extract_xcom = extract_xcom
    def _to_real_pod(
        self,
        cmds: List[str],
        args: List[str],
        namespace: str,
        name: str,
        image: str,
        envs: Dict[str, str],
        labels: Dict[str, str],
        annotations: Dict[str, str],
        resources: "DbndExtendedResources",
        secrets: List["Secret"],
    ) -> k8s.V1Pod:

        # TODO add yaml template as basis
        BASE_CONTAINER_NAME = "base"
        kc: KubernetesEngineConfig = self
        meta = k8s.V1ObjectMeta(labels=labels,
                                name=name,
                                namespace=namespace,
                                annotations=annotations)
        if kc.image_pull_secrets:
            image_pull_secrets = [
                k8s.V1LocalObjectReference(i)
                for i in kc.image_pull_secrets.split(",")
            ]
        else:
            image_pull_secrets = []
        spec = k8s.V1PodSpec(
            # init_containers=kc.init_containers,
            containers=[
                k8s.V1Container(
                    image=image,
                    command=cmds,
                    env_from=[],
                    name=BASE_CONTAINER_NAME,
                    env=[
                        k8s.V1EnvVar(name=key, value=val)
                        for key, val in envs.items()
                    ],
                    args=args,
                    image_pull_policy=kc.image_pull_policy,
                )
            ],
            image_pull_secrets=image_pull_secrets,
            service_account_name=kc.service_account_name,
            node_selector=kc.node_selectors,
            # dns_policy=kc.dnspolicy,
            host_network=kc.hostnetwork,
            tolerations=kc.tolerations,
            affinity=kc.affinity,
            security_context=kc.security_context,
        )

        k8_pod = k8s.V1Pod(spec=spec, metadata=meta)
        for configmap_name in kc.configmaps:
            env_var = k8s.V1EnvFromSource(
                config_map_ref=k8s.V1ConfigMapEnvSource(name=configmap_name))
            k8_pod.spec.containers[0].env_from.append(env_var)

        volumes = kc.volumes or []
        for volume in volumes:
            k8_pod = volume_shims.attach_to_pod(k8_pod, volume)

        mounts = kc.volume_mounts or []
        for volume_mount in mounts:
            k8_pod = attach_volume_mount(k8_pod, volume_mount)

        secret: Secret
        for secret in secrets:
            if AIRFLOW_ABOVE_10:
                k8_pod = secret.attach_to_pod(k8_pod)
            else:
                k8_pod = attach_to_pod(secret, k8_pod)

        k8_pod = resources.attach_to_pod(k8_pod)
        return k8_pod