Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kubernetes Executor Config Volumes Break Airflow UI #9860

Closed
marcusianlevine opened this issue Jul 16, 2020 · 19 comments
Closed

Kubernetes Executor Config Volumes Break Airflow UI #9860

marcusianlevine opened this issue Jul 16, 2020 · 19 comments
Labels
kind:bug This is a clearly a bug provider:cncf-kubernetes Kubernetes provider related issues

Comments

@marcusianlevine
Copy link
Contributor

marcusianlevine commented Jul 16, 2020

Apache Airflow version: 1.10.11

Kubernetes version (if you are using kubernetes) (use kubectl version): 1.16.9

Environment:

  • Cloud provider or hardware configuration: AWS
  • OS (e.g. from /etc/os-release): Ubuntu
  • Kernel (e.g. uname -a): 5.3.0-1019-aws #21~18.04.1-Ubuntu SMP x86_64 GNU/Linux
  • Install tools: Docker image with Airflow pip installed via pipenv

What happened:

After adding a specification for Volume and VolumeMount objects to the executor_config for KubernetesExecutor, the Airflow UI explodes with the following message when I try to clear the task or do any other action on it:

TypeError: Object of type VolumeMount is not JSON serializable

Once this error is thrown after clearing a task with the volume-containing executor_config, that DAG no longer loads at all in the Airflow UI

What you expected to happen:

The KubernetesExecutor dynamically adds my specific volumes to the Pod spec

How to reproduce it:
In an Airflow environment configured to use the KubernetesExecutor, pass a spec of the following form to the executor_config:

from airflow.kubernetes.volume_mount import VolumeMount
from airflow.kubernetes.volume import Volume

my_volume = Volume(
    name='my-pvc',
    configs={
        'persistentVolumeClaim': {'claimName': 'my-pvc'}
    }
)
my_volume_mount = VolumeMount(
    name='my-pvc', mount_path='/example/mount/path',
    sub_path=None, read_only=False
)

executor_config = {
    'KubernetesExecutor': {'volumes': [my_volume], 'volume_mounts': [my_volume_mount]}
}

# I didn't bother defining an example DAG, this should cause an issue with any operator
my_task = BashOperator(task_id='example-task', executor_config=executor_config, dag=dag)

Once such a task is defined, click the Clear button from the UI and it will throw the TypeError above

Anything else we need to know:

Obviously the volume mounts specified via airflow.cfg work, but we'd like to be able to dynamically add volumes to tasks that need them without having all of our jobs mount volumes unnecessarily

@marcusianlevine marcusianlevine added the kind:bug This is a clearly a bug label Jul 16, 2020
@boring-cyborg
Copy link

boring-cyborg bot commented Jul 16, 2020

Thanks for opening your first issue here! Be sure to follow the issue template!

@kaxil kaxil added this to the Airflow 1.10.12 milestone Jul 16, 2020
@kaxil kaxil added the k8s label Jul 16, 2020
@aneesh-joseph
Copy link
Contributor

aneesh-joseph commented Jul 17, 2020

It should probably work if you pass in kubernetes.client.models.V1VolumeMount and kubernetes.client.models.V1Volume instead
of VolumeMount and Volume . I think we now have greater control on how the worker pods are generated - https://github.com/apache/airflow/blob/1.10.11/airflow/kubernetes/pod_generator.py#L111-L170

@kaxil , hope this flexibility will be available in 1.10.12 as well :)

@dimberman
Copy link
Contributor

Fixed :) #10084

@appunni-m
Copy link

Hey I am using kubernetes.client.models.V1VolumeMount

I am using airflow 1.10.12 . This was broken in scheduler completely in 1.10.10 but it's not anymore there but,

My dag is failing with this error now

    import pandas
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 674, in exec_module
  File "<frozen importlib._bootstrap_external>", line 786, in get_code
  File "<frozen importlib._bootstrap_external>", line 503, in _code_to_bytecode
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/utils/timeout.py", line 43, in handle_timeout
    raise AirflowTaskTimeout(self.error_message)
airflow.exceptions.AirflowTaskTimeout: Timeout, PID: 1
Traceback (most recent call last):
  File "/home/airflow/.local/bin/airflow", line 37, in <module>
    args.func(args)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/utils/cli.py", line 76, in wrapper
    return f(*args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/bin/cli.py", line 538, in run
    dag = get_dag(args)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/bin/cli.py", line 164, in get_dag
    'parse.'.format(args.dag_id))
airflow.exceptions.AirflowException: dag_id could not be found: 

And when I goto Graph views I get this error as well

Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/decorators.py", line 121, in wrapper
    return f(self, *args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/flask_appbuilder/security/decorators.py", line 109, in wraps
    return f(self, *args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/decorators.py", line 92, in view_func
    return f(*args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/decorators.py", line 56, in wrapper
    return f(*args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/utils/db.py", line 74, in wrapper
    return func(*args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/views.py", line 1666, in graph
    show_external_logs=bool(external_logs))
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/views.py", line 202, in render_template
    **kwargs
  File "/home/airflow/.local/lib/python3.6/site-packages/flask_appbuilder/baseviews.py", line 281, in render_template
    template, **dict(list(kwargs.items()) + list(self.extra_args.items()))
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/templating.py", line 140, in render_template
    ctx.app,
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/templating.py", line 120, in _render
    rv = template.render(context)
  File "/home/airflow/.local/lib/python3.6/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/home/airflow/.local/lib/python3.6/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/home/airflow/.local/lib/python3.6/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/templates/airflow/graph.html", line 18, in top-level template code
    {% extends "airflow/dag.html" %}
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/templates/airflow/dag.html", line 19, in top-level template code
    {% extends base_template %}
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/templates/airflow/master.html", line 19, in top-level template code
    {% extends 'appbuilder/baselayout.html' %}
  File "/home/airflow/.local/lib/python3.6/site-packages/flask_appbuilder/templates/appbuilder/baselayout.html", line 2, in top-level template code
    {% import 'appbuilder/baselib.html' as baselib %}
  File "/home/airflow/.local/lib/python3.6/site-packages/flask_appbuilder/templates/appbuilder/init.html", line 60, in top-level template code
    {% block tail %}
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/www_rbac/templates/airflow/graph.html", line 116, in block "tail"
    var task_instances = {{ task_instances|tojson }};
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 376, in tojson_filter
    return Markup(htmlsafe_dumps(obj, **kwargs))
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 290, in htmlsafe_dumps
    dumps(obj, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 211, in dumps
    rv = _json.dumps(obj, **kwargs)
  File "/usr/local/lib/python3.6/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/local/lib/python3.6/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/lib/python3.6/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/airflow/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 100, in default
    return _json.JSONEncoder.default(self, o)
  File "/usr/local/lib/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'V1VolumeMount' is not JSON serializable

@dimberman
Copy link
Contributor

@appunni-dishq can you please post the DAG you're using?

@appunni-m
Copy link

appunni-m commented Sep 22, 2020

from airflow import DAG
from airflow.contrib.operators.spark_submit_operator import SparkSubmitOperator
from datetime import datetime, timedelta
from airflow.models import Variable
from airflow.contrib.operators.kubernetes_pod_operator import \
    KubernetesPodOperator
from airflow.hooks.base_hook import BaseHook
from airflow.contrib.operators.slack_webhook_operator import \
    SlackWebhookOperator
from airflow.contrib.kubernetes.secret import Secret
from kubernetes.client.models import V1VolumeMount as VolumeMount, \
    V1Volume as Volume


conf = {**}
conf["spark.kubernetes.authenticate.submission.oauthToken"] = \
    Variable.get("TOKEN")
conf["spark.kubernetes.authenticate.submission.caCertFile"] = \
    "/mnt/secrets/ca.crt"

gke_crt_volume = Volume(
    name="spark-crt",
    secret={
        "secretName": "spark-cert"
    }
)

gke_crt_volume_mount = VolumeMount(
    name="spark-crt",
    mount_path="/mnt/secrets",
    read_only=True
)

executor_config = {
    "KubernetesExecutor": {
        "request_memory": "500Mi",
        "limit_memory": "500Mi",
        "limit_cpu": "200m",
        "request_cpu": "200m",
        "node_selectors": {
            "env": "production"
        },
        volumes=[gke_crt_volume],
        volume_mounts=[gke_crt_volume_mount]
    }
}
default_args = {
    'owner': 'appunni',
    'depends_on_past': False,
    'email_on_failure': False,
    'email_on_retry': False,
    'start_date': datetime(2019, 7, 17),
    'retries': 2,
    'retry_delay': timedelta(seconds=60),
    'on_failure_callback': task_fail_slack_alert,
    'on_success_callback': on_success_slack_alert,
    'schedule_interval': None,
    "executor_config": executor_config,
    'pool': 'engineering'
}

dag = DAG(dag_id='spark_tasks',  catchup=False,
          default_args=default_args, schedule_interval=None)

SparkSubmitOperator(
        task_id=name.replace("-", "_"),
        application="local:///main/{file}".format(file=file),
        name=name.replace("_", "-"),
        dag=_dag,
        env_vars=envs,
        conf=conf,
        executor_config=executor_config,
        conn_id=conn,
        jars="local:///spark/app-assembly.jar",
    )

This is what it roughly looks like. I tried to include all details as much as possible let me know if you need more @dimberman

@dimberman
Copy link
Contributor

Hi @appunni-dishq

I think you defined your executor_config incorrectly.

The entire thing is a dict, so you need to write it like this:

executor_config = {
    "KubernetesExecutor": {
        "request_memory": "500Mi",
        "limit_memory": "500Mi",
        "limit_cpu": "200m",
        "request_cpu": "200m",
        "node_selectors": {"env": "production"},
        "volumes": [gke_crt_volume],
        "volume_mounts": [gke_crt_volume_mount],
    }
}

instead of

executor_config = {
    "KubernetesExecutor": {
        "request_memory": "500Mi",
        "limit_memory": "500Mi",
        "limit_cpu": "200m",
        "request_cpu": "200m",
        "node_selectors": {
            "env": "production"
        },
        volumes=[gke_crt_volume],
        volume_mounts=[gke_crt_volume_mount]
    }
}

@appunni-m
Copy link

Sorry I wrote it wrong here actually it was like this

executor_config = {
    "KubernetesExecutor": {
        "request_memory": "500Mi",
        "limit_memory": "500Mi",
        "limit_cpu": "200m",
        "request_cpu": "200m",
        "node_selectors": {"env": "production"}
    }
}

executor_config = {
    "KubernetesExecutor": dict(
        **executor_config["KubernetesExecutor"],
        volumes=[gke_crt_volume],
        volume_mounts=[gke_crt_volume_mount]
    )
}

@appunni-m
Copy link

It's definitely not a syntax issue @dimberman

@dimberman
Copy link
Contributor

@appunni-dishq

I started airflow with the following DAG using the 1.10.12 release:

from airflow import DAG
from airflow.contrib.operators.spark_submit_operator import SparkSubmitOperator
from datetime import datetime, timedelta
from airflow.models import Variable
from airflow.contrib.operators.kubernetes_pod_operator import \
    KubernetesPodOperator
from airflow.hooks.base_hook import BaseHook
from airflow.contrib.operators.slack_webhook_operator import \
    SlackWebhookOperator
from airflow.contrib.kubernetes.secret import Secret
from kubernetes.client.models import V1VolumeMount as VolumeMount, \
    V1Volume as Volume


conf = {}
# conf["spark.kubernetes.authenticate.submission.oauthToken"] = \
#     Variable.get("TOKEN")
# conf["spark.kubernetes.authenticate.submission.caCertFile"] = \
#     "/mnt/secrets/ca.crt"

gke_crt_volume = Volume(
    name="spark-crt",
    secret={
        "secretName": "spark-cert"
    }
)

gke_crt_volume_mount = VolumeMount(
    name="spark-crt",
    mount_path="/mnt/secrets",
    read_only=True
)

executor_config = {
    "KubernetesExecutor": {
        "request_memory": "500Mi",
        "limit_memory": "500Mi",
        "limit_cpu": "200m",
        "request_cpu": "200m",
        "node_selectors": {"env": "production"}
    }
}

executor_config = {
    "KubernetesExecutor": dict(
        **executor_config["KubernetesExecutor"],
        volumes=[gke_crt_volume],
        volume_mounts=[gke_crt_volume_mount]
    )
}

default_args = {
    'owner': 'appunni',
    'depends_on_past': False,
    'email_on_failure': False,
    'email_on_retry': False,
    'start_date': datetime(2019, 7, 17),
    'retries': 2,
    'retry_delay': timedelta(seconds=60),
    'schedule_interval': None,
    "executor_config": executor_config,
    'pool': 'engineering'
}

dag = DAG(dag_id='spark_tasks',  catchup=False,
          default_args=default_args, schedule_interval=None)

name = "my-task"
SparkSubmitOperator(
        task_id=name.replace("-", "_"),
        application="local:///main/{file}",
        name=name.replace("_", "-"),
        dag=dag,
        conf=conf,
        executor_config=executor_config,
        jars="local:///spark/app-assembly.jar",
    )

I see it rendered on the UI with no issue

Screen Shot 2020-09-22 at 10 47 22 AM

Is there a difference between my DAG and yours? Can you try changing the DAG name and re-rendering? Can you also show what the error looks like on the UI?

@appunni-m
Copy link

Enable the dag and try again

@appunni-m
Copy link

appunni-m commented Sep 22, 2020

I had the dag previously before I changed version, I will change dag name and try again as there is a chance old dag id might be the issue

@appunni-m
Copy link

appunni-m commented Sep 22, 2020

image

I renamed the dag

This is how it looks like, I started the dag after enabling it and then refreshed and that's when it happens @dimberman

@dimberman
Copy link
Contributor

@appunni-dishq can you try the DAG I posted and confirm that it causes the same issue? (sorry for the back-and-forth, I'm genuinely confused why I can't replicate this)

@appunni-m
Copy link

appunni-m commented Sep 22, 2020

Hey I enabled it and ran the task, and only after beginning first run the error came. I am using Kubernetes to deploy airflow and this is the docker I am using may be that is the different you can tell what I am doing wrong

FROM apache/airflow:1.10.12-python3.6

USER root

RUN buildDeps="gcc python3-dev"  \
   && apt-get update \
   && apt-get install -y $buildDeps --no-install-recommends

RUN pip3 install pyspark==2.4.3 py4j==0.10.7 --no-cache

RUN pip3 install apache-airflow[postgres,crypto,gcp,google_auth,kubernetes,slack,jdbc,password,aws]==1.10.12 --no-cache

RUN apt-get purge -y --auto-remove gcc python3-dev

USER airflow

RUN curl -O https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz \
    && tar zxvf openjdk-11.0.2_linux-x64_bin.tar.gz \
    && rm openjdk-11.0.2_linux-x64_bin.tar.gz

ENV JAVA_HOME=/opt/airflow/jdk-11.0.2

RUN curl -O https://archive.apache.org/dist/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz \
    && tar -xvf spark-2.4.3-bin-hadoop2.7.tgz \
    && rm spark-2.4.3-bin-hadoop2.7.tgz

ENV PYSPARK_PYTHON=/usr/local/bin/python
ENV SPARK_HOME=/opt/airflow/spark-2.4.3-bin-hadoop2.7/
ENV PATH=$PATH:/opt/airflow/dags/
ENV PYTHONPATH=/opt/airflow/dags/

@dimberman

@appunni-m
Copy link

May be it's serialization which causes this ?

@appunni-m
Copy link

appunni-m commented Sep 22, 2020

Hi @dimberman intial error I talked about

    import pandas
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 674, in exec_module
  File "<frozen importlib._bootstrap_external>", line 786, in get_code
  File "<frozen importlib._bootstrap_external>", line 503, in _code_to_bytecode
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/utils/timeout.py", line 43, in handle_timeout
    raise AirflowTaskTimeout(self.error_message)
airflow.exceptions.AirflowTaskTimeout: Timeout, PID: 1
Traceback (most recent call last):
  File "/home/airflow/.local/bin/airflow", line 37, in <module>
    args.func(args)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/utils/cli.py", line 76, in wrapper
    return f(*args, **kwargs)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/bin/cli.py", line 538, in run
    dag = get_dag(args)
  File "/home/airflow/.local/lib/python3.6/site-packages/airflow/bin/cli.py", line 164, in get_dag
    'parse.'.format(args.dag_id))
airflow.exceptions.AirflowException: dag_id could not be found: 

This was caused by multiple instance of dags because of the way I hosted my volume, Same dags repeating causes more load on the executor which needs more cpu but times out which I saw that kubernetes_executor using more cpu since upgrade to 1.10.12 from 1.10.10, may be it's worth checking this performance regression out.

The serialization error as I suspect is some remaining code in Airflow Web from 1.10.11 you guys were not aware of which tries to do serialization some how if a serialized dag is already found. This was happening once dag starts running and a task starts. So I guess it has something to do with the specifics. I will let you know more as soon as I know. Please ping me if you need more help to Debug this. I have the helm chart which I use which I can share.

@nirousseau
Copy link

Hello,

I am also facing the issue described above (UI Breaks).

Airflow 1.10.12 with KubernetesExecutor.

here is my dag :

# -*- coding: utf-8 -*-

"""
### Tutorial Documentation
Documentation that goes along with the Airflow tutorial located
[here](https://airflow.apache.org/tutorial.html)
"""
# [START tutorial]
# [START import_module]
from datetime import timedelta

from helpers.k8s_executor import get_config as executor_config

from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.utils.dates import days_ago

# [END import_module]

# [START default_args]
# These args will get passed on to each operator
# You can override them on a per-task basis during operator initialization
default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': days_ago(2),
    'email': ['airflow@example.com'],
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
    # 'queue': 'bash_queue',
    # 'pool': 'backfill',
    # 'priority_weight': 10,
    # 'end_date': datetime(2016, 1, 1),
    # 'wait_for_downstream': False,
    # 'dag': dag,
    # 'sla': timedelta(hours=2),
    # 'execution_timeout': timedelta(seconds=300),
    # 'on_failure_callback': some_function,
    # 'on_success_callback': some_other_function,
    # 'on_retry_callback': another_function,
    # 'sla_miss_callback': yet_another_function,
    # 'trigger_rule': 'all_success'
}
# [END default_args]

# [START instantiate_dag]
with DAG(
        'k8s_tutorial',
        default_args=default_args,
        description='A simple tutorial DAG on K8S',
        schedule_interval=timedelta(days=1),
) as dag:
    # [END instantiate_dag]

    # t1, t2 and t3 are examples of tasks created by instantiating operators
    # [START basic_task]
    t1 = BashOperator(
        task_id='print_date',
        bash_command='date',
        executor_config=executor_config()
    )

    t2 = BashOperator(
        task_id='sleep',
        depends_on_past=False,
        bash_command='sleep 300',
        retries=3,
        executor_config=executor_config()
    )
    # [END basic_task]

    # [START documentation]
    dag.doc_md = __doc__

    t1.doc_md = """\
    #### Task Documentation
    You can document your task using the attributes `doc_md` (markdown),
    `doc` (plain text), `doc_rst`, `doc_json`, `doc_yaml` which gets
    rendered in the UI's Task Instance Details page.
    ![img](http://montcs.bloomu.edu/~bobmon/Semesters/2012-01/491/import%20soul.png)
    """
    # [END documentation]

    t1 >> t2

# [END tutorial]

here is the helper included that triggers the UI crash :

def get_config():
    """
    Override Executor Configuration for K8S
    :return:
    """
    from kubernetes.client import models as k8s

    return {
        "KubernetesExecutor": {
            "request_cpu": "200m",
            "limit_cpu": "200m",
            "request_memory": "128Mi",
            "limit_memory": "128Mi",
            "labels": {
                "app": "airflow",
                "airflow-postgresql-client": "true"
            },
            "security_context": k8s.V1PodSecurityContext(
                run_as_user=1000,
                run_as_group=1000
            ),
            "init_containers": [
                k8s.V1Container(
                    name="git-sync-clone",
                    image="my_private_registry/k8s/images/git:latest",
                    command=[
                        "/scripts/git-clone.sh"
                    ],
                    args=[
                        "MY_GIT_REPO",
                        "master",
                        "/git",
                        "MY_GIT_HOST",
                        "443",
                        "id_rsa"
                    ],
                    resources=k8s.V1ResourceRequirements(
                        requests={"cpu": "100m", "memory": "64Mi"},
                        limits={"cpu": "100m", "memory": "64Mi"}
                    ),
                    security_context=k8s.V1PodSecurityContext(
                        run_as_user=1000,
                        run_as_group=1000
                    ),
                    volume_mounts=[
                        k8s.V1VolumeMount(
                            mount_path="/git",
                            name="airflow-dags",
                            read_only=False
                        ),
                        k8s.V1VolumeMount(
                            mount_path="/scripts",
                            name="git-clone",
                            read_only=True
                        )
                    ]
                )
            ],
            "volumes": [
                k8s.V1Volume(
                    name="git-clone",
                    config_map=k8s.V1ConfigMapVolumeSource(
                        default_mode=0o777,
                        name="sandbox-airflow-scripts-git"
                    )
                ),
                k8s.V1Volume(
                    name="airflow-dags",
                    empty_dir=k8s.V1EmptyDirVolumeSource()
                ),
                k8s.V1Volume(
                    name="airflow-logs",
                    empty_dir=k8s.V1EmptyDirVolumeSource()
                )
            ]
        }
    }

Crash traceback :


                          ____/ (  (    )   )  \___
                         /( (  (  )   _    ))  )   )\
                       ((     (   )(    )  )   (   )  )
                     ((/  ( _(   )   (   _) ) (  () )  )
                    ( (  ( (_)   ((    (   )  .((_ ) .  )_
                   ( (  )    (      (  )    )   ) . ) (   )
                  (  (   (  (   ) (  _  ( _) ).  ) . ) ) ( )
                  ( (  (   ) (  )   (  ))     ) _)(   )  )  )
                 ( (  ( \ ) (    (_  ( ) ( )  )   ) )  )) ( )
                  (  (   (  (   (_ ( ) ( _    )  ) (  )  )   )
                 ( (  ( (  (  )     (_  )  ) )  _)   ) _( ( )
                  ((  (   )(    (     _    )   _) _(_ (  (_ )
                   (_((__(_(__(( ( ( |  ) ) ) )_))__))_)___)
                   ((__)        \\||lll|l||///          \_))
                            (   /(/ (  )  ) )\   )
                          (    ( ( ( | | ) ) )\   )
                           (   /(| / ( )) ) ) )) )
                         (     ( ((((_(|)_)))))     )
                          (      ||\(|(|)|/||     )
                        (        |(||(||)||||        )
                          (     //|/l|||)|\\ \     )
                        (/ / //  /|//||||\\  \ \  \ _)
-------------------------------------------------------------------------------
Node: sandbox-airflow-web-69c87579cf-p94wg
-------------------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.7/site-packages/flask_admin/base.py", line 69, in inner
    return self._run_view(f, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/flask_admin/base.py", line 368, in _run_view
    return fn(self, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/flask_login/utils.py", line 258, in decorated_view
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/airflow/www/utils.py", line 384, in view_func
    return f(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/airflow/www/utils.py", line 290, in wrapper
    return f(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/airflow/utils/db.py", line 74, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/airflow/www/views.py", line 1779, in graph
    show_external_logs=bool(external_logs))
  File "/usr/local/lib/python3.7/site-packages/airflow/www/views.py", line 405, in render
    return super(AirflowViewMixin, self).render(template, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/flask_admin/base.py", line 308, in render
    return render_template(template, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/flask/templating.py", line 140, in render_template
    ctx.app,
  File "/usr/local/lib/python3.7/site-packages/flask/templating.py", line 120, in _render
    rv = template.render(context)
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.7/site-packages/airflow/www/templates/airflow/graph.html", line 22, in top-level template code
    {% import 'admin/static.html' as admin_static with context %}
  File "/usr/local/lib/python3.7/site-packages/airflow/www/templates/airflow/dag.html", line 21, in top-level template code
    {% import 'admin/lib.html' as lib with context %}
  File "/usr/local/lib/python3.7/site-packages/airflow/www/templates/airflow/master.html", line 20, in top-level template code
    {% extends "admin/master.html" %}
  File "/usr/local/lib/python3.7/site-packages/airflow/www/templates/admin/master.html", line 20, in top-level template code
    {% extends 'admin/base.html' %}
  File "/usr/local/lib/python3.7/site-packages/flask_admin/templates/bootstrap3/admin/base.html", line 95, in top-level template code
    {% block tail %}
  File "/usr/local/lib/python3.7/site-packages/airflow/www/templates/airflow/graph.html", line 115, in block "tail"
    var task_instances = {{ task_instances|tojson }};
  File "/usr/local/lib/python3.7/site-packages/flask/json/__init__.py", line 376, in tojson_filter
    return Markup(htmlsafe_dumps(obj, **kwargs))
  File "/usr/local/lib/python3.7/site-packages/flask/json/__init__.py", line 290, in htmlsafe_dumps
    dumps(obj, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/flask/json/__init__.py", line 211, in dumps
    rv = _json.dumps(obj, **kwargs)
  File "/usr/local/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/local/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/lib/python3.7/site-packages/flask/json/__init__.py", line 100, in default
    return _json.JSONEncoder.default(self, o)
  File "/usr/local/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type V1Container is not JSON serializable

@ajbosco
Copy link
Contributor

ajbosco commented Dec 2, 2020

We're hitting this same error. As @appunni-dishq pointed out above, it only happens in the graph UI when the DAG is enabled and has at least one DAG run.

Any suggestions on a workaround, @dimberman ?

@ashb ashb added the provider:cncf-kubernetes Kubernetes provider related issues label Feb 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug This is a clearly a bug provider:cncf-kubernetes Kubernetes provider related issues
Projects
None yet
Development

No branches or pull requests

8 participants