Help us understand the problem. What is going on with this article?

Kubernetes Engine でGPUエンコーディング - NVENC

More than 1 year has passed since last update.

Google Kubernetes Engine のコンテナGPUで動画エンコード( NVENC )を行い、高速エンコードとスケーラビリティを両立できます。
Container Engine GPU の入門記事は機械学習向けのものが多くて、動画処理のものが見当たらなかったので記事を書きました。

Dockerビルドマシンの側では、GPUはもちろんNVIDIAドライバすら入れる必要がないので楽です。

準備

DockerイメージのビルドマシンはGoogle Compute EngineのVMを使うと手っ取り早く便利です。
今回はCentOS 7を使用しました。
なお、イメージをGoogleクラウドストレージ上にContainer Registryとして保存するので、VMにストレージへの読み取りと書き込み権限が必要です。

Dockerイメージをビルド

(1) Dockerをインストール

# yum install -y yum-utils
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum makecache fast
# yum install -y docker-ce
# systemctl start docker

(2) nvidia-docker2をインストール

# distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
# curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | tee /etc/yum.repos.d/nvidia-docker.repo
# yum -y install nvidia-docker2
# pkill -SIGHUP dockerd

(3) Dockerfileを作成

こちらに基づいてDockerfileを作成しています。
GKEではUbuntuベースが推奨されているようなので、Ubuntu16.04を選択しました。

Dockerfile
FROM ubuntu:16.04
LABEL maintainer "NVIDIA CORPORATION <cudatools@nvidia.com>"

RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates apt-transport-https gnupg-curl && \
    rm -rf /var/lib/apt/lists/* && \
    NVIDIA_GPGKEY_SUM=d1be581509378368edeec8c1eb2958702feedf3bc3d17011adbf24efacce4ab5 && \
    NVIDIA_GPGKEY_FPR=ae09fe4bbd223a84b2ccfce3f60f4b3d7fa2af80 && \
    apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub && \
    apt-key adv --export --no-emit-version -a $NVIDIA_GPGKEY_FPR | tail -n +5 > cudasign.pub && \
    echo "$NVIDIA_GPGKEY_SUM  cudasign.pub" | sha256sum -c --strict - && rm cudasign.pub && \
    echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/cuda.list && \
    echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list

ENV CUDA_VERSION 9.2.148

ENV CUDA_PKG_VERSION 9-2=$CUDA_VERSION-1
RUN apt-get update && apt-get install -y --no-install-recommends \
        cuda-cudart-$CUDA_PKG_VERSION && \
    ln -s cuda-9.2 /usr/local/cuda && \
    rm -rf /var/lib/apt/lists/*

# nvidia-docker 1.0
LABEL com.nvidia.volumes.needed="nvidia_driver"
LABEL com.nvidia.cuda.version="${CUDA_VERSION}"

RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \
    echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf

ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64

# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_REQUIRE_CUDA "cuda>=9.2"

# FFMPEG
RUN set -x \
 && apt update \
 && apt install -y gcc git make pkg-config devscripts \
 && apt install -y yasm nasm zlib1g-dev \
 && cd /usr/local/src \
 && curl -L http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz -o lame-3.99.5.tar.gz \
 && tar xvzf lame-3.99.5.tar.gz \
 && cd lame-3.99.5 \
 && ./configure \
 && make \
 && make install \
 && cd /usr/local/src \
 && git clone http://git.videolan.org/git/x264.git \
 && cd x264 \
 && ./configure --enable-shared --disable-asm \
 && make \
 && make install \
 && export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig \
 && echo /usr/local/lib >> /etc/ld.so.conf \
 && ldconfig \
 && cd /usr/local/src \
 && curl -L https://github.com/FFmpeg/nv-codec-headers/releases/download/n8.0.14.6/nv-codec-headers-8.0.14.6.tar.gz -o nv-codec-headers-8.0.14.6.tar.gz \
 && tar xvzf nv-codec-headers-8.0.14.6.tar.gz \
 && cd nv-codec-headers-n8.0.14.6 \
 && make \
 && make install \
 && cd /usr/local/src \
 && git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg \
 && cd ffmpeg \
 && ./configure --enable-nvenc --enable-libx264 --enable-gpl --enable-libmp3lame \
 && make \
 && make install \
 && cd /usr/local/src \
 && rm -rf *

#この辺から下はご自身のプロジェクトに合わせてください。
# Node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - \
 && apt-get install -y nodejs \
 && mkdir /var/video_encode
COPY ./video_encode /var/video_encode
CMD /usr/bin/node /var/video_encode/bin/www
EXPOSE 3000

(4) DockerビルドしてPUSH

下記の「asia.gcr.io」の部分は好きなリージョンに変えてもOK。
Dockerfileのあるディレクトリで、

# nvidia-docker build -t asia.gcr.io/自分のGCPプロジェクト名/test-encode .
# gcloud auth configure-docker
# nvidia-docker push asia.gcr.io/自分のGCPプロジェクト名/test-encode

Kubernetes Engine コンソールでの作業

(1) クラスタを作成

コンソールのクラスタメニュー > クラスタを作成
cluster.png

  • ゾーン/リージョンによって提供されるGPUが異なります。

  • GPUを使うノードプールと使わないノードプールを分けて作成することが推奨です。
    GPUを要求するPodは nvidia.com/gpu テイントによってGPUノードにスケジュールされる仕組みになっています。

(2) NVIDIAデバイスドライバの用意

クラスタの一覧で新しくクラスタが作成されたことを確認し、右にある「接続」メニューからCloud Shellを開きます。
NVIDIAのデバイスドライバをインストールするデーモンセットを設定します。

# kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/stable/nvidia-driver-installer/cos/daemonset-preloaded.yaml
結果:
daemonset.extensions "nvidia-driver-installer" created

(3) 先程のDockerイメージをデプロイ

コンソールのワークロードメニュー > デプロイ
deploy.png

デプロイ後、ワークロードのメニューからYAMLを編集し、下記の resources の箇所を書き換えて nvidia.com/gpu でGPU数を指定して保存します。

apiVersion: extensions/v1beta1
kind: Deployment
... 略
    spec:
      containers:
      - name: 〇〇
        image: 〇〇
        resources:
          limits:
            nvidia.com/gpu: 1

※ 編集後、"Insufficient nvidia"などのエラーでPodがすぐに起動しない場合がありますが、しばらく待っていれば解消されます。

※ ワークロードのオートスケーラーの設定について
Pod毎にできるだけ同じGPUを使わないようにすることが望ましい場合、CPUターゲット値を低めにしたほうが良いです。CPUターゲット値が高いと、CPUをあまり消費しないアプリケーションの場合、同じノード内にPodが次々と作られていき、GPUを共有します。

(4) NVENCができるか確認

Podにexecして確認しましょう。
稼働中のPod名はワークロードのメニューで確認できます。

CloudShell
# kubectl exec -it Pod名 /bin/bash

Pod内に入ったら、h264_nvenc でエンコードしてみる。

# ffmpeg -i test.mov -vcodec h264_nvenc -b:v 2000k -acodec libmp3lame -b:a 128k output.mp4

(5) アプリケーションを公開(必要に応じて)

lb.png

以上

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away