ボリュームとマウント
このラボは本物のVM上で動きます
この環境はPodではなく、KubeVirtが起動した仮想マシンです。Linuxカーネルが別に動き、systemdが実際にサービスを管理し、dockerは模倣ではなく本物のDockerエンジンです。docker runで起動したコンテナは実際にプロセスになり、docker execもdocker logsもそのまま動作します。
以前はこのラボがPodの中で動いていました。カーネル権限をすべて落とした環境だったため、コンテナを起動するステップが塞がれており、イメージアーカイブを自分で展開してみるという回り道で学んでいました。もう回り道は必要ありません。
知っておくべきことが2つあります。
- 最初の起動に1分ほどかかります。VMが起動してDockerをインストールするためです。Podのラボ(通常40秒)より遅くなります。
- ブラウザープレビューはありません。VMへの接続は、採点用のポート1つしか開いていません。Webサーバーを起動した場合は、VMの中で
curlを使って確認してください。
目標
ボリューム・バインド・読み取り専用のマウントを自分で作り、コンテナを削除してもデータが残ることと、バックアップ・復元が往復できることを確認します。
なぜ重要なのか
「コンテナは状態を持たない」という言葉は、コンテナが状態を扱えないという意味ではなく、状態をコンテナの外に置きなさいという意味です。この区別ができないと、再デプロイのたびにデータが消えるか、逆に、ボリュームが雪だるま式に溜まっても誰も削除できない状態になります。もう1つあります。読み取り専用マウントは、パフォーマンスではなく意図の宣言です。このコンテナが何を書き込んではいけないのかをマニフェストに書いておけば、あとでそのルールを破るコードがデプロイされた瞬間、静かに見過ごされずにエラーとして表れます。
ステップ
/root/ops1を作成し、dk-dataという名前付きボリュームを作ります。dk-writerというコンテナでdk-dataを/dataにマウントし、/data/hello.txtにvolume-aliveを書き込みます。dk-writerコンテナを削除したあと、新しいコンテナで同じボリュームを読んで内容が残っているかを確認し、その出力を/root/ops1/persist.txtとして保存します。/root/ops1/site/index.htmlを作成してlabhub-siteを入れ、nginx:1.27-alpineをdk-siteという名前で起動します。このとき、/root/ops1/siteを/usr/share/nginx/htmlにバインドマウントします。dk-roコンテナを起動し、dk-dataを/dataに読み取り専用でマウントして、その中でファイルの書き込みを試み、出力されたエラーメッセージを/root/ops1/ro-error.txtとして保存します。dk-site2コンテナを--mount構文で起動し、ステップ4と同じ元と先で接続します。ただし読み取り専用にします。dk-dataボリュームの内容を/root/ops1/dk-data.tgzにバックアップします。アーカイブの中にhello.txtが入っている必要があります。dk-data-restoreという新しいボリュームを作り、バックアップを復元します。元と内容が同じである必要があります。
参考
- 一時的な作業用のコンテナは
docker run --rmで起動すると、後始末が不要です。 - バックアップは
docker run --rm -v dk-data:/source:ro -v /root/ops1:/backup alpine:3.20 tar czf /backup/dk-data.tgz -C /source .の形です。 - よくある間違い1: ステップ5でコンテナがすぐに終了してしまうと、採点対象が残りません。バックグラウンドで動き続けるようにしてください。
- よくある間違い2: ステップ7で
-Cなしに絶対パスのまま格納すると、復元時にパスがずれます。
名前付きボリュームを作る
/root/ops1を作成し、dk-dataという名前付きボリュームを作ります。
ボリュームを扱うサブコマンドのグループが別にあります。作るだけでよく、まだコンテナは必要ありません。
ボリュームにファイルを書き込む
dk-writerというコンテナでdk-dataを/dataにマウントし、/data/hello.txtにvolume-aliveを書き込みます。
コンテナを起動してボリュームをマウントし、ファイルを書き込みます。名前を付けておいてください。次のステップで、その名前のコンテナを削除します。
コンテナを削除しても残るか
dk-writerコンテナを削除したあと、新しいコンテナで同じボリュームを読んで内容が残っているかを確認し、その出力を/root/ops1/persist.txtとして保存します。
ファイルを書き込んだコンテナを削除したあと、新しいコンテナで同じボリュームを読んでみてください。確認した内容は、ファイルにも残します。
ホストのディレクトリをそのまま接続する
/root/ops1/site/index.htmlを作成してlabhub-siteを入れ、nginx:1.27-alpineをdk-siteという名前で起動します。このとき、/root/ops1/siteを/usr/share/nginx/htmlにバインドマウントします。
バインドマウントは、ホストのパスを直接指定します。nginxのデフォルトのドキュメントルートのパスに接続すると、すぐに確認できます。
読み取り専用で接続する
dk-roコンテナを起動し、dk-dataを/dataに読み取り専用でマウントして、その中でファイルの書き込みを試み、出力されたエラーメッセージを/root/ops1/ro-error.txtとして保存します。
マウントオプションに読み取り専用のフラグを付けて、中で書き込みを試み、出力されたエラーメッセージをそのまま保存してください。
--mount構文で書き直す
dk-site2コンテナを--mount構文で起動し、ステップ4と同じ元と先で接続します。ただし読み取り専用にします。
短い形式と同じ結果になる必要があります。type、source、target、readonlyを、カンマで区切ってつなげます。
ボリュームをバックアップする
dk-dataボリュームの内容を/root/ops1/dk-data.tgzにバックアップします。アーカイブの中にhello.txtが入っている必要があります。
ボリュームとバックアップ先のディレクトリを同時にマウントした一時コンテナを使います。-Cでソースの中に入ると、パスがきれいになります。
新しいボリュームに復元する
dk-data-restoreという新しいボリュームを作り、バックアップを復元します。元と内容が同じである必要があります。
新しいボリュームを作り、アーカイブを展開して入れてください。元と内容がまったく同じである必要があります。