Jedipunkz's Blog

A Blog about Infrastructure Technologies

Chef-Container Beta を使ってみる

こんにちは。@jedipunkz です。

昨晩 Chef が Chef-Container を発表しました。

まだ Beta リリースでバージョンは 0.2.0 です。(gem だと 0.1.1)

Docker を代表とするコンテナ周りの技術が最近、盛んにリリースされていますし、今 後クラウドプラットフォーム上でコンテナを使ってアプリを動かすケースも増えてくる のではないでしょうか。Dockerfile を使っても Chef-Solo を使ってソフトウェアをデ プロイ出来るのだけどそれだけだとしんどいので、コンテナに特化した Chef が出てき たってことだと思います。特徴として SSH でログインしてブートストラップするので はなくて Runit + Chef-init を用いてコンテナにデプロイすることが挙げられます。

では実際に使ってみたのでその時の手順をまとめてみます。

事前に用意する環境

下記のソフトウェアを予めインストールしておきましょう。

  • docker
  • chef
  • berkshelf

ここで注意なのですが後に knife コマンドを使って Docker イメージをビルドします。 つまり root 権限が必要です。rbenv 等を使って ruby, chef をインストールすると、 辛いかもしれませんので OS のパッケージを使ってインストールすると良いと思います。 この辺りは今後改善策が出てくるかも…。

尚、インストール方法はここでは割愛します。

Chef-Container のインストール

下記の2つの Gems をインストールします。

  • knife-container
  • chef-container
1
2
% sudo gem install knife-container
% sudo gem install chef-container

使用方法

まず knife コマンドを使って操作に必要なディレクトリとファイルを生成します。

1
% knife container docker init chef/ubuntu-12.04 -r 'recipe[apache2]' -z -b

ここで ‘chef/ubuntu-12.04’ は Docker のイメージ名です。chef-init 等の環境が予 め入っていました。このイメージ以外では今のところ動作を確認していません..。これは後にまとめで触れます。

上記のコマンドの結果で得られるディレクトリとファイル達です。

1
2
3
4
5
6
7
8
9
.
└── dockerfiles
    └── chef
        └── ubuntu-12.04
            ├── Berksfile
            ├── chef
            │   ├── first-boot.json
            │   └── zero.rb
            └── Dockerfile

また dockerfiles/chef/ubuntu-12.04/Dockerfile を確認すると…

1
2
3
4
5
6
7
# BASE chef/ubuntu-12.04:latest
FROM chef/ubuntu-12.04
ADD chef/ /etc/chef/
RUN chef-init --bootstrap
RUN rm -rf /etc/chef/secure/*
ENTRYPOINT ["chef-init"]
CMD ["--onboot"]

イメージを取得 -> ディレクトリ同期 -> chef-init 実行 -> /etc/chef/secure 配下削除、と 実行しているようです。

次に first-boot.json という名前のファイルを生成します。chef-init が解釈するファ イルです。

1
2
3
4
5
6
7
8
9
10
{
   "run_list": [
      "recipe[apache2]"
   ],
   "container_service": {
      "apache2": {
         "command": "/usr/sbin/apache2 -k start"
      }
   }
}

ではいよいよ knife コマンドで Docker イメージをビルドします。

1
% sudo knife container docker build chef/ubuntu-12.04 -z

すると、下記のように Docker イメージが出来上がります。

1
2
3
4
5
% sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
chef/ubuntu-12.04   11                  03fd2357596f        4 days ago          397.7 MB
chef/ubuntu-12.04   11.12               03fd2357596f        4 days ago          397.7 MB
chef/ubuntu-12.04   11.12.8             03fd2357596f        4 days ago          397.7 MB

出来上がったイメージを利用してコンテナを稼働します。

1
2
3
4
% sudo docker run chef/ubuntu-12.04
% sudo docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
191cfdaf0bdb        650a89f73ed8        chef-init --onboot   39 minutes ago      Up 39 minutes                           agitated_almeida

まとめ

コンテナと言っても今現在は Docker のみに対応しているようです。また init の際に指定する Docker イメージ の中に chef-init が入っている必要がありそうです。Build する前に予めイメージを作っておく必要があるという のはしんどいので、今後改善されるかもしれません。

そもそも Docker やコンテナ技術の登場で Puppet, Chef を代表とするツール類が不要になるのでは?という議論が 幾つかの場面であったように思います。つまりコンテナのイメージに予めソフトウェアを配布しそれを用いて稼働 することで、マシンが起動した後にデプロイすることが必要ないよね?という発想です。今回紹介したようにコンテナの イメージを生成するのに Chef を用いるということであれば、また別の議論になりそうです。また稼働したコンテナに ソフトウェアをデプロイすることも場合によっては必要なので、この辺りの技術の完成度が上がることを期待したいです。

参考 URL


JTF2014 で Ceph について話してきた!

こんにちは。@jedipunkz です。

今日、JTF2014 (July Tech Festa 2014) というイベントで Ceph のことを話してきま した。Ceph ユーザ会の会員として話してきたのですが Ceph ユーザ会は実は最近発足 したばかりのユーザ会で、まだまだ活動が活発ではありません。もし興味がある方いらっ しゃいましたら是非参加よろしくお願いしますー。下記の Google Groups になります。

https://groups.google.com/forum/#!forum/ceph-jp

ユーザ会としての勉強会として初になるのですが、今回このイベントで自分は Ceph-Deploy について話してきました。とりあえず皆さんに使ってもらいたかったので この話をしてきました。が、予定時間がメチャ短かったので超絶早口で頑張った分、皆 さんに理解してもらえなかった気がしてちょっと反省…。なので、このブログを利用 して少し細くさせてもらいます。

今日の発表資料はこちらです!

今日のテーマは 「Ceph-Deploy を使って Ceph を構築してみる」だったのですが、下 記のテーマを持って資料を作っています。

  • 単にミニマム構成ではなく運用を考慮した実用性のある構成
  • OSD, MON, MDS の各プロセスとノード・ディスクの数の関係を知ってもらう

特に「実用性のある..」は意識したつもりでした。そのために前提とした構成に下記の 特徴を持たせています。(資料 6 ページ目に構成図があります。確認してみてください。)

  • オブジェクト格納用ディスクは複数/ノードを前提
  • OSD レプリケーションのためのクラスタネットワークを用いる構成
  • OSD の扱うジャーナル格納用ディスクは高速な SSD を用いる
  • MDS は利用する HW リソースの特徴が異なるので別ノードへ配置

ストレージ全体を拡張したければ

  • 図中 ceph01-03 の様なノードを増設する
  • ceph01-03 にディスクとそれに対する OSD を増設する

ですが、前者がベストでしょう。ノード増設の場合 ceph-deploy を用いて

  • ceph-deploy mon create <新規ホスト名> で MON を稼働
  • ceph-dploy disk zap, osd create で OSD を稼働

で簡単に可能です。MDS の増設も負荷状況を見ながらするといいでしょう。自分はまだ Ceph を運用していないので、各プロセスがどのようなリソースの消費の仕方をするの か知りません。MDS がどのような数で運用していくべきなのか。早く運用から得たノウ ハウが共有されないかなぁと期待しています。

また今回話すのを忘れたのですが SSD をジャーナル格納用ディスクとして用いたのは ハードディスクに対して高速でアクセス出来ること・またメタデータはファイルオブジェ クトに対して小容量で済む、といった理由からです。メタデータを扱うのに適している と思います。また将来的には幾つかの KVS データベースソフトウェアをメタデータ管 理に使う実装がされるそうです。

以上です。皆さん、是非 Ceph を使ってみてください! また興味のある方はユーザ会 への加入をご検討くださいー。


Mesos + Marathon + Deimos + Docker を試してみた!

こんにちは。@jedipunkz です。

以前 Mesos, Docker について記事にしました。

http://jedipunkz.github.io/blog/2013/09/28/mesos-architecture-number-1/ http://jedipunkz.github.io/blog/2013/10/01/methos-architecture-number-2-docker-on-mesos/

Twitter で Docker 関連のオーケストレーションツールについて呟いていたら @everpeace さんから こんな情報をもらいました。

Deimos !!! 知らなかった。Mesos の Docker プラグインらしく下記の場所にありました。

https://github.com/mesosphere/deimos

色々調べいたら、こんな資料が見つかりました。どうやらまだ公開されて4日しか経っていないようです。

http://mesosphere.io/learn/run-docker-on-mesosphere/

Mesos + Marathon + Deimos + Docker をオールインワン構成で構築する手順が書かれています。

内容はほぼ同じですが、一応自分がやってみて理解したことをまとめたいので下記に記していきます。

構築してみる

手順をまとめてスクリプトにしました。パッケージは Ubuntu 13.10 用のようですが 14.04 のホスト で実行出来ました。14.04 のパッケージはまだ見つかっていません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
# disable ipv6
echo 'net.ipv6.conf.all.disable_ipv6 = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.default.disable_ipv6 = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# install related tools
sudo apt-get update
sudo apt-get -y install curl python-setuptools python-pip python-dev python-protobuf

# install zookeeper
sudo apt-get -y install zookeeperd
echo 1 | sudo dd of=/var/lib/zookeeper/myid

# install docker
sudo apt-get -y install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io
sudo docker pull libmesos/ubuntu

# install mesos
curl -fL http://downloads.mesosphere.io/master/ubuntu/13.10/mesos_0.19.0-xcon3_amd64.deb -o /tmp/mesos.deb
sudo dpkg -i /tmp/mesos.deb
sudo mkdir -p /etc/mesos-master
echo in_memory  | sudo dd of=/etc/mesos-master/registry
curl -fL http://downloads.mesosphere.io/master/ubuntu/13.10/mesos_0.19.0-xcon3_amd64.egg -o /tmp/mesos.egg
sudo easy_install /tmp/mesos.egg

# install marathon
curl -fL http://downloads.mesosphere.io/marathon/marathon_0.5.0-xcon2_noarch.deb -o /tmp/marathon.deb
sudo dpkg -i /tmp/marathon.deb

# restart each services
sudo service docker.io restart
sudo service zookeeper restart
sudo service mesos-master restart
sudo service mesos-slave restart

# install deimos
sudo pip install deimos
sudo mkdir -p /etc/mesos-slave

## Configure Deimos as a containerizer
echo /usr/bin/deimos  | sudo dd of=/etc/mesos-slave/containerizer_path
echo external     | sudo dd of=/etc/mesos-slave/isolation

プロセスの確認

実行が終わると各プロセスが確認出来ます。オプションでどのプロセスが何を見ているか大体 わかりますので見ていきます。

mesos-master

mesos-master は zookeeper を参照して 5050 番ポートで起動しているようです。

1
2
% ps ax | grep mesos-master
 1224 ?        Ssl    0:30 /usr/local/sbin/mesos-master --zk=zk://localhost:2181/mesos --port=5050 --log_dir=/var/log/mesos --registry=in_memory

mesos-slave

mesos-slave は同じく zookeeper を参照して containerizer を deimos として稼働していることが わかります。

1
2
% ps ax | grep mesos-slave
 1225 ?        Ssl    0:12 /usr/local/sbin/mesos-slave --master=zk://localhost:2181/mesos --log_dir=/var/log/mesos --containerizer_path=/usr/bin/deimos --isolation=external

zookeeper

zookeeper は OpenJDK7 で稼働している Java プロセスです。

1
2
% ps ax | grep zookeeper
 1073 ?        Ssl    1:07 /usr/bin/java -cp /etc/zookeeper/conf:/usr/share/java/jline.jar:/usr/share/java/log4j-1.2.jar:/usr/share/java/xercesImpl.jar:/usr/share/java/xmlParserAPIs.jar:/usr/share/java/netty.jar:/usr/share/java/slf4j-api.jar:/usr/share/java/slf4j-log4j12.jar:/usr/share/java/zookeeper.jar -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,ROLLINGFILE org.apache.zookeeper.server.quorum.QuorumPeerMain /etc/zookeeper/conf/zoo.cfg

docker

docker が起動していることも確認できます。設定は特にしていないです。

1
2
% ps axuw | grep docker
root       831  0.0  0.3 364776 14924 ?        Sl   01:30   0:01 /usr/bin/docker.io -d

Marathon の WebUI にアクセス

Marathon の WebUI にアクセスしてみましょう。

まだ何も Tasks が実行されていないので一覧には何も表示されないと思います。

Tasks の実行

Marathon API に対してクエリを発行することで Mesos の Tasks として Docker コンテナを稼働させることが出来ます。 下記のファイルを ubuntu.json として保存。

1
2
3
4
5
6
7
8
9
10
{
    "container": {
    "image": "docker:///libmesos/ubuntu"
  },
  "id": "ubuntu",
  "instances": "1",
  "cpus": ".5",
  "mem": "512",
  "uris": [ ]
}

下記の通り localhost:8080 が Marathon API の Endpoint になっているのでここに対して作成した JSON を POST します。

1
% curl -X POST -H "Content-Type: application/json" localhost:8080/v2/apps -d@ubuntu.json

Tasks の一覧を取得してみます。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[{"id":"ubuntu","cmd":"","env":{},"instances":1,"cpus":0.5,"mem":512.0,"executor":"","constraints":[],"uris":[],"ports":[13049],"taskRateLimit":1.0,"container":{"image":"docker:///libmesos/ubuntu","options":[]},"version":"2014-06-13T01:45:58.693Z","tasksStaged":1,"tasksRunning":0}]}

Tasks の一覧が JSON で返ってきます。id : ubuntu, インスタンス数 : 1, CPU 0.5, メモリー : 512MB で Task が稼働していることが確認出来ます。

ここで WebUI 側も見てみましょう。

一つ Task が稼働していることが確認出来ると思います。

その Task をクリックすると詳細が表示されます。

次に Tasks のスケーリングを行ってみましょう。 下記の通り ubuntu.json を修正し instances : 2 とする。これによってインスタンス数が2に増えます。

1
2
3
4
5
6
7
8
9
10
{
    "container": {
    "image": "docker:///libmesos/ubuntu"
  },
  "id": "ubuntu",
  "instances": "2",
  "cpus": ".5",
  "mem": "512",
  "uris": [ ]
}

修正した JSON を POST します。

1
% curl -X PUT -H "Content-Type: application/json" localhost:8080/v2/apps/ubuntu -d@ubuntu.json

Tasks の一覧を取得し containers が 2 になっていることが確認できます。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[{"id":"ubuntu","cmd":"","env":{},"instances":2,"cpus":0.5,"mem":512.0,"executor":"","constraints":[],"uris":[],"ports":[17543],"taskRateLimit":1.0,"container":{"image":"docker:///libmesos/ubuntu","options":[]},"version":"2014-06-13T02:40:04.536Z","tasksStaged":3,"tasksRunning":0}]}

最後に Tasks を削除してみましょう。

1
% curl -X DELETE -H "Content-Type: application/json" localhost:8080/v2/apps/ubuntu

Tasks が削除されたことを確認します。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[]}

Marathon API v2

Marathon API v2 について下記の URL に仕様が載っています。上記に記したクエリ以外にも色々載っているので 動作を確認してみるといいと思います。

https://github.com/mesosphere/marathon/blob/master/docs/api/http/REST_template.md

まとめ

オールインワン構成が出来ました。また動作確認も無事出来ています。 以前試した時よりも大分、手順が簡潔になった印象があります。また参考資料中に

“checkout our other multi-node tutorials on how to scale Docker in your data center.”

とありますが、まだ見つかっていません(´・ω・`)見つかった方教えてくださいー。

以前試した時は Mesos-Master の冗長化が出来なかったので今回こそ Multi Mesos-Masters, Multi Mesos-Slaves の構成を作ってみたいと思います。

また今月?になって続々と Docker のオーケストレーションツールを各社が公開しています。

centurion

New Relic が開発したオーケストレーションツール。 https://github.com/newrelic/centurion

helios

Spotify が開発したオーケストレーションツール。 https://github.com/spotify/helios

fleet

CoreOS 標準搭載。 https://github.com/coreos/fleet

geard

RedHat が Red Hat Enterprise Linux Atomic Host に搭載しているツール。 http://openshift.github.io/geard/

Kubernetes

Google が開発したオーケストレーションツール。 https://github.com/GoogleCloudPlatform/kubernetes

shipper

Python のコードで Docker をオーケストレーション出来るツール。 https://github.com/mailgun/shipper

幾つか試したのですが、まだまだ動く所までいかないツールがありました。github の README にも “絶賛開発中なのでプロダクトレディではない” と書かれています。これからでしょう。


クラウドライブラリ Fog で AWS を操作!..のサンプル

こんにちは。@jedipunkz です。

最近 OpenStack でサービスを開発!.. じゃなくて AWS でプロトタイプサービス作っ ているのですが、Ruby で開発したかったので Fog を使っています。EC2 と ELB の API を叩くコードになりつつあるのですが、サンプルコードって世の中に中々無いと気 がついたので、このブログ記事にサンプルコードを載せたいと思います。

Fog とは ?

Fog http://fog.io/ はクラウドライブラリソフトウェアです。AWS, Rackspace, CloudStack, OpenStack .. と数ある世の中のクラウドプラットフォームを扱うために 用意されたソフトウェアです。対応しているプラットフォームの種別は下記を見ると参 考になります。

http://fog.io/about/provider_documentation.html

ドキュメントがまだまだ揃っていなく、Fog のコードを覗きながら実装するしかない状 況です。なので「こう使えば良い!」というお手本があまりネット上にも無い気がしま す。

ドキュメントは一応下記にあります。 が使い方がよくわからない・・!(´;ω;`)ブワッ

http://rubydoc.info/gems/fog/frames/index

EC2 インスタンスを使ってみる

まずは AWS EC2 の API を叩いて t1.micro インスタンスを立ち上げてみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'fog'

compute = Fog::Compute.new({
  :provider => 'AWS',
  :aws_access_key_id => '....',
  :aws_secret_access_key => '....',
  :region => 'ap-northeast-1'
})

server = compute.servers.create(
  :image_id => 'ami-cedaa2bc',
  :flavor_id => 't1.micro',
  :key_name => 'test_key',
  :tags => {'Name' => 'test'},
  :groups => 'ssh-secgroup'
)

server.wait_for { print "."; ready? }

puts "created instance name :", server.dns_name

解説

  • compute = … とあるところで接続情報を記しています。

“ACCESS_KEY_ID” や “SECRET_ACCESS_KEY” はみなさん接続する時にお持ちですよね。それ とリージョン名やプロバイダ名 (ここでは AWS) を記して AWS の API に接続します。

  • server = … とあるところで実際にインスタンスを作成しています。

ここではインスタンス生成に必要な情報を盛り込んでいます。Flavor 名や AMI イメー ジ名・SSH 鍵の名前・セキュリティグループ名等です。

便利なメソッド

server = … でインスタンスを生成すると便利なメソッドを扱って情報を読み込むこ とが出来ます。

1
2
3
4
5
6
server.dns_name # => public な DNS 名を取得
server.private_dns_name # => private な DNS 名を取得
server.id # => インスタンス ID を取得
server.availability_zone # => Availability Zone を取得
server.public_ip_address # => public な IP アドレスを取得
server.private_ip_address # => private な IP アドレスを取得

これは便利…

モジュール化して利用

毎回コードの中でこれらの接続情報を書くのはしんどいので、Ruby のモジュールを作 りましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module AWSCompute
  def self.connect()
    conn = Fog::Compute.new({
      :provider => 'AWS',
      :aws_access_key_id => '...',
      :aws_secret_access_key => '...',
      :region => '...'
    })
    begin
      yield conn
    ensure
      # conn.close
    end
  rescue Errno::ECONNREFUSED
  end
end

こう書いておくと例えば…

インスタンスのターミネイト

1
2
3
4
5
AWSCompute.connect() do |sock|
  server = sock.servers.get(instance_id)
  server.destroy
  return server.id
end

インスタンスの起動

1
2
3
4
5
AWSCompute.connect() do |sock|
  server = sock.servers.get(instance_id)
  server.start
  return server.id
end

インスタンスの停止

1
2
3
4
5
AWSCompute.connect() do |sock|
  server = sock.servers.get(instance_id)
  server.stop
  return server.id
end

等と出来ます。

ELB (Elastic LoadBalancer) を使ってみる

同様に ELB を扱うコードのサンプルも載せておきます。同じくモジュール化して書くと

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module AWSELB
  def self.connect()
    conn = Fog::AWS::ELB.new(
      :aws_access_key_id => '...',
      :aws_secret_access_key => '...',
      :region => '...',
    )
    begin
      yield conn
    ensure
      # conn.close
    end
  rescue Errno::ECONNREFUSED
  end
end

としておいて…

ELB の新規作成

下記のコードで ELB を新規作成出来ます。

1
2
3
4
5
6
7
AWSELB.connect() do |sock|
  availability_zone = '...'
  elb_name = '...'
  listeners = [{ "Protocol" => "HTTP", "LoadBalancerPort" => 80, "InstancePort" => 80, "InstanceProtocol" => "HTTP" }]
  result = sock.create_load_balancer(availability_zone, elb_name, listeners)
  p result
end

この状態では ELB に対してインスタンスが紐付けられていないので使えません。下記の操作で インスタンスを紐付けてみましょう。

1
2
3
4
5
6
AWSELB.connect() do |sock|
  insntance_id = '...'
  elb_name = '...'
  result = sock.register_instances_with_load_balancer(instance_id, elbname)
  p result
end

insntance_id には紐付けたいインスタンスの ID を、elb_name には先ほど作成した ELB の名前を 入力します。 この操作を繰り返せば AWS 上にクラスタが構成出来ます。

逆にクラスタからインスタンスの削除したい場合は下記の通り実行します。

1
2
3
4
AWSELB.connect() do |sock|
  result = sock.deregister_instances_from_load_balancer(instance_id, elbname)
  p result
end

まとめ

今回は Fog を紹介しましたが Python 使いの方には libcloud をおすすめします。

https://libcloud.apache.org/

Apache ファウンデーションが管理しているクラウドライブラリです。こちらも複数の クラウドプラットフォームに対応しているようです。

Fog で OpenStack も操作したことがあるのですが、AWS 用のコードの方が完成度が高 いのか、戻り値などが綺麗に整形されていて扱いやすかったり、メソッドも豊富に用意 されていたりという印象でした。これは… OpenStack 用の Fog コードにコントリビュー トするチャンス・・!

皆さんもサンプルコードお持ちでしたら、ブログ等で公開していきましょうー。 ではでは。


stackforge/openstack-chef-repo で OpenStack Icehouse デプロイ

こんにちは。@jedipunkz です。

またまた OpenStack のデプロイをどうするか?についてです。

今まで自分の中では Rackspace Private Cloud で使われている Rackspace 管理の rcbops/chef-cookbooks が今現在使うならベストの選択だと思っていました。これは内 部で Chef が使われていてしかも Cookbooks が Github 上で公開されています。 Apache ライセンスで使えるので、サービス構築にも使えちゃうというモノ。

先日、ある OpenStack コアデベロッパーの方から「jedipunkz さん、やっぱり rcbops がいいですか?運営とかどうなっているんでしょう?マージの規準とかどうなのかな?」 と質問受けました。確かにマージの基準は Rackspace Private Cloud がベースになり ますし、管理しているエンジニアの一覧を見ていると Rackspace 社のエンジニアがメ インですし、今後どうなるのか分からない…。

逃げ道は用意したほうが良さそう。

ということで、以前自分も暑かったことのある StackForge の openstack-chef-repo を久々に使ってみました。Icehouse 構成がこの時点で既に組めるようになっていて、 以前よりだい〜ぶ完成度増した感があります。今回は nova-network 構成を作ってみた のですが、Neutron 構成ももちろん出来そうなので後に調べてまた公開したいです。

StackForge とは

StackForge は OpenStack のデプロイ・CI の仕組みとして公式に用いられているもの。 公式サイトは下記の場所にある。

http://ci.openstack.org/stackforge.html

StackForge の openstack-chef-repo は下記の場所にある。

https://github.com/stackforge/openstack-chef-repo

openstack-chef-repo はまだ ‘stable/icehouse’ ブランチが生成されていない。が直 ちに master からブランチが切られる様子。

目的

StackForge の openstack-chef-repo を用いて Icehouse リリース版の OpenStack を デプロイするための方法を記す。今回は未だ ‘stable/icehouse’ ブランチが無いので master ブランチを用いて Icehouse リリース版 OpenStack を構築する。

構成

構成はこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
   +-----------------+
   |    GW Router    |
+--+-----------------+
|  |
|  +-------------------+-------------------+--------------------------------------
|  |eth0               |eth0               |eth0                      VM Network (fixed)
|  +-----------------+ +-----------------+ +-----------------+ +-----------------+ 
|  | Controller Node | |  Compute Node   | |  Compute Node   | | Chef Workstation|
|  +-----------------+ +-----------------+ +-----------------+ +-----------------+ 
|  |eth1               |eth1               |eth1               |  
+--+-------------------+-------------------+-------------------+------------------
                                                                 API/Management Network
  • Nova-Network 構成
  • 今回は fixed network 用の NIC を eth0(物理 NIC) にアサイン
  • fixed network 用のネットワークをパブリックにする
  • API/Management Network 側に全ての API を出す。またここから The Internet に迂回出来るようにする
  • VM Network も GW を介して The Internet へ迂回出来るようにする
  • 全ての操作は ‘Chef Workstaion’ から行う
  • Compute ノードはキャパシティの許す限り何台でも可

IP 一覧 (この記事での例)

  • Controller : 10.200.9.46 (eth0), 10.200.10.46 (eth1)
  • Compute : 10.200.9.47 (eth0), 10.200.10.47 (eth1)
  • Compute : 10.200.9.48 (eth0), 10.200.10.48 (eth1)

手順

openstack-chef-repo をワークステーションノード上で取得する。

1
2
% git clone https://github.com/stackforge/openstack-chef-repo.git
% cd openstack-chef-repo

Berksfile があるのでこれを用いて Chef Cookbooks を取得する。

1
% berks install --path=./cookbooks

Roles, Cookbooks を Chef サーバにアップロードする。

1
2
% knife cookbook upload -o cookbooks -a
% knife role from file roles/*.rb

1 Environment に対して 1 OpenStack クラスタである。今回構築するクラスタのため の Environment を作成する。

下記を environments/icehouse-nova-network.rb として生成する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
name "icehouse-nova-network"
description "separated nodes environment"

override_attributes(
    "release" => "icehouse",
    "osops_networks" => {
      "management" => "10.200.10.0/24",
      "public" => "10.200.10.0/24",
      "nova" => "10.200.10.0/24"
    },
    "mysql" => {
      "bind_address" => "0.0.0.0",
      "root_network_acl" => "%",
      "allow_remote_root" => true,
      "server_root_password" => "secrete",
      "server_repl_password" => "secrete",
      "server_debian_password" => "secrete"
    },
    "nova" => {
      "network" => {
        "fixed_range" => "172.18.0.0/24",
        "public_interface" => "eth0"
      }
    },
    "rabbitmq" => {
      "address" => "10.200.10.46",
      "port" => "5672"
    },
    "openstack" => {
      "developer_mode" => true,
      "compute" => {
        "rabbit" => {
          "host" => "10.200.10.46"
        },
        "novnc_proxy" => {
          "bind_interface" => "eth1"
        },
        "libvirt" => {
          "bind_interface" => "eth1"
        },
        "network" => {
          "fixed_range" => "10.200.9.0/24"
        },
        "rabbit_server_chef_role" => "os-ops-messaging",
        "networks" => [
        {
          "label" => "private",
          "ipv4_cidr" => "10.200.9.0/24",
          "num_networks" => "1",
          "network_size" => "255",
          "bridge" => "br200",
          "bridge_dev" => "eth0",
          "dns1" => "8.8.8.8",
          "dns2" => "8.8.4.4",
          "multi_host" => "T"
        }
        ]
      },
      "identity" => {
        "bind_interface" => "eth1",
        "users" => {
          "demo" => {
            "password" => "demo",
            "default_tenant" => "service",
            "roles" => {
              "Member" => [ "Member" ]
            }
          }
        }
      },
      "image" => {
        "api" => {
          "bind_interface" => "eth1"
        },
        "debug" => true,
        "identity_service_chef_role" => "os-identity",
        "rabbit_server_chef_role" => "os-ops-messaging",
        "registry" => {
          "bind_interface" => "eth1"
        },
        "syslog" => {
          "use" => false
        },
        "upload_image" => {
          "cirros" => "http://hypnotoad/cirros-0.3.0-x86_64-disk.img",
        },
        "upload_images" => [
          "cirros"
        ]
      },
      "network" => {
        "api" => {
          "bind_interface" => "eth1",
        }
      },
      "db" => {
        "bind_interface" => "eth1",
        "compute" => {
          "host" => "10.200.10.46"
        },
        "identity" => {
          "host" => "10.200.10.46"
        },
        "image" => {
          "host" => "10.200.10.46"
        },
        "network" => {
          "host" => "10.200.10.46"
        },
        "volume" => {
          "host" => "10.200.10.46"
        },
        "dashboard" => {
          "host" => "10.200.10.46"
        }
      },
      "mq" => {
        "bind_interface" => "eth1",
        "host" => "10.200.10.46",
        "user" => "guest",
        "vhost" => "/nova",
        "servers" => "10.200.10.46",
        "compute" => {
          "service_type" => "rabbitmq",
          "rabbit" => {
            "host" => "10.200.10.46",
            "port" => "5672"
          }
        },
        "block-storage" => {
          "service_type" => "rabbitmq",
          "rabbit" => {
            "host" => "10.200.10.46",
            "port" => "5672"
          }
        }
      },
      "endpoints" => {
        "compute-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8774",
          "path" => "/v2/%(tenant_id)s"
        },
        "compute-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8774",
          "path" => "/v2/%(tenant_id)s"
        },
        "compute-ec2-admin-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8773",
          "path" => "/services/Admin"
        },
        "compute-ec2-admin" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8773",
          "path" => "/services/Admin"
        },
        "compute-ec2-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8773",
          "path" => "/services/Cloud"
        },
        "compute-ec2-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8773",
          "path" => "/services/Cloud"
        },
        "compute-xvpvnc-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "6081",
          "path" => "/console"
        },
        "compute-xvpvnc" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "6081",
          "path" => "/console"
        },
        "compute-novnc-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "6080",
          "path" => "/vnc_auto.html"
        },
        "compute-novnc" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "6080",
          "path" => "/vnc_auto.html"
        },
        "compute-vnc" => {
          "host" => "0.0.0.0",
          "scheme" => "http",
          "port" => "6080",
          "path" => "/vnc_auto.html"
        },
        "image-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9292",
          "path" => "/v2"
        },
        "image-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9292",
          "path" => "/v2"
        },
        "image-registry-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9191",
          "path" => "/v2"
        },
        "image-registry" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9191",
          "path" => "/v2"
        },
        "identity-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "5000",
          "path" => "/v2.0"
        },
        "identity-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "5000",
          "path" => "/v2.0"
        },
        "identity-admin" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "35357",
          "path" => "/v2.0"
        },
        "volume-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8776",
          "path" => "/v1/%(tenant_id)s"
        },
        "block-storage-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8776",
          "path" => "/v1/%(tenant_id)s"
        },
        "telemetry-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8777",
          "path" => "/v1"
        },
        "telemetry-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8777",
          "path" => "/v1"
        },
        "network-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9696",
          "path" => "/v2"
        },
        "network-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "9696",
          "path" => "/v2"
        },
        "orchestration-api-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8004",
          "path" => "/v1/%(tenant_id)s"
        },
        "orchestration-api" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8004",
          "path" => "/v1/%(tenant_id)s"
        },
        "orchestration-api-cfn-bind" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8000",
          "path" => "/v1"
        },
        "orchestration-api-cfn" => {
          "host" => "10.200.10.46",
          "scheme" => "http",
          "port" => "8000",
          "path" => "/v1"
        },
        "mq" => {
          "port" => "5672"
        }
      }
    }
)

生成した environment を Chef サーバにアップロードする。

1
% knife environment from file environments/icehouse-nova-network.rb

Spiceweasel をインストールする。Spiceweasel は yml ファイルを元に knife の操作 を書き出して、またそれを一気に実行することが出来るツールです。

1
2
% gem install spiceweasel --no-ri --no-rdoc
% rbenv rehash

infrastructure.yml を下記の通り修正する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
berksfile:
    options: '--no-freeze --halt-on-frozen'

cookbooks:
- apache2:
- apt:
- aws:
- build-essential:
- chef_handler:
- database:
- dmg:
- erlang:
- git:
- homebrew:
- iptables:
- logrotate:
- memcached:
- mysql:
- openssl:
- openstack-block-storage:
- openstack-common:
- openstack-compute:
- openstack-dashboard:
- openstack-identity:
- openstack-image:
- openstack-network:
- openstack-object-storage:
- openstack-ops-messaging:
- openstack-ops-database:
- openstack-orchestration:
- openstack-telemetry:
- pacman:
- postgresql:
- python:
- rabbitmq:
- runit:
- selinux:
- statsd:
- windows:
- xfs:
- yum:
- yum-epel:
- yum-erlang_solutions:

roles:
- allinone-compute:
- os-compute-single-controller:
- os-base:
- os-ops-caching:
- os-ops-messaging:
- os-ops-database:
- os-block-storage:
- os-block-storage-api:
- os-block-storage-scheduler:
- os-block-storage-volume:
- os-client:
- os-compute-api:
- os-compute-api-ec2:
- os-compute-api-metadata:
- os-compute-api-os-compute:
- os-compute-cert:
- os-compute-conductor:
- os-compute-scheduler:
- os-compute-setup:
- os-compute-vncproxy:
- os-compute-worker:
- os-dashboard:
- os-identity:
- os-image:
- os-image-api:
- os-image-registry:
- os-image-upload:
- os-telemetry-agent-central:
- os-telemetry-agent-compute:
- os-telemetry-api:
- os-telemetry-collector:
- os-network:
- os-network-server:
- os-network-l3-agent:
- os-network-dhcp-agent:
- os-network-metadata-agent:
- os-network-openvswitch:
- os-object-storage:
- os-object-storage-account:
- os-object-storage-container:
- os-object-storage-management:
- os-object-storage-object:
- os-object-storage-proxy:

environments:
- icehouse-nova-network:

nodes:
- 10.200.10.46:
    run_list: role[os-compute-single-controller]
    options: -N opstall01 -E icehouse-nova-network --sudo -x thirai
- 10.200.10.47:
    run_list: role[os-compute-worker]
    options: -N opstall02 -E icehouse-nova-network --sudo -x thirai
- 10.200.10.48:
    run_list: role[os-compute-worker]
    options: -N opstall03 -E icehouse-nova-network --sudo -x thirai

※ nodes: 項にはデプロイしたいノードと Roles を割り当て列挙する。

spiceweasel を実行する。この時点ではこれから実行されるコマンドの一覧が表示され るのみである。

1
2
3
4
5
6
7
8
% spiceweasel infrastructure.yml
berks upload --no-freeze --halt-on-frozen -b ./Berksfile
knife cookbook upload apache2 apt aws build-essential chef_handler database dmg erlang git homebrew iptables logrotate memcached mysql openssl openstack-block-storage openstack-common openstack-compute openstack-dashboard openstack-identity openstack-image openstack-network openstack-object-storage openstack-ops-messaging openstack-ops-database openstack-orchestration openstack-telemetry pacman postgresql python rabbitmq runit selinux statsd windows xfs yum yum-epel yum-erlang_solutions
knife environment from file separated.rb
knife role from file allinone-compute.rb os-base.rb os-block-storage-api.rb os-block-storage-scheduler.rb os-block-storage-volume.rb os-block-storage.rb os-client.rb os-compute-api-ec2.rb os-compute-api-metadata.rb os-compute-api-os-compute.rb os-compute-api.rb os-compute-cert.rb os-compute-conductor.rb os-compute-scheduler.rb os-compute-setup.rb os-compute-single-controller.rb os-compute-vncproxy.rb os-compute-worker.rb os-dashboard.rb os-identity.rb os-image-api.rb os-image-registry.rb os-image-upload.rb os-image.rb os-network-dhcp-agent.rb os-network-l3-agent.rb os-network-metadata-agent.rb os-network-openvswitch.rb os-network-server.rb os-network.rb os-object-storage-account.rb os-object-storage-container.rb os-object-storage-management.rb os-object-storage-object.rb os-object-storage-proxy.rb os-object-storage.rb os-ops-caching.rb os-ops-database.rb os-ops-messaging.rb os-telemetry-agent-central.rb os-telemetry-agent-compute.rb os-telemetry-api.rb os-telemetry-collector.rb
knife bootstrap 10.200.10.46 -N opstall01 -E separated --sudo -x thirai -r 'role[os-compute-single-controller]'
knife bootstrap 10.200.10.47 -N opstall02 -E separated --sudo -x thirai -r 'role[os-compute-worker]'
knife bootstrap 10.200.10.48 -N opstall03 -E separated --sudo -x thirai -r 'role[os-compute-worker]'

-e オプションを付与すると実際にこれらのコマンドが実行される。実行してデプロイを行う。

1
% spiceweasel -e infrastructure.yml

この時点で、下記の操作も行われる。

  • Nova-Network 上に仮想ネットワークの生成
  • OS イメージのダウンロードと登録 (Environment に記したモノ)

Cinder の設定

デプロイ完了したところで cinder-volume プロセスは稼働しているが物理ディスクの アサインが済んでいない。これは Chef では指定出来ないので手動で行う。

予め Cinder 用の物理ディスクを Controller ノードに付与する。(ここでは /dev/sdb1)

1
2
3
4
controller% sudo -i
controller# pvcreate /dev/sdb1
controller# vgcreate cinder-volumes /dev/sdb1
controller# service cinder-volume restart

これで完了。

使ってみる

ではデプロイした OpenStack を使って仮想マシンを作ってみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
controller% sudo -i
controller# source openrc
controller# nova keypair-add novakey01 > novakey01
controller# chmod 400 novakey01
controller# nova boot --image cirros --flavor 1 --key_name novakey01 cirros01
controller# nova list
+--------------------------------------+----------+--------+------------+-------------+--------------------+
| ID                                   | Name     | Status | Task State | Power State | Networks           |
+--------------------------------------+----------+--------+------------+-------------+--------------------+
| e6687359-1aef-4105-a8db-894600001610 | cirros01 | ACTIVE | -          | Running     | private=10.200.9.2 |
+--------------------------------------+----------+--------+------------+-------------+--------------------+
controller# ssh -i novakey01 -l cirros 10.200.9.2
vm# ping www.goo.ne.jp

仮想マシンが生成され The Internet に対して通信が行えたことを確認。

次に仮想ディスクを生成して上記で作成した仮想マシンに付与する。

1
2
3
4
5
6
7
8
9
10
11
12
controller# cinder create --display-name vol01 1
+--------------------------------------+-----------+--------------+------+-------------+----------+--------------------------------------+
|                  ID                  |  Status   | Display Name | Size | Volume Type | Bootable |             Attached to              |
+--------------------------------------+-----------+--------------+------+-------------+----------+--------------------------------------+
| 0f3726a0-c2f5-45bc-bcf2-1f6eb746f5c8 | available |    vol02     |  1   |     None    |  false   | b286387c-2311-4134-ab59-850fee3e4650 |
+--------------------------------------+-----------+--------------+------+-------------+----------+--------------------------------------+
controller# nova volume-attach e6687359-1aef-4105-a8db-894600001610 0f3726a0-c2f5-45bc-bcf2-1f6eb746f5c8 auto
controller# ssh -i novakey01 -l cirros 10.200.9.2
vm# mkfs.ext4 /dev/vdb
vm# mount -t ext4 /dev/vdb /mnt
vm# df -h | grep mnt
/dev/vdb        976M  1.3M  908M   1% /mnt

仮想ディスクを仮想マシンに付与しマウントできることを確認出来た。

まとめ

今回は Nova-Network 構成の Icehouse を構築出来た。Nova-Network は Havana でサポート終了との話が延期 になっていることは聞いていたが Icehouse でもしっかり動いている。また後に Neutron 構成も調査を行う。 Neutron 構成は下記の Environments を参考にすると動作するかもしれない。

https://github.com/stackforge/openstack-chef-repo/blob/master/environments/vagrant-multi-neutron.json

キーとなるのは、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"network": {
  "debug": "True",
  "dhcp": {
    "enable_isolated_metadata": "True"
  },
  "metadata": {
    "nova_metadata_ip": "192.168.3.60"
  },
  "openvswitch": {
    "tunnel_id_ranges": "1:1000",
    "enable_tunneling": "True",
    "tenant_network_type": "gre",
    "local_ip_interface": "eth2"
  },
  "api": {
    "bind_interface": "eth1"
  }
},

この辺り。

残っている問題点

VNC コンソールにアクセス出来ない。調べたのですが、environment の修正で直せる問 題ではないように見えました。

cookbooks/openstack-compute/templates/default/nova.conf.rb を確認すると下記の ようになっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
##### VNCPROXY #####
novncproxy_base_url=<%= @novncproxy_base_url %>
xvpvncproxy_base_url=<%= @xvpvncproxy_base_url %>

# This is only required on the server running xvpvncproxy
xvpvncproxy_host=<%= @xvpvncproxy_bind_host %>
xvpvncproxy_port=<%= @xvpvncproxy_bind_port %>

# This is only required on the server running novncproxy
novncproxy_host=<%= @novncproxy_bind_host %>
novncproxy_port=<%= @novncproxy_bind_port %>

vncserver_listen=<%= @vncserver_listen %>
vncserver_proxyclient_address=<%= @vncserver_proxyclient_address %>

vncserver_listen, vncserver_proxyclient_address はそれぞれ

  • @vncserver_listen
  • @vncserver_proxyclient_address

という変数が格納されることになっている。

では cookbooks/openstack-compute/recipes/nova-common.rb を確認すると、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template '/etc/nova/nova.conf' do
  source 'nova.conf.erb'
  owner node['openstack']['compute']['user']
  group node['openstack']['compute']['group']
  mode 00644
  variables(
    sql_connection: sql_connection,
    novncproxy_base_url: novnc_endpoint.to_s,
    xvpvncproxy_base_url: xvpvnc_endpoint.to_s,
    xvpvncproxy_bind_host: xvpvnc_bind.host,
    xvpvncproxy_bind_port: xvpvnc_bind.port,
    novncproxy_bind_host: novnc_bind.host,
    novncproxy_bind_port: novnc_bind.port,
    vncserver_listen: vnc_endpoint.host,
    vncserver_proxyclient_address: vnc_endpoint.host,
    以下略

となっている。vncserver_listen, vncserver_proxyclient_address 共に vnc_endpoint.host が格納されることになっている。vnc_endpont.host は

1
vnc_endpoint = endpoint 'compute-vnc' || {}

となっており、Attributes の

1
2
3
4
5
6
"compute-vnc" => {
  "host" => "0.0.0.0",
  "scheme" => "http",
  "port" => "6080",
  "path" => "/vnc_auto.html"
},

の設定が入ることになる。つまり上記のような Attributes だと vncserver_listen, vncserver_proxyclient_address 共に ‘0.0.0.0’ のアドレスが controller, compute ノードの双方に入ってしまい、NoVNC が正しく格納しないことになる。

解決したらまたここに更新版を載せたいと思いまーす!

以上です。


Mirantis OpenStack (Neutron GRE)を組んでみた!

こんにちは。@jedipunkz です。

皆さん、Mirantis OpenStack はご存知ですか? OpenStack ディストリビューションの 1つです。以下、公式サイトです。

http://software.mirantis.com/main/

この Mirantis OpenStack を使って OpenStack Havana (Neutron GRE) 構成を作ってみ ました。その時のメモを書いていきたいと思います。

構成は?

構成は下記の通り。

※ CreativeCommon

特徴は

  • Administrative Network : Fuel Node, DHCP + PXE ブート用
  • Management Network : 各コンポーネント間 API 用
  • Public/Floating IP Network : パブリック API, VM Floating IP 用
  • Storage Network : Cinder 配下ストレージ <-> インスタンス間用
  • 要インターネット接続 : Public/Floating Networks
  • Neutron(GRE) 構成

です。タグ VLAN 使って物理ネットワークの本数を減らすことも出来るはずですが、僕 の環境では何故かダメだったので上記の4つの物理ネットワークを別々に用意しました。

Fuel ノードの構築

Fuel ノードとは、OpenStack の各ノードをデプロイするための管理ノードのことです。 DHCP + PXE を管理する Cobbler やデプロイツールの Puppet が内部で稼働し、 Administrative Network 上で稼働したノードを管理・その後デプロイします。

構築方法は…

下記の URL より ISO ファイルをダウンロード。

http://software.mirantis.com/main/

Administrative Network に NIC を出したノードを上記の ISO から起動。

Grub メニューが表示されたタイミングで “Tab” キーを押下。

上記画面にてカーネルオプションにて hostname, ip, gw, dns を修正。下記は例。

1
2
3
vmlinuz initrd=initrd.img biosdevname=0 ks=cdrom:/ks.cfg ip=10.200.10.76
gw=10.200.10.1 dns1=8.8.8.8 netmask=255.255.255.0 hostname=fuel.cpi.ad.jp
showmenu=no_

ブラウザで http://10.200.10.76:8080 (上記例)にアクセスし、新しい ‘OpenStack Environment’ を作成する。

1
2
Name : 任意
OpenStack Release : Havana on CentOS6.4

なお、Ubuntu 構成も組めるが、私の環境では途中でエラーが出力した。

Next を押下し、ネットワーク設定を行う。今回は ‘Nuetron GRE’ を選択。

‘Save Settings’ を押下し設定を保存。この時点では ‘Verify Networks’ は行えない。 少なくとも 2 ノードが必要。次のステップで2ノードの追加を行う。

ノードの追加

下記の4つのネットワークセグメントに NIC を出したノードを用意し、起動する。起動 すると Administrative Network 上で稼働している Cobbler によりノードが PXE 起動 しミニマムな OS がインストールされる。これは後に Fuel ノードよりログインがされ、 各インターフェースの Mac アドレス等の情報を知るためです。ネットワークベリファ イ等もこのミニマムな OS 越しに実施されます。

  • Administrative Network
  • Public/Floating IP Network
  • Storage Network
  • Management Network

ノードが稼働した時点で Fuel によりノードが認識されるので、ここでは2つのノード をそれぞれ

  • Controller ノード
  • Compute ノード

として画面上で割り当てます。

インターフェースの設定

http://10.200.10.76:8000/#cluster/1/nodes にログインし作成した Environment を選択。その後、’Nodes’ タブを押下。ノードを選択し、’Configure Interfaces’ を 選択。各ノードのインターフェースの Mac アドレスを確認し、各々のネットワークセ グメントを紐付ける。尚、Fuel ノードから ‘root’ ユーザで SSH(22番ポート) にノン パスフレーズで公開鍵認証ログインが可能となっている。Fuel ノードに対しては SSH (22番ポート) にて下記のユーザにてログインが可能です。

username : root
password : r00tme

ネットワークの確認

http://10.200.10.76:8000/#cluster/1/network にて ‘Networks’ タブを開き、’Verify Networks’ を押下。ネットワーク設定が正しく行われているか否かを確認。

デプロイ

http://10.200.10.76:8000/#cluster/1/nodes にて ‘Deploy Changes’ を押下しデプ ロイ開始。kickstart にて OS が自動でインストールされ puppet にて fuel ノードか ら自動で OpenStack がインストールされます。

OpenStack へのアクセス

SSH では下記のステップで OpenStack コントローラノードにログイン。

fuel ノード (SSH) -> node-1 (OpenStack コントローラノード)(SSH)

ブラウザで Horizon にアクセスするには

http://10.200.10.2

にアクセス。これは例。Administrative Network に接続している NIC の IP アドレス へ HTTP でログイン。

まとめ

Mirantis OpenStack Neutron (GRE) 構成が組めた。上記構成図を見て疑問に思ってい た “VM 間通信のネットワークセグメント” であるが、Administrative Network のセグ メントを用いている事が判った。これは利用者が意図しているとは考えづらいので、正 直、あるべき姿では無いように思える。が、上記構成図に VM ネットワークが無い理由 はこれにて判った。

下記はノード上で ovs-vsctl show コマンドを打った結果の抜粋です。

1
2
3
4
5
6
7
8
9
10
11
Bridge "br-eth1"
    Port "br-eth1"
        Interface "br-eth1"
            type: internal
    Port "br-eth1--br-fw-admin"
        trunks: [0]
        Interface "br-eth1--br-fw-admin"
            type: patch
            options: {peer="br-fw-admin--br-eth1"}
    Port "eth1"
        Interface "eth1"

今回の構成は eth1 は Administrative Network に割り当てていました。

一昔前は OS のディストリビュータが有料サポートをビジネスにしていました。Redhat がその代表格だと思いますが、今は OS 上で何かを実現するにもソフトウェアの完成度 が高く、エンジニアが困るシチュエーションがそれほど無くなった気がします。そこで その OS の上で稼働する OpenStack のサポートビジネスが出てきたか!という印象で す。OpenStack はまだまだエンジニアにとって敷居の高いソフトウェアです。自らクラ ウドプラットフォームを構築出来るのは魅力的ですが、サポート無しに構築・運用する には、まだ難しい技術かもしれません。こういったディストリビューションが出てくる 辺りが時代だなぁと感じます。

尚、ISO をダウンロードして利用するだけでしたら無償で OK です。


Geard のポートマッピングについて調べてみた

こんにちは。@jedipunkz です。

今週 Redhat が ‘Redhat Enterprise Linux Atomic Host’ しましたよね。Docker を特 徴としたミニマムな OS だとのこと。その内部で用いられている技術 Geard について 少し調べてみました。複数コンテナの関連付けが可能なようです。ここでは調べた結果 について簡単にまとめていきます。

参考資料

http://openshift.github.io/geard/deploy_with_geard.html

利用方法

ここではホスト OS に Fedora20 を用意します。

まず Geard をインストール

1
% sudo yum install --enablerepo=updates-testing geard

下記の json ファイルを作成します。ここにはコンテナをデプロイするための情報と関 連付けのための情報を記します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ${EDITOR} rockmongo_mongodb.json
{
  "containers":[
    {
      "name":"rockmongo",
      "count":1,
      "image":"derekwaynecarr/rockmongo",
      "publicports":[{"internal":80,"external":6060}],
      "links":[{"to":"mongodb"}]
    },
    {
      "name":"mongodb",
      "count":1,
      "image":"ccoleman/ubuntu-mongodb",
      "publicports":[{"internal":27017}]
    }
  ]
}

上記のファイルの解説。

  • コンテナ ‘rockmongo’ と ‘mongodb’ を作成
  • それぞれ1個ずつコンテナを作成
  • ‘image’ パラメータにて docker イメージの指定
  • ‘publicports’ パラメータにてコンテナ内部とホスト側のポートマッピングを行う
  • ‘links’ パラメータで ‘rockmongo’ を ‘mongodb’ に関連付け

では、デプロイ開始します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ sudo gear deploy rockmongo_mongo.json
2014/04/22 07:21:12 Deploying rockmongo_mongo.json.20140422-072112
2014/04/22 07:21:12 appending 27017 on rockmongo-1: &{PortPair:{Internal:27017 External:0} Target:127.0.0.1:27017} &{Id:rockmongo-1 Image:derekwaynecarr/rockmongo From:rockmongo On:0xc2100bb980 Ports:[{PortPair:{Internal:80 External:6060} Target::0}] add:true remove:false container:0xc21000be00 links:[]}
2014/04/22 07:21:12 ports: Releasing
2014/04/22 07:21:12 systemd: Reloading daemon
local PortMapping: 80 -> 6060
local Container rockmongo-1 is installed
2014/04/22 07:21:12 ports: Releasing
2014/04/22 07:21:12 systemd: Reloading daemon
local PortMapping: 27017 -> 4000
local Container mongodb-1 is installed
linking rockmongo: 127.0.0.1:27017 -> localhost:4000
local Links set on local
local Container rockmongo-1 starting
local Container mongodb-1 starting

ブラウザにてホスト OS に接続することで rockmongo の管理画面にアクセスが可能。

1
http://<ホストOSのIP:6060>/

ポートマッピング管理

デプロイが完了して、実際に RockMongo の管理画面にアクセス出来たと思います。 関連付けが特徴と言えそうなのでその解析をしてみました。

Geard のコンテナ関連付けはホストとコンテナのポート管理がキモとなっていることが 解ります。これを紐解くことで geard のコンテナ管理を理解します。

1
2
3
4
5
                    'rockmongo' コンテナ             'mongodb' コンテナ
+----------+        +--------------------------+        +-------------------+
|  Client  |->6060->|->80-> RockMongo ->27017->|->4000->|->27017-> Mongodb  |
+----------+        +--------------------------+        +-------------------+
                |-------------------- docker ホスト --------------------|

上記 ‘gear deploy’ コマンド発行時のログと json ファイルにより上図のような構成 になっていることが理解できます。一つずつ読み解いていきましょう。

  • ‘rockmongo’ コンテナの内部でリスンしている 80 番ポートはホスト OS の 6060 番へ変換
  • ‘rockmongo’ コンテナ内で稼働する RockMongo の config.php から ‘127.0.0.1:27017’ でリスンしていることが解る

試しに ‘derekwaynecarr/rockmongo:latest’ に /bin/bash でログインし config.php を確認。

1
2
3
4
$ sudo docker run -i -t derekwaynecarr/rockmongo:latest /bin/bash
bash-4.1# grep mongo_host /var/www/html/config.php
$MONGO["servers"][$i]["mongo_host"] = "127.0.0.1";//mongo host
$MONGO["servers"][$i]["mongo_host"] = "127.0.0.1";
  • デプロイ時のログと json ファイルの ‘links’ パラメータより、ホストのポートに動的に(ここでは 4000番ポート) に変換されることが解ります。
1
linking rockmongo: 127.0.0.1:27017 -> localhost:4000
  • ホストの 4000 番ポートは動的に ‘mongodb’ コンテナの内部ポート 27017 にマッピングされる

これらのポートマッピングによりそれぞれのコンテナの連携が取れている。

まとめと考察

Geard は下記の2つを特徴とした技術だと言えるとことがわかりました。

  • コンテナを json で管理しデプロイする仕組みを提供する
  • コンテナ間の関連付けをホスト OS のポートを動的に管理・マッピングすることで行う

同じような OS に CoreOS https://coreos.com/ がありますが、こちらも docker, sytemd 等を特徴としています。さらに etcd を使ってクラスタの構成等が可能になっ ていますが、Geard はホストのポートを動的に管理することで関連付けが可能なことが わかりました。

実際に触ってみた感覚から言えば、まだまだ実用化は厳しい状況に思えますが、今後へ の展開に期待したい技術です。


OpenStack Havana Cinder,Glance の分散ストレージ Ceph 連携

こんにちは!@jedipunkz です。

今回は Havana 版の OpenStack Glance, Cinder と分散ストレージの Ceph を連携させ る手順を書いていきます。元ネタはこちら。下記の Ceph の公式サイトに手順です。

https://ceph.com/docs/master/rbd/rbd-openstack/

この手順から下記の変更を行って、ここでは記していきます。

  • Nova + Ceph 連携させない
  • cinder-backup は今のところ動作確認出来ていないので省く
  • 諸々の手順がそのままでは実施出来ないので補足を入れていく。

cinder-backup は Cinder で作成した仮想ディスクのバックアップを Ceph ストレージ 上に取ることが出来るのですが、そもそも Ceph 上にある仮想ディスクを Ceph にバッ クアップ取っても意味が薄いですし、まだ動いていないので今回は省きます。LVM やそ の他ストレージを使った Cinder 連携をされている方にとっては cinder-backup の Ceph 連携は意味が大きくなってくると思います。

構成

下記の通りの物理ネットワーク6つの構成です。 OpenStack, Ceph 共に最小構成を前提にします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
              +--------------------------------------------------------------------- external
              |
+--------------+--(-----------+--------------+------------------------------------------ public
|              |  |           |              |
+------------+ +------------+ +------------+ +------------+ +------------+ +------------+
| controller | |  network   | |  compute   | |   ceph01   | |   ceph02   | |   ceph03   |
+------------+ +------------+ +------------+ +------------+ +------------+ +------------+
|  |           |  |           |  |  |        |  |  |        |  |  |        |  |  |
+--------------+--(-----------+--(-----------+--(--(--------+--(--(--------+--(--(------- management
   |              |              |  |           |  |           |  |           |  |
   |              +--------------+--(-----------(--(-----------(--(-----------(--(------- guest
   |                                |           |  |           |  |           |  |
   +--------------------------------+-----------+--(-----------+--(-----------+--(------- storage
                                               |              |              |
                                               +--------------+--------------+------- cluster

特徴

  • 最小構成 controller x 1 + network x 1 + compute x 1 + ceph x 3
  • OpenStack API の相互通信は management ネットワーク
  • OpenStack VM 間通信は guest ネットワーク
  • OpenStack 外部通信は public ネットワーク
  • OpenStack VM の floating-ip (グローバル) 通信は external ネットワーク
  • Ceph と OpenStack 間の通信は storage ネットワーク
  • Ceph の OSD 間通信は cluster ネットワーク
  • ここには記されていないホスト ‘workstation’ から OpenStack, Ceph をデプロイ

前提の構成

前提構成の OpenStack と Ceph ですが、ここでは構築方法は割愛します。OpenStack は rcbops/chef-cookbooks を。Ceph は ceph-deploy を使って自分は構築しました。 下記の自分のブログに構築手順が載っているので参考にしてみてください。

OpenStack 構築方法

http://jedipunkz.github.io/blog/2013/11/17/openstack-havana-chef-deploy/

Ceph 構築方法

http://jedipunkz.github.io/blog/2014/02/27/journal-ssd-ceph-deploy/

OpenStack + Ceph 連携手順

では実際に連携するための手順を記していきます。

rbd pool の作成

Ceph ノードの何れかで下記の手順を実施し rbd pool を作成する。

1
2
3
ceph01% sudo ceph osd pool create volumes 128
ceph01% sudo ceph osd pool create images 128
ceph01% sudo ceph osd pool create backups 128

ssh 鍵の配置

Ceph ノードから OpenStack の controller, compute ノードへ接続出来るよう鍵を配 布します。

1
2
ceph01% ssh-copy-id <username>@<controller_ip>
ceph01% ssh-copy-id <username>@<compute_ip>

sudoers の設定

controller, compute ノード上で sudoers の設定を予め実施する。 /etc/sudoers.d/ として保存する。

1
<username> ALL = (root) NOPASSWD:ALL

ceph パッケージのインストール

controller ノード, compute ノード上で Ceph パッケージをインストールする。

1
2
3
4
5
6
7
controller% wget -q -O- 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' | sudo apt-key add -
controller% echo deb http://ceph.com/debian/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
controller% sudo apt-get update && sudo apt-get install -y python-ceph ceph-common

compute% wget -q -O- 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' | sudo apt-key add -
compute% echo deb http://ceph.com/debian/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
compute% sudo apt-get update && sudo apt-get install -y python-ceph ceph-common

controller ノード, compute ノード上でディレクトリを作成する。

1
2
controller% sudo mkdir /etc/ceph
compute   % sudo mkdir /etc/ceph

ceph.conf を controller, compute ノードへ配布する。

1
2
3
ceph01% sudo -i
ceph01# ssh <controller_ip> sudo tee /etc/ceph/ceph.conf </etc/ceph/ceph.conf
ceph01# ssh <compute_ip> sudo tee /etc/ceph/ceph.conf </etc/ceph/ceph.conf

ceph 上にユーザを作成

Ceph 上に cinder, glance 用の新しいユーザを作成する。

1
2
3
ceph auth get-or-create client.cinder mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=volumes, allow rx pool=images'
ceph auth get-or-create client.glance mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=images'
ceph auth get-or-create client.cinder-backup mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=backups'

キーリングの作成と配置

client.cinder, client.glance, client.cinder-backup のキーリングを作成する。また作成したキーリングを controller ノードに配布する。

1
2
3
4
5
6
ceph01% sudo ceph auth get-or-create client.glance | ssh {your-glance-api-server} sudo tee /etc/ceph/ceph.client.glance.keyring
ceph01% ssh {your-glance-api-server} sudo chown glance:glance /etc/ceph/ceph.client.glance.keyring
ceph01% sudo ceph auth get-or-create client.cinder | ssh {your-volume-server} sudo tee /etc/ceph/ceph.client.cinder.keyring
ceph01% ssh {your-cinder-volume-server} sudo chown cinder:cinder /etc/ceph/ceph.client.cinder.keyring
ceph01% sudo ceph auth get-or-create client.cinder-backup | ssh {your-cinder-backup-server} sudo tee /etc/ceph/ceph.client.cinder-backup.keyring
ceph01% ssh {your-cinder-backup-server} sudo chown cinder:cinder /etc/ceph/ceph.client.cinder-backup.keyring

client.cinder のキーリングを compute ノードに配置する。

1
ceph01% sudo ceph auth get-key client.cinder | ssh {your-compute-node} tee client.cinder.key

libvirt への secret キー追加

compute ノード上で secret キーを libvirt に追加する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
compute% uuidgen
457eb676-33da-42ec-9a8c-9293d545c337

cat > secret.xml <<EOF
<secret ephemeral='no' private='no'>
  <uuid>457eb676-33da-42ec-9a8c-9293d545c337</uuid>
  <usage type='ceph'>
    <name>client.cinder secret</name>
  </usage>
</secret>
EOF
compute % sudo virsh secret-define --file secret.xml
Secret 457eb676-33da-42ec-9a8c-9293d545c337 created
compute% sudo virsh secret-set-value --secret 457eb676-33da-42ec-9a8c-9293d545c337 --base64 $(cat client.cinder.key) && rm client.cinder.key secret.xml

glance 連携手順

controller ノードの /etc/glance/glance-api.conf に下記を追記。 default_store=file と標準ではなっているので下記の通り rbd に書き換える。

1
2
3
default_store=rbd
rbd_store_user=glance
rbd_store_pool=images

cinder 連携手順

controller ノードの /etc/cinder/cinder.conf に下記を追記。 volume_driver は予め LVM の設定が入っていると思われるので書き換える。 また rbd_secret_uuid は先ほど生成した uuid を記す。

1
2
3
4
5
6
7
8
volume_driver=cinder.volume.drivers.rbd.RBDDriver
rbd_pool=volumes
rbd_ceph_conf=/etc/ceph/ceph.conf
rbd_flatten_volume_from_snapshot=false
rbd_max_clone_depth=5
glance_api_version=2
rbd_user=cinder
rbd_secret_uuid=457eb676-33da-42ec-9a8c-9293d545c337

ceph.conf への追記

上記で配布した ceph.conf にはキーリングのパスが記されていない。controller ノー ド上の /etc/ceph/ceph.conf に下記の通り追記する。

ここは公式サイトには印されていないのでハマりました。ポイントです。

1
2
[client.keyring]
  keyring = /etc/ceph/ceph.client.cinder.keyring

OpenStack のそれぞれのコンポーネントを再起動かける

1
2
3
4
controller% sudo glance-control api restart
compute   % sudo service nova-compute restart
controller% sudo service cinder-volume restart
controller% sudo service cinder-backup restart

動作確認

では動作確認を。Glance に OS イメージを登録。その後そのイメージを元にインスタ ンスを作成。Cinder 上に仮想ディスクを作成。その後先ほど作成したインスタンスに 接続しマウント。そのマウントした仮想ディスク上で書き込みが行えるか確認をします。

テストで Ubuntu Precise 12.04 のイメージを glance を用いて登録する。

1
2
controller% wget http://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64-disk1.img
controller% glance image-create --name precise-image --is-public true --container-format bare --disk-format qcow2 < precise-server-cloudimg-amd64-disk1.img

テスト VM を稼働する。

1
2
3
controller% nova boot --nic net-id=<net_id> --flavor 2 --image precise-image --key_name novakey01 vm01
controller% cinder create --display-name vol01 1
controller% nova volume-attach <instance_id> <volume_id> auto

テスト VM へログインしファイルシステムを作成後、マウントする。

1
2
3
controller% ssh -i <key_file_path> -l ubuntu <instance_ip>
vm01% sudo mkfs -t ext4 /dev/vdb
vm01% sudo mount -t ext4 /dev/vdb /mnt

マウントした仮想ディスク上でデータを書き込んでみる。

1
vm01% sudo dd if=/dev/zero of=/mnt/500M bs=1M count=5000

まとめ

Ceph, Cinder の Ceph 連携が出来ました!

OpenStack Grizzly 版時代に Ceph 連携は取っていたのですが Havana では

  • cinder-bacup の Ceph 連携
  • nova の Ceph 連携

が追加されていました。Nova 連携をとるとインスタンスを稼働させる際に通常は controller ノードの /var/lib/nova 配下にファイルとしてインスタンスイメージが作 成されますが、これが Ceph 上に作成されるとのことです。Nova 連携は是非とってみ たいのですが、今のところ動いていません。引き続き調査を行います。

cinder-backup も少し連携取ってみましたが backup_driver に Ceph ドライバの指定 をしているにも関わらず Swift に接続しにいってしまう有り様でした..。こちらも引 き続き調査します。またステートが ‘in-use’ の場合バックアップが取れず ‘available’ なステートでないといけないようです。確かに書き込み中に操作が行われ てしまってもバックアップの整合性が取れないですし、ここは仕方ないところですね。


rcbops/chef-cookbooks で Keystone 2013.2.2(Havana) + Swift 1.10.0 を構築

こんにちは。@jedipunkz です。

追記

2014/03/20 : 一旦削除していた記事なのですが、無事動作が確認出来たので再度アッ プします!

第17回 OpenStack 勉強会で rcbops/chef-cookbooks の話をしてきたのですが会場から 質問がありました。「Havana の Swift 構成を作る Cookbooks はどこにありますか?」 と。私が試したのが Grizzly 時代のモノで、よく rcbops/chef-cookbooks を見てみる と Havana ブランチ又は Havana に対応したリリースタグのファイル構成に Swift が 綺麗サッパリ消えているではありませんか・・!下記の Swift の Cookbooks は幸い github 上に残っていました。

https://github.com/rcbops-cookbooks/swift

が rcbops/chef-cookbooks との関連付けが切れています・・。ぐあぁ。

ということで Havana 構成の Keystone 2013.2.2 と Swift 1.10.0 の構成を Chef で 作らねば!と思い色々試していたら結構あっさりと出来ました。今回はその方法を書い ていきたいと思います!

構成

構成は…以前の記事 http://jedipunkz.github.io/blog/2013/10/27/swift-chef/ と同じです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+-----------------+
|  load balancer  |
+-----------------+
|
+-------------------+-------------------+-------------------+-------------------+---------------------- proxy network
|                   |                   |                   |                   |                   
+-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+
|   chef server   | | chef workstation| |   swift-mange   | |  swift-proxy01  | |  swift-proxy02  | 
+-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+ ...> scaling
|                   |                   |                   |                   |                   
+-------------------+-------------------+-------------------+-------------------+-------------------+-- storage network
|                   |                   |                   |                   |                   |
+-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+ 
| swift-storage01 | | swift-storage02 | | swift-storage03 | | swift-account01 | | swift-account02 | | swift-account03 |
+-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+ +-----------------+ ..> scaling

手順

では早速手順を記していきますね。毎回なのですが Chef ワークステーション・Chef サーバの環境構築については割愛します。オムニバスインストーラを使えば Chef サー バの構築は簡単ですし、ワークステーションの構築も Ruby インストール -> gem で Chef をインストール -> .chef 配下を整える、で出来ます。

rcbops/chef-cookbooks の取得。現在 Stable バージョンの refs/tags/v4.2.1 を用いる。

1
2
3
4
5
6
% git clone https://github.com/rcbops/chef-cookbooks.git ./chef-cookbooks-4.2.1
% cd ./chef-cookbooks-4.2.1
% git checkout -b v4.2.1 refs/tags/v4.2.1
% git submodule init
% git submodule sync
% git submodule update

ここで本家 rcbops/chef-cookbooks と関連付けが消えている rcbops-cookbooks/swift を cookbooks ディレクトリ配下にクローンします。あと念のため ‘havana’ ブランチ を指定します。コードを確認したところ何も変化はありませんでしたが。

1
2
3
4
% git clone https://github.com/rcbops-cookbooks/swift.git cookbooks/swift
% cd cookbooks/swift
% git checkout -b havana remotes/origin/havana
% cd ../..

cookbooks, roles の Chef サーバへのアップロードを行います。

1
2
% knife cookbook upload -o cookbooks -a
% knife role from file role/*.rb

今回の構成 (1クラスタ) 用の environments/swift-havana.json を作成します。json ファイルの名前は任意です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{
  "name": "swift-havana",
  "description": "",
  "cookbook_versions": {
  },
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": {
  },
  "override_attributes": {
    "package_component": "havana",
    "osops_networks": {
      "management": "10.200.9.0/24",
      "public": "10.200.10.0/24",
      "swift": "10.200.9.0/24"
    },
    "keystone": {
      "pki": {
        "enabled": false
      },
      "admin_port": "35357",
      "admin_token": "admin",
      "admin_user": "admin",
      "tenants": [
        "admin",
        "service"
      ],
      "users": {
        "admin": {
          "password": "secrete",
          "roles": {
            "admin": [
              "admin"
            ]
          }
        },
        "demo": {
          "password": "demo",
          "default_tenant" : "service",
          "roles": {
            "admin": [ "admin" ]
          }
        }
      },
      "db": {
        "password": "keystone"
      }
    },
    "mysql": {
      "root_network_acl": "%",
      "allow_remote_root": true,
      "server_root_password": "secrete",
      "server_repl_password": "secrete",
      "server_debian_password": "secrete"
    },
    "monitoring": {
      "procmon_provider": "monit",
      "metric_provider": "collectd"
    },
    "vips": {
      "keystone-admin-api": "10.200.9.11",
      "keystone-service-api": "10.200.9.11",
      "keystone-internal-api": "10.200.9.11",
      "swift-proxy": "10.200.9.11",
      "config": {
        "10.200.9.112": {
          "vrid": 12,
          "network": "management"
        }
      }
    },
    "developer_mode": false,
    "swift": {
      "swift_hash": "307c0568ea84",
      "authmode": "keystone",
      "authkey": "20281b71-ce89-4b27-a2ad-ad873d3f2760"
    }
  }
}

作成した environment ファイル environments/swift-havana.json を chef-server へアップ ロードする。

1
% knife environment from file environments/swift-havana.json

Cookbooks の修正

swift cookbooks を修正します。havana からは keystone を扱うクライアントは keystone.middleware.auth_token でなく keystoneclient.middleware.auth_token を 使うように変更掛かっていますので、下記のように修正しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% cd cookbooks/swift/templates/default
% diff -u proxy-server.conf.erb.org proxy-server.conf.erb
--- proxy-server.conf.erb.org   2014-03-20 16:28:28.000000000 +0900
+++ proxy-server.conf.erb       2014-03-20 16:28:13.000000000 +0900
@@ -243,7 +243,8 @@
 use = egg:swift#keystoneauth

 [filter:authtoken]
-paste.filter_factory = keystone.middleware.auth_token:filter_factory
+#paste.filter_factory = keystone.middleware.auth_token:filter_factory
+paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
 auth_host = <%= @keystone_api_ipaddress %>
 auth_port = <%= @keystone_admin_port %>
 auth_protocol = <%= @keystone_admin_protocol %>
% cd ../../../..

デプロイ

かきのとおり knife bootstrap する。

1
2
3
4
5
6
7
8
9
% knife bootstrap <manage_ip_addr> -N swift-manage -r 'role[base]','role[mysql-master]','role[keystone]','role[swift-management-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <proxy01_ip_addr> -N swift-proxy01 -r "role[base]","role[swift-proxy-server]",'role[swift-setup]','role[openstack-ha]' -E swift-havana --sudo -x thirai
% knife bootstrap <proxy02_ip_addr> -N swift-proxy02 -r "role[base]","role[swift-proxy-server]",'role[openstack-ha]' -E swift-havana --sudo -x thirai
% knife bootstrap <storage01_ip_addr> -N swift-storage01 -r 'role[base]','role[swift-object-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <storage02_ip_addr> -N swift-storage02 -r 'role[base]','role[swift-object-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <storage03_ip_addr> -N swift-storage03 -r 'role[base]','role[swift-object-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <account01_ip_addr> -N swift-account01 -r 'role[base]','role[swift-account-server]','role[swift-container-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <account02_ip_addr> -N swift-account02 -r 'role[base]','role[swift-account-server]','role[swift-container-server]' -E swift-havana --sudo -x thirai
% knife bootstrap <account03_ip_addr> -N swift-account03 -r 'role[base]','role[swift-account-server]','role[swift-container-server]' -E swift-havana --sudo -x thirai

ここでバグ対策。Swift 1.10.0 にはバグがあるので下記の通り対処します。

keystone.middleware.s3_token に既知のバグがあり、下記のように対処します。この 状態ではバグにより swift-proxy が稼働してない状態ですが後の各ノードでの chef-client 実行時に稼働する予定です。

1
2
3
4
5
6
7
8
9
% diff /usr/lib/python2.7/dist-packages/keystone/exception.py.org /usr/lib/python2.7/dist-packages/keystone/exception.py
--- exception.py.org    2014-03-12 16:45:00.181420694 +0900
+++ exception.py        2014-03-12 16:44:47.173177081 +0900
@@ -18,6 +18,7 @@

 from keystone.common import config
 from keystone.openstack.common import log as logging
+from keystone.openstack.common.gettextutils import _
 from keystone.openstack.common import strutils

上記のバグ報告は下記の URL にあります。

https://bugs.launchpad.net/ubuntu/+source/swift/+bug/1231339

zone 番号を付与します。

1
2
3
4
5
6
% knife exec -E "nodes.find(:name => 'swift-storage01') {|n| n.set['swift']['zone'] = '1'; n.save }"
% knife exec -E "nodes.find(:name => 'swift-account01') {|n| n.set['swift']['zone'] = '1'; n.save }"
% knife exec -E "nodes.find(:name => 'swift-storage02') {|n| n.set['swift']['zone'] = '2'; n.save }"
% knife exec -E "nodes.find(:name => 'swift-account02') {|n| n.set['swift']['zone'] = '2'; n.save }"
% knife exec -E "nodes.find(:name => 'swift-storage03') {|n| n.set['swift']['zone'] = '3'; n.save }"
% knife exec -E "nodes.find(:name => 'swift-account03') {|n| n.set['swift']['zone'] = '3'; n.save }"

zone 番号が付与されたこと下記の通りを確認します

account-server の確認

1
2
3
4
5
6
% knife exec -E 'search(:node,"role:swift-account-server") \
  { |n| z=n[:swift][:zone]||"not defined"; puts "#{n.name} has the role \
  [swift-account-server] and is in swift zone #{z}"; }'
swift-account01 has the role       [swift-account-server] and is in swift zone 1
swift-account02 has the role       [swift-account-server] and is in swift zone 2
swift-account03 has the role       [swift-account-server] and is in swift zone 3

container-server の確認

1
2
3
4
5
6
% knife exec -E 'search(:node,"role:swift-container-server") \
  { |n| z=n[:swift][:zone]||"not defined"; puts "#{n.name} has the role \
  [swift-container-server] and is in swift zone #{z}"; }'
swift-account01 has the role       [swift-container-server] and is in swift zone 1
swift-account02 has the role       [swift-container-server] and is in swift zone 2
swift-account03 has the role       [swift-container-server] and is in swift zone 3

object-server の確認

1
2
3
4
5
6
% knife exec -E 'search(:node,"role:swift-object-server") \
  { |n| z=n[:swift][:zone]||"not defined"; puts "#{n.name} has the role \
  [swift-object-server] and is in swift zone #{z}"; }'
swift-storage01 has the role   [swift-object-server] and is in swift zone 1
swift-storage02 has the role   [swift-object-server] and is in swift zone 2
swift-storage03 has the role   [swift-object-server] and is in swift zone 3

Chef が各々のノードに搭載された Disk を検知出来るか否かを確認する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
% knife exec -E \
  'search(:node,"role:swift-object-server OR \
  role:swift-account-server \
  OR role:swift-container-server") \
  { |n| puts "#{n.name}"; \
  begin; n[:swift][:state][:devs].each do |d| \
  puts "\tdevice #{d[1]["device"]}"; \
  end; rescue; puts \
  "no candidate drives found"; end; }'
    swift-storage02
            device sdb1
    swift-storage03
            device sdb1
    swift-account01
            device sdb1
    swift-account02
            device sdb1
    swift-account03
            device sdb1
    swift-storage01
            device sdb1

swift-manage ノードにて chef-client を実行し /etc/swift/ring-workspace/generate-rings.sh を更新します。

1
swift-manage% sudo chef-client

generate-rings.sh の ‘exit 0’ 行をコメントアウトし実行します。

1
2
swift-manage% sudo ${EDITOR} /etc/swift/ring-workspace/generage-rings.sh
swift-manage% sudo /etc/swift/ring-workspace/generate-rings.sh

この操作で /etc/swift/ring-workspace/rings 配下に account, container, object 用の Rings ファイル群が生成されたことを確認出来るはずです。これらを swift-manage 上で既に稼働している git サーバに push し管理します。

1
2
3
4
5
swift-manage# cd /etc/swift/ring-workspace/rings
swift-manage# git add account.builder container.builder object.builder
swift-manage# git add account.ring.gz container.ring.gz object.ring.gz
swift-manage# git commit -m "initial commit"
swift-manage# git push

各々のノードにて chef-client を実行することで git サーバ上の Rings ファイル群 を取得し、swift プロセスを稼働させます。

1
2
3
4
5
6
7
8
swift-proxy01# chef-client
swift-proxy02# chef-client
swift-storage01# chef-client
swift-storage02# chef-client
swift-storage03# chef-client
swift-account01# chef-client
swift-account02# chef-client
swift-account03# chef-client

3台のノードが登録されたかどうかを下記の通り確認行います。

1
2
3
4
5
6
7
8
swift-proxy01% sudo swift-recon --md5
[sudo] password for thirai:
===============================================================================
--> Starting reconnaissance on 3 hosts
===============================================================================
[2013-10-18 11:14:43] Checking ring md5sums
3/3 hosts matched, 0 error[s] while checking hosts.
===============================================================================

動作確認

構築が出来ました!ということで動作の確認をしてみましょう。

テストコンテナ ‘container01’ にテストファイル ‘test’ をアップロードしてみる。

1
2
3
4
5
6
7
swift-storage01% swift -V 2 -A http://<ip_addr_keystone>:5000/v2.0/ -U admin:admin -K secrete stat
swift-storage01% swift -V 2 -A http://<ip_addr_keystone>:5000/v2.0/ -U admin:admin -K secrete post container01
swift-storage01% echo "test" > test
swift-storage01% swift -V 2 -A http://<ip_addr_keystone>:5000/v2.0/ -U admin:admin -K secrete upload container01 test
swift-storage01% swift -V 2 -A http://<ip_addr_keystone>:5000/v2.0/ -U admin:admin -K secrete list
container01
swift-storage01% swift -V 2 -A http://<ip_addr_keystone>:5000/v2.0/ -U admin:admin -K secrete list container01 test

まとめ

前回「実用的な Swift 構成を Chef でデプロイ」の記事で記した内容とほぼ手順は変 わりませんでした。rcbops-cookbooks/rcbops-utils 内にソフトウェアの取得先レポジ トリを記すレシピが下記の場所にあります。

https://github.com/rcbops-cookbooks/osops-utils/blob/master/recipes/packages.rb

そして havana ブランチの attributes を確認すると Ubuntu Cloud Archive の URL が記されていることが確認出来ます。下記のファイルです。

https://github.com/rcbops-cookbooks/osops-utils/blob/havana/attributes/repos.rb

ファイルの中身の抜粋です。

1
2
3
4
5
6
7
"havana" => {
  "uri" => "http://ubuntu-cloud.archive.canonical.com/ubuntu",
  "distribution" => "precise-updates/havana",
  "components" => ["main"],
  "keyserver" => "hkp://keyserver.ubuntu.com:80",
  "key" => "EC4926EA"
},

これらのことより、rcbops-utils の attibutes で havana (実際には ‘havana-proposed’) をレポジトリ指定するように Cookbooks 構成を管理してあげれば Havana 構成の Keystone, Swift が構築出来ることになります。ちなみに havana-proposed で Swift や Keystone のどのバージョンがインストールされるかは、 下記の Packages ファイルを確認すると判断出来ます。

http://ubuntu-cloud.archive.canonical.com/ubuntu/dists/precise-proposed/havana/main/binary-amd64/Packages

以上です。


Sensu,Chef,OpenStack,Fog を使ったオレオレオートスケーラを作ってみた!

こんにちは。@jedipunkz です。

今まで監視システムの Sensu やクラウドプラットフォームの OpenStack、コンフィギュ レーションマネージメントツールの Chef やクラウドライブラリの Fog 等使ってきま したが、これらを組み合わせるとオレオレオートスケーラ作れるんじゃないか?と思い、 ちょろっと作ってみました。

ちなみに自分はインフラエンジニアでしかも運用の出身なので Ruby に関しては初心者 レベルです。Chef で扱っているのと Rails アプリを作った経験はありますが、その程 度。Fog というクラウドライブラリにコントリビュートしたことはアリますが..。ちな みに Fog のコントリビュート内容は OpenStack Neutron(当時 Quantum) の仮想ルータ の操作を行う実装です。

そんな自分ですが…設計1周間・実装1周間でマネージャと CLI が出来ました。 また暫く放置していたマネージャと CLI に WebUI くっつけようかなぁ?と思って sinatra の学習を始めたのですが、学習を初めて 1.5 日で WebUI が動くところまで行 きました。何故か?Ruby には有用な技術が揃っているから・・!(´;ω;`)ブワッ

オレオレオートスケーラ ‘sclman’ の置き場所

https://github.com/jedipunkz/sclman

スクリーンショット

構成は?

1
2
3
4
5
6
7
8
9
+-------------- public network                  +-------------+
|                                               |sclman-api.rb|
+----+----+---+                                 |  sclman.rb  |
| vm | vm |.. |                                 |sclman-cli.rb|
+-------------+ +-------------+ +-------------+ +-------------+
|  openstack  | | chef server | | sensu server| | workstation |
+-------------+ +-------------+ +-------------+ +-------------+
|               |               |               |
+---------------+---------------+---------------+--------------- management network

‘sclman’ っていう名前です。上図の workstation ノードで稼働します。処理の流れは

処理の流れ

  • 1) sclman-cli.rb もしくは WebUI から HTTP クラスタのセットを OpenStack 上に生成
  • 2) 生成された VM に対して Chef で nginx をインストール
  • 3) Chef の Roles である ‘LB’ と ‘Web” が同一 Envrionment になるようにブートストラップ
  • 4) LB VM のバックエンドに Web VM が指し示される
  • 5) bootstrap と同時に sensu-client をインストール
  • 6) Web VM の load を sensu で監視
  • 7) sclman.rb (マネージャ) は Sensu AP を定期的に叩いて Web VM の load を監視
  • 8) load が高い environment があれが該当 environment の HTTP クラスタに VM を追加
  • 9) LB VM は追加された VM へのリクエストを追加
  • 10) 引き続き監視し一定期間 load が上がらなけれ Web VM を削除
  • 11) LB VM は削除された VM へのリクエストを削除

といった感じです。要約すると CLI/WebUI から HA クラスタを作成。その時に LB, Web ミドルウェアと同時に sensu クライアントを VM に放り込む。監視を継続して負 荷が上昇すれば Web インスタンスの数を増加させ LB のリクエスト振り先にもその追 加した VM のアドレスを追加。逆に負荷が下がれば VM 削除と共にリクエスト振り先も 削除。この間、人の手を介さずに処理してくれる。です。

使い方

詳細な使い方は github の README.md を見て下さい。ここには簡単な説明だけ書いて おきます。

  • sclman を github から取得して bundler で必要な gems をインストールします。
  • chef-repo に移動して Berkshelf で必要な cookbooks をインストールします。
  • cookbooks を用いて sensu をデプロイします。
  • Omnibus インストーラーを使って chef サーバをインストールします。
  • OpenStack をインストールします。
  • sclman.conf を環境に合わせて修正します。
  • sclman.rb (マネージャ) を稼働します。
  • sclman-api.rb (WebUI/API) を稼働します。
  • sclman-cli.rb (CLI) もしくは WebUI から最小構成の HTTP クラスタを稼働します。
  • この状態で ‘Web’ Role のインスタンスに負荷が掛かると ‘Web’ Role のインスタンスの数が増加します。
  • また逆に負荷が下がるとインスタンス数が減ります。

負荷の増減のシビアさは sclman.conf のパラメータ ‘man_sensitivity’ で決定します。 値が長ければ長いほど増減のし易さは低下します。

まとめ

こんな僕でも Ruby の周辺技術使ってなんとなくの形が出来ましたー。ただまだまだ課 題はあって、インフラを制御するアプリってエラーハンドリングが難しいっていうこと です。帰ってくるエラーの一覧などがクラウドプラットフォーム・クラウドライブラリ のドキュメントにあればいいのだけど、まだそこまで行ってない。Fog もまだまだ絶賛 開発中と言うかクラウドプラットフォームの進化に必死で追いついている状態なので、 僕らがアプリを作るときには自分でエラーを全部洗い出す等の作業が必要になるかもし れない。大変だけど面白い所でもありますよね!これからも楽しみです。