「Python Celery」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(カテゴリを訂正)
 
(同じ利用者による、間の1版が非表示)
132行目: 132行目:
   
 
{{ic|celery.py}} の中で {{ic|CELERYBEAT_SCHEDULE}} を指定したい場合、Celery がタスクを認識できるように {{ic|app.conf}} プレフィックスを追加する必要があります。その後 Celery デーモンを起動するときに {{ic|1=--beat --schedule=/var/lib/celery/celerybeat-schedule}} パラメータを追加してください。さらに、{{ic|/var/lib/celery}} ディレクトリが存在している必要があり所有者は celery を実行するユーザーでなければなりません。
 
{{ic|celery.py}} の中で {{ic|CELERYBEAT_SCHEDULE}} を指定したい場合、Celery がタスクを認識できるように {{ic|app.conf}} プレフィックスを追加する必要があります。その後 Celery デーモンを起動するときに {{ic|1=--beat --schedule=/var/lib/celery/celerybeat-schedule}} パラメータを追加してください。さらに、{{ic|/var/lib/celery}} ディレクトリが存在している必要があり所有者は celery を実行するユーザーでなければなりません。
 
== chroot で Celery を実行 (実験的) ==
 
 
[[chroot]] に celery をインストールすることでセキュリティを向上させることができます。セキュリティを高めるために、chroot には Celery アプリケーションを実行するのに必要なファイルだけを含めて、ファイルのパーミッションは出来る限り最小にします。例えば {{ic|/usr/bin}} などのディレクトリは所有者を root にして読み込み・書き込みができないようにします。
 
 
このセクションは [[Nginx#chroot でインストール]]を Celery 用に改変しています。
 
 
{{Warning|あくまで実験的なセットアップであるため安定して使える設定ができる保証はありません。自己責任で行ってください。}}
 
 
=== chroot ディレクトリとデバイスの作成 ===
 
 
Arch にはデフォルトで {{ic|http}} ユーザーとグループが存在し、celery を動かすのに使うことができます。chroot は {{ic|/srv/http/apps/celery}} に作成します:
 
 
# mkdir -p /srv/http/apps/celery
 
# cd /srv/http/apps/celery
 
 
Celery は {{ic|/dev/null}} と {{ic|/dev/urandom}} を必要とします。{{ic|/dev/random}} が存在しなくても Celery は起動時にクラッシュしません。chroot にインストールするには {{ic|/dev/}} ディレクトリを作成して ''mknod'' でデバイスを追加してください。{{ic|/dev/}} を全てマウントしないようにすることで、攻撃者は {{ic|/dev/sda1}} など重要なデバイスにアクセスするのが難しくなります。
 
 
{{Tip|
 
* {{ic|/srv/http/apps/celery}} は no-dev オプションを付けずにマウントしてください。
 
* ''mknod'' のオプションについては {{ic|man mknod}} や {{ic|<nowiki>ls -l /dev/{null,urandom}</nowiki>}} を見てください。}}
 
# mkdir /srv/http/apps/celery/dev
 
# mknod -m 0666 /srv/http/apps/celery/dev/null c 1 3
 
# mknod -m 0666 /srv/http/apps/celery/dev/random c 1 8
 
# mknod -m 0444 /srv/http/apps/celery/dev/urandom c 1 9
 
 
=== 必要なディレクトリの作成 ===
 
 
{{Pkg|python-virtualenv}} を使って必要な python のファイルを持ち込むのが元のアイデアですが、virtualenv は半分ほどの作業しか行わず、chroot で Celery を実行するには他の依存関係を解消する必要があります。virtualenv で作成した環境に調整を加えます:
 
 
# virtualenv --always-copy /srv/http/apps/celery
 
 
必要なディレクトリを作成:
 
 
# cd /srv/http/apps/celery
 
# mkdir {usr,dev,etc,run,tmp,var,proc}
 
# mv {lib,bin,include} usr
 
# ln -s usr/lib lib
 
# ln -s usr/bin bin
 
# ln -s usr/lib lib64
 
# ln -s usr/include include
 
# cd usr/
 
 
{{Note|64ビットのカーネルを使っている場合、{{ic|lib64}} と {{ic|usr/lib64}} から {{ic|usr/lib}} へのシンボリックリンクを作成してください: {{ic|cd $JAIL; ln -s usr/lib lib64}} と {{ic|cd $JAIL/usr; ln -s lib lib64}} を実行。}}
 
 
# ln -s lib lib64
 
 
Celery は {{ic|/proc/loadavg}} を必要とします。{{ic|/srv/http/apps/celery/tmp}} と {{ic|/srv/http/apps/celery/run}} でバインドマウントしてください。攻撃者がメモリを占有できないように容量は制限します:
 
 
# touch /srv/http/apps/celery/proc/loadavg
 
# mount --bind /proc/loadavg /srv/http/apps/celery/proc/loadavg
 
# mount -t tmpfs none /srv/http/apps/celery/run -o 'noexec,size=1M'
 
# mount -t tmpfs none /srv/http/apps/celery/tmp -o 'noexec,size=100M'
 
 
再起動後もマウントを維持するため、以下のエントリを {{ic|/etc/fstab}} に追加してください:
 
 
{{hc|/etc/fstab|<nowiki>
 
tmpfs /srv/http/apps/celery/run tmpfs rw,noexec,relatime,size=1024k 0 0
 
tmpfs /srv/http/apps/celery/tmp tmpfs rw,noexec,relatime,size=102400k 0 0
 
/proc/loadavg /srv/http/apps/celery/proc/loadavg none bind
 
</nowiki>}}
 
 
celery のログフォルダを作成:
 
 
# mkdir -p /srv/http/apps/celery/var/log/celery
 
# chown http:http /srv/http/apps/celery/var/log/celery
 
 
=== chroot の作成 ===
 
 
python の依存パッケージをコピー:
 
 
# cp $(ldd /usr/bin/python | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') /srv/http/apps/celery/lib
 
 
{{Note|{{ic|linux-vdso.so}} をコピーしないでください: 本当のライブラリではなく {{ic|/usr/lib}} には存在しません。64ビット環境の場合 {{ic|ld-linux-x86-64.so}} が {{ic|/lib64}} にあります。}}
 
 
chroot から実行するため、通常の virtualenv は機能しません。完全な python のライブラリフォルダをコピーする必要があります (site-packages は除く):
 
 
# mv /srv/http/apps/celery/lib/python3.5/site-packages /tmp
 
# rm -r /srv/http/apps/celery/lib/python3.5/*
 
# mv /tmp/site-packages /srv/http/apps/celery/lib/python3.5/
 
#
 
# cp -r -p /usr/lib/python3.5 /tmp
 
# rm -r /tmp/python3.5/site-packages
 
# mv /tmp/python3.5/* /srv/http/apps/celery/lib/python3.5/
 
 
celery をインストール:
 
 
# source /srv/http/apps/celery/bin/activate
 
# pip install celery
 
 
Celery は {{ic|libssl}} を必要とします:
 
 
# cp $(ldd /usr/lib/libssl.so.1.0.0 | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') /srv/http/apps/celery/usr/lib
 
# cp /usr/lib/libssl.so* /srv/http/apps/celery/usr/lib
 
 
マルチスレッディングを使用する場合 Celery は {{ic|libgcc_s}} を必要とします:
 
# cp /usr/lib/libgcc_s* /srv/http/apps/celery/usr/lib
 
 
# cp $(ldd /usr/lib/libssl.so.1.0.0 | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') /srv/http/apps/celery/usr/lib
 
# cp /usr/lib/libssl.so* /srv/http/apps/celery/usr/lib
 
 
Celery は {{ic|/bin/getent}} を必要とし、さらに {{ic|libnss_files}} も必要です:
 
 
# cp /bin/getent /srv/http/apps/celery/bin
 
# cp /lib/libnss_files* /srv/http/apps/celery/lib
 
 
chroot 後に celery を起動する前に {{ic|$HOME}} を登録するのに {{ic|/bin/env}} が必要です:
 
 
# cp /bin/env /srv/http/apps/celery/bin
 
 
タスクモジュールをコピー (以下の例ではタスクモジュールの名前が {{ic|test_task}} で {{ic|/lib/python3.5/site-packages/test_task}} に保存されています):
 
 
# cp -r /lib/python3.5/site-packages/test_task lib/python3.5/site-packages
 
 
必要なライブラリやシステムファイルなどをコピー:
 
 
# cp -rfvL /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf} /srv/http/apps/celery/etc
 
 
chroot 用に制限したユーザー・グループファイルを作成します。システムユーザーやグループが攻撃者から操られないようにするためです。
 
 
{{hc|/srv/http/apps/celery/etc/group|
 
http:x:33:
 
nobody:x:99:
 
}}
 
 
{{hc|/srv/http/apps/celery/etc/passwd|
 
http:x:33:33:http:/:/bin/false
 
nobody:x:99:99:nobody:/:/bin/false
 
}}
 
 
{{hc|/srv/http/apps/celery/etc/shadow|
 
http:x:14871::::::
 
nobody:x:14871::::::
 
}}
 
 
{{hc|/srv/http/apps/celery/etc/gshadow|
 
http:::
 
nobody:::
 
}}
 
 
=== chroot のパッケージ ===
 
 
パッケージを chroot にコピーしてください。
 
{{Tip|python のパッケージ方法については [http://python-packaging-user-guide.readthedocs.org/en/latest/distributing/#configuring-your-project packaging] や [http://docs.celeryproject.org/en/latest/getting-started/next-steps.html#our-project celery project structure] を参照してください。}}
 
 
プロジェクトが {{ic|your_project}} ディレクトリに存在し以下のような構造となっている場合:
 
.
 
|-setup.py
 
|-CHANGES.txt
 
|-MANIFEST.in
 
|-README.txt
 
|-package_name
 
|-__init__.py
 
|-celery.py
 
|-task_1.py
 
|-task_2.py
 
|-(...)
 
 
開発モードでパッケージをインストール:
 
 
# cd /srv/http/apps/celery/your_project
 
# source ../bin/activate
 
# pip install -e .
 
 
以下のファイルを作成してください:
 
{{hc|/srv/http/apps/celery/lib/python3.5/site-packages/package_name.egg-link|2=/your_project
 
.}}
 
 
{{hc|/srv/http/apps/celery/lib/python3.5/site-packages/easy-install.pth|2=/your_project
 
(...)}}
 
 
{{Note|
 
* easy-install.pth には virtualenv の中にインストールした他のパッケージを記述します。your_project を指し示さないエントリを修正しないでください。
 
* {{ic|python setup.py develop}} を実行してパッケージをインストールすることもでき、その場合は {{ic|/srv/http/apps/celery/lib/python3.5/site-packages/setuptools.pth}} を更新する必要があります。}}
 
 
{{hc|/srv/http/apps/celery/lib/python3.5/site-packages/setuptools.pth|2=/usr/lib/python3.5/site-packages}}
 
 
=== chroot のテスト ===
 
 
以下のコマンドを実行することで chroot が正しく設定されているか確認できます:
 
 
# /usr/bin/chroot --userspec=root:root /srv/http/apps/celery env -i HOME=/ /usr/bin/python -m celery worker -c 10 -A package_name --uid=33 --gid=33 --pidfile=/run/celery.pid --logfile=/var/log/celery/celery.log --loglevel="INFO"
 
 
Celery は root で起動しますが、http ユーザーに移行されます。
 
 
{{Note|
 
* 上記のテストを実行する前に RabbitMQ を起動しておく必要があります。
 
* プロジェクトのブローカーの認証情報は RabbitMQ の設定と合わせておく必要があります。
 
* celery/rabbitmq のトラフィックが通過できるように設定されているかファイアウォールを確認してください。}}
 
 
=== systemd の chroot ユニット ===
 
 
systemd ユニットを作成:
 
{{hc|/etc/systemd/system/celery.service|2=[Unit]
 
Description=Celery Nodes Daemon
 
After=network.target
 
 
[Service]
 
Type=oneshot
 
ExecStart=/usr/bin/chroot --userspec=root:root /srv/http/apps/celery /usr/bin/env -i HOME=/ /usr/bin/python -m celery multi start 2 -A package_name --uid=33 --gid=33 --pidfile:1=/run/celery1.pid --pidfile:2=/run/celery2.pid --logfile=/var/log/celery/celery.log
 
ExecStop=/usr/bin/chroot --userspec=root:root /srv/http/apps/celery /usr/bin/python -m celery multi stopwait 2 --uid=33 --gid=33 --pidfile:1=/run/celery1.pid --pidfile:2=/run/celery2.pid --logfile=/var/log/celery/celery.log --loglevel="INFO"
 
ExecReload=/usr/bin/chroot --userspec=root:root /srv/http/apps/celery /usr/bin/python -m celery multi restart 2 -A package_name --uid=33 --gid=33 --pidfile:1=/run/celery1.pid --pidfile:2=/run/celery2.pid --logfile=/var/log/celery/celery.log
 
KillMode=control-group
 
RemainAfterExit=yes
 
 
[Install]
 
WantedBy=multi-user.target}}
 
 
{{ic|celery.service}} を[[起動]]してください。
 
 
== トラブルシューティング ==
 
[[#systemd の chroot ユニット]]が特に問題を報告しないのに celery サービスが機能しない場合、コンソールから chroot の中の celery を起動して詳しくログを確認することができます。例:
 
 
# /usr/bin/chroot --userspec=root:root /srv/http/apps/celery /usr/bin/env -i HOME=/ /usr/bin/python -m celery worker -A package_name --uid=33 --gid=33 --pidfile=/run/celery.pid --logfile=/var/log/celery/celery.log --loglevel="INFO"
 

2024年7月9日 (火) 18:20時点における最新版

プロジェクトウェブサイト より:

Celery は分散されたメッセージ受け渡しに基づく非同期のタスクキュー・ジョブキューです。リアルタイム処理に焦点が当てられていますが、スケジューリングもサポートしています。タスクは非同期 (バックグラウンド) または同期的 (準備ができるまで待機) に実行できます。

インストール

python-celery パッケージをインストールしてください。他の python パッケージと同じように Python 3.x と互換性のあるパッケージが入手できます。Python 2.x と互換性のあるパッケージが必要な場合は python2-celery[リンク切れ: アーカイブ: aur-mirror] をインストールしてください。

Celery のドキュメント より: "Celery はメッセージを送信・受信するための手段を必要とします"。選択肢のひとつとして RabbitMQ が存在し、公式リポジトリからインストールできます。

設定

Celery

設定ファイルを保存するためのディレクトリ /etc/celery/ を作成する必要があります。サンプル設定ファイルが Celery のドキュメント に記載されています。

celery@celery.service起動有効化してください。

RabbitMQ

RabbitMQ は設定を /etc/rabbitmq/rabbitmq-env.conf に保存します。

デフォルト設定:

NODENAME=rabbit@rakieta
NODE_IP_ADDRESS=0.0.0.0
NODE_PORT=5672

LOG_BASE=/var/log/rabbitmq
MNESIA_BASE=/var/lib/rabbitmq/mnesia

RabbitMQ は Unix ソケットをサポートしていないため 0.0.0.0127.0.0.1 で置き換えると良いでしょう。

設定をシンプルにするために HOME=/var/lib/rabbitmq も追加すると良いでしょう。環境変数について詳しくは RabbitMQ のドキュメント を参照してください。

rabbitmq.service起動有効化してください。

ノート: rabbitmq-service は rabbitmq ユーザーとして実行され、ホームフォルダは /var/lib/rabbitmq の中に保存されます。フォルダとサブフォルダの所有者が rabbitmq ユーザーになっていることを確認してください。

RabbitMQ のドキュメント に従ってユーザーとバーチャルホストを追加:

$ cd /var/lib/rabbitmq
$ su rabbitmq -c 'rabbitmqctl add_user myuser mypassword'
$ su rabbitmq -c 'rabbitmqctl add_vhost myvhost'
$ su rabbitmq -c 'rabbitmqctl set_user_tags myuser mytag'
$ su rabbitmq -c 'rabbitmqctl set_permissions -p myvhost myuser ".*" ".*" ".*"'

詳しくは RabbitMQ の管理者ガイド を読んでください。

su rabbitmq -c "rabbitmqctl status" を実行したときに badrpc,nodedown となる場合、問題の解決方法が こちらの記事 に載っています。

ノート: su rabbitmq -c "erl" を実行することで erlang のプロンプトをエラーなく表示できます。

セキュリティ

Celery ドキュメント のセキュリティセクションを読んでください。

サンプルタスク

Celery アプリケーション

Celery ドキュメント に従って python のサンプルタスクを作成:

test.py
from celery import Celery
    
    app = Celery('tasks', backend='amqp', broker='amqp://myuser:mypassword@localhost:5672/myvhost')
    
    @app.task
    def add(x, y):
        return x + y

amqp://myuser:mypassword@localhost:5672/myvhost は RabbitMQ を設定したときに作成したユーザー・バーチャルホストと同じにしてください。

Celery によって使われるデフォルトのブローカーは RabbitMQ であるため backend='amqp' パラメータは任意です。

テスト

test.py のあるディレクトリで以下のコマンドを実行:

$ celery -A task worker --loglevel=info

そして (同一ディレクトリに) 以下のファイルを作成:

call.py
from test import add
    
    add.delay(4, 4)

実行:

$ python call.py

コンソールからワーカーの情報が出力されます:

Received task: task.add[f4aff99a-7477-44db-9f6e-7e0f9342cd4e]
Task task.add[f4aff99a-7477-44db-9f6e-7e0f9342cd4e] succeeded in 0.0007182330009527504s: 8

Celery サービスのモジュールの準備

Celery ドキュメント に書かれていることとは少し異なる手順で説明しています。

test_task モジュールを作成:

# mkdir /lib/python3.5/site-packages/test_task
# touch /lib/python3.5/site-packages/test_task/__init__.py
# touch /lib/python3.5/site-packages/test_task/test_task.py
# touch /lib/python3.5/site-packages/test_task/celery.py
/lib/python3.5/site-packages/test_task/celery.py
from __future__ import absolute_import

from celery import Celery

app = Celery('tasks', backend='amqp', broker='amqp://myuser:mypassword@localhost:5672/myvhost')

if __name__ == '__main__':
 app.start()
/lib/python3.5/site-packages/test_task/test_task.py
from __future__ import absolute_import

from test_task.celery import app

@app.task
def add(x, y):
 return x + y

コンソールで python を起動して以下のコマンドを実行できるはずです:

>>> from test_task import celery

/etc/celery/celery.conf の中の以下の行を:

CELERY_APP="proj"

以下のように置き換えてください:

CELERY_APP="test_task"

celery@celery.service再起動してください。

タスクを定期的に実行

Celery Beat を使うことでタスクを定期実行することができます。基本的なセットアップは Celery のドキュメントページ で説明されています。

celery.py の中で CELERYBEAT_SCHEDULE を指定したい場合、Celery がタスクを認識できるように app.conf プレフィックスを追加する必要があります。その後 Celery デーモンを起動するときに --beat --schedule=/var/lib/celery/celerybeat-schedule パラメータを追加してください。さらに、/var/lib/celery ディレクトリが存在している必要があり所有者は celery を実行するユーザーでなければなりません。