【问题标题】:how to run celery with django on openshift 3如何在 openshift 3 上用 django 运行 celery
【发布时间】:2018-01-04 19:57:26
【问题描述】:

在我的 django pod 中启动 celery beat 和工作进程的最简单方法是什么?

我正在将我的 Openshift v2 Django 应用程序迁移到 Openshift v3。我正在使用 Pro 订阅。我真的是 Openshift v3 和 docker 以及容器和 kubernetes 的菜鸟。我已经使用本教程https://blog.openshift.com/migrating-django-applications-openshift-3/ 来迁移我的应用程序(效果很好)。

我现在正在努力研究如何开始芹菜。在 Openshift 2 上,我只使用了一个动作挂钩 post_start:

source $OPENSHIFT_HOMEDIR/python/virtenv/bin/activate

python $OPENSHIFT_REPO_DIR/wsgi/podpub/manage.py celery worker\
--pidfile="$OPENSHIFT_DATA_DIR/celery/run/%n.pid"\
--logfile="$OPENSHIFT_DATA_DIR/celery/log/%n.log"\

python $OPENSHIFT_REPO_DIR/wsgi/podpub/manage.py celery beat\
--pidfile="$OPENSHIFT_DATA_DIR/celery/run/celeryd.pid"\
--logfile="$OPENSHIFT_DATA_DIR/celery/log/celeryd.log" &
-c 1\
--autoreload &

这是一个非常简单的设置。它只是使用 django 数据库作为消息代理。没有rabbitMQ之类的。

会为此分配一个 openshift“工作”吗?还是更好地使用 powershift image (https://pypi.python.org/pypi/powershift-image) 操作命令?但我不明白如何执行它们。

这是我唯一的应用程序的当前部署配置“

apiVersion: v1
kind: DeploymentConfig
metadata:
  annotations:
    openshift.io/generated-by: OpenShiftNewApp
  creationTimestamp: 2017-12-27T22:58:31Z
  generation: 67
  labels:
    app: django
  name: django
  namespace: myproject
  resourceVersion: "68466321"
  selfLink: /oapi/v1/namespaces/myproject/deploymentconfigs/django
  uid: 64600436-ab49-11e7-ab43-0601fd434256
spec:
  replicas: 1
  selector:
    app: django
    deploymentconfig: django
  strategy:
    activeDeadlineSeconds: 21600
    recreateParams:
      timeoutSeconds: 600
    resources: {}
    rollingParams:
      intervalSeconds: 1
      maxSurge: 25%
      maxUnavailable: 25%
      timeoutSeconds: 600
      updatePeriodSeconds: 1
    type: Recreate
  template:
    metadata:
      annotations:
    openshift.io/generated-by: OpenShiftNewApp
      creationTimestamp: null
      labels:
    app: django
    deploymentconfig: django
    spec:
      containers:
      - image: docker-registry.default.svc:5000/myproject/django@sha256:6a0caac773acc65daad2e6ac87695f9f01ae3c99faba14536e0ec2b65088c808
    imagePullPolicy: Always
    name: django
    ports:
    - containerPort: 8080
      protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /opt/app-root/src/data
      name: data
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: data
    persistentVolumeClaim:
      claimName: django-data
  test: false
  triggers:
  - type: ConfigChange
  - imageChangeParams:
      automatic: true
      containerNames:
      - django
      from:
    kind: ImageStreamTag
    name: django:latest
    namespace: myproject
      lastTriggeredImage: docker-registry.default.svc:5000/myproject/django@sha256:6a0caac773acc65daad2e6ac87695f9f01ae3c99faba14536e0ec2b65088c808
    type: ImageChange

我正在使用 mod_wsgi-express,这是我的 app.sh

ARGS="$ARGS --log-to-terminal"
ARGS="$ARGS --port 8080"
ARGS="$ARGS --url-alias /static wsgi/static"

exec mod_wsgi-express start-server $ARGS wsgi/application

非常感谢您的帮助。谢谢

【问题讨论】:

  • 最简单的可能是在启动脚本中有一个环境变量,检查它是否运行工作进程或节拍进程。然后有两个部署,一个用于工作人员,另一个用于设置环境变量以运行节拍进程。除了部署名称和环境变量之外,部署将是相同的。
  • 感谢您的回答。但我认为我对 Openshift 的了解仍然太少,无法真正理解您的答案。您是否建议我在部署配置中添加更多容器?或者为 celery worker 和 beat 创建单独的部署配置/应用程序?如果我有单独的 celery 应用程序,它们将如何与我的 django 应用程序交互?我在持久存储上使用 sqlite 数据库。为了清楚起见,我添加了我的部署配置。
  • 将持久卷与 SQLite 一起使用会使事情变得复杂,因为我期望您使用单独的数据库实例。您是否有理由不能使用 Django 和 Celery 都可以与之交互的单独的 PostgreSQL 数据库?
  • 顺便说一句,您使用的是什么 WSGI 服务器?如果您使用的是 mod_wsgi-express,它有一个特性可以用来运行和管理 Celery 进程。这种方式都可以在一个容器中完成。如果您使用的是 mod_wsgi-express,请向我展示您当前用于启动它的 app.sh 文件,然后我可以提出修改建议和其他操作。
  • 其实我没有特别的理由需要使用 sqlite。我只是想对使用 sqlite 的 openshift v2 应用程序进行快速而肮脏的迁移。我愿意稍后转移到 postgreSQL 数据库。我将我的 app.sh 添加到帖子中

标签: django celery openshift openshift-3


【解决方案1】:

我已经设法让它工作了,虽然我对它不太满意。我将很快迁移到 postgreSQL 数据库。这是我所做的:

wsgi_mod-express 有一个名为 service-script 的选项,它会在实际应用程序之外启动一个附加进程。所以我更新了我的 app.sh:

#!/bin/bash

ARGS=""

ARGS="$ARGS --log-to-terminal"
ARGS="$ARGS --port 8080"
ARGS="$ARGS --url-alias /static wsgi/static"
ARGS="$ARGS --service-script celery_starter scripts/startCelery.py"

exec mod_wsgi-express start-server $ARGS wsgi/application

注意最后的 ARGS=... 行。

我创建了一个 python 脚本来启动我的 celery worker 并进行节拍。 startCelery.py:

import subprocess

OPENSHIFT_REPO_DIR="/opt/app-root/src"

OPENSHIFT_DATA_DIR="/opt/app-root/src/data"

pathToManagePy=OPENSHIFT_REPO_DIR + "/wsgi/podpub"

worker_cmd = [
    "python",
    pathToManagePy + "/manage.py",
    "celery",
    "worker",
    "--pidfile="+OPENSHIFT_REPO_DIR+"/%n.pid",
    "--logfile="+OPENSHIFT_DATA_DIR+"/celery/log/%n.log",
    "-c 1",
    "--autoreload"
    ]
print(worker_cmd)


subprocess.Popen(worker_cmd, close_fds=True)

beat_cmd = [
    "python",
    pathToManagePy + "/manage.py",
    "celery",
    "beat",
    "--pidfile="+OPENSHIFT_REPO_DIR+"/celeryd.pid",
    "--logfile="+OPENSHIFT_DATA_DIR+"/celery/log/celeryd.log",
    ]
print(beat_cmd)

subprocess.Popen(beat_cmd)

这实际上是有效的,但是当我尝试启动 celery worker 时,我一直收到一条消息说 “当工作人员接受使用 pickle 序列化的消息时,以超级用户权限运行工作人员是一个非常糟糕的主意! 如果你真的想继续,那么你必须设置 C_FORCE_ROOT 环境变量(但请在做之前考虑一下)。"

即使我将这些配置添加到我的 settings.py 以删除 pickle 序列化程序,它仍然给我同样的错误消息。

CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ACEEPT_CONTENT = ['json']

我不知道为什么。 最后我将 C_FORCE_ROOT 添加到我的 .s2i/enviroment

C_FORCE_ROOT=true

现在它起作用了,至少我是这么认为的。我的下一份工作只会在几个小时内完成。我仍然愿意接受任何进一步的建议和提示。

【讨论】:

  • 服务脚本确实是要推荐的。我会使用单独的脚本来启动 Celery 主守护进程和节拍进程。我还会使用os.execl() 以便 Celery 进程替换该进程,而不是将其作为子进程运行。这是确保它正确接收信号所必需的。
  • 我不理解 root 警告,因为如果您使用的是 S2I 构建器,它不会以 root 运行。它可能会进行过度热心的检查,并且还会检查是否以组root 运行。作为root 组运行是完全可以的,所以它不应该抱怨。
  • 就我而言,这是 Celery 的一个缺陷。他们有github.com/celery/celery/blob/…,所以它确实会检查组root,而实际上并没有任何不好的原因。
  • 由于 Celery 中的奇怪限制,我认为设置 C_FORCE_ROOT=true 没有问题。
猜你喜欢
  • 1970-01-01
  • 2016-02-09
  • 2016-10-17
  • 1970-01-01
  • 2017-11-14
  • 2017-09-11
  • 2017-11-29
  • 1970-01-01
  • 2013-02-25
相关资源
最近更新 更多