テンプレートを使用したサンプルシステムの構築#
本構成はFJcloud-O 東日本/西日本リージョン3向けとなります。
要求事項#
仮想サーバや仮想ネットワーク、ファイアーウォールやセキュリティグループのルール等、何度も利用する構成を定型化することで以下の要求事項に対応します。
- システムを一括で配備したい(自動化)
- 開発/検証/本番等の環境を同一の内容で構築したい
- 他のシステムでも再利用できるようにしたい
本パターンではテンプレートを使用しサンプルシステムを構築することで、テンプレートを使用したスタック作成の概要と手順を理解することを目的とします。
対応するデザインパターン概要#
1. FJcloud-Oでのテンプレート#
FJcloud-Oでは、システム上で提供される複数の仮想リソースを使用して、環境を自動で構築するオーケストレーション機能が提供されています。
オーケストレーション機能では、仮想ルータ、サブネット等のネットワークの設定や、ロードバランサー、仮想サーバ等のサーバの設定、ファイアーウォールやセキュリティグループ等のアクセス制御設定等のシステムのかたまりを、スタックとして扱います。
このスタックをYAML形式のテキストで定義したものをテンプレートまたはHEATテンプレートと呼んでいます。
テンプレートをIaaSポータルやAPI経由で投入することで、オーケストレーション機能が働いてシステムを一括で構築することが出来ます。
2. テンプレートの書式#
テンプレートで使用されるYAMLとは構造化されたデータを表現するためのフォーマットです。
以下の3つの主要セクションで構成されます。
- parameters:
作成/設定するリソースの入力パラメータに関する記述 - resources:
作成/設定する固有のリソースに関する記述 - outputs:
アウトプットのパラメータに関する記述
構造 (イメージ図)#
以下サンプルシステムの構築を自動化するテンプレートを例として、スタックの作成、およびスタックの削除を記載します。
各リソースの名称は括弧内の値が付与されます。
※仮想ルータ(RT2)は外部ネットワークへの接続なし
実装サンプル#
1. スタックの作成#
(1) テンプレートの内容#
以下のサンプルテンプレートを使用してリソースの作成を行います。
parameters, resources, outputsセクション内の各オブジェクトに関して、以下の(B)~(D)の手順を参考として必要に応じたパラメータ修正やリソース数の増減を行ってください。
- サンプルテンプレート
heat_template_version: 2013-05-23 description: A single-server deployment including inflastructures parameters: # Infla parameters service_network1_name: type: string description: Name of the service network default: NW2 service_subnet1_name: type: string description: Name of the service subnetwork. default: SN2 service_router1_name: type: string description: Name of the service vrouter. default: RT2 service_subnet1_cidr: type: string description: CIDR representation of the service subnet. default: 192.168.2.0/24 service_subnet1_gw_ip: type: string description: Gateway IP of Subnet default: 192.168.2.1 service_subnet1_gw_port_name: type: string description: Gateway port name of Subnet default: GWport2 security_group_name: type: string description: Security Group name default: SG2 nameserver_ip1: type: string description: IP of the dns nameserver1. default: 8.8.8.8 nameserver_ip2: type: string description: IP of the dns nameserver2. default: 8.8.4.4 firewall1_name: type: string description: Name of the firewall1 default: FW2 firewall1_policy_name: type: string description: Name of the firewall1 Policy default: FWpolicy2 # Server parameters port_name: type: string description: name of vm default: Port2 key_name: type: string description: name of keypair default: Key2 image: type: string description: Image ID or image name to use for the server default: 1e8d4a48-bbde-416f-b6fd-fff016673d6c volume_name: type: string description: name of volume default: Volume2 flavor: type: string description: Flavor for the server to be created default: fdbf1331-9dfe-4119-872d-3b88d1cb61b8 vm_name: type: string description: name of vm default: VM2 resources: # Infla resources service_network1: type: OS::Neutron::Net properties: name: { get_param: service_network1_name } service_subnet1: type: OS::Neutron::Subnet properties: cidr: { get_param: service_subnet1_cidr } name: { get_param: service_subnet1_name } gateway_ip: { get_param: service_subnet1_gw_ip } network_id: { get_resource: service_network1 } dns_nameservers: [{ get_param: nameserver_ip1 }, { get_param: nameserver_ip2 }] gw_port1: type: OS::Neutron::Port properties: network_id: { get_resource: service_network1 } fixed_ips: [{"ip_address": {get_param: service_subnet1_gw_ip }, "subnet_id": {get_resource: service_subnet1 }}] name: { get_param: service_subnet1_gw_port_name } service_router1: type: OS::Neutron::Router properties: name: { get_param: service_router1_name } service_router_interface1: depends_on: service_router1 type: OS::Neutron::RouterInterface properties: router_id: { get_resource: service_router1 } port_id: { get_resource: gw_port1 } security_group: type: OS::Neutron::SecurityGroup properties: description: test Security groups rule name: { get_param: security_group_name } rules: [{"direction": ingress, "port_range_max": 22, "port_range_min": 22, "protocol": tcp, "remote_ip_prefix": 192.168.2.0/24 }, {"direction": ingress, "protocol": icmp, "remote_ip_prefix": 192.168.2.0/24 }] firewall1: type: OS::Neutron::Firewall properties: description: test Firewall name: { get_param: firewall1_name } firewall_policy_id: {get_resource: firewall1_policiy } value_specs: {"router_ids": [{get_resource: service_router1}]} firewall1_policiy: type: OS::Neutron::FirewallPolicy properties: audited: true description: test Firewall Policy firewall_rules: [{ get_resource: firewall_rule1 },{ get_resource: firewall_rule2 },{ get_resource: firewall_rule3 }] name: { get_param: firewall1_policy_name } firewall_rule1: type: OS::Neutron::FirewallRule properties: description: test Firewall rule1 destination_port: "80" protocol: tcp source_ip_address: {get_param: service_subnet1_cidr} action: allow firewall_rule2: type: OS::Neutron::FirewallRule depends_on: firewall_rule1 properties: description: test Firewall rule2 source_port: "53" protocol: udp source_ip_address: {get_param: service_subnet1_cidr} destination_ip_address: {get_param: nameserver_ip1} action: allow firewall_rule3: type: OS::Neutron::FirewallRule depends_on: firewall_rule1 properties: description: test Firewall rule3 source_port: "53" protocol: udp source_ip_address: {get_param: service_subnet1_cidr} destination_ip_address: {get_param: nameserver_ip2} action: allow # Server resources port: type: OS::Neutron::Port properties: name: { get_param : port_name } network_id: { get_resource: service_network1 } security_groups: - {get_resource: security_group } fixed_ips: - subnet_id: { get_resource: service_subnet1 } key: type: OS::Nova::KeyPair properties: name: { get_param: key_name } save_private_key: true sys-vol: type: OS::Cinder::Volume properties: name: { get_param: volume_name } size: 60 volume_type: M2 image : { get_param: image } server: type: OS::Nova::Server properties: key_name: { get_resource: key } flavor: { get_param: flavor } networks: ["port": {get_resource: port} ] name: { get_param: vm_name } block_device_mapping_v2: - device_name: vda volume_id: {get_resource: sys-vol} outputs: private_key: description: private key of created key pair value: { get_attr: [key, private_key] }
(A) 事前準備#
-
APIにて仮想サーバのフレーバー一覧を取得し、必要となるフレーバーのIDを控えてください。
curl -Ss $COMPUTE/v2/$PROJECT_ID/flavors/detail -X GET -H "X-Auth-Token: $OS_AUTH_TOKEN" | jq '.flavors[] | {"name": .name, "vcpus": .vcpus, "ram": .ram, "id": .id,}'
-
APIにてイメージ一覧を取得し、必要となるOSのイメージIDを控えてください。
curl $IMAGE/v2/images -X GET -H "X-Auth-Token: $OS_AUTH_TOKEN" | jq '.images[] | {"name": .name, "id":.id}'
(B) parametersセクション内の設定項目#
各パラメータの設定値は以下表の通りです。
必要に応じて修正ください。
パラメータ | 設定値例 | 説明 |
---|---|---|
service_network1_name | NW2 | 作成する仮想ネットワークの名前を指定 |
service_subnet1_name | SN2 | 作成するサブネットの名前を指定 |
service_router1_name | RT2 | 作成するルータの名前を指定 |
service_subnet1_cidr | 192.168.2.0/24 | 作成するサブネットのCIDRを指定 |
service_subnet1_gw_ip | 192.168.2.1 | サブネットのゲートウェイIPを指定 |
service_subnet1_gw_port_name | GWport2 | サブネットのゲートウェイポートの名前を指定 |
security_group_name | SG2 | セキュリティグループの名前を指定 |
nameserver_ip1 | 8.8.8.8 | サブネットに配備するサーバが使用するDNSサーバ1のIPアドレスを指定 |
nameserver_ip2 | 8.8.4.4 | サブネットに配備するサーバが使用するDNSサーバ2のIPアドレスを指定 |
firewall1_policy_name | FWpolicy2 | ファイアーウォールポリシー名を指定 |
port_name | Port2 | 作成する仮想サーバのポート名を指定 |
key_name | Key2 | 作成するキーペア名を指定 ここで作成するキーペアが仮想マシンの作成時に使用される |
image | 1e8d4a48-bbde-416f-b6fd-fff016673d6c | 仮想サーバの作成に使用するイメージIDを指定 |
volume_name | Volume2 | 仮想サーバにアタッチさせるシステムストレージのボリューム名を指定 |
flavor | fdbf1331-9dfe-4119-872d-3b88d1cb61b8 | 作成する仮想サーバのフレーバーIDを指定 |
vm_name | VM2 | 作成する仮想サーバの名前を指定 |
(C) resourcesセクション内の設定項目#
- セキュリティグループ
以下のルールを保持するセキュリティグループが作成され、仮想サーバ(VM2)のポートに適用されます。
必要に応じて修正ください。
ルール | 方向 | オープンポート | ポート | 接続先 | セキュリティグループまたは CIDR | IPバージョン |
---|---|---|---|---|---|---|
ALL ICMP | 受信 | - | - | CIDR | 192.168.2.0/24 | IPv4 |
カスタムTCPルール | 受信 | ポート | 22 | CIDR | 192.168.2.0/24 | IPv4 |
- ファイアーウォール
以下のファイアーウォールルールが作成され、ファイアーウォールポリシーとして仮想ルータ(RT2)に適用されます。
必要に応じて修正ください。
no | 名前 | プロトコル | IP バージョン |
アクション | Srcアドレス | Srcポート | Destアドレス | Destポート |
---|---|---|---|---|---|---|---|---|
1 | *firewall_rule1* | tcp | 4 | allow | 192.168.2.0/24 | null | null | 80 |
2 | *firewall_rule2* | udp | 4 | allow | 192.168.2.0/24 | 53 | 8.8.8.8 | null |
3 | *firewall_rule3* | udp | 4 | allow | 192.168.2.0/24 | 53 | 9.9.9.9 | null |
- システムストレージ
システムストレージ容量は60GBとなっています。
必要に応じて修正ください。
(D) outputsセクション内の設定項目#
作成するキーペアの秘密鍵を出力します。
必要に応じて修正ください。
(2) スタックの作成#
IaaSポータルでは、以下の手順でスタックを作成します。
- 「テンプレート」⇒「スタック」と選択した画面で、画面右上の「+」ボタンをクリックします。
- 以下を入力して「作成」をクリックすると、「スタック」画面に戻り、スタックが "CREATE_IN_PROGRESS" というステータスで作成中になります。
項目 | 設定値例 | 説明 |
---|---|---|
スタック名 | sample_stack | 任意のスタック名を指定 英数字と、"_"、"-"、"." のみ使用可。先頭文字は英字。 |
テンプレート 指定方法 |
YAML | 以下よりテンプレートの指定方法を選択 |
テンプレート ファイル |
(上記のテンプレートの内容を編集したものをコピー/ペースト) | テンプレートの指定方法に合わせて、項目名が以下のように変化 |
タイムアウト (分) |
10分 | 任意の値を入力 |
失敗時のリソース削除 | 「削除する」をチェックしない | テンプレート実行失敗時に、失敗するまでに作成したリソースを削除する場合はチェックをする |
Note
既存のセキュリティグループ数やセキュリティグループルール数との合計がプロジェクトの制限値を超える場合は、スタック作成が失敗するか、またはルールが一部作成されないで作成完了します。
- しばらく時間をおいて、「スタック」画面をリロードします。
スタックの作成が完了していると、ステータスが "CREATE_COMPLETE" となります。
スタックの作成が失敗していると、ステータスが "CREATE_FAILED" となります。
(3) スタックの確認#
スタックが作成されたら、テンプレートの内容と実際の設定状況を照合して確認してください。
Note
スタックが "CREATE_COMPLETE" となっていても、セキュリティグループのルール数が制限値を超えていて、ルールが作成されていない場合があります。
2. スタックの削除#
(1) スタックの削除#
IaaSポータルでは、以下の手順でスタックを削除します。
- 「テンプレート」⇒「スタック」と選択した画面で、削除したいスタックの「アクション」メニューから、「削除」をクリックします。
- 「スタック削除の確認」ウィンドウがポップアップされます。確認して「削除」をクリックします。
「削除」クリックすると、「スタック」画面に戻り、"DELETE_IN_PROGRESS" というステータスで削除中になります。 - しばらく時間をおいて、「スタック」画面をリロードします。
スタックの削除が完了していると、スタックが一覧からなくなっています。
スタックの削除が失敗していると、ステータスが "DELETE_FAILED" となります。
Warning
スタックを作成中に、スタックを削除しないでください。
"DELETE_FAILED" となって、スタックが削除できなくなる可能性があります。
メリット・効果#
テンプレート配備 パターンを利用した場合のメリット・効果は以下の通りです。
- 何度も利用する構成を定型化 (=テンプレート化) することにより、容易に、システムを一括で配備することが可能(自動化)
- 開発/検証/本番等の環境等、同一の内容で環境を構築したい場合に、容易に、複数の環境を同じ内容で配備することが可能
- テンプレートを流用したり再利用することで、構築コストを低減可能
注意事項#
- 本パターンは2020年6月時点のFJcloud-O 東日本/西日本リージョン3で動作検証しています。
- 仕様により、外部ネットワークに接続させるルータの作成を含むテンプレートを使用してスタックを新規に作成することはできません。
テンプレートにより作成したルータを外部ネットワークに接続させるには、IaaSポータルの「仮想ルータ一覧」画面より対象の仮想ルータの「アクション」⇒「編集」をクリックし、外部ネットワークとして「fip-net」を設定してください。
その際には、必要に応じてセキュリティグループおよびファイアーウォールの設定を変更してください。 - テンプレートのパラメータごとの詳細は HEATテンプレート解説書 でご確認ください。
東日本/西日本リージョン3ではテンプレートの仕様が一部異なります。詳細は こちら を参照ください。 - テンプレートに設定したパラメータがプロジェクトの制限値を超えている場合は、スタック作成が失敗したり、スタック作成が完了していても不備が出たりする場合があります。