LoginSignup
12
13

More than 5 years have passed since last update.

イメージビルドせずにKubernetes機能だけでがんばる

Last updated at Posted at 2018-12-04

イメージビルド(Dockerfile)の何がいやなのか

  • Dockerfile自体の管理をしないといけない
  • Dockerfileとイメージの対応を管理しないといけない
  • イメージにアップデートが必要な場合、そのイメージをBASEにしているイメージもビルドしなおす必要が出てくる
    • イメージ継承が多いと、再ビルド作業が連鎖で発生していく

Kubernetesの機能でだいたい出来るんじゃないか?疑惑

  • Dockerfileの次のような使い方をKubernetesの機能で置き換えていきます
    • RUNでアプリの追加インストール(apt, yum)
    • ADD,COPYでスクリプトを入れる
    • CMD, ENTRYPOINTで起動時のコマンド変更
    • USERで実行ユーザー・グループを変える
  • 次の使い方は置き換え断念します
    • RUNでコンパイル
      • Kubernetesの機能でやるとPod起動時にコンパイルすることになります。起動が遅くなります
      • コンパイル済みのアプリを組み込んだイメージを作成するしかなさそうです

「RUNでアプリの追加インストール」の置き換え

  • イメージ内にインストールするのではなく、インストール済みのイメージを組み合わせるといけそうです
    1. KubernetesのPodには複数のコンテナを含めることが出来ます
      • サイドカーパターンと呼ばれるものです。
      • この機能を使えば、 アプリのインストールをコンテナの組み合わせに置き換え出来そうです image.png
    2. KubernetesのInit Containers機能を使うと、コンテナAで処理実行→コンテナBで処理実行→・・・といったフローを組むことが出来ます
      • サーバー起動の前処理で何かコマンド実行したいけど、そのコマンドがイメージに入っていない、という場合に使えそうです
      • 実行結果の受け渡しには、EmptyDirという機能が使えます。
        • EmptyDirはPod作成時に作られ、Podを消すと消える一時ボリュームです。
        • Pod内の各コンテナでマウントすることでコンテナ間のデータ受け渡しに使えます。 image.png

サイドカーパターンの補足

image.png

  • 別々のコンテナがネットワークスタック(NIC、loopback interface等)を共有します
    • 各コンテナのアプリの待ち受けポートは、localhostの待ち受けポートとして相互通信できます
    • container1がポート80で待ち受ける場合、container2からlocalhost:80でcontainer1にアクセスできます
      • Pod内のコンテナ同士で待ち受けポートが被らないようにしないといけません
      • これだけだとファイルシステムが分離されていてコンテナ間でファイル共有ができません。
        • EmptyDirを作ることで共有ボリュームを持てます

image.png

「ADD,COPYでスクリプトを入れる」の置き換え

  • configMapでスクリプトファイルを作ってしまいましょう
    • configMap自体はその名の通り、設定ファイルを配布するための機能です
    • 実態としてはテキストファイルを配布する機能なので、スクリプトを配布するのにも使えます

「CMD, ENTRYPOINTで起動時のコマンド変更」の置き換え

  • これはPodのYAMLでコマンドを指定すればいいでしょう

「USERで実行ユーザー・グループを変える」の置き換え

  • これはsecurityContextrunAsUser, runAsGroup, supplementalGroupsを使えばいけそうです
    • 注意: Dockerの仕様上、イメージの中にrunAsGroupで指定したグループが存在しない時はrootグループで実行されます
    • その場合は起動時に、groupaddしてからrunuserコマンドを実行してやればいいと思います

実際にやってみる

Tensorboardにbasic認証をつけてみる

  • TensorboardはDeep Learningの結果をグラフで表示してくれるwebサーバーです
  • Tensorboardは認証をサポートしません ので、basic認証するにはnginx等が必要です
  • もしイメージビルドでやるなら、TensorboardイメージへのNginxインストールをRUNでした後に、設定ファイルをcopyすることになります
  • イメージビルドの代わりに、解説したサイドカーパターンを使ってみます
    • TensorboardイメージとNginxイメージを使います
    • あとはKubernetesのyamlで実装してみます

各YAML

nginx-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  auth.conf: |
    server {
     listen 80 default_server;

     location / {
         auth_basic              "Restricted";
         auth_basic_user_file    auth.htpasswd;

         proxy_pass                          http://localhost:6006;
         proxy_read_timeout                  900;
     }
    }
  auth.htpasswd: |
    foo:$apr1$odHl5EJN$KbxMfo86Qdve2FH4owePn.
tensorboard-basic-auth.yml
apiVersion: v1
kind: Pod
metadata:
  name: tensorboard-basic-auth
  labels:
    app: tensorboard-basic-auth
spec:
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config
  containers:
  - image: tensorflow/tensorflow:1.12.0-py3
    name: tensorflow
    command: ["/usr/local/bin/tensorboard", "--logdir", "path/to/logs"]
  - image: nginx:alpine
    name: nginx
    ports:
      - name: nginx
        containerPort: 80
    volumeMounts:
      - name: config-volume
        mountPath: /tmp/config
    command:
      - sh
      - "-c"
      - |
          cp /tmp/config/auth.conf /etc/nginx/conf.d/auth.conf
          cp /tmp/config/auth.htpasswd /etc/nginx/auth.htpasswd
          rm /etc/nginx/conf.d/default.conf
          nginx -g "daemon off;"
tensorboard-service.yml
apiVersion: v1
kind: Service
metadata:
  name: tensorboard-basic-auth
  labels:
    app: tensorboard-basic-auth
spec:
  type: NodePort
  ports:
  - name: nginx
    port: 80
    nodePort: 30036
  selector:
    app: tensorboard-basic-auth
  • 備考
    • ここを参考に作りました
    • Nginxの設定ファイルの解説はここ にあります
    • 上記のyamlの場合は「foo/bar」でログインできます
    • configMapで2つの設定ファイルauth.confauth.htpasswdを定義しています
    • それらを/tmp/configにマウントしたのち、cpで本来置くべき場所に配置しています
      • configMapのマウントはReadOnlyなので、cpをmvにすると失敗します
      • 直接配置先にマウントさせることもできるはずですが、YAMLの記述が増えるので今回はやっていません
      • localhost:6006の6006はTensorboardコンテナのデフォルト待ち受けポートです
    • Tensorboardについて、本来はyaml中にある「path/to/logs」の部分に学習ログを置く必要がありますが、今回は省略しています
    • その他いろいろ省略しています
      • https対応
      • 認証情報部分はConfigMapよりSecretの方がいい

作成

  • kubectl create -f nginx-config.yml
  • kubectl create -f tensorboard-basic-auth.yml
  • kubectl create -f tensorboard-service.yml

動作確認

image.png

  • basic認証画面が出てきます
  • foo/bar以外を入れると認証失敗します

image.png

  • foo/barを入れるとtensorboardが表示されます

その他の使い方の参考

まとめ

  • コンパイル以外のDocker build作業はだいたいなくせそうです
  • Docker buildをなくしたいかどうかは個人の趣味によりそうですが、私はあまりビルドしたくありません
    • 冒頭に書いた理由
    • kubernetes上で設定ファイルの確認・変更がしやすいです
      • 設定ファイル変更のたびにビルドとかしなくて済みます
  • デメリットとしてイメージを探す作業は生じますが。。
12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13