ObjectStorageのマウント設定のCHEFクックブック

#[SoftLayerクッキングLABO] (http://qiita.com/MahoTakara/items/464da29ccf932698b753)

# このクックブックの出来ること

オブジェクト・ストレージをブロックストレージとしてマウントするためのクックブックです。 ご存知のとおり、オブジェクト・ストレージは従量制課金のストレージなので、ログやデータの保管の見積もりが難しい場合、安くスタートできるストレージです。　しかし、オブジェクト・ストレージは、ブロック・ストレージと異なりHTTPでしかアクセスできません。　そこで Cloudfuse というソフトウェアを組み合わせて、ブロック・ストレージとしてマウントするものです。


# クックブックの自動作業内容の要約
この objectstorage01 クックブックは、以下の設定を適用します。

- Cloudfuse に必要なパッケージを導入
- Cloudfuse の tar を展開して、ビルド、インストール
- オブジェクト・ストレージの認証情報の設定
- fstab にマウント・ポイント追加
- マウント用ディレクトリ作成
- オブジェクト・ストレージを /os にマウント実行

このクックブックを適用した時の実績時間は、以下の様に約１分でした。

```
# chef-solo -o objectStorage01
< 中略 >
Running handlers:
Running handlers complete
Chef Client finished, 13/14 resources updated in 01 minutes 15 seconds
```

# 本クックブックの置き場所
最新版のクックブックはGitHubの https://github.com/takara9/objectStorage01 においてあります。 適用方法などは、このURLのREADME.dmに記載しています。

# 対応するソフトレイヤー活用ガイド
このレシピを利用することで、以下の設計パターンや設定作業を自動化することができます。

- [デザインパターン 8.6 大容量データのアーカイブ化] (https://www.change-makers.jp/post/10277)
- [コンフィグレーション・ガイド 5 オブジェクト・ストレージ編 5.9 Linuxにマウントするには？] (https://www.change-makers.jp/post/10362)

# テスト済みのLinuxディストリビューション
SoftLayerでサーバーオーダー時に選択できるOSの中から、確認できたもののリストです。

- Ubuntu 14.04 64bit minimal install
- CentOS 7 64bit minimal install
- CentOS 6 64bit minimal install


# レシピの説明

オブジェクト・ストレージのアカウントを持ち、APIキーを取得している必要があります。 このアカウント作成とAPIキー取得の方法は、[コンフィグレーション・ガイド 5.1 オブジェクト・ストレージを利用するには？]( https://www.change-makers.jp/post/10354 ) の 「オブジェクト・ストレージのAPIを使ったアクセス」に案内があります。

このレシピに必要なファイルは、以下のディレクトリ・ツリーに表す３本です。

```
root@ChefWs:~/chef-repo/site-cookbooks# tree objectStorage01/
objectStorage01/
├── README.md
├── attributes
│   └── default.rb     <-- (1)オブジェクト・ストレージの認証情報
├── files
│   └── default
│       └── cloudfuse.tgz  <-- (2) cloudfuseインストールファイル
├── recipes
│   └── default.rb <-- (3) レシピ本体
└── templates
    └── default
```


## (1)オブジェクト・ストレージの認証情報
この認証情報は、attributes の default.rb に設定します。 以下のアスタリスクの場所を置き換えます。
```
default["objectstorage"]["username"]="*********:*********"
default["objectstorage"]["apikey"]="****************************************************************"
default["objectstorage"]["authurl"]="https://****.objectstorage.softlayer.net/auth/v1.0/"
```

## (2) cloudfuseインストールファイル

この tar ファイルは、GitHUB の https://github.com/redbo/cloudfuse をクローンして　tar コマンドでまとめたものです。

```
$ git clone https://github.com/redbo/cloudfuse.git
$ tar czvf cloudfuse.tgz cloudfuse
$ sha256sum cloudfuse.tgz 
3afb37d739ca47bad19eee28abaa73703ccda7ce5df6a2279fc70bf96eeb5f6b  cloudfuse.tgz
```

## (3) レシピ本体の説明
レシピの説明は Ruby コード入れた注釈を参照ねがいます。 Linuxのディストリビューションによる非互換部分は、判定して対応する様に書いています。

```
# -*- coding: utf-8 -*-
#
# Cookbook Name:: objectStorage01
# Recipe:: default
#

#
# CloudFuseを動作させるために必要な
# パッケージのインストール
#
case node['platform']
when 'ubuntu','deb ian'
  execute 'apt-get update' do
    command 'apt-get update'
    action :run
  end

  %w{
    build-essential 
    libcurl4-openssl-dev 
    libxml2-dev 
    libssl-dev 
    libfuse-dev
  }.each do |pkgname|
    package "#{pkgname}" do
      action :install
    end
  end

when 'centos','redhat'
  execute 'yum update' do
    command 'yum update -y'
    action :run
  end

  %w{
    gcc
    make
    fuse-devel
    curl-devel
    libxml2-devel
    openssl-devel
    fuse
  }.each do |pkgname|
    package "#{pkgname}" do
      action :install
    end
  end
end


#
# cloudfuse の tar ファイルを対象サーバーへ転送する
# この tar ファイルは、以下のURLから取得したものです
# https://github.com/redbo/cloudfuse
#
filename = "cloudfuse.tgz"
file_checksum = "aea8ec51613c6a3f7ffd8cbed76b27d4fb0d028a796952e9f582b7e9c3ab2307"
work_dir = "/root/_cloudfuse_work"
cookbook_file "/root/#{filename}" do
  source "#{filename}"
  checksum "#{file_checksum}"
end


#
# cloudfuseを展開、ビルド、インストールします
#
script "install_cloudfuse" do
  interpreter "bash"
  user        "root"
  code <<-EOL
    install -d #{work_dir}
    tar zxvf /root/#{filename} -C #{work_dir}
    cd #{work_dir}/cloudfuse
    ./configure
    make
    make install
  EOL
end


#
# アトリビュートdefailt.rb や ロールからのオバーライドの設定値を
# ローカル変数にセットして、cloudfuseの認証ファイルに書き込む
#
os_username = node["objectstorage"]["username"]
os_api_key = node["objectstorage"]["apikey"]
os_authurl = node["objectstorage"]["authurl"]

file "/root/.cloudfuse" do
  owner "root"
  group "root"
  mode 0600
  config_file = "username=#{os_username}\n" \
    "api_key=#{os_api_key}\n" \
    "authurl=#{os_authurl}\n"
  content "#{config_file}}\n"
  action :create
end

#
# /etc/fstabの修正方法には、file で修正する方法が取れるが、
# しかし、複数のレシピを適用した場合、CHEFが定義する適用ルールに違反するため
# 動作しないケースが起こる。
# この問題を回避するため、rubyブロックから/etc/fstabに追加を加える
#
# fileで設定する場合のためコメント化して残しておく
#
#file '/etc/fstab' do
#  owner "root"
#  group "root"
#  mode 0644
#  not_if 'grep "^cloudfuse" /etc/fstab'
#  new_content = File.read( path )
#  p new_content
#  content "#{new_content}\n" \
#  "cloudfuse /os fuse auto,_netdev,defaults,gid=106,umask=007,allow_other    0 0\n"
#  action :create
#end
#
# Ruby block で /etc/fstab に変更設定
ruby_block 'adding_fstab_entry' do
  block do
    file = "/etc/fstab"
    line = "cloudfuse /os fuse auto,_netdev,defaults,gid=106,umask=007,allow_other    0 0\n"
    if (`grep "^cloudfuse" #{file}`.size == 0) then
    File::open(file, "a") do |f|
        f.write "#{line}"
      end
    end
  end
  action :run
end

#
# ディレクトリ作成
#
directory '/os' do
  owner 'root'
  group 'root'
  mode '0755'
  action :create
end

#
# オブジェクト・ストレージをブロック・ストレージとしてマウント
#
execute "/os" do
  command 'mount /os'
  ignore_failure true
end
```

#レシピの適用手順

このレシピは、物理サーバーと仮想サーバーのどちらでも対応しますが、簡単に試せる様に最小仮想サーバーでの適用例をご紹介します。次のシェルを利用して、仮想サーバーを注文します。 slcli コマンドの説明は "slcli vs create -h " で見る事ができます。

```
slcli vs create \
--hostname webap1 --domain softlayer.com \
--datacenter tok02 \
--cpu 1 --memory 1 \
--os UBUNTU_LATEST_64 \
--billing hourly \
--public \
--key 370981 \
--network 100
```
仮想サーバーの起動は、次のコマンドの action 欄が "- "になっていて、作業が無くなった状態になっていれば、完了した事になります。

```
chef@ChefWs:~/chef-repo/site-cookbooks$ slcli vs list
:..........:..........:.................:...............:............:........:
:    id    : hostname :    primary_ip   :   backend_ip  : datacenter : action :
:..........:..........:.................:...............:............:........:
: 13040349 :  webap1  : 161.202.142.196 :  10.132.253.7 :   tok02    :   -    :
:..........:..........:.................:...............:............:........:
```


本クックブックの適用方法として、スタンドアロン、knife リモート適用、Chef Server 利用の３パターンをご紹介します。


## スタンドアロンで実行する方法

knife や chef-server を使わず、chef-solo コマンドを利用するだけの方法です。
プロビジョニング完了後に、設定対象サーバーにログインして、以下のコマンドを順次実行してきます。
ここでknifeを実行する理由は、/var/chef/cookbooks のディレクトを作成するためです。

```
# curl -L https://www.opscode.com/chef/install.sh | bash
# knife cookbook create dummy -o /var/chef/cookbooks
# cd /var/chef/cookbooks
# git clone https://github.com/takara9/objectStorage01
```
git のバージョンが1.9以降であれば、次の様に一回で落とせます。

```
# git -C /var/chef/cookbooks clone https://github.com/takara9/objectStorage01
```
適応前に、オブジェクト・ストレージの認証情報をattributesのファイルに設定します。

```
# vi objectStorage01/attributes/default.rb 
```
準備が完了したら objectStorage01 クックブックを適用します。

```
# chef-solo -o objectStorage01
< 中略 >
Running handlers complete
Chef Client finished, 13/14 resources updated in 01 minutes 15 seconds
```




## Knife Solo で利用する方法 
レポジトリ用のディレクトリを作成して初期化します。

```
$ mkdir chef-solo-repo
$ cd chef-solo-repo
$ knife solo init .
```
site-cookbooksの下にクックブックをクローンします。

```
$ cd site-cookbooks/
$ git clone https://github.com/takara9/objectStorage01 
```
一応、GitHubから落ちてきているか確認しておきます。

```
$ pwd
/home/chef/chef-solo-repo/site-cookbooks
$ ls
objectStorage01
```
attributes/default.rb を編集して認証情報をセットした後、
hostnameのインスタンスに、クックブックを適用します。

```
$ cd /home/chef/chef-solo-repo
$ knife solo bootstrap root@hostname -i sshkey -r 'recipe[objectStorage01]'
```

## CHEF Server から適用する方法
Chef WorkStaion のリポジトリに移動して、クックブックをクローンします。

```
$ pwd
/home/chef/chef-repo/cookbooks
$ git clone https://github.com/takara9/objectStorage01
```
クックブックをCHEFサーバーへアップロードする

```
$ knife cookbook upload objectStorage01 
Uploading objectStorage01 [0.1.0]
Uploaded 1 cookbook.
```
ロールを作成して、オブジェクトストレージの認証情報のAttributeを上書きする様にします。

```
$ knife role create webserver
```
先に作成したロールを指定して、CHEFクライアントをインストールします。

```
$ knife bootstrap hostname -i sshkey -N web01 -r 'role[webserver]'
```



#### 適用後のサーバーの状態

クックブックの適用結果を確認します。次の様に'/os'がマウントされていれば成功です。

```
# df
ファイルシス   1K-ブロック    使用     使用可 使用% マウント位置
/dev/xvda2        25412940 1763356   22352024    8% /
devtmpfs            497688       0     497688    0% /dev
tmpfs               505924       0     505924    0% /dev/shm
tmpfs               505924    6620     499304    2% /run
tmpfs               505924       0     505924    0% /sys/fs/cgroup
/dev/xvda1          245679  133940      98632   58% /boot
cloudfuse       8589934588       0 8589934588    0% /os
```
lsコマンドを実行するとオブジェクト・ストレージのコンテナのリストが表示されます。
/os直下は、コンテナに対応していないので、ファイルを保存できない点が注意です。

```
# ls -al /os
合計 4
drwxrwx---   2 root  106    0  1月  1  1970 .
drwxr-xr-x. 19 root root 4096 11月  9 10:01 ..
drwxrwx---   2 root  106    0 11月  9 10:02 archive
drwxrwx---   2 root  106    0 11月  9 10:02 backup_contents
drwxrwx---   2 root  106    0 11月  9 10:02 backup_dbdata
drwxrwx---   2 root  106    0 11月  9 10:02 log
```



# Chef 関連マニュアル
このレシピを作るにあたって参照したCHEFマニュアルのリンクです。
- script  (https://docs.chef.io/resource_script.html )
- execute (https://docs.chef.io/resource_execute.html )
- package (https://docs.chef.io/resource_package.html )
- About the Recipe DSL (https://docs.chef.io/dsl_recipe.html#about-the-recipe-dsl )
- About Ohai (https://docs.chef.io/ohai.html )
- ruby_block (https://docs.chef.io/resource_ruby_block.html)
- directory (https://docs.chef.io/resource_directory.html)
- mount (https://docs.chef.io/resource_mount.html)