無料枠が続く限り Microsoft Azure を弄ってみる。
Blob ストレージとは
Microsoft Azure におけるストレージ
上記に詳しいことはおまかせして...以下の四種類に分類される。
- Blob ストレージ
- テーブル ストレージ
- キュー ストレージ
- ファイルストレージ(※ドキュメント上ではプレビューとなっている)
また、以下の図でストレージサービスの概要を把握することが出来る。
(出典:Microsoft Azure Storage の概要)
更に以下のように整理することで個人的にすんなり入ってきた。(※あくまでも個人的見解なので微妙な違いはあると思われる)
Microsoft Azure | Amazon Web Service | 備考 |
---|---|---|
Blob ストレージ | Amazon S3 | |
テーブルサービス | Amazon Dynamo DB | |
キューストレージ | Amazon SQS | |
ファイルストレージ | Amazon EFS | ※ファイル共有サービスという点では似ているがレイヤーが異なる |
ということで、今回は Blob ストレージを触りながら学んでみたい。
Blob とは
ここでの Blob とはストレージに保存する以下のようなファイル等を指す。(ドキュメントより抜粋)
- ドキュメント
- 写真、ビデオ、音楽、ブログなどのソーシャル データ
- ファイル、コンピューター、データベース、およびデバイスのバックアップ データ
- Web アプリケーションのイメージとテキスト
- クラウド アプリケーションの構成データ
- ログやその他の大きなデータセットなどのビッグ データ
Amazon S3 で言うところの「オブジェクト」を指すと思われる。
Blob はコンテナに放り込む
Blob はコンテナと呼ばれる Amazon S3 で言うところの「バケット」に放り込むことになる。ドキュメントには Blob をグルーピングするのがコンテナであると書かれている。コンテナには以下のような特徴がある。
- ストレージアカウントの上限 500TB を超えない限りはコンテナは作りたい放題
- コンテナ内の Blob も作りたい放題
- コンテナ単位でアクセスコントロールを定義することが出来る
三種類の Blob ストレージ
名称 | 用途、特徴 |
---|---|
ブロック BLOB | ドキュメント、メディア ファイル、バックアップなどの格納に適している |
追加 BLOB | 新しいブロックを最後に追加することによってのみ更新できる(※現時点ではちょっと理解し難い) |
ページ BLOB (ディスク) | ランダムな書き込みをサポートするように最適化されおり、最大 1 TB までサイズを拡張可能、仮想マシンのディスクとして使用可能 |
ストレージのスペック
気になるストレージのスケーラビリティやスペックについては以下のドキュメントに整理されている。
コンテナ、Blob の命名規則
コンテナ、Blob には以下のような命名規則があるので注意する。
コンテナ名
- 英数小文字、記号はハイフンは OK
- 英数字で始める
- 連続するハイフンは NG
- 3 ~ 36 文字
blob 名
- 任意の文字
- 1 ~ 1024 文字以下
- 大文字、小文字は区別される
- URL 予約文字(: とか / とか...?)はエスケープする
- パスは 254 階層まで
- S3 と同様にディレクトリという概念は存在しないが
/
パスで仮想ディレクトリ構造を作ることが可能
旧ポータルでポチポチ使う Blob ストレージ
ストレージアカウントを作る
[+新規] をクリックしてストレージアカウント作成を開始する。
[簡易作成] から以下を指定する。
をそれぞれプルダウンから指定する。
ストレージアカウント作成完了。引き続き、コンテナを作成する。
コンテナを作る
ストレージアカウントから [コンテナー] タブをクリックして [コンテナーを作成する] をクリック。
[名前] と [アクセス] プルダウンから以下を選択する。
- プライベート(コンテナの所有者のみアクセス可能)
- パブリックコンテナー(コンテナとコンテナ内データにアクセス可能)
- パブリック Blob(コンテナの Blob のみにアクセス可能)
パブリックコンテナーを利用することで Amazon S3 のウェブホスティング機能のようなことを実装可能なようだ。
コンテナ作成完了。
Blob をアップロードする(のは...)
- 管理コンソール(manage.windowsazure.com)からは出来ないので注意
- Azure Storage Explorer というツールがあるとのこと
Azure SDK for Ruby と使う Blob ストレージ
動作確認環境
$ cat /etc/debian_version 8.1 $ ruby -v ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
参考
SDK のインストール
$ sudo gem install azure --no-ri --no-rdoc -V
上記で最新(0.7.0)の Microsoft Azure SDK for Ruby がインストールされるが...今回は最新ではなく一つ前のバージョン(0.6.2)ですすめる。理由は後述...。
アクセスキーを控える
ストレージアカウントにアクセスする為のアクセスキーを確認して控えておく。
ちょっと問題
README を参考にして以下のようなコンテナを作成するサンプルを用意して実行すると...
#!/usr/bin/env ruby require "azure" Azure.storage_account_name = "komanechi" Azure.storage_access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # # Create Instance # blob_service = Azure.blobs # # Create Container # blob_service.create_container("hoge")
以下のようなエラー。
/usr/local/bundle/gems/azure-0.7.0/lib/azure/core/http/http_request.rb:150:in `call':c: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. (Azure::Core::Http::HTTPError) RequestId:c47fa16c-0001-0040-0942-e8bdfa000000 Time:2015-09-06T01:25:49.6986168Z from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/http/signer_filter.rb:28:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/http/signer_filter.rb:28:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/http/http_request.rb:97:in `block in with_filter' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/service.rb:36:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/filtered_service.rb:34:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/core/signed_service.rb:41:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/blob/blob_service.rb:1380:in `call' from /usr/local/bundle/gems/azure-0.7.0/lib/azure/blob/blob_service.rb:119:in `create_container' from ./demo_0.7.0.rb:20:in `<main>'
HTTP リクエストのヘッダ内に何らの署名が必要なようだ。これ以上の追跡は改めてということで...旧バージョン(0.6.4)を利用してみることにする。
$ gem install azure --version '0.6.4' --no-ri --no-rdoc -V
以下、コンテナを作成するサンプル。
#!/usr/bin/env ruby gem "azure", "0.6.4" require "azure" Azure.storage_account_name = "komanechi" Azure.storage_access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # # Create Instance # blob_service = Azure::BlobService.new # # Create Container # def create_container blob_service.create_container("hoge") end # # Check Container List # containers = blob_service.list_containers() # # Output Container Infomation # containers.each do |container| puts "Container Name: " + container.name puts "Container Properties: " + "#{container.properties}" unless container.name = "hoge" create_container end end
サンプルスクリプトを実行すると...以下のように出力される。
$ ./demo.rb Container Name: hoge Container Properties: {:last_modified=>"Sun, 06 Sep 2015 02:14:19 GMT", :etag=>"\"0x8D2B660DF557864\"", :lease_status=>"unlocked", :lease_state=>"available"} Container Name: nahanaha Container Properties: {:last_modified=>"Sun, 06 Sep 2015 00:32:28 GMT", :etag=>"\"0x8D2B652A4D8E918\"", :lease_status=>"unlocked", :lease_state=>"available"}
ポータルを見てみる。
コンテナを確認出来た。
さらに、コンテナに Blob をアップロードするサンプル。
#!/usr/bin/env ruby gem "azure", "0.6.4" require "azure" container_name = ARGV[0] Azure.config.storage_account_name = "komanechi" Azure.storage_access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # # Create Instance # blob_service = Azure::BlobService.new # # Upload blob # puts "Blob upload..." content = File.open("test.txt", "rb") { |file| file.read } blob = blob_service.create_block_blob(container_name,"test-txt", content) # # Output blob name # puts "Blob List..." blobs = blob_service.list_blobs(container_name) blobs.each do |blob| puts " Blob Name: " + blob.name puts " Blob Properties: " + "#{blob.properties}" end
サンプルスクリプトを実行すると...以下のように出力される。
$ ./upload.rb ${container_name} Blob upload... done.. Blob List... Blob Name: test-txt Blob Properties: {:last_modified=>"Sun, 06 Sep 2015 02:46:58 GMT", :etag=>"0x8D2B6656F27EDA2", :lease_status=>"unlocked", :lease_state=>"available", :content_length=>0, :content_type=>"application/octet-stream", :content_encoding=>"ASCII-8BIT", :content_language=>"", :content_md5=>"1B2M2Y8AsgTpgAmY7PhCfg==", :cache_control=>"", :blob_type=>"BlockBlob"}
更に Blob を削除したいので以下のようなサンプルスクリプトを作成。
#!/usr/bin/env ruby gem "azure", "0.6.4" require "azure" @container_name = ARGV[0] Azure.config.storage_account_name = "komanechi" Azure.storage_access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # # Create Instance # @blob_service = Azure::BlobService.new # # Delete blob # def delete_blob(blob_name) puts "Delete blob..." @blob_service.delete_blob(@container_name, blob_name) puts " done..." end # # Main(Output blob name and Delete blob) # puts "Blob List..." blobs = @blob_service.list_blobs(@container_name) blobs.each do |blob| puts " Blob Name: " + blob.name puts " Blob Properties: " + "#{blob.properties}" delete_blob(blob.name) end
サンプルスクリプトを実行すると...
$ ./delete.rb hoge Blob List... Blob Name: test-txt Blob Properties: {:last_modified=>"Sun, 06 Sep 2015 03:06:46 GMT", :etag=>"0x8D2B668334886A9", :lease_status=>"unlocked", :lease_state=>"available", :content_length=>0, :content_type=>"application/octet-stream", :content_encoding=>"ASCII-8BIT", :content_language=>"", :content_md5=>"1B2M2Y8AsgTpgAmY7PhCfg==", :cache_control=>"", :blob_type=>"BlockBlob"} Delete blob... done... # もう一回実行 $ ./delete.rb hoge Blob List...
雑なスクリプトで恐縮だが、コンテナの作成、Blob のアップロード、リスト、削除を一通り体験。
fluent-plugin-azurestorage と使う Blob ストレージ
せっかくなので
Blob ストレージにログを放り込んでみたいので fluent-plugin-azurestorage というプラグインを利用してアクセスログを Blob ストレージに放り込んでみる。
尚、最新のバージョン(0.7.0)で動作させようとすると Azure::BlobService
からインスタンスを生成する際に以下のようなエラーとなる。
2015-09-06 03:37:58 +0000 [error]: unexpected error error_class=NameError error=#<NameError: uninitialized constant Azure::BlobService>
ということで、Azure SDK for Ruby のバージョンに注意する(最新バージョンは使わない)。
尚、本プラグインは
Azure Storate output plugin buffers logs in local file and upload them to Azure Storage periodically. This plugin is porting from fluent-plugin-s3 for AzureStorage.
とあるので設定ファイルのパラメータレベルでは fluent-plugin-s3 と互換性があると思われる。
動作確認環境
雑にコンテナ化したものを利用する。
以下、コンテナの fluentd や OS のバージョン。
$ docker exec fluentd cat /etc/debian_version 8.1 $ docker exec fluentd fluentd --version fluentd 0.12.15
プラグインのインストール
動作確認環境と前後するが、以下のようにインストール。
# プラグインのインストール $ sudo gem install fluent-plugin-azurestorage --no-ri --no-rdoc -V # プラグインインストール時に最新の Azure SDK for Ruby がインストールされるのでアンインストールする $ gem uninstall azure --version '0.7.0' # 一つ前の Azure SDK for Ruby をインストールする $ gem install azure --version '0.6.4' --no-ri --no-rdoc -V
fluentd の設定
以下のように設定する。
<source> type forward port 24224 bind 0.0.0.0 </source> <match docker.*> type copy <store> type stdout </store> <store> type azurestorage azure_storage_account fluentd azure_storage_access_key ${ストレージアカウントのアクセスキー} azure_container logs azure_storage_type blob store_as gzip auto_create_container true path logs/ azure_object_key_format %{path}%{time_slice}_%{index}.%{file_extension} buffer_path /var/log/td-agent/buffer/azurestorage time_slice_format %Y%m%d-%H time_slice_wait 10m utc flush_interval 10s </store> </match>
主なパラメータについては以下のとおり。
パラメータ | 設定値 |
---|---|
azure_storage_account | ストレージアカウント名 |
azure_storage_access_key | ストレージアカウントのアクセスキー |
azure_container | コンテナ名(auto_create_container が true の場合、自動で作成する) |
azure_storage_type | blob |
store_as | コンテナに保存する blob のファイルタイプ(json や gzip 等をサポート) |
auto_create_container | true(コンテナが存在しない場合にはコンテナを自動作成する) |
その他のパラメータについては README を。
ログが保存されていることを確認
- 以下のようにコンテナを起動する
# fluentd コンテナの起動 docker run -d \ --name=fluentd \ -p 24224:24224 \ --env 'STORAGE_NAME=${STORAGE_NAME}' \ --env 'STORAGE_ACCESS_KEY=${STORAGE_ACCESS_KEY}' \ --env 'STORAGE_CONTAINER=${STORAGE_CONTAINER}' \ inokappa/fluentd-azure-blob /app/start.sh # nginx コンテナの起動 docker run -d \ -p 80:80 \ --log-driver=fluentd \ --log-opt=fluentd-address=${FLUENTD_PORT_24224_TCP_ADDR}:24224 \ --log-opt=fluentd-tag=docker.{{.FullID}} \ --name=nginx \ nginx
- nginx コンテナにアクセス
curl localhost curl localhost curl localhost curl localhost curl localhost
- コンテナにログがアップロードされていることを確認
- ダウンロードして確認
2015-09-06T05:20:59Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"log":"172.17.42.1 - - [06/Sep/2015:05:20:59 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\"","container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e","container_name":"/nginx","source":"stdout"} 2015-09-06T05:21:00Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"container_name":"/nginx","source":"stdout","log":"172.17.42.1 - - [06/Sep/2015:05:21:00 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\"","container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e"} 2015-09-06T05:21:00Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"container_name":"/nginx","source":"stdout","log":"172.17.42.1 - - [06/Sep/2015:05:21:00 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\"","container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e"} 2015-09-06T05:21:01Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"log":"172.17.42.1 - - [06/Sep/2015:05:21:01 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\"","container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e","container_name":"/nginx","source":"stdout"} 2015-09-06T05:21:01Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e","container_name":"/nginx","source":"stdout","log":"172.17.42.1 - - [06/Sep/2015:05:21:01 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\""} 2015-09-06T05:21:01Z docker.40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e {"container_id":"40ca6635a2ba8706627c2219f074c7ab9eeb9fc8385077cd9c9071af2789546e","container_name":"/nginx","source":"stdout","log":"172.17.42.1 - - [06/Sep/2015:05:21:01 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.33.0\" \"-\""}
一通りの動作確認終わり。
おわり
Blob ストレージとは...からちょっとした応用までやってみたが、Amazon S3 と概念的には似ていると感じた。 尚、コスト、セキュリティ、可用性、耐久性、制限事項等についてはドキュメントを引き続き読んで理解を深めたい。 また、最新版の SDK については手元の環境において発生するエラーについても引き続き調査したいと思う。
以上。