そうだコンテナー データセンターを作ろう (Part4. 基礎工事編)


嫌な嫌な花粉症のシーズンですね。花粉のおかげで工事も進まないので、久々にコンテナ DC ブログです。

前回書いた通り土地を競売で取得したので、今回から本格的なコンテナ DC 建設工事に入ります。

Docker?いやいや、コンテナといったら物理でしょ

コンテナ DC のキモといえば海上輸送用のコンテナ。ネット上でも結構売ってる業者が見つかりますが、数年前から目をつけていたユーエンさんにお邪魔してきました。横浜の展示場 (といっても、横浜のふ頭にある広大なコンテナ置き場) で即売会を年に何度かやっていて、誰でも見学や買い付けに行けます。

このほかにも、JR 貨物が JR コンテナの中古を売りに出していたり、建築確認申請に通ったと謳っているコンテナを扱っている業者もあるようです。

ネットだと新古とか中古コンテナがどんなもんか中々わからないですが、この二枚を見比べてもらえば大体わかりますかね。新古は完全な新品ではないので数回つかった痕跡があります。(よく見ると奥の床がめくれてます。もちろん、ちゃんと交換してから納品してくれるとのこと。)

中古でも塗装や補修をすればきれいになるんでしょうが、所詮は鉄の塊なので凹みとかキズは結構気になりますね。

改造済みの電灯やらコンセントがついたコンテナも見せてもらいました。ただ、電柱からコンテナへの電気の引き込みはやってくれないようだったのと、断熱やら電気工事を含めて見積もりを取ったら結構な額になったので、改造は自前でやることにして今回は素のコンテナだけを買っています。

おっさん、キミにきめた!

コンテナの設置は水平さえ出せればどうにでもなるようで、コンクリ板で高さを調整する程度でも設置が可能だそうです。ただ、長く使うからには基礎を打っておかないと不安なので、近場の工務店にお願いしました。

が、この工務店の仕事が遅すぎてお話にならない。見積りは催促しても全然送ってくれないし、施工前の打ち合わせも一切なし、施工日の連絡も一週間前に「来週のどっかで」って言ってくる始末。結局前日になるまで日取りは決まらず、一日では全部終わらないので肝心のコンクリ流し込むところは見に行けずです…。(自前でやる案もありましたが、かなりの肉体労働になりそうで、一人じゃ到底無理そうだったので仕方ないんですが。)

とまあ、色々あって私は見に行けなかったのですが、世の中には「おっさんレンタル」なんて便利なものがあるんですね。さすがに直前すぎて無理だろうと思いつつ、前日の深夜に現場の様子見と撮影をお願いしたら明朝早々にオッケーとの返事がきて、いっぱい写真を撮ってくれました。かなり非常識かつムチャなお願いをしたのに対応してくれた某おっさんには本当に感謝です。

以下、ざっくりと工程をご紹介。詳しいことはこことか、この辺を見てください。

今回は左右に二点基礎としましたが、レーザーで水平を測って水糸を張り、根切り (穴を掘り) ます。

コンクリを流し込むための型枠を組んで、セパや添え木で動かないように固定します。

強度を出すために鉄筋をいれて。

左右で高さをそろえて、離型剤を塗ります。

あとはミキサー車からコンクリートを流し込んで完了。冬場なので 1 週間くらい乾燥させてから木枠を外します。

出来上がった二点基礎がこちら。意外に高低差があったようで、手前のほうが基礎の高さがありますね。

今回はここまで。次の更新はまた暫く期間が開くと思います。


大量の Azure VM を展開してみる


Azure がついに 7 周年らしいですね。おめでとうございます。(私は 20 歳で触り始めたので、気づけば 6 年以上使っていることに…。)

さて、昨日同僚から、「明日のトレーニングで使う VM を 40 台作りたい」と相談を受けて、片手間でデプロイしたので、落書き程度にメモを残しておきます。

1. 展開方法

詳しく話を聞くと、RDS 環境のトレーニング用に VM 5 台 (CB, SH1, SH2, Web, Client) x8 セットが明日までに欲しいとのこと。

パッと思いつく方法としては、以下の 4 通りくらいでしょうか。

  • ポータルからポチポチする (論外)
  • Azure PowerShell で単純にループさせてシリアルでデプロイする (遅い)
  • Azure PowerShell でパラレルでデプロイする (面倒)
  • JSON テンプレートを使う

どの方法でも作れますが、今日はデプロイに時間をかけられないので JSON にしました。(夕方相談を受けて、明日使うということだったので。)

なお、余談ですが PowerShell で複数リソースをパラレル展開する方法は以下にメモってあります。ただ、これも作成するリソース数が増えると、エラーを吐きやすくなってデバッグが面倒なので、今回は候補から除外。

2. JSON テンプレートの作り方

使い慣れていない人に PowerShell とか JSON テンプレートって言うとあからさまに嫌な顔されるんですが、一回作って慣れてしまえば大したことはないです。

JSON が初めての人は、横着せずに以下全部きっちり目を通しましょう。これだけ知っていれば十分なので。

で、具体的にどう作るかというと、既存のテンプレートをパクってきて切り貼りします。

 

今回は VM を大量に複製したいので、名前に loop と入った以下をベースにします。

このまま [Deploy to Azure] ボタンでサクっとデプロイできるのですが、40 と入れると 5 台までしか作れないとエラーになります。生の JSON を開いてみると、以下の通り numberOfInstances のパラメーターが maxValue 5 となっているので、40 などに書き換えてしまいましょう。

なお、運用環境の場合は 1 つのストレージ (20000 IOPS 上限) に大量の VHD (500 IOPS 上限) を配置するとパフォーマンスに影響があるので、適切にストレージを分割する必要があります。あと、Premium ストレージについては 35 TB の容量制限もあるので気を付けましょう。

    "numberOfInstances": {
      "type": "int",
      "defaultValue": 2,
      "minValue": 2,
      "maxValue": 5,
      "metadata": {
        "description": "Number of VMs to deploy, limit 5 since this sample is using a single storage account"
      }
    },

 

次に Visualize ボタンを押して含まれるリソースを確認すると以下が入っていることがわかります。リソース名に copyindex() とついている VM と NIC は、1 つしか定義されていませんが、ループさせて必要数だけ作成されるようになっています。

生の JSON をさらに深堀してみると、例えば NIC は以下のように定義されています。name は nic0, nic1, nic2… などとなるように、copyindex() でループのカウンタ (0, 1, 2…) をセットして、concat で文字列を結合しています。また、copy セクションで count として設定されている数だけループするように定義してあります。(ここでは、あとで任意の値が設定できるよう、numberOfInstances というパラメーターが入っています。)

    {
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat('nic', copyindex())]",
      "apiVersion": "2016-03-30",
      "location": "[resourceGroup().location]",
      "copy": {
        "name": "nicLoop",
        "count": "[parameters('numberOfInstances')]"
      },
      "dependsOn": [
        "[variables('virtualNetworkName')]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnet1Ref')]"
              }
            }
          }
        ]
      }
    },

 

同じく VM についても 1 台分しか定義されていませんが、ループさせて numberOfInstances 台だけ展開されるようになっています。その他、コンピューター名やVHD のパス、NIC の ID なども copyIndex() を使って定義されていることに気を付けましょう。

    {
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[concat('myvm', copyIndex())]",
      "apiVersion": "2016-03-30",
      "location": "[resourceGroup().location]",
      "copy": {
        "name": "virtualMachineLoop",
        "count": "[parameters('numberOfInstances')]"
      },
      "dependsOn": [
        "nicLoop",
        "[variables('storageAccountName')]"
      ],
      "properties": {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets', variables('availabilitySetName'))]"
        },
        "hardwareProfile": {
          "vmSize": "Standard_D1_v2"
        },
        "osProfile": {
          "computerName": "[concat('vm', copyIndex())]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": "[variables('imageReference')]",
          "osDisk": {
            "name": "osdisk",
            "vhd": {
              "uri": "[concat(reference(variables('StorageAccountName'), '2016-01-01').primaryEndpoints.blob, 'vhds/osdisk', copyIndex(), '.vhd')]"
            },
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces',concat('nic', copyindex()))]"
            }
          ]
        }
      }
    }

各パラメーターを一通り見てみると、実は Public IP が付与されていないことが判明します。このままでは直接 RDP できないので、他の Public IP 付きの VM を展開するテンプレートから Public IP の定義と、NIC の依存関係の部分をパクってきます。

なお、この際にリソース名等に使われている変数 (variables) が定義されていなかったりするので、concat(‘pip’, copyIndex()) などへ変更し、Public IP と NIC を紐づけるなど、ベースのテンプレートと整合性が取れるように微修正します。

    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[variables('publicIPAddressName')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "[parameters('dnsLabelPrefix')]"
        }
      }
    },
    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('nicName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
              },
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    },

とまあ、こんな具合でそれっぽいテンプレートが出来上がったら、ポータルの [新規] – [テンプレートのデプロイ] に張り付けて、デプロイしてみましょう。(コンピューター名を役割ごとに別で定義したかったので、以下では VM やら NIC、Public IP を 5 台分コピーして定義しています)

 

大体どっかしら間違っていて、展開前の検証フェーズで失敗すると思います。エラーに表示された内容やキーワードを頼りに、カッコがそろっているか、パラメーターが前後と整合性がとれているかなどを確認しましょう。あとは修正とデプロイを繰り返して、期待したものが出来上がるまで微調整すれば終わりです。

 

3. 余談

大量の VM を展開する際は、サブスクリプションのクォータに気を付けましょう。足りない場合は引き上げ申請をすればいいんですが、数日~1 週間程度かかるので、急ぎの場合はリージョンを変えればいいと思います。(ARM はリージョン毎にクォーター設定されているので。)

ちなみに、クォーターはプレビュー ポータル (https://preview.portal.azure.com) のサブスクリプション ブレードから細かく見れるようになっています。(そのうち一般のポータルにも来るはず?)

 

あと、JSON の編集は Visual Studio もしくは Visual Studio Code を使うとかなり便利です。

 

そんなこんなで、実質 2 時間くらいで無事デプロイが終わりました。クラウドの時代なので、このくらい片手間でサクっと出来ると便利ですね。業務効率化は正義!


Azure VM に大容量ディスクを作ってみる


気まぐれで、Azure VM に大容量ディスクをアタッチしたくなったので、どこまで出来るのか試してみました。

1.概要

まず、前提として Azure VM にアタッチできるディスク (VHD) は 1 本 1 TB が上限です。これは Azure Storage の Page BLOB の上限です。

このため、1 TB の VHD を複数アタッチして、OS の中でソフトウェア RAID 等を構成する必要があります。

また、Azure VM のサイズによってアタッチできる本数の上限が決まっています。G5 / GS5 のサイズで最大 64 本 (64 TB) になりますが、G シリーズはお高いので、一般的に使うサイズだと 32 本 (32 TB) が上限と思ったほうがよいでしょう。

2. 手順

データ ディスクの追加はポータルからもできますが、64 本もアタッチするのは面倒なので Azure PowerShell でサクっとやります。

# 既存の VM 情報を取得
$VM = Get-AzureRmVM -Name "&amp;lt;VM 名&amp;gt;" -ResourceGroupName "<リソース グループ名>"

# 新規で 1023 GB のディスクを 64 本アタッチ
for($i = 0; $i -lt 64; $i++){
    if($i -gt 32){
        Add-AzureRmVMDataDisk -VM $VM -Name "datadisk$($i)" -VhdUri "https://<ストレージ アカウント名 1>.blob.core.windows.net/vhds/datadisk$($i).vhd" -DiskSizeInGB 1023 -Lun $i -CreateOption Empty
    }else{
        Add-AzureRmVMDataDisk -VM $VM -Name "datadisk$($i)" -VhdUri "https://<ストレージ アカウント名 2>.blob.core.windows.net/vhds/datadisk$($i).vhd" -DiskSizeInGB 1023 -Lun $i -CreateOption Empty
    }
}

# 設定を反映
Update-AzureRmVM -VM $VM -ResourceGroupName $VM.ResourceGroupName

これで、VM に 64 本のデータ ディスク (および OS ディスクと一時ディスク) がアタッチされた状態になります。

注意事項:

  • Standard ストレージの場合、1 つのストレージに 20000 IOPS 制限があります。1 BLOB (VHD) あたり 500 IOPS が上限なので、パフォーマンスの観点からは 40 本以上のディスクはストレージを分散させます。
  • Premium ストレージの場合、1 つのストレージに 35 TB 上限があります。課金も恐ろしい額になるので注意しましょう。

 

あとは Windows Server の記憶域スペース・記憶域プールを使って、64 TB の大きなプールを作ってから、ディスクを切り出しましょう。

以下、スクショでお楽しみください。


「Raspberry Pi 3でつくる IoTプログラミング」が出ます。


2015/11 発刊の「Raspberry Pi 2とWindows 10ではじめるIoTプログラミング」が大好評をいただいたおかげで、Raspberry Pi 3 対応の新刊が今月末に発売されることになりました。前回と同じく、林 宜憲さんとの共著になります。

半年で情報が古くなるクラウドの時代に本を出すのも楽じゃないですが、Windows 10 IoT Core とか Azure に興味をもってもらうきっかけになればと思って頑張って書いてますんで、手に取っていただけたら嬉しいです。(実際、一年足らずでかなり更新が入っていたり、Preview だったサービスが GA していたり大変でした…。)

あ、あと、エゴサしたら発売前なのに fabcross でも言及いただいていたようで、感謝感謝。

引き続き、気の向くままにアレコレ情報発信を頑張りますんで、皆様よろしくお願いしますー。


そうだコンテナー データセンターを作ろう (Part3. 不動産競売編)


前回までのあらすじ

過去 2 回にわたって候補地の選定について書いてきました。

が、半年近く探しても一向に要件を満たす土地が見つからず…

それは不思議な出会いなの?

不動産検索サイトを巡回するのが日課になったある日、ふと裁判所の競売物件の一覧にも目を通していると、コンテナを置くために用意された土地と言わんばかりの物件に出会いました。しかも都内から 1 時間前後で接道 4 m 以上、電気もネットワークも問題なし、価格も予算内という条件的にも文句なしの神物件。

こんな奇跡はそうそう無いのでまあダメ元で…と、不動産検索をやめて突如競売について情報収集をすることに。当然ですが競売の知識は何もないうえに、気づいたのが遅く、入札期間まで 2 週間程度しかないという中々の強行スケジュールです。

ひとまず徹夜で Web を彷徨い、そもそも競売の流れや手続きがどうなっているか情報収集。

単純に「入札して、最高額の人が落札して終わり」というわけではなく、諸々手続きが必要なうえ、Web を物色しているとかなりリスクも高そうな様子…。今回は土地なので居座られる可能性は低いのですが、家屋がある場合には立ち退き交渉やら、引っ越し費用の負担、強制執行の手続きが必要になることもあるそうで。通常の不動産と違って事前に内見できないし、瑕疵担保責任が生じないので、安いからといって不用意に手を出すのは止めたほうが良さそうな感じでした。

とはいえ、多少のリスクを怖がっていたら何もできないので、競売の流れを把握したところで物件情報 (3 点セット) をがっつり読み込みます。

不動産競売では、売却物件ごとに「物件明細書」、「現況調査報告書」、「評価書」がセットになった、いわゆる 3 点セットが BIT で公開されていて、物件にもよるでしょうが 20 – 30 ページにわたって入札期間や開札期日といったスケジュールから、権利関係や関係人陳述、物件の占有状況に至るまで記載されています。

もちろん、記載内容が全ての事実関係を網羅できているわけではないので 100 パーセント信じるわけにもいかないのですが、競売に入札する人が知りえる情報はこれが全て (あとは現地調査くらい) なので、誰が誰に貸していたかなどの権利関係や、占有者の有無などを中心に何度も目を通すようにします。

あと、落札金額は首都圏だと売却基準額の 2 倍を超すことも多々あるそうで、過去の売却結果やら近隣の不動産価格にも目を配っておかないとダメそうでした。

 

そんな感じで、念入りに下調べをしたら、現地視察に行く暇もなく入札期間に突入…。しかも入札に必要な書類は平日わざわざ管轄裁判所まで取りに行かないという事で、仕事を休むわけにもいかず、競売のサポートをしている「競売くん」なるサイトから買うことに。(タダで置いてある書類を「セルフ入札セット」と称して高値で売るのはどうなんだと思いつつ、時間がないので渋々購入…)

入札には、ざっくり以下のものが必要でした。

  • 入札書 (入札金額を書いて厳封)
  • 入札保証金振込証明書 (売却基準価額の 2 割を保証金として事前振り込み)
  • 入札者の住民票

ちなみに、入札には不動産業者が多く参加していて、かつ利益が出るギリギリのラインで入札してくるそうで、そんな背景もあってか競売のサポート業者が高い手数料を取ってアドバイスやら諸手続きを代行しているようです。まあ、他人に頼んだところで落札できる保証はないですし、必要な情報はネットで十分揃ったので、結局のところ私は全部自分で調べて入札まで独学でやっています。

いざ開札!

入札期間が終わって一週間すると、ついに裁判所で開札が行われます。が、仕事があるので現地には行けず、BITS の開札結果ページを F5 連打。「まあ、素人が適当にやって落札できるわけもないだろう」と思いながら結果をみると… おやおや、見覚えのある落札価格が載っているではないですか。この時点で、「マジかー、やっちまったなー。」という賢者モードに突入。

それから一週間して正式に売却許可が出ると落札結果と振り込み等々の書類が届くはずなのですが、待ちきれずに裁判所へ。(撮影 NG なので写真が撮れないのが残念です。)さらに、現地へ一度も行っていなかったこともあり、落札金額を支払う前に現地を初めて視察に行きます。

そんなこんなで落札した (厳密には最高価買受申出人になる) のですが、各所から素人が不動産競売に手を出すのは危ないといわれるので、念のため落札後に法律の専門家にも相談へ行ってます。競売の情報を探しているときからお世話になったブログがあり、どうやら元々は裁判所勤務で不動産関係を担当されていた方らしいので、そちらへご相談。急に連絡したのに親身になって相談に乗ってもらえて、特に怪しいところもないことが分かったので大変助かりました。資料一式と聞きたいことを整理していったこともあり、1 時間以内だから無料でいいよとも言ってくれたのですが、プロにタダで仕事を頼むのは嫌なので、きちんと謝礼はお支払いしました。

面倒な事務手続き…

怒涛の二週間が過ぎ、特に懸念点もなくなったので、ついに落札手続きへ。ただ、必要書類が多くて地味に面倒臭い…。

  • 法務局で登記事項証明書 (不動産登記簿謄本) を取り寄せ
  • 落札者の住民票を取り寄せ
  • 国庫へ保管金を納税
  • 登録免許税の納付
  • etc…

まあ、送付されてきた書面を読めば全部書いてあるので、各地の役所に行って書類をとるだけなんですけど。

で、裁判所の手続きが終わると、法務局が嘱託で不動産移転登記をやってくれます。一週間程度で法務局から登記識別情報が届き、晴れて私に所有権が移ります。ここまで終わると、元の所有者へ明け渡しの同意書を送ったり、権利関係者にも所有権移転の連絡して立ち退いてもらったり、といった当事者間の交渉に。幸いトラブルもなくスムーズに進みましたが、開札結果が分かってから何だかんだ一か月半くらいかかりました。

 

20 代半ばで自分の土地を持つことになるとは思ってもなかったですし、まさか不動産競売に手を出すとか想像もしてなかったですが、やってみると何とかなるもんですね。

ここまでの出費

領収書が残っているものを中心に書き出すと、だいたい 200 万くらい。

  • 入札書類: ¥ 5,250
  • 書類コピー代: ¥ 900
  • 入札保証金 + 残高 + 手数料: 約 ¥ 1,800,000
  • 所有権移転登記登録免許税 + 抹消登記登録免許税: ¥ 37,600
  • 収入印紙: ¥ 1,200
  • 嘱託書送付料 + 登記完了証等返送料 + 買受人への送付料: ¥ 2,174
  • 住民票: ¥ 300
  • 評価額証明書: ¥ 300
  • 明け渡し合意書の送付: ¥594
  • 各種交通費: 約 ¥ 10,000

 

次回から、本格的にコンテナ DC 建築に入ります。


Get-SubscriptionDetails を大幅アップデートしました


冬休みの宿題がようやく終わったので、GSD 最新版公開しましたよ。

Get-SubscriptionDetails (https://github.com/ShuheiUda/Get-SubscriptionDetails)

Azure PowerShell 3.3.0 に含まれる IaaS / Network 系 Get 系コマンドは大体網羅したつもり。
あと、クリックすると詳細ビューが開くようになったので、主要パラメーターは全部見れるはずです。

手っ取り早く試したい人は以下の 2 行でどうぞ。

Invoke-WebRequest "https://raw.githubusercontent.com/ShuheiUda/Get-SubscriptionDetails/master/Get-SubscriptionDetails.ps1" -OutFile "$env:USERPROFILE\Desktop\Get-SubscriptionDetails.ps1"
. "$env:USERPROFILE\Desktop\Get-SubscriptionDetails.ps1" -SubscriptionID "サブスクリプション ID"

これで IP レンジの重複とか、NSG の設定ミスとかも一発で分かりますね。便利!

バグ報告・フィードバックはお気軽にコメントくださいー。