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

feat(helm): Helm template for Celery beat (for reporting and alerting) #13116

Merged
merged 14 commits into from
Feb 16, 2021
Merged

feat(helm): Helm template for Celery beat (for reporting and alerting) #13116

merged 14 commits into from
Feb 16, 2021

Conversation

Yann-J
Copy link
Contributor

@Yann-J Yann-J commented Feb 14, 2021

SUMMARY

This PR adds an optional kubernetes Deployment to run the Celery beat, which is needed in order to trigger the scheduled alerts and reports (as per the excellent unpublished guide at https://github.com/apache/superset/blob/4fa3b6c7185629b87c27fc2c0e5435d458f7b73d/docs/src/pages/docs/installation/email_reports.mdx).

It is off by default, and needs to be enabled with supersetBeat.enabled.

The new pod is defined pretty much exactly like the worker pod except that:

  • replicas is always 1, since this needs to be a singleton
  • The command is different

Note that for the chart to be able to execute reports, we still need to check all the other boxes, in particular:

  • Make sure one webdriver is installed - for this, the commands mentioned in the guide above can be added as a custom supersetWorker.command (this is only needed in the worker container) with the existing chart, with something like this in your values.yaml:
supersetWorker:
  command:
    - /bin/sh
    - -c
    - |
      # Install chrome webdriver
      # See https://github.com/apache/superset/blob/4fa3b6c7185629b87c27fc2c0e5435d458f7b73d/docs/src/pages/docs/installation/email_reports.mdx
      apt update
      wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
      apt install -y --no-install-recommends ./google-chrome-stable_current_amd64.deb
      wget https://chromedriver.storage.googleapis.com/88.0.4324.96/chromedriver_linux64.zip
      unzip chromedriver_linux64.zip
      chmod +x chromedriver
      mv chromedriver /usr/bin
      apt autoremove -yqq --purge
      apt clean
      rm -f google-chrome-stable_current_amd64.deb chromedriver_linux64.zip

      # Run
      . {{ .Values.configMountPath }}/superset_bootstrap.sh; celery --app=superset.tasks.celery_app:app worker
  • Perform all the required Celery setup by overriding the superset_config.py. This is now possible with the latest chart from master by specifying overrides in your values.yaml such as:
configOverrides:
  celery_conf: |
    from celery.schedules import crontab

    class CeleryConfig(object):
      BROKER_URL = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
      CELERY_IMPORTS = ('superset.sql_lab', )
      CELERY_RESULT_BACKEND = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
      CELERY_ANNOTATIONS = {'tasks.add': {'rate_limit': '10/s'}}
      CELERY_IMPORTS = ('superset.sql_lab', "superset.tasks", "superset.tasks.thumbnails", )
      CELERY_ANNOTATIONS = {
          'sql_lab.get_sql_results': {
              'rate_limit': '100/s',
          },
          'email_reports.send': {
              'rate_limit': '1/s',
              'time_limit': 600,
              'soft_time_limit': 600,
              'ignore_result': True,
          },
      }
      CELERYBEAT_SCHEDULE = {
          'reports.scheduler': {
              'task': 'reports.scheduler',
              'schedule': crontab(minute='*', hour='*'),
          },
          'reports.prune_log': {
              'task': 'reports.prune_log',
              'schedule': crontab(minute=0, hour=0),
          },
          'cache-warmup-hourly': {
              'task': 'cache-warmup',
              'schedule': crontab(minute='*/30', hour='*'),
              'kwargs': {
                  'strategy_name': 'top_n_dashboards',
                  'top_n': 10,
                  'since': '7 days ago',
              },
          }
      }

    CELERY_CONFIG = CeleryConfig
  reports: |
    EMAIL_PAGE_RENDER_WAIT = 60
    WEBDRIVER_BASEURL = "http://superset:8088/"
    WEBDRIVER_BASEURL_USER_FRIENDLY = "https://superset.qa.oneacrefund.org/"
    WEBDRIVER_TYPE= "chrome"
    WEBDRIVER_OPTION_ARGS = [
        "--force-device-scale-factor=2.0",
        "--high-dpi-support=2.0",
        "--headless",
        "--disable-gpu",
        "--disable-dev-shm-usage",
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-extensions",
    ]
  feature_flags: |
    import ast

    FEATURE_FLAGS = {
        "ALERT_REPORTS": True,
    }
    EMAIL_NOTIFICATIONS = ast.literal_eval(os.getenv("EMAIL_NOTIFICATIONS", "True"))
    SMTP_HOST = os.getenv("SMTP_HOST","localhost")
    SMTP_STARTTLS = ast.literal_eval(os.getenv("SMTP_STARTTLS", "True"))
    SMTP_SSL = ast.literal_eval(os.getenv("SMTP_SSL", "False"))
    SMTP_USER = os.getenv("SMTP_USER","superset")
    SMTP_PORT = os.getenv("SMTP_PORT",25)
    SMTP_PASSWORD = os.getenv("SMTP_PASSWORD","superset")
    SMTP_MAIL_FROM = os.getenv("SMTP_MAIL_FROM","[email protected]")

    SLACK_API_TOKEN = os.getenv("SLACK_API_TOKEN",None)

extraSecretEnv:
  SLACK_API_TOKEN: xoxb-...
  SMTP_PASSWORD: ...

extraEnv:
  SMTP_HOST: smtp.gmail.com
  SMTP_USER: ...
  SMTP_PORT: "587"
  SMTP_MAIL_FROM: ...

The above would probably need to be added to the doc together with PR #13104 for the Kubernetes case.

TEST PLAN

  • Update values.yaml with supersetBeat.enabled: true and upgrade your chart release
  • See your new pod running!

ADDITIONAL INFORMATION

Copy link
Contributor

@vnourdin vnourdin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your PR! I said on Slack that I would open one, but as our templates aren't up-to-date with those of master it took me some time 😅

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "superset.fullname" . }}-beat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially named the pods the same way you did, but some colleague said that beat is kind of generic, and it would be better naming it {{ template "superset.fullname" . }}-celerybeat.
I let you judge 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that makes sense...

Comment on lines +35 to +39
checksum/superset_config.py: {{ include "superset-config" . | sha256sum }}
checksum/connections: {{ .Values.supersetNode.connections | toYaml | sha256sum }}
checksum/extraConfigs: {{ .Values.extraConfigs | toYaml | sha256sum }}
checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }}
checksum/configOverrides: {{ .Values.configOverrides | toYaml | sha256sum }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[K8S newbie] What's the point of those annotations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since those values will change on any content updates of the source values, this will force a patch of the Deployment, and a restart of the pods whenever we publish an update to these (otherwise, updates to a ConfigMap does not automatically force the pods mounting them to restart).

helm/superset/values.yaml Outdated Show resolved Hide resolved
@vnourdin
Copy link
Contributor

Also, we need to add documentation on the K8S part about this celery beat, I think this PR is the good one to do it!
Otherwise, we can add it in the other one that document Alerts&Reports, but seem more atomic to do it here.
I can help on this, I'm on the Superset's Slack if you want to reach me 😉

Co-authored-by: Valentin Nourdin <[email protected]>
@Yann-J
Copy link
Contributor Author

Yann-J commented Feb 16, 2021

Also, we need to add documentation on the K8S part about this celery beat, I think this PR is the good one to do it!
Otherwise, we can add it in the other one that document Alerts&Reports, but seem more atomic to do it here.
I can help on this, I'm on the Superset's Slack if you want to reach me 😉

Yes, I agree this deserves a documentation update.

Another thing I've been wondering about is Celery Flower... I'm a total noob about Celery / Flask... and in fact Python in general, so I'm not 100% sure what flower does... but I have the impression we might need one pod for it as well?

@vnourdin
Copy link
Contributor

Flower is an interface that allow us to monitor celery workers and see which worker run which task!

helm/superset/values.yaml Outdated Show resolved Hide resolved
Co-authored-by: Valentin Nourdin <[email protected]>
@Yann-J
Copy link
Contributor Author

Yann-J commented Feb 16, 2021

Flower is an interface that allow us to monitor celery workers and see which worker run which task!

OK. So from a Helm point of view this would mean that:

  • We would also want a service to expose its port(s)
  • Potentially we'll want to scale it - and potentially separately from the main pods

@vnourdin
Copy link
Contributor

  • Yes, we want to expose its port, it's done on our instance, I'll check what differs from master charts.
  • I don't know if this instance must be a singleton or not, should check.

command:
- "/bin/sh"
- "-c"
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; celery beat --app=superset.tasks.celery_app:app --pidfile /tmp/celerybeat.pid --schedule /tmp/celerybeat-schedule"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no trace of flower in the master chart in fact 😮 To add it, we should do something really similar to this PR, plus a service dedicated to flower.
I think this is out of the scope of this PR, my team will switch back to the master charts, and we will open PR to add what's missing, but not sure when this will be. 😕
If you have some time to do it, I would gladly help!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, different PR... and probably not high prio...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, but flower by default does not support auth, and it exposes dangerous functionality and sensitive info. May be a bit out of scope

helm/superset/templates/deployment-beat.yaml Outdated Show resolved Hide resolved
helm/superset/templates/deployment-beat.yaml Outdated Show resolved Hide resolved
helm/superset/templates/deployment-beat.yaml Outdated Show resolved Hide resolved
helm/superset/templates/deployment-beat.yaml Outdated Show resolved Hide resolved
helm/superset/templates/deployment-beat.yaml Outdated Show resolved Hide resolved
@Yann-J
Copy link
Contributor Author

Yann-J commented Feb 16, 2021

Sorry, I forgot to update the template to reflect the supersetCeleryBeat name change!

@vnourdin
Copy link
Contributor

No problem, Github suggestions isn't perfect 😅
Sorry for flooding the PR.

Copy link
Member

@dpgaspar dpgaspar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the suggestion on how to add the webdriver is not ideal. Calling @craig-rueda here for some additional thoughts

command:
- "/bin/sh"
- "-c"
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; celery beat --app=superset.tasks.celery_app:app --pidfile /tmp/celerybeat.pid --schedule /tmp/celerybeat-schedule"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, but flower by default does not support auth, and it exposes dangerous functionality and sensitive info. May be a bit out of scope

@Yann-J
Copy link
Contributor Author

Yann-J commented Feb 16, 2021

LGTM, the suggestion on how to add the webdriver is not ideal. Calling @craig-rueda here for some additional thoughts

Yes I definitely agree... installing stuff at runtime isn't a really good practice since it creates extra risks and often requires running as root. The best would really be to have a pre-built image for it, but I'm not aware of any official ones, and this is out of scope of this PR anyway...

Btw I would argue that the same goes for the way extra pip packages are installed (which also requires running the containers as root...)

Copy link
Member

@craig-rueda craig-rueda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@craig-rueda craig-rueda merged commit 2e93784 into apache:master Feb 16, 2021
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.2.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/XL 🚢 1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants