これは何?
レンダリングファームはとはたくさんの計算機を並べてそれをうまく使って早く3DCGをレンダリングするというものです。
これを使うことにより、3DCGアニメーションなどレンダリングに時間のかかる作業を、高速に実行することができます。
今回使用するのはオープンソースの3D統合開発環境であるBlenderです。
Blenderには元から分散レンダリングの仕組みが搭載されているので、たくさんのマシンをセットアップし、Blenderを起動しておけば、レンダリングファームを作ることができますが、この記事ではKubernetesを使って、簡単にBlenderのレンダリングファームを作る方法を紹介します。
blenderのレンダリングクラスタ
2.79で利用できるadd-onであるNetwork Rendererを使います。
(最近リリースされた2.8ではどうやるかわからず・・😭)
構成は下図のようになっており、client(普通に使っているBlenderアプリケーション)からジョブをmasterに投入し、masterがjobをslaveに振り分けるようです。
結果(画像)は最終的にはclientに返却されます。
BlenderのDockerイメージ
rndevfx/docker-blender-render-cluster | |
A docker based multi machine render setup. Contribute to rndevfx/docker-blender-render-cluster development by creating an account on GitHub. |
ちょうどdockerを使ってレンダリングファームを作っている人がいたので、これをそのまま使わせてもらいます。
Kubernetes環境の用意
今回はminikubeを使います。minikubeはローカルにVMを作ってKubernetesクラスタを構築するものなので、これで作ったクラスタではBlenderのレンダリングは全く早くなりませんが、同じ方法を使うことで様々なKubernetes環境でこの手法が使えるため、動作の確認という意味では手軽で良い方法だと考えました。
minikubeのセットアップは公式ページなどに詳しく書かれているので割愛します。
マニフェストファイル一覧
masterのマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: blender
name: blender
spec:
replicas: 1
selector:
matchLabels:
run: blender
template:
metadata:
labels:
run: blender
spec:
containers:
- image: d3v0x/blender-render-cluster:2.79
name: blender
env:
- name: RENDER_MODE
value: "MASTER"
MasterのService
minikube tunnel
でアクセスするために必要です。
apiVersion: v1
kind: Service
metadata:
labels:
run: blender
name: blender
spec:
type: LoadBalancer
ports:
- port: 8000
protocol: TCP
targetPort: 8000
selector:
run: blender
Slaveのマニフェスト
replicasを増やすだけで簡単にslaveが増やせます。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: blender-slave
name: blender-slave
spec:
replicas: 2
selector:
matchLabels:
run: blender-slave
template:
metadata:
labels:
run: blender-slave
spec:
containers:
- image: d3v0x/blender-render-cluster:2.79
name: blender
env:
- name: MASTER_PORT_8000_TCP_ADDR
value: "blender"
注意
手元で利用しているBlender(client)のバージョンとKubernetesで動かしているBlender(master,slave)のバージョンが同じである必要があります。
Blenderのmasterへのアクセス
ここまで紹介したmanifestをminikube上にデプロイしたら、ブラウザから動作を確認してみます。
$ minikube tunnel
を実行して、ServiceのIPに簡単にアクセスできるようにします。 (以前書いた minikube tunnelを試してみた
が参考になると思います。)
これで、ServiceのIPでブラウザからBlenderのmasterにアクセスすることができます。
まずServiceのIPアドレスを調べます。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
blender LoadBalancer 10.109.59.222 10.109.59.222 8000:31702/TCP 9m40s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12m
この例だとブラウザで http://10.109.59.222:8000
にアクセスすれば良いわけです。
こんなふうにWeb UIが出てくれば成功です。
よくみると「Slaves」の項目に2つのSlaveが登録されていることも確認できます。
Blenderのclientの設定
次にBlenderのclientからmasterへの設定を行います。
UserPreference -> Add-ons から Network Rendererを有効化します。
そうするとNetwork Renderを選ぶことができます。
Propaties -> Renderパネルに下図のようにmasterのIPアドレス(さっきブラウザで確認したもの)を指定します。
動作の様子
まず一度ファイルを保存する必要があります。リモートでのレンダリングは簡単にいうとファイルをそれぞれ転送して、部分的にレンダリングさせているだけなので、実施前には必ずファイルの保存が必要です。未保存のデータはレンダリングされません。
Propaties -> Renderパネルにある「Send job」をクリックすると、masterにレンダリングjobを発行できます。
しばらくするとWebUIにjobがあらわれます。
Not Finishedとなっていることから、今はまだ実行中ということがわかります。
これがFinishedとなったのちに、Propaties -> Renderパネルにある「Get Image」をクリックするとその結果をクライアント側で取得できます。
感想
3Dのレンダリングパイプラインはjobを細切れにしてレンダリングして返すだけなので、一時的なデータしか持たないためPVなどを使わずとも、Kubernetesで扱うことができそうだと感じました。
もっと大きなデータやアニメーションを扱う場合はレンダリング結果が巨大になるのでNFSなどに格納するのが良いかもしれません。
最新のBlenderでのネットワークレンダリングが試せなかったのが残念。(知っている方、教えてください)