zaki work log

作業ログやら生活ログやらなんやら

[Docker / Kubernetes] コンテナでOpenSSHサーバーを立てる

検証用などでリモートにSSHサーバーが必要な際に、linuxserver/openssh-server のコンテナを使うと簡単に準備できる。

github.com

認証情報やrootへの昇格設定をすべて環境変数でセットできるためアクセス方法の自由度が高いのが特徴。たぶん。
ベースはAlpine Linuxなので軽量。

使い方

Docker HubのOverviewに必要事項は全部書かれているが基本的に以下の認証設定を押さえておけばすぐに使える。
ただしポートは2222/tcp固定。

ベースとなるコンテナ起動コマンドは以下。
ユーザー名はzakiとする。

docker run -d \
  -e USER_NAME=zaki \
  lscr.io/linuxserver/openssh-server:latest

認証設定

パスワード認証の場合

デフォルトは鍵認証のみ(というかPasswordAuthenticationno)
パスワード認証を有効にするにはPASSWORD_ACCESStrueにセットした上で、認証に使用するパスワードをUSER_PASSWORDに指定する。

docker run -d \
  -e USER_NAME=zaki \
  -e USER_PASSWORD=curry_tabetai \
  -e PASSWORD_ACCESS=true \
  lscr.io/linuxserver/openssh-server:latest
zaki@cloud-dev2:~$ ssh zaki@172.17.0.2 -p 2222
The authenticity of host '[172.17.0.2]:2222 ([172.17.0.2]:2222)' can't be established.
ED25519 key fingerprint is SHA256:Y2iOtf/txdhXB5LK2G0Vg2mv5dXEjK5ZIoyfSzfl09o.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[172.17.0.2]:2222' (ED25519) to the list of known hosts.
zaki@172.17.0.2's password:   # ここにUSER_PASSWORDで指定したパスワードを入力
Welcome to OpenSSH Server
166d399aaee7:~$ 

検証用だからええやんとは思いつつ、パスワードを引数にべた書きしたくない場合は、ファイルにパスワードを記載してそれを引数にしてもOK
ただし、パスワードファイルはホストOSでなくコンテナ内に存在する必要があるので、バインドマウントでコンテナから参照できるようにしつつパスを指定する。

以下はカレントにcurry_tabetaiと書かれたpass.txtファイルがある場合。
これをコンテナの/tmp/pass.txtとして参照できるようにして起動する。

docker run -d \
  -e USER_NAME=zaki \
  -e USER_PASSWORD_FILE=/tmp/pass.txt \
  -e PASSWORD_ACCESS=true \
  -v ./pass.txt:/tmp/pass.txt \
  lscr.io/linuxserver/openssh-server:latest

鍵認証の場合

公開鍵を設定するための変数をセットする。

docker run -d \
  -e USER_NAME=zaki \
  -e PUBLIC_KEY="ssh-rsa AAAAB3Nz......." \
  lscr.io/linuxserver/openssh-server:latest
$ ssh zaki@172.17.0.2 -p 2222 -i ~/.ssh/privatekey
The authenticity of host '[172.17.0.2]:2222 ([172.17.0.2]:2222)' can't be established.
ED25519 key fingerprint is SHA256:N5zBaCP+ZuXXwThg4//PPvDz/GkxiETIp5d/Tz29g3Y.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[172.17.0.2]:2222' (ED25519) to the list of known hosts.
Welcome to OpenSSH Server
3021f56ab182:~$ 

この通り鍵認証でアクセスできる。

パスワードの時と同様に鍵情報を引数にべた書きしたくなくファイル渡ししたい場合は、PUBLIC_KEY_FILEで指定できる。ただしパスワードの時と同様にコンテナ内のパスを指定する。

docker run -d \
  -e USER_NAME=zaki \
  -e PUBLIC_KEY_FILE=/tmp/id.pub \
  -v ./.ssh/id_rsa.pub:/tmp/id.pub \
  lscr.io/linuxserver/openssh-server:latest

また、UbuntuのOSインストールの時のように、たとえばGitHubのようにオンライン上に公開鍵が保存されている場合は、URL指定も可能。

docker run -d \
  -e USER_NAME=zaki \
  -e PUBLIC_KEY_URL=https://github.com/zaki-lknr.keys \
  lscr.io/linuxserver/openssh-server:latest

root昇格

要はコンテナのシェルでsudoを使えるようにするかどうか。

パスワード認証の場合は、認証に使うパスワードで昇格できる。
鍵認証設定の場合でかつパスワード認証を未設定の場合は、パスワード不要で昇格できる。

今までのコマンドのパターンに-e SUDO_ACCESS=trueを加えればOK

Docker Composeの場合

上の説明があれば公式READMEのdocker-composeの記述に当てはめれば問題ないはず。

github.com

Kubernetesの場合

Dockerと違ってファイル渡しは基本的に難しいけど、環境変数でパラメタを渡すだけであれば簡単にクラスター上にSSHサーバーをデプロイできる。
レプリカ数を操作することで簡単に複数のSSHサーバーを並べることもできる。
IPリーチするにはLoadBalancer Serviceなどの工夫が必要なので使い方は限られるけど。

Deploymentでデプロイするには以下のようなマニフェストを用意すればOK

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sample-server
  name: sample-server
spec:
  replicas: 10
  selector:
    matchLabels:
      app: sample-server
  template:
    metadata:
      labels:
        app: sample-server
    spec:
      containers:
      - image: lscr.io/linuxserver/openssh-server:latest
        name: sample-server
        env:
        - name: USER_NAME
          value: zaki
        - name: USER_PASSWORD
          value: curry_tabetai
        - name: PASSWORD_ACCESS
          value: "true"

true/falseの指定はクォートしないと文字列でなくbooleanと解釈されて動作しないので注意。


ちなみにPythonは入ってないので、そのままではAnsibleの処理対象ノードとしては使えないので追加したりする必要がある。
固定の接続情報でSSHサーバーを立てたうえでいろいろカスタマイズするのであれば、もっと別のベースイメージからビルドした方がよいと思うが、「SSHで接続さえできればOKで、認証情報を柔軟に設定したい」であれば使い勝手は良いと思う。