RDO(Havana)でHeatを試してみる手順です。ネットワーク構成は、下記のオールインワン構成と同じです。
ただし、今回は、Fedora19を「最小限のインストール」+ 「標準アドオン」でインストールします。インストールしたら次のコマンドで事前準備します。
# setenforce 0 # sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config # yum -y update # yum -y install iptables-services # systemctl stop firewalld.service # systemctl mask firewalld.service # systemctl start iptables.service # systemctl enable iptables.service # yum -y install mariadb-server # rm -f /usr/lib/systemd/system/mariadb.service # cp /usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/mariadb.service
続いて、PackstackでRDO(Havana)をインストールします。Answer FileでHeatのインストールを指示しています。
# yum -y install http://repos.fedorapeople.org/repos/openstack/openstack-havana/rdo-release-havana-8.noarch.rpm # yum -y install openstack-packstack # packstack --gen-answer-file=answers.txt # sed -i 's/CONFIG_PROVISION_DEMO=.*/CONFIG_PROVISION_DEMO=n/' answers.txt # sed -i 's/CONFIG_SWIFT_INSTALL=.*/CONFIG_SWIFT_INSTALL=n/' answers.txt # sed -i 's/CONFIG_NAGIOS_INSTALL=.*/CONFIG_NAGIOS_INSTALL=n/' answers.txt # sed -i 's/CONFIG_HEAT_INSTALL=.*/CONFIG_HEAT_INSTALL=y/' answers.txt # sed -i 's/CONFIG_HEAT_CLOUDWATCH_INSTALL=.*/CONFIG_HEAT_CLOUDWATCH_INSTALL=y/' answers.txt # sed -i 's/CONFIG_HEAT_CFN_INSTALL=.*/CONFIG_HEAT_CFN_INSTALL=y/' answers.txt # packstack --answer-file=answers.txt # openstack-config --set --existing /etc/heat/heat.conf ec2authtoken auth_uri http://127.0.0.1:5000/v2.0 # . ~/keystonerc_admin # heat-manage db_sync
最後のdb_syncは「SADeprecationWarning」が出ても無視してください。インストールが終わったら、「/etc/sysconfig/iptables」のセクション「:nova-filter-top - [0:0]」の頭に下記の項目を追加しておきます。
-A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT -A INPUT -p tcp -m tcp --dport 8003 -j ACCEPT
ここで、一回、サーバを再起動します。サーバが起動したら、テナントを作成するために次のスクリプトを用意します。
config.sh
#!/bin/sh -e #### public="192.168.199.0/24" gateway="192.168.199.1" nameserver="8.8.8.8" pool=("192.168.199.100" "192.168.199.199") private=("192.168.101.0/24") #### export LANG=en_US.utf8 function config_tenant { . /root/keystonerc_admin # # Upload glance image # if ! glance image-show "Fedora19" >/dev/null 2>&1; then glance image-create --name "Fedora19" \ --disk-format qcow2 --container-format bare --is-public true \ --copy-from http://cloud.fedoraproject.org/fedora-19.x86_64.qcow2 fi if ! glance image-show "F17-x86_64-cfntools" >/dev/null 2>&1; then glance image-create --name F17-x86_64-cfntools \ --disk-format qcow2 --container-format bare --is-public true \ --copy-from http://fedorapeople.org/groups/heat/prebuilt-jeos-images/F17-x86_64-cfntools.qcow2 fi # # create project and users # keystone user-get demo_admin && keystone user-delete demo_admin keystone user-get demo_user && keystone user-delete demo_user keystone tenant-get demo && keystone tenant-delete demo keystone tenant-create --name demo keystone user-create --name demo_admin --pass passw0rd keystone user-create --name demo_user --pass passw0rd keystone user-role-add --user demo_admin --role admin --tenant demo keystone user-role-add --user demo_user --role _member_ --tenant demo # # initialize neutron db # neutron_services=$(systemctl list-unit-files --type=service \ | grep -E 'neutron\S+\s+enabled' | cut -d" " -f1) for s in ${neutron_services}; do systemctl stop $s; done mysqladmin -f drop ovs_neutron mysqladmin create ovs_neutron neutron-netns-cleanup for s in $neutron_services; do systemctl start $s; done sleep 5 # # create external network # tenant=$(keystone tenant-list | awk '/ services / {print $2}') neutron net-create \ --tenant-id $tenant ext-network --shared \ --provider:network_type local --router:external=True neutron subnet-create \ --tenant-id $tenant --gateway ${gateway} --disable-dhcp \ --allocation-pool start=${pool[0]},end=${pool[1]} \ ext-network ${public} # # create router # tenant=$(keystone tenant-list|awk '/ demo / {print $2}') neutron router-create --tenant-id $tenant demo_router neutron router-gateway-set demo_router ext-network # # create private networks # for (( i = 0; i < ${#private[@]}; ++i )); do name=$(printf "private%02d" $(( i + 1 ))) subnet=${private[i]} neutron net-create \ --tenant-id $tenant ${name} --provider:network_type local neutron subnet-create \ --tenant-id $tenant --name ${name}-subnet \ --dns-nameserver ${nameserver} ${name} ${subnet} neutron router-interface-add demo_router ${name}-subnet done # # configure security components # . /root/keystonerc_admin export OS_USERNAME=demo_admin export OS_PASSWORD=passw0rd export OS_TENANT_NAME=demo nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 nova secgroup-add-rule default tcp 80 80 0.0.0.0/0 nova secgroup-add-rule default icmp 8 0 0.0.0.0/0 if nova keypair-list | grep -q '^| mykey |'; then nova keypair-delete mykey fi nova keypair-add mykey > ~/mykey.pem chmod 600 ~/mykey.pem for i in $(seq 1 5); do neutron floatingip-create ext-network done } # main extnic="" while [[ -z $extnic ]]; do echo -n "VM access NIC: " read extnic done if ! ovs-vsctl list-ports br-ex | grep -q ${extnic}; then ovs-vsctl add-port br-ex ${extnic} fi config_tenant 2>/dev/null echo echo "Configuration finished."
これを実行すると「VM access NIC:」と表示されるので、VMアクセス用のNIC(この絵で言うところの「em2」)を入力します。
この後は、ユーザ「demo_admin」用のkeystonercファイルを用意して、このユーザからHeatを利用します。
keystonerc_demo_admin
export OS_USERNAME=demo_admin export OS_TENANT_NAME=demo export OS_PASSWORD=passw0rd export OS_AUTH_URL=http://192.168.199.10:35357/v2.0/ export PS1='[\u@\h \W(keystone_demo_admin)]\$ '
デモ用のテンプレートファイルを用意します。PostgreSQLサーバを構築した後、RoRの伝言板アプリのサーバを構築して、DB接続設定するというシナリオです。PostgreSQLサーバの構築は、GitHubからPuppetマニフェストを取得して適用することで行います。RoRの方は、シェルスクリプトで頑張っています。
dengonban.template
{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "A Database instance running a local PostgreSQL server", "Parameters" : { "GitRepo" : { "Description" : "Git Repository URL", "Type" : "String", "Default" : "https://github.com/enakai00/pgsql_puppet" }, "GitTag" : { "Description" : "Git Tag", "Type" : "String", "Default" : "heat-demo1.0" }, "KeyName" : { "Description" : "KeyPair to enable SSH access", "Type" : "String" }, "InstanceType" : { "Description" : "Instance type", "Type" : "String", "AllowedValues" : [ "m1.tiny", "m1.small", "m1.medium", "m1.large", "m1.xlarge" ], "ConstraintDescription" : "must be a valid instance type.", "Default" : "m1.small" }, "ImageName" : { "Description" : "Image name of instance", "Type" : "String", "Default" : "F17-x86_64-cfntools" } }, "Resources" : { "PgSQLDatabaseServer": { "Type": "AWS::EC2::Instance", "Properties": { "SubnetId" : "013cd465-7e75-4edc-ae83-6476fcf9178b", "ImageId" : { "Ref" : "ImageName" }, "InstanceType" : { "Ref" : "InstanceType" }, "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -x\n", "GitRepository=", { "Ref" : "GitRepo" }, "\n", "ConfigTag=", { "Ref" : "GitTag" }, "\n", "yum -y install puppet git\n", "RepoName=${GitRepository##*/}\n", "RepoName=${RepoName%.git}\n", "mkdir -p /tmp/gittmp\n", "cd /tmp/gittmp\n", "git clone $GitRepository\n", "cd $RepoName\n", "git checkout $ConfigTag\n", "export FACTER_manifest_dir=\"/tmp/gittmp/$RepoName\"\n", "puppet apply main.pp\n", "# All is well so signal success\n", "/opt/aws/bin/cfn-signal -e 0 -r \"PostgreSQL Database setup complete\" '", { "Ref" : "PgSQLWaitHandle" }, "'\n" ]]}} } }, "PgSQLWaitHandle" : { "Type" : "AWS::CloudFormation::WaitConditionHandle" }, "PgSQLWaitCondition" : { "Type" : "AWS::CloudFormation::WaitCondition", "DependsOn" : "PgSQLDatabaseServer", "Properties" : { "Handle" : {"Ref" : "PgSQLWaitHandle"}, "Timeout" : "6000" } }, "WebServer": { "Type": "AWS::EC2::Instance", "DependsOn": "PgSQLWaitCondition", "Properties": { "SubnetId" : "013cd465-7e75-4edc-ae83-6476fcf9178b", "ImageId" : { "Ref" : "ImageName" }, "InstanceType" : { "Ref" : "InstanceType" }, "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -x\n", "export DB_IP=", { "Fn::GetAtt" : [ "PgSQLDatabaseServer", "PublicIp" ] }, "\n", "yum install -y rubygem-rails rubygem-pg postgresql\n", "echo '*:*:*:postgres:pas4pgsql' > /root/.pgpass && chmod 600 /root/.pgpass\n", "psql -h $DB_IP -U postgres -c \"create user rails encrypted password 'pas4rails'\"\n", "psql -h $DB_IP -U postgres -c \"create database dengonban_development owner rails\"\n", "psql -h $DB_IP -U postgres -c \"create database dengonban_production owner rails\"\n", "mkdir /root/rails && cd /root/rails\n", "rails new dengonban -d postgresql\n", "sed -i \"s/ username:.*/ username: rails/\" /root/rails/dengonban/config/database.yml\n", "sed -i \"s/ password:.*/ password: pas4rails\\n host: $DB_IP/\" /root/rails/dengonban/config/database.yml\n", "cd /root/rails/dengonban\n", "rails generate scaffold Messages name:string content:text date:datetime\n", "rake db:migrate RAILS_ENV=\"development\"\n", "rake db:migrate RAILS_ENV=\"production\"\n", "sed -i \"s/ # config.time_zone =.*/ config.time_zone = 'Tokyo'/\" /root/rails/dengonban/config/application.rb\n", "rails s -e production -p 80 -d\n" ]]}} } }, "WebServerIPAssoc" : { "Type" : "AWS::EC2::EIPAssociation", "Properties" : { "InstanceId" : { "Ref" : "WebServer" }, "EIP" : "192.168.199.105" } } } }
2箇所の"SubnetId"は、下記のコマンドで表示されるIDに書き換えておいてください。
# neutron subnet-list | grep private01 | cut -d"|" -f2 013cd465-7e75-4edc-ae83-6476fcf9178b
そして、おもむろにテンプレートからスタックを構築します。
# . keystonerc_demo_admin # heat stack-create -f dengonban.template -P "KeyName=mykey" dengonban +--------------------------------------+------------+--------------------+----------------------+ | id | stack_name | stack_status | creation_time | +--------------------------------------+------------+--------------------+----------------------+ | 642c1678-8966-461c-bbfe-c75c17b75e95 | dengonban | CREATE_IN_PROGRESS | 2014-02-06T07:01:16Z | +--------------------------------------+------------+--------------------+----------------------+
この後は、/var/log/heat/engine.logを眺めながら構築が終わるのを待ちます。構築が終わるとこんな感じになります。
# heat stack-list +--------------------------------------+------------+-----------------+----------------------+ | id | stack_name | stack_status | creation_time | +--------------------------------------+------------+-----------------+----------------------+ | 642c1678-8966-461c-bbfe-c75c17b75e95 | dengonban | CREATE_COMPLETE | 2014-02-06T07:01:16Z | +--------------------------------------+------------+-----------------+----------------------+ # nova list +--------------------------------------+--------------------------------------------+--------+------------+-------------+------------------------------------------+ | ID | Name | Status | Task State | Power State | Networks | +--------------------------------------+--------------------------------------------+--------+------------+-------------+------------------------------------------+ | c7b48220-ea3c-4053-b699-d3bed8cde657 | dengonban-PgSQLDatabaseServer-wptgqlxdmbt6 | ACTIVE | None | Running | private01=192.168.101.3 | | 5896b645-a398-4827-9d76-306f7ec9c418 | dengonban-WebServer-s3n5y4wshlq2 | ACTIVE | None | Running | private01=192.168.101.4, 192.168.199.105 | +--------------------------------------+--------------------------------------------+--------+------------+-------------+------------------------------------------+
RoRのサンプルによくある伝言板アプリが動いていることが分かります。
実用性はよく分かりませんが、Havanaでは、Horizonダッシュボードからもスタックの状態が確認できて、こんなポンチ絵も表示できます。