Dockerコンテナにsshdが必要ない理由

人々が最初のDockerコンテナを起動すると、「コンテナに入れる方法は?」と尋ねられます。もちろん、この質問に対する「額で」答えは、「SSHサーバーを起動して接続してください!」です。 このトピックの目的は、実際にはコンテナー内にsshdが必要ないことを示すことです(もちろん、コンテナーが実際にSSHサーバーをカプセル化するように設計されている場合を除きます)。



SSHサーバーの起動は、コンテナの「内部」にすばやく簡単にアクセスできるため、魅力的なアイデアです。 誰もがSSHクライアントの使用方法を知っています。私たちは毎日それを行います。パスワードとキーのアクセス、ポート転送に精通しており、一般的にSSHアクセスは身近なものであり、確実に機能します。



しかし、もう一度考えてみましょう。



RedisまたはJava Webサービス用のDockerイメージを構築していると想像してみましょう。 いくつか質問をしたいと思います。



なぜsshが必要なのですか?

ほとんどの場合、バックアップの作成、ログの確認、プロセスの再起動、設定の編集、gdb、strace、または同様のユーティリティを使用したデバッグを行います。 したがって、これはSSHなしで実行できます。



キーとパスワードをどのように管理しますか?

多くのオプションはありません-それらをイメージに「きつく」縫い付けるか、外部ボリュームに配置します。 キーまたはパスワードを更新するために必要なことを考えてください。 縫い付けられている場合は、イメージを再構築し、改造して、コンテナを再起動する必要があります。 世界の終わりではなく、何とかエレガントではありません。 最善の解決策は、データを外部ボリュームに配置し、そのボリュームへのアクセスを制御することです。 これは機能しますが、コンテナにボリュームへの書き込みアクセス権がないことを確認することが重要です。 結局のところ、アクセスがある場合、コンテナはデータを損傷する可能性があり、SSH経由で接続できなくなります。 さらに悪いことに、1つのボリュームが複数のコンテナで認証用のストレージメディアとして使用されると、一度にすべてにアクセスできなくなります。 ただし、これは、どこでもSSHアクセスを使用している場合のみです。



セキュリティ更新プログラムをどのように管理しますか?

SSHサーバーは実際には非常に信頼できるものです。 しかし、これはまだ外の世界への窓です。 そのため、更新プログラムをインストールし、セキュリティを監視する必要があります。 つまり 無害なコンテナ自体には、外部からのハッキングに対して潜在的に脆弱な領域があり、注意が必要です。 私たち自身のために問題を作成しました。



「SSHサーバーを追加するだけ」ですべてが機能しますか?

いや Dockerは1つのプロセスを管理および監視します。 コンテナ内の複数のプロセスを制御する場合は、MonitやSupervisorなどが必要になります。 また、コンテナに追加する必要があります。 したがって、「1つのタスクに1つのコンテナ」という単純な概念を、構築、更新、管理、保守が必要な複雑なものに変えます。



コンテナイメージを作成する責任はありますが、コンテナアクセスポリシーを管理する責任もありますか?

小さな会社では、これは重要ではありません-ほとんどの場合、両方の機能を実行します。 しかし、大規模なインフラストラクチャを構築する場合、1人が画像を作成し、アクセス権の管理にまったく別の人が関与する可能性が高くなります。 したがって、SSHサーバーをコンテナに「埋め込む」ことは最良の方法ではありません。



しかし、どうすれば...





バックアップしますか?


データは外部ボリュームに保存する必要があります。 その後、--volumes-fromオプションを使用して別のコンテナを起動し、同じボリュームにアクセスできます。 この新しいコンテナは、データバックアップタスクを実行するように特別に設計されます。 別の利益:バックアップツールとデータリカバリを更新/交換する場合、すべてのコンテナを更新する必要はありませんが、これらのタスクを実行するように設計されたコンテナのみを更新する必要があります。



ログを確認しますか?


外部ボリュームを使用してください! はい、同じソリューションです。 さて、それが合ったら何ができますか? すべてのログを特定のフォルダーに書き込み、それが外部ボリューム上にある場合、別のコンテナー(「ログインスペクター」)を作成し、その中で必要なことを行うことができます。 繰り返しますが、ログを分析するための特別なツールが必要な場合は、元のコンテナを散らかすことなく、この個別のコンテナにインストールできます。



サービスを再起動しますか?


適切に設計されたサービスは、信号を使用して再起動できます。 foo restartコマンドを実行すると、ほとんどの場合、特定のシグナルがプロセスに送信されます。 docker kill -sコマンドを使用してシグナルを送信できます。 一部のサービスは信号に応答しませんが、TCPソケットやUNIXソケットなどからコマンドを受信します。 外部からTCPソケットに接続できます。UNIXソケットの場合も、外部ボリュームを使用します。



「しかし、それはすべて複雑です!」 -いいえ、そうでもありません。 fooサービスが/var/run/foo.sockにソケットを作成し、 fooctl restartを実行して正しく再起動する必要があると想像してみましょう。 -v / var / runでサービスを開始するだけです(または/ var / runボリュームをDockerfileに追加します)。 サービスを再起動する場合は、同じイメージを--volumes-fromオプションを使用して実行します 。 次のようになります。



#   CID=$(docker run -d -v /var/run fooservice) #       docker run --volumes-from $CID fooservice fooctl restart
      
      







構成を編集しますか?


まず、運用構成の変更を基本的な変更と区別する必要があります。 このイメージに基づいて起動される将来のすべてのコンテナに影響を与える重要な何かを変更する場合は、その変更をイメージ自体に縫い付ける必要があります。 つまり この場合、SSHサーバーは必要ありません。イメージを編集する必要があります。 「しかし、運用上の変更はどうですか?」とあなたは尋ねます。 「結局のところ、サービスの過程で構成を変更する必要があるかもしれません。たとえば、仮想サーバーをWebサーバー構成に追加しますか?」 この場合、... wait-wait ... outer volumeを使用する必要があります! 構成はその上にあるはずです。 「構成エディター」の役割を持つ特別なコンテナーを選択することもできます。必要に応じて、そこにお気に入りのエディター、プラグインなどをインストールします。 そして、これらはすべて基本コンテナには影響しません。

「しかし、私は一時的な編集を行い、さまざまな値を試して結果を確認するだけです!」 さて、この質問に対する答えについては、次のセクションをお読みください。



サービスをデバッグしますか?


そして、コンテナの「内部」で実際のコンソールアクセスが本当に必要な場合になりました。 結局のところ、gdbを実行し、どこかでstraceを実行し、構成を編集する必要があります。 この場合、 nsenterが必要です



nsenterとは



nsenterは、 名前空間の内部を取得できる小さなユーティリティです。 厳密に言えば、既存のネームスペースに入り、新しいネームスペースでプロセスを開始できます。 「ここではどのような名前空間について話しているのですか?」 これはDockerコンテナーに関連する重要な概念であり、コンテナーを互いに独立させ、親オペレーティングシステムから独立させることができます。 詳細に触れない場合: nsenterを使用すると、内部にSSHサーバーがなくても、既存のコンテナーにコンソールアクセスできます。



nsenterはどこで入手できますか?


Githubから: jpetazzo / nsenter 走れる

 docker run -v /usr/local/bin:/target jpetazzo/nsenter
      
      







これによりnsenter/ usr / local / binにインストールれ、すぐに使用できます。 さらに、 nsenterはすでに一部のディストリビューションに統合されています。



使い方は?


まず、内部に入れたいコンテナのPIDを見つけます。

 PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
      
      







コンテナに入ります:

 nsenter --target $PID --mount --uts --ipc --net --pid
      
      







コンテナの「内部」でコンソールにアクセスできます。 スクリプトまたはプログラムをすぐに実行する場合は、それらを引数としてnsenterに追加します。 これはchrootのように少し動作しますが、唯一の違いはディレクトリに関するものではなく、コンテナに関するものです。



リモートアクセスはどうですか?




Dockerコンテナへのリモートアクセスが必要な場合は、少なくとも2つの方法があります。





最初の方法は非常に簡単ですが、ホストマシンのルート権限が必要です(セキュリティポイントからはあまり良くありません)。 2番目の方法では、SSH認証キーの特別な「 コマンド 」機能を使用します。 次のような「クラシックな」 authorized_keysを見たことがあるでしょう。



 ssh-rsa AAAAB3N…QOID== jpetazzo@tarrasque
      
      





(もちろん、実際のキーははるかに長くなります。)ここで、特定のコマンドを指定できます。 特定のユーザーにSSHアクセスを使用してマシンの空きRAMの量をチェックさせたいが、コンソールへのフルアクセスを与えたくない場合は、 authorized_keysに次のように記述できます。



 command="free" ssh-rsa AAAAB3N…QOID== jpetazzo@tarrasque
      
      







これで、ユーザーがこのキーを使用して接続すると、無料コマンドがすぐに起動されます。 そして、何も開始できません。 (技術的には、 no-port-forwardingを追加することができます。authorized_keysのマンページの詳細を参照してください)。 このメカニズムの考え方は、権限と責任の分離です。 アリスはコンテナイメージを作成しますが、運用サーバーにはアクセスできません。 Bettyには、デバッグのためにリモートアクセスする権利があります。 シャーロット-ログの表示専用。 等



結論



すべてのDockerコンテナでSSHサーバーを実行するのは本当に単純なことですか? 正直に言うと、これは災害ではありません。 さらに、これはホストシステムにアクセスできない場合でも唯一のオプションかもしれませんが、コンテナ自体にアクセスする必要があります。 しかし、この記事で見たように、コンテナーにSSHサーバーを配置せずに、必要なすべての機能にアクセスできると同時に、非常に洗練されたシステムアーキテクチャを実現する方法はたくさんあります。 はい、dockerはこれを行うことができます。 しかし、Dockerコンテナーをこのような「ミニVPS」に変える前に、これが本当に必要であることを確認してください。



All Articles