Dockerはボリュームの永続化にOpenStack Cinderを使用する

Dockerはボリュームの永続化にOpenStack Cinderを使用する

1 背景

1.1 OpenStack Cinder の紹介

OpenStack Cinder は、OpenStack にブロック ストレージ サービスを提供します。その機能はAWSのEBSサービスに似ています。現在、OpenStack Nova 仮想マシンに仮想ハードディスク機能を提供する、つまり、追加の弾性ハードディスクとして仮想マシンにボリュームをマウントするために最も一般的に使用されています。 OpenStack Cinder ボリュームを仮想マシンにマウントするプロセスの分析については、以前のブログ「OpenStack 仮想マシンにデータ ボリュームをマウントするプロセスの分析」を参照してください。このブログは、この記事の内容を理解するための基礎でもあります。

[[207107]]

ただし、OpenStack Cinder は Nova 仮想マシンにクラウド ディスク機能を提供するだけではありません。実際、Cinder は誰がそのボリュームを消費しているかを気にしません。仮想マシンに加えて、物理マシンやコンテナの場合もあります。 Cinder ボリュームを物理マシンにマウントする方法は以前に紹介しました。 OpenStack における稀ではあるが役に立つ操作を参照できます。 Cinderボリュームを仮想マシンと物理マシンにマウントする方法を紹介しました。最後に残っているのは、Cinder ボリュームを Docker コンテナにマウントする方法です。この記事では、それを詳しく紹介し、2つのドライバーの例を通して実践していきます。

1.2 Dockerボリュームの概要

Docker コンテナ自体はステートレスであるため、コンテナが終了した後はデータは保存されないことがわかっています。ただし、実際の使用シナリオでは、ビジネスデータを保存する必要があります。 Docker はボリュームを使用して永続的なストレージとデータ共有を実現します。

デフォルトでは、Docker はローカル ディレクトリをコンテナのボリュームとして使用し、コンテナ インスタンスによって指定されたパスにマウントします。ユーザーは、次のように既存のパスを Docker ボリュームとして指定できます。

  1. mkdirデータ
  2. docker run -t -i --rm -v `pwd`/data:/data busybox  

上記のコマンドは、ローカル データ ディレクトリをコンテナーの /data パスにマウントします。ソース ディレクトリ パスには絶対パスを使用する必要があることに注意してください。そうでない場合、Docker はそれをボリューム名として扱います。

ローカル パスを指定することはできません。その場合、Docker は Docker ボリュームとして新しい空のディレクトリを自動的に作成します。

  1. docker run -t -i --rm -v /data ビジーボックス 

作成されたボリュームを表示するには、docker volume ls を使用します。

  1. $ dockerボリュームls
  2. ドライバーボリューム 
  3. ローカル0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788

ソース パスを表示するには、inspect サブコマンドを使用します。

  1. $ docker ボリューム検査 0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788
  2. [
  3. {
  4. 「作成日時」 : 「2017-09-30T17:21:56+08:00」
  5. 「ドライバー」 「ローカル」
  6. 「ラベル」 : null
  7. 「マウントポイント」 : 「/var/lib/docker/volumes/0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788/_data」
  8. 「名前」 : 「0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788」
  9. 「オプション」 : {},
  10. 「スコープ」 「ローカル」  
  11. }
  12. ]

上記の出力から、ローカル ソース ディレクトリは /var/lib/docker/volumes/0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788/_data であり、Docker によって自動的に作成されていることがわかります。

このことから、Docker によって作成されたボリュームは現在のホスト マシンのコンテナーにのみ使用でき、他のホストのコンテナーにマウントすることはできないこともわかります。この場合、一部のステートレス サービスのみを実行できます。 HA を満たす必要があるステートフル サービスの場合、ホスト マシンがハングアップした後でもコンテナーを別のホスト マシンに移行できるように、分散共有ボリュームを使用してデータを永続化する必要があります。 Docker 自体は分散共有ストレージ ソリューションを提供しませんが、代わりにプラグイン メカニズムを通じてサードパーティのストレージ システムと統合します。これについては次のセクションで詳しく説明します。

1.3 Dockerボリュームプラグインの紹介

前述したように、Docker 自体は分散共有ボリューム ソリューションを提供しませんが、代わりにサードパーティの分散共有システムを統合できる柔軟なプラグイン メカニズムを提供します。ユーザーは、プラグイン ドライバー インターフェイスを実装するだけで、独自のストレージ システムに接続できます。たとえば、現在非常に人気のあるオープンソースの分散ストレージ システムである Ceph、AWS EBS、OpenStack Cinder などです。これらの外部ストレージ システムをプロバイダーと呼びます。

公式のボリューム プラグイン プロトコル ドキュメントでは次の点が強調されていることに言及する価値があります。

  • プラグインがアクティブ化されたときに VolumeDriver として登録される場合、ホスト ファイル システム上の書き込み可能なパスを Docker デーモンに提供する必要があります。

つまり、Docker は外部ストレージ システムを直接読み書きすることはできず、ストレージ システムをホスト マシンのローカル ファイル システムにマウントする必要があります。 Docker はそれをローカル ディレクトリとしてコンテナにマウントします。つまり、外部ストレージデバイスをローカルファイルシステムにマウントできる限り、Docker ボリュームとして使用できます。たとえば、ceph rbd の場合、最初にローカルにマッピングし、ホストによって指定されたパスにマウントする必要があります。このパスはパスと呼ばれます。これは仮想マシンとは異なります。 rbd が仮想マシンにマウントされると、QEMU はローカルにマッピングすることなく、rbd プロトコルを介して直接読み取りおよび書き込みを行うことができます。

Docker マウント分散ストレージ システムの原理を理解するには、まず公式に定義されたプラグイン プロトコル インターフェイスを理解する必要があります。

  • create: ボリュームを作成します。
  • 削除: ボリュームを削除します。
  • mount: ボリュームをコンテナにマウントします。
  • umount: コンテナからボリュームをアンマウントします。
  • get/list: ボリューム情報を取得します。

上記の作成と削除は比較的簡単です。 2 つのコア インターフェイスは mount と umount です。ストレージ システムによってインターフェースの実装が異なります。ここでは、Cinder インターフェースの実装のみを扱います。これまであまり研究したことがなかったので、これまでに学んだ知識を使って、Cinder ボリュームを使用した Docker の実装原理について大胆に推測してみましょう。

1.4 DockerはCinderボリューム原則の推測を使用する

以前、Docker プラグイン インターフェースを紹介しました。ここで、OpenStack Cinder に接続する必要があるとします。 Cinder ストレージ バックエンドは LVM を使用します。 Docker プラグイン インターフェースは次のように実装されていると推測されます。

  • create: Cinder API を直接呼び出してボリュームを作成します。
  • リモート: Cinder API を直接呼び出してボリュームを削除します。
  • get/list: Cinder API を直接呼び出してボリューム リストを取得します。
  • mount: 前述のように、Docker ボリュームは最初にローカルにマウントする必要があります。これは、Cinder の local-attach とまったく同じです。詳細については、OpenStack におけるまれではあるが便利な操作を参照してください。ローカル デバイスにローカル接続した後、ブロック デバイスにファイル システムがインストールされていない場合は、マウント操作でファイル システムをフォーマットする必要もあります。ファイル システムを作成したら、それをホスト ファイル システムにマウントするだけです。 Docker は、基盤となるストレージ システムが何であるかを気にしません。単にホストのディレクトリとして扱います。残りの作業は、Docker がローカル ディレクトリをマウントする場合と同じです。
  • umount: 説明は必要ありません。非常に明確で、ローカル ファイル システムから umount し、ローカル デバイスから切り離すだけです。

Docker で Cinder ボリュームをマウントするためのソリューションは多数あります。たとえば、次のようになります。

  • docker cinder ドライバー: コンテナーで OpenStack-Cinder Block Storage を使用できるようにする Docker ボリューム プラグイン。
  • fuxi: Docker コンテナが Cinder ボリュームと Manila 共有を使用できるようにします。
  • REX-Ray: Docker や Mesos などのコンテナ ランタイムをサポートするように設計されたストレージ管理ソリューション。
  • Flocker: Flocker は、Docker 化されたアプリケーション用のオープンソースのコンテナ データ ボリューム オーケストレーターです。

上記の原則は単なる私たちの推測です。この推測が正しいかどうかは、上記のスキームを研究し、実践することで検証できます。

2 Docker Cinder ドライバーの実践

2.1 Docker Cinder ドライバーの紹介

docker-cinder-driver は john griffith によって開発され、Cinder ボリューム ドライバーをマウントするための Docker を実装します。著者は、Nova 以外のブロック ストレージである Cinder を紹介する特別ブログも書いています。また、OpenStack Days East 2016: Consuming Cinder from Docker での著者の共有 pptslides や、2016 Austin の共有ビデオ Cinder and Docker like peanut butter and chocolate も参照できます。

2.2 環境整備

実験の前に、DevStack ツールを使用して allinone OpenStack テスト環境をデプロイしました。コードは最新のマスター ブランチに基づいており、対応する Cinder コミットは 2b58f2bb04c229c738b5cc806575ed3503fd1bfe です。 Cinder は LVM バックエンド ストレージを使用し、構成は次のとおりです。

  1. [lvmドライバ-1]
  2. イメージボリュームキャッシュが有効 = True  
  3. ボリュームクリア = ゼロ
  4. lvm_type = 自動
  5. iscsi_helper = tgtadm
  6. ボリュームグループ = スタックボリューム-lvmdriver-1
  7. ボリュームドライバ = cinder.volume.drivers.lvm.LVMVolumeDriver
  8. ボリュームバックエンド名 = lvmdriver-1

以降のすべての操作はこの DevStack 環境で実行され、再度強調されることはありません。

docker cinder ドライバーのドキュメントには、install.sh スクリプトを通じて直接ダウンロードできると記載されています。

  1. 次のコマンドを実行して、docker ドライバーをインストールします。シュ

ただし、この方法でダウンロードしたコードは、最新のコードでコンパイルされていない可能性があります (個人テストには落とし穴があります)。最新バージョンを使用するには、手動でコンパイルするしかありません。まず、Go 開発環境をインストールする必要があります。 go言語開発環境については、公式のインストールドキュメントを参照してください。

Ubuntu は apt-get を使用して直接インストールできます。

  1. sudo apt-get で golang-go をインストールします

cinder-docker-driver ソース コードをローカル コンピューターにダウンロードします。

  1. git クローン https://github.com/j-griffith/cinder-docker-driver

go build を使用して直接コンパイルします。

  1. cd cinder-docker-driver
  2. mkdir -p ベンダー/ソース
  3. ln -s `pwd`/vendor/golang.org/ vendor/src
  4. ln -s `pwd`/vendor/github.com vendor/src
  5. GOPATH=`pwd`/vendor をエクスポートします
  6. 構築する

主に Cinder の認証情報を含む設定ファイルを作成します。

  1. mkdir -p /var/lib/cinder/dockerdriver
  2. cat >/var/lib/cinder/dockerdriver/config.json <<EOF
  3. {
  4. 「エンドポイント」 : 「http://10.0.2.15/identity/v3」
  5. 「ユーザー名」 : 「admin」
  6. 「パスワード」 : 「nomoresecret」
  7. 「テナントID」 : 「ae21d957967d4df0865411f0389ed7e8」
  8. 「ドメイン名」 : 「デフォルト」
  9. 「リージョン」 「リージョン 1」  
  10. }
  11. 終了

エンドポイントは認証 URL です。バージョン /v3 が含まれており、DomainName 構成項目が含まれている必要があることに注意してください。

設定が完了したら、cinder-docker-driver サービスを直接実行できます。

  1. nohup ./cinder-docker-driver &  
  2. テールf ./nohup

2.3 機能検証

次のようにして Docker を使用してボリュームを作成します。

  1. root@devstack:~# docker ボリューム作成-d cinder --name int32bit-test-1 -o size=2  
  2. int32bit-テスト-1
  3. root@devstack:~# docker ボリューム ls
  4. ドライバーボリューム 
  5. cinder int32bit-テスト-1

コンテナを起動し、int32bit-test-1 をマウントします。

  1. root@devstack:~# docker run -t -i --rm -v int32bit-test-1:/int32bit-test-1 busybox  
  2. / # cd /int32bit-test-1/
  3. /int32bit-テスト-1 # ls
  4. 紛失物+拾得物
  5. /int32bit-test-1 # echo "HelloWorld" >hello.txt
  6. /int32bit-テスト-1 # ls
  7. hello.txt 紛失+発見
  8. /int32bit-テスト-1 #

上記では、先ほど作成したボリュームを /int32bit-test-1 にマウントし、hello.txt ファイルに HelloWorld を書き込みました。

コンテナを起動したときの cinder-docker-driver ログは次のとおりです。

  1. 時刻= "2017-09-29T21:29:44+08:00"  レベル=debug msg= "ボリューム ID が見つかりました: 58837c2b-af79-4f89-97ea-40e2622d2c52"  
  2. 時刻= "2017-09-29T21:29:44+08:00"  レベル=debug msg= "イニシエーター IQN を収集します..."  
  3. 時刻= "2017-09-29T21:29:44+08:00"  レベル=debug msg= "次の iqn が見つかりました: [iqn.1993-08.org.debian:01:19a8a9ca754f]"  
  4. 時刻= "2017-09-29T21:29:44+08:00"  レベル= デバッグ メッセージ = "IP の値は = [127.0.0.1/8 10.0.2.15/24 192.168.99.101/24 192.168.122.1/24 172.17.0.1/16 ::1/128 fe80::a00:27ff:fe94:2f20/64 fe80::a00:27ff:fe69:2326/64 fe80::42:bcff:fee4:89ac/64]\n"  
  5. 時刻= "2017-09-29T21:29:44+08:00"  レベル=debug msg= "InitializeConnection を発行します..."  
  6. 時刻= "2017-09-29T21:29:47+08:00"  レベル=debug msg= "引数を使用してノード エントリを作成します: [-m node -T iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52 -p 10.0.2.15:3260]"  
  7. 時刻= "2017-09-29T21:29:47+08:00"  レベル=debug msg= "ユーザー名を 36eDQkERhAAKXGi8CMFC に更新"  
  8. 時刻= "2017-09-29T21:29:47+08:00"  レベル=debug msg= "パスワードを次のものに更新: GLFkwC6eV8abbtk8"  
  9. 時刻= "2017-09-29T21:29:48+08:00"   level =info msg= "エラーなしで iSCSI ターゲットにログインしました: [-m node -T iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52 -p 10.0.2.15:3260 --login]"  
  10. 時刻= "2017-09-29T21:29:48+08:00"  レベル=info msg= "パスを待機中"  
  11. 時刻= "2017-09-29T21:29:49+08:00"  レベル= デバッグ メッセージ = "パスが見つかりました: /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1"  
  12. 時刻= "2017-09-29T21:29:49+08:00"  レベル= デバッグ メッセージ = "utils.getDeviceFileFromIscsiPath を開始します: /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1"  
  13. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "デバイスが見つかりました: [lrwxrwxrwx 1 root root 9 Sep 29 21:29 /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1 -> sdd\n]"  
  14. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "/dev/sdd のベースを使用"  
  15. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "(パス、デバイスファイル) にボリュームが接続されました: /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1、/dev/sdd"  
  16. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "iSCSI 接続が完了しました"  
  17. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "utils.GetFSType を開始します: /dev/sdd"  
  18. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "デバイスをフォーマットしています"  
  19. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "utils.FormatVolume を開始します: /dev/sdd、ext4"  
  20. 時刻= "2017-09-29T21:29:49+08:00"  レベル=debug msg= "デバイス: /dev/sdd で mkfs.ext4 を実行します"  
  21. 時刻= "2017-09-29T21:29:50+08:00"   level =debug msg="mkfs コマンド結果: mke2fs 1.42.13 (2015 年 5 月 17 日)\ n524288 個の 4k ブロック131072 個の inodeを持つファイルシステムを作成しています\nファイルシステム UUID: 02318688-7448-4d25-98dd-0527a2bd9733
  22. ブロック保存されるスーパーブロックのバックアップ:
  23. 32768、98304、163840、229376、294912
  24. グループテーブルの割り当て: 0/16 完了
  25. inode テーブルの書き込み: 0/16 完了
  26. ジャーナルを作成中 (16384 ブロック): 完了
  27. スーパーブロックファイルシステムのアカウンティング情報の書き込み: 0/16 完了"
  28. 時刻= "2017-09-29T21:29:50+08:00"  レベル=debug msg= "ユーティリティを開始します。デバイス: /dev/sdd を /var/lib/cinder/mount/int32bit-test-1 にマウントします"  
  29. 時刻= "2017-09-29T21:29:50+08:00"  レベル=debug msg= "/var/lib/cinder/mount/int32bit-test-1 のマウント /dev/sdd からの応答: "  
  30. 時刻= "2017-09-29T21:29:50+08:00"  レベル=debug msg= "gophercloud Attach を呼び出します..."  
  31. 時刻= "2017-09-29T21:29:50+08:00"  レベル=debug msg= "結果を添付: {ErrResult:{Result:{Body:<nil> Header:map[] Err:<nil>}}}"  

ログから、ボリュームをマウントする本質は、ボリュームを iscsi 経由でローカル コンピューターに接続し (ローカル接続)、ext4 ファイル システムとしてフォーマットしてから、ホスト マシンの /var/lib/cinder/mount ディレクトリにマウントすることであることがわかります。これは基本的に私たちの推測と同じです。

これは lsblk で確認できます:

  1. ルート@devstack:~/cinder-docker-driver# lsblk -s | grep int32bitテスト 
  2. sdd 8:48 0 2G 0 ディスク /var/lib/cinder/mount/int32bit-test-1

Docker コンテナ インスタンスを終了すると、ボリュームはローカル マシンから自動的に切断されます。

作成したボリュームを手動でローカルマシンに接続し、マウントするには、cinder を使用します。 Cinder のローカル アタッチの詳細については、OpenStack でのまれではあるが便利な操作を参照してください。

  1. root@devstack:~# cinder リスト
  2. + --------------------------------------+----------+---------------------+------+-------------+----------+-------------+  
  3. | ID |ステータス |名前|サイズ|ボリュームタイプ |起動可能 |添付|
  4. + --------------------------------------+----------+---------------------+------+-------------+----------+-------------+  
  5. | 58837c2b-af79-4f89-97ea-40e2622d2c52 |利用可能 | int32bit-テスト-1 | 2 | lvmドライバ-1 |誤り| |
  6. + --------------------------------------+----------+---------------------+------+-------------+----------+-------------+  
  7. root@devstack:~# cinderローカル-attach 58837c2b-af79-4f89-97ea-40e2622d2c52
  8. + ----------+-----------------------------------+  
  9. |プロパティ |価値 |
  10. + ----------+-----------------------------------+  
  11. |パス | /dev/sdd |
  12. | scsi_wwn | 360000000000000000e000000000010001 |
  13. |タイプ |ブロック |
  14. + ----------+-----------------------------------+  
  15. root@devstack:~# /dev/sdd /mnt をマウントします

先ほど書いたファイルを確認してください:

  1. root@devstack:~# cat /mnt/hello.txt
  2. こんにちは世界

コンテナを通じて書き込んだHelloWorldが出力されていることがわかります。

docker cinder ドライバーは基本的に、以前の推測が正しいことを確認しました。

3 伏羲

3.1 伏羲プロジェクトの紹介

OpenStack fuxi は比較的新しいプロジェクトです。もともとはマグナム プロジェクトから分離され、2016 年 2 月 26 日に OpenStack コミュニティによってコミュニティ プロジェクトとして承認されました。現在は主に Huawei によって開発されています。その目的は、Docker コンテナが Cinder ボリュームと Manila 共有を永続ストレージ ボリュームとして使用できるようにすることです。

3.2 環境の準備

OpenStack 環境では、以前の DevStack 環境が引き続き使用されます。 fuxiのインストールプロセスは次のとおりです。

まず、依存パッケージをインストールします。実際、これらのパッケージは基本的に DevStack にインストールされています。

  1. sudo apt-getアップデート 
  2. sudo apt-get install python-dev git libffi-dev libssl-dev gcc
  3. sudo apt-get install open -iscsi
  4. sudo apt-get sysfsutils をインストールします

fuxi ソースコードをダウンロードしてインストールします:

  1. git クローン https://github.com/openstack/fuxi.git
  2. cd フクシ
  3. sudo pip インストール -r requirements.txt
  4. sudo python setup.py インストール
  5. ln -s /lib/udev/scsi_id /usr/ local /bin #ルート

generate_config_file_samples.sh を実行して構成ファイル テンプレートを生成し、それを /etc/fuxi ディレクトリにコピーします。

  1. ./tools/generate_config_file_samples.sh
  2. sudo cp etc/fuxi.conf.sample /etc/fuxi/fuxi.conf

設定ファイルを修復します。最終的な構成ファイルは次のようになります。

  1. root@devstack:~# cat /etc/fuxi/fuxi.conf | grep -v '^#' | grep -v '^$'  
  2. [デフォルト]
  3. 私のIP = 10.0.2.15
  4. ボリュームプロバイダ = cinder
  5. [燃え殻]
  6. リージョン名 = リージョン1
  7. ボリュームコネクタ = osbrick
  8. ファイルタイプ = ext4
  9. 認証URL = http://10.0.2.15/identity/v3
  10. プロジェクト名 = 管理者
  11. project_domain_name =デフォルト 
  12. ユーザー名 = admin
  13. user_domain_name =デフォルト 
  14. パスワード= nomoresecret
  15. [キーストーン]
  16. [マニラ]
  17. ボリュームコネクタ = osbrick
  18. auth_type =パスワード 
  19. [新星]

auth_url には /v3 などのバージョンを含める必要があることに注意してください。

サービスを開始します:

  1. fuxi-server --config-file /etc/fuxi/fuxi.conf  

3.3 機能検証

Docker を使用してボリュームを作成します。

  1. $ docker ボリューム作成-d fuxi --name int32bit-test-fuxi  
  2. int32bit テスト fuxi
  3. docker ボリューム ls | grep int32bit-テスト-fuxi
  4. fuxi int32bit-テスト-fuxi

ボリュームを Docker コンテナにマウントします。

  1. $ docker run -ti --rm -v int32bit-test-fuxi:/int32bit-test-fuxibusybox  
  2. / # cd /int32bit-test-fuxi/
  3. /int32bit-test-fuxi # ls
  4. a b c 紛失+拾得

ボリュームが実際にローカル パスにマップされていることを確認できます。

  1. $ lsblk -Sf
  2. 名前HCTL タイプ ベンダー モデル REV トランザクションFSTYPE ラベル UUID マウントポイント
  3. sda 2:0:0:0 ディスク ATA VBOX ハードディスク 1.0 sata sda
  4. sdb 11:0:0:1 ディスク IET 仮想ディスク 0001 iscsi sdb ext4 d04b16a1-3392-41df-999f-e6c36b5d0cd6 /fuxi/data/cinder/int32bit-test-fuxi
  5. sr0 1:0:0:0 rom VBOX CD-ROM 1.0 ata sr0

fuxi は最初にボリュームをローカル コンピューターに接続し、指定されたパスにマウントしてから、Docker コンテナーにマウントしていることがわかります。これは私たちの推測と一致しています。次に、ソースコードの観点から分析します。

3.4 Dockerはfuxiを使用してボリュームソースコード分析をマウントします

Fuxi のマウントは、fuxi/volumeprovider/cinder.py モジュールの Cinder クラスを通じて実装されます。このクラスは、前に紹介した Docker ボリューム プラグイン インターフェイスに対応する provider.Provider インターフェイスを実装します。私たちは主にそのマウント方法を研究します:

  1. t(自分、docker_volume_name):
  2. cinder_volume、状態 = self._get_docker_volume(docker_volume_name)
  3. LOG.info( "状態 %(st)s の Docker ボリューム %(d_v)s %(vol)s を取得します" ,
  4. { 'd_v' : docker_volume_name, 'vol' : cinder_volume,
  5. 'st' : 状態})
  6.  
  7. コネクタ = self._get_connector()
  8. 状態 == NOT_ATTACH の場合:
  9. コネクタ.connect_volume(cinder_volume)
  10. elif 状態 == ATTACH_TO_OTHER:
  11. cinder_volume.multiattachの場合:
  12. コネクタ.connect_volume(cinder_volume)
  13. それ以外
  14. msg = _( "ボリューム {0} {1} は共有できません" ).format(
  15. docker_volume_name、cinder_volume)
  16. 例外を発生させます。FuxiException(msg)
  17. elif 状態 != ATTACH_TO_THIS:
  18. msg = _( "ボリューム %(vol_name)s %(c_vol)s は正しい状態ではありません。"  
  19. 「現在の状態は %(state)s です」 )
  20. LOG.error(msg, { 'vol_name' : docker_volume_name,
  21. 'c_vol' : シンダーボリューム、
  22. '状態' : 状態})
  23. 例外を発生させる。NotMatchedState()

上記は主に Cinder API を通じてボリューム情報を取得し、その接続ステータスを確認します。

  • ボリュームが接続されていない場合は、直接接続します。
  • ボリュームが別のホストに接続されている(使用中)場合は、マルチアタッチをサポートしているかどうかを確認します。ある場合は、直接マウントします。そうでない場合、例外がスローされ、マウントは失敗します。
  • ボリュームが現在のホストに接続されている場合、ボリュームはローカルにマウントされていることを意味しますが、これは期待どおりではないため、例外が直接スローされます。

これまで問題がなく、ボリュームがローカル コンピューターに正常に接続されていると仮定すると、ローカル コンピューターにマップされている仮想デバイスの名前を取得できます。次のコードは、パスの準備ができているかどうかを確認します。

  1. link_path = コネクタ.get_device_path(cinder_volume)
  2. os.path.exists(link_path)が存在しない場合は:
  3. LOG.warning( "デバイスリンクファイルが見つかりませんでした。"  
  4. 「だから再構築する
  5. コネクタ.disconnect_volume(cinder_volume)
  6. コネクタ.connect_volume(cinder_volume)
  7.  
  8. devpath = os.path.realpath(link_path)
  9. devpathでない場合  os.path.exists(devpath)が存在しません:
  10. msg = _( "ボリュームデバイスパスが見つかりません" )
  11. LOG.エラー(メッセージ)
  12. 例外を発生させます。FuxiException(msg)

ボリュームが /dev/sdd などのデバイス名に正常に取得された場合、最後のタスクはそれをローカル ファイル システムにマウントすることです。

  1. マウントポイント = self._get_mountpoint(docker_volume_name)
  2. self._create_mountpoint(マウントポイント)
  3. fstype = cinder_volume.metadata.get( 'fstype' , cinder_conf.fstype)
  4. mount.do_mount(デバイスパス、マウントポイント、ファイルシステムタイプ)
  5. マウントポイントを返す

マウントポイントはマウントするターゲット ディレクトリであり、そのパスは volume_dir + volume_type + volume_name です。 Volume_dir は設定ファイルを通じて設定され、デフォルトでは /fuxi/data です。 Volume_type は cinder です。ボリューム名が int32bit-test-volume であると仮定すると、マウント パスは /fuxi/data/cinder/int32bit-test-volume になります。

create_mountpoint はマウント ディレクトリを作成します。

  1. (自分自身、マウントポイント):
  2. "" " Docker ボリュームマウント ポイント ディレクトリを作成します
  3. :param mountpoint: Docker ボリュームパス。
  4. 「」 「
  5. 試す:
  6. os.path.exists (マウントポイント)または  os.path.isdir(マウントポイント)ではありません:
  7. utils.execute ( 'mkdir' , '-p' , '-m=755' , マウントポイント,
  8. run_as_root = True )
  9. LOG.info( "マウントポイント %s を正常に作成しました" , マウントポイント)
  10. processutils.ProcessExecutionErrorを除き e:
  11. LOG.error( "ボリュームの作成時にエラーが発生しました"  
  12. 「ディレクトリ。エラー: %s」 、e)

最後に、mount.do_mount が呼び出されます。 Mount は、fuxi によって実装された共通マウント ライブラリです。コードはfuxi/common/mount.pyにあります。

  1. (devpath、マウントポイント、fstype):
  2. "" "デバイスのマウント操作を実行します
  3.  
  4. :param devpath: マウントデバイスパス
  5. :param mountpoint: マウントポイントパス
  6. :param fstype: ファイル システムのタイプ。
  7. 「」 「
  8. 試す:
  9. check_already_mounted(devpath, mountpoint) の場合:
  10. 戻る 
  11.  
  12. マウンタ = マウンタ()
  13. mounter.mount(デバイスパス、マウントポイント、ファイルシステムタイプ)
  14. 例外を除く。MountException:
  15. 試す:
  16. mounter.make_filesystem(devpath, fstype)
  17. mounter.mount(デバイスパス、マウントポイント、ファイルシステムタイプ)
  18. exceptions.FuxiExceptionを除き、eとして:
  19. excutils.save_and_reraise_exception()を使用する場合:
  20. LOG.error(str(e))

このメソッドは、Mounter の mount メソッドを直接呼び出します。マウントが失敗した場合、ファイル システムは再作成され、フォーマットされてから再度マウントされます (最初のマウント時にファイル システムがインストールされていないため、マウントは必ず失敗します)。マウント方法は次のとおりです。

  1. (自己、devpath、マウントポイント、fstype=なし):
  2. 試す:
  3. fstypeの場合:
  4. utils.execute ( 'mount' '-t' 、 fstype 、 devpath 、 mountpoint 、
  5. run_as_root = True )
  6. それ以外
  7. utils.execute ( 'mount' 、 devpath 、 マウントポイント 、
  8. run_as_root = True )
  9. processutils.ProcessExecutionErrorを除き e:
  10. msg = _( "ブロックデバイスのマウント中に予期しないエラーが発生しました。"  
  11. 「開発パス: {0}」  
  12. 「マウントポイント: {1}」  
  13. "エラー: {2}" ).format(devpath, mountpoint, e)
  14. 例外を発生させます。MountException(msg)

したがって、ソースコードを調べることで、以前の推測が正しいことが再度確認されました。

4 REX-Ray

REX-Ray は、EMC チームが主導するオープン ソース プロジェクトであり、Docker、Mesos、その他のコンテナー ランタイム環境に継続的なストレージ アクセスを提供します。汎用ストレージ、仮想化、クラウド プラットフォームを網羅するように設計されており、高度なストレージ機能を提供します。言い換えれば、REX-Ray は、Ceph、Cinder、EBS などのさまざまなプロバイダーを統合し、Docker にボリュームを提供するための統合ツールをさらにカプセル化して提供します。残念ながら、Docker に Cinder ボリュームをマウントするには、Docker を Nova 仮想マシンにインストールし、仮想マシンを OpenStack 管理ネットワークに接続できる必要があります。詳細については、「Cinder: cinder ドライバーの使用中にボリュームの接続に失敗しました」を参照してください。したがって、実際の使用シナリオは限られているため、この記事では詳細には説明しません。

【この記事は51CTOコラムニスト「Fu Guangping」によるオリジナル記事です。転載が必要な場合は51CTOまでご連絡ください]

この著者の他の記事を読むにはここをクリックしてください

<<:  分散システムを学ぶにはどうすればいいですか? 1つの記事ですべてを入手できます!

>>:  MozillaがWebXR標準を提案し、複合現実技術を標準化すると発表

推薦する

Dynatrace が中国銀行のアプリケーション パフォーマンス管理の実現を支援

[51CTO.comより引用] 「モバイルバンキングアプリをダウンロードすると、無料で送金や金融商品...

推奨: hostus-大容量メモリ VPS/768m メモリ/年間 10 ドルの支払い

昨日、私はホストのボスに、なぜあなたのウェブサイトはこんなに醜いのに、それを直さないのかと尋ねました...

テンセントニュースチャンネルを例に、情報サイトの内部リンク構造を分析する

私の友人の多くは、テンセントの QQ ニュース チャンネルをよく知っていると思います。毎日 QQ に...

Kubernetes ネットワークの 4 つのシナリオの分析

この記事では、コンテナ間、Pod 間、Pod からサービス、外部から内部の 4 つのシナリオにおける...

百度の今後のSEOアルゴリズム調整に関する予測

Baidu の SEO に関する提案では、SEO はウェブサイト上の高品質なコンテンツを検索エンジン...

スライス サーバー: E-2288G、128G メモリ、NVMe、4 つの RTX3090 グラフィック カード、1Gbps 帯域幅、無制限のトラフィック、超高 DDoS 保護

以前、スライシングサーバーを紹介しました。最も強力なのは、8つのGTX1080Tiです。今回は、4つ...

Douban FM: 「気取った」ユーザーに課金することで無料ユーザーから広告料を稼ぐ

Douban FMの有料版が最近リリースされ、月額10元で、ユーザー課金モデルの模索が正式に始まった...

ボスが命じた再入可能分散ロックがついに実現〜

[[330080]]この記事はWeChatの公開アカウント「Program Pass」から転載したも...

競合他社を注意深く研究することによってのみ、ウェブサイトは勝利できる

私たちがどんな業界にいようと、何をしていようと、常にさまざまな競合相手が存在します。ウェブサイトの最...

タオバオ割引ナビゲーションサイトJiukuaiyouの最適化分析

最近、SEOをやっている友達とQQでよくチャットしています。彼はタオバオの割引ナビゲーションサイトを...

SEO 診断: ストック イメージ ウェブサイト診断の提案

この2日間は家で何もすることがなく、会社もソフト記事を書くことを要求していません。とても退屈です。ま...

Kubernetes (k8s) ラベルの詳細

ポッド コントローラーを使用して作成されたポッドの IP アドレスと名前は、ポッドに障害が発生すると...

2019年のデジタル中国指数レポートが発表され、デジタル経済の次の成長点は産業によって牽引されるだろう

5月21日、2019年テンセントグローバルデジタルエコシステムカンファレンスが昆明で盛大に開幕した。...

Kaola.com の完全なクラウドネイティブ移行への道

今年8月末、1年間「アリ動物園」にいたKoala.comが初めて戦略的なアップグレードを発表した。同...

初心者のSEO体験

Baiduの四半期アップデートは1か月以上続いています。その理由についてはさまざまな意見があり、誰も...