機械学習エンジニアの備忘録

主に自分が勉強したことのメモ

kubernetesでsshできるpodを作る

普段自分は機械学習の研究用途でkubernetes (k8s)上のクラスターでjupyterlabを立ててそこでコーディングをしています。
なんですが、jupyterlabだと補完がいまいちだったり、pyファイルの編集においては補完が全く効かなかったりで何かいい方法はないか模索していたんですが、最近VSCodeでremote serverに接続して開発できる機能が追加されました。

code.visualstudio.com

crieit.net

この機能を使うことで、リモートのサーバにsshしてファイルを編集できますし、pythonインタープリタもサーバの環境を使えます。
つまり、dockerで機械学習ディープラーニング用の環境を作ってGPUが乗ったサーバでコンテナを立ててしまえば、Pytorchやkerasの補完がモリモリ効いたままコーディングができて実行もすぐできて超絶便利になりそうです。

単なるDockerでsshできるコンテナを建てることは簡単なんですが、Kubernetes上でやろうとすると少しハマったのでその備忘録を残しておきます。

ちなみに、単なるDockerでsshできるコンテナを建てるには以下の方法で簡単にできます。

docs.docker.jp

上記と同様のパスワード認証の方法でk8sにpodを立ててsshしようとしてもPermission Deny(Publickey, password)でアクセスできませんでした。

いろいろ調査したところ、鍵認証の方法ならsshに成功しました。
基本的なやり方は下記と同じです。

GitHub - ruediste/docker-sshd: Dockerized SSH server prepared for Kubernetes

まず、下記のようなDockerfileでssh用imageを作って適当なrepositoryにpush しておきます。

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd

RUN apt-get install -y less curl iputils-ping

RUN sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \
&& sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config \
&& sed -ri 's/^StrictModes\s+.*/StrictModes no/' /etc/ssh/sshd_config \
&& sed -ri 's/HostKey \/etc\/ssh\//HostKey \/etc\/ssh\/hostKeys\//g' /etc/ssh/sshd_config \
&& echo "PasswordAuthentication no" >> /etc/ssh/sshd_config \
&& echo "GatewayPorts yes" >> /etc/ssh/sshd_config

RUN rm /etc/ssh/ssh_host*

EXPOSE 22

CMD ["/usr/sbin/sshd", "-De"]

次に、ホスト鍵関連のファイルを生成するgenerateHostKeys.shのようなシェルスクリプトを作って実行します。

#!/bin/bash
rm -rf hostKeys
mkdir hostKeys
ssh-keygen -q -t rsa  -f hostKeys/ssh_host_rsa_key -N "" -C ""
ssh-keygen -q -t dsa  -f hostKeys/ssh_host_dsa_key -N "" -C ""
ssh-keygen -q -t ecdsa  -f hostKeys/ssh_host_ecdsa_key -N "" -C ""
ssh-keygen -q -t ed25519  -f hostKeys/ssh_host_ed25519_key -N "" -C ""
kubectl --namespace default delete secret ssh-host-keys
kubectl --namespace default create secret generic ssh-host-keys \
--from-file=hostKeys/ssh_host_rsa_key \
--from-file=hostKeys/ssh_host_rsa_key.pub \
--from-file=hostKeys/ssh_host_dsa_key \
--from-file=hostKeys/ssh_host_dsa_key.pub \
--from-file=hostKeys/ssh_host_ecdsa_key \
--from-file=hostKeys/ssh_host_ecdsa_key.pub \
--from-file=hostKeys/ssh_host_ed25519_key \
--from-file=hostKeys/ssh_host_ed25519_key.pub

また、ユーザ認証用の公開鍵をauthorized_keysとして保存しておきます。

次に、先ほどつくったホスト鍵ファイルたちとauthorized_keysをk8s上でセキュアに扱うためにSecretsを使います。
k8sのSecretsに関しては下記のサイトがわかりやすかったです。

ubiteku.oinker.me

上で作ったファイルたちをSecretsとして登録するUpdateKeys.shを作って実行します。

#!/bin/sh
# Update the keys stored in ssh.yaml from the authorized-keys file
kubectl --namespace default delete secret ssh-keys
kubectl --namespace default create secret generic ssh-keys --from-file=./authorized_keys

あとはk8ssshサーバを立てるマニフェストを書いて下記の設定を追加した上でpodを立ててあげればOKです。

volumeMounts:
    - mountPath: /root/.ssh/
        name: ssh-dir
      - mountPath: /etc/ssh/hostKeys/
        name: ssh-host-keys

volumes:
  - name: ssh-dir
    secret:
      secretName: ssh-keys
      defaultMode: 0600
  - name: ssh-host-keys
    secret:
      secretName: ssh-host-keys
      defaultMode: 0600

あとは普通にsshできます。

$ ssh root@<PodのIPアドレス>