CloudStack Cloud ガイド¶
はじめに¶
本セクションの目的は、Ansible モジュールを 1 つにまとめて CloudStack コンテキストで Ansible を使用する方法を説明します。その他の使用例は、各モジュールの詳細セクションに記載されています。
Ansible には、CloudStack ベースのクラウドと対話するための追加モジュールが多数含まれています。すべてのモジュールは、チェックモードに対応しており、冪等であるように設計されています。これらは作成およびテストされており、コミュニティーによって維持されます。
Note
一部のモジュールには、ドメイン管理または root 管理者権限が必要です。
要件¶
CloudStack モジュールを使用する前提条件は最小限です。Ansible 自体に加えて、すべてのモジュールには python ライブラリー cs
https://pypi.org/project/cs/ が必要です。
この Python モジュールは、実行ホスト (通常はワークステーション) にインストールする必要があります。
$ pip install cs
もしくは、Debian 9 および Ubuntu 16.04 から始まります。
$ sudo apt install python-cs
Note
cs には、CloudStack API などの、アドホックの対話用のコマンドラインインターフェースも含まれています ($ cs listVirtualMachines state=Running
)。
制限および既知の問題¶
VPC のサポートは Ansible 2.3 以降で改善されましたが、まだ完全に実装されていません。コミュニティーは VPC 統合で機能しています。
認証情報ファイル¶
認証情報とクラウドのエンドポイントをモジュール引数として渡すことができますが、ほとんどの場合、認証情報を cloudstack.ini ファイルに保存する作業ははるかに少なくなります。
Python ライブラリー cs は、以下の順番で認証情報ファイルを検索します (最後のコピーが優先されます)。
- ホームディレクトリーの
.cloudstack.ini
(ドットは必須)。 - .ini ファイルを参照する
CLOUDSTACK_CONFIG
環境変数。 - 現在の作業ディレクトリーにある
cloudstack.ini
(ドットなし) ファイル (Playbook と同じディレクトリー)。
ini ファイルの構造は以下のようになります。
$ cat $HOME/.cloudstack.ini
[cloudstack]
endpoint = https://cloud.example.com/client/api
key = api key
secret = api secret
timeout = 30
Note
セクション [cloudstack]
はデフォルトのセクションです。CLOUDSTACK_REGION
環境変数を使用してデフォルトのセクションを定義できます。
バージョン 2.4 における新機能
ENV 変数は、ライブラリー cs
のドキュメントに記載されている CLOUDSTACK_*
に対応します。たとえば、CLOUDSTACK_TIMEOUT
、CLOUDSTACK_METHOD
などが Ansible に実装されています。cloudstack.ini に不完全な設定を設定することも可能です。
$ cat $HOME/.cloudstack.ini
[cloudstack]
endpoint = https://cloud.example.com/client/api
timeout = 30
ENV 変数または task パラメーターを設定して、不足しているデータに対応します。
---
- name: provision our VMs
hosts: cloud-vm
tasks:
- name: ensure VMs are created and running
delegate_to: localhost
cs_instance:
api_key: your api key
api_secret: your api secret
...
リージョン¶
複数の CloudStack リージョンを使用する場合は、必要な数だけセクションを定義し、任意の名前を付けることができます。以下に例を示します。
$ cat $HOME/.cloudstack.ini
[exoscale]
endpoint = https://api.exoscale.ch/compute
key = api key
secret = api secret
[example_cloud_one]
endpoint = https://cloud-one.example.com/client/api
key = api key
secret = api secret
[example_cloud_two]
endpoint = https://cloud-two.example.com/client/api
key = api key
secret = api secret
Hint
セクションは、異なるアカウントを使用して同じリージョンにログインするためにも使用できます。
引数 api_region
を CloudStack モジュールに渡すと、必要なリージョンが選択されます。
- name: ensure my ssh public key exists on Exoscale
cs_sshkeypair:
name: my-ssh-key
public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
api_region: exoscale
delegate_to: localhost
または、すべてのリージョンでタスクを実行する場合は、リージョンリストをループします。
- name: ensure my ssh public key exists in all CloudStack regions
local_action: cs_sshkeypair
name: my-ssh-key
public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
api_region: "{{ item }}"
loop:
- exoscale
- example_cloud_one
- example_cloud_two
環境変数¶
バージョン 2.3 における新機能
Ansible 2.3 以降、ドメイン (CLOUDSTACK_DOMAIN
)、アカウント (CLOUDSTACK_ACCOUNT
)、プロジェクト (CLOUDSTACK_PROJECT
)、VPC (CLOUDSTACK_VPC
)、およびゾーン (CLOUDSTACK_ZONE
) に環境変数を使用できます。これにより、すべてのタスクの引数が繰り返し実行されず、タスクが簡素化されます。
以下は、Ansible のブロック機能と組み合わせて使用する例を示しています。
- hosts: cloud-vm
tasks:
- block:
- name: ensure my ssh public key
cs_sshkeypair:
name: my-ssh-key
public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- name: ensure my ssh public key
cs_instance:
display_name: "{{ inventory_hostname_short }}"
template: Linux Debian 7 64-bit 20GB Disk
service_offering: "{{ cs_offering }}"
ssh_key: my-ssh-key
state: running
delegate_to: localhost
environment:
CLOUDSTACK_DOMAIN: root/customers
CLOUDSTACK_PROJECT: web-app
CLOUDSTACK_ZONE: sf-1
Note
モジュール引数 (例: zone: sf-2
) を使用して環境変数を上書きすることは可能です。
Note
CLOUDSTACK_REGION
とは異なり、この追加の環境変数は CLI cs
では無視されます。
ユースケース¶
以下は、モジュールを使用して仮想マシンをクラウドにプロビジョニングする方法を示すものです。通常と同様に、これを行う方法は 1 つだけではありません。しかし、いつものように、最初はシンプルに保つことは、常に良いスタートです。
ユースケース: Advanced Networking CloudStack 設定のプロビジョニング¶
CloudStack クラウドには高度なネットワーク設定があり、静的な NAT を取得し、ファイアウォールポート 80 および 443 を開く Web サーバーをプロビジョニングを行います。さらに、アクセスを提供しないデータベースサーバーをプロビジョニングします。SSH で仮想マシンにアクセスするには、SSH ジャンプホストを使用します。
インベントリーは以下のようになります。
[cloud-vm:children]
webserver
db-server
jumphost
[webserver]
web-01.example.com public_ip=198.51.100.20
web-02.example.com public_ip=198.51.100.21
[db-server]
db-01.example.com
db-02.example.com
[jumphost]
jump.example.com public_ip=198.51.100.22
ご覧のとおり、Web サーバーおよびジャンプホストのパブリック IP は、インベントリーで直接変数 public_ip
として割り当てられます。
ジャンプホスト、Web サーバー、およびデータベースサーバーを設定し、group_vars
を使用します。group_vars
ディレクトリーには、cloud-vm、jumphost、webserver、db-server の 4 つのファイルが含まれています。クラウドインフラストラクチャーのデフォルトを指定する cloud-vm があります。
# file: group_vars/cloud-vm
---
cs_offering: Small
cs_firewall: []
データベースサーバーはより多くの CPU および RAM を取得する必要があるため、Large
オファリングを使用するように定義します。
# file: group_vars/db-server
---
cs_offering: Large
Web サーバーは、水平的にスケーリングするのと同様に、Small
オファリングを取得します。これはデフォルトのオファリングです。また、既知の Web ポートがグローバルに開いていることを確認します。
# file: group_vars/webserver
---
cs_firewall:
- { port: 80 }
- { port: 443 }
さらに、オフィス IPv4 ネットワークから仮想マシンにアクセスするためにポート 22 のみを開くジャンプホストをプロビジョニングします。
# file: group_vars/jumphost
---
cs_firewall:
- { port: 22, cidr: "17.17.17.0/24" }
ここからが重要です。Playbook を作成して、infra.yml
を呼び出すインフラストラクチャーを作成します。
# file: infra.yaml
---
- name: provision our VMs
hosts: cloud-vm
tasks:
- name: run all enclosed tasks from localhost
delegate_to: localhost
block:
- name: ensure VMs are created and running
cs_instance:
name: "{{ inventory_hostname_short }}"
template: Linux Debian 7 64-bit 20GB Disk
service_offering: "{{ cs_offering }}"
state: running
- name: ensure firewall ports opened
cs_firewall:
ip_address: "{{ public_ip }}"
port: "{{ item.port }}"
cidr: "{{ item.cidr | default('0.0.0.0/0') }}"
loop: "{{ cs_firewall }}"
when: public_ip is defined
- name: ensure static NATs
cs_staticnat: vm="{{ inventory_hostname_short }}" ip_address="{{ public_ip }}"
when: public_ip is defined
上記のプレイでは、3 つのタスクを定義し、グループの cloud-vm
をターゲットとして使用し、クラウド内の仮想マシンをすべて処理しますが、代わりにこれらの仮想マシンに SSH を使用するため、delegate_to: localhost
を使用してワークステーションからローカルに API 呼び出しを実行します。
最初のタスクでは、実行中の仮想マシンが Debian テンプレートを使用して作成されていることを確認します。仮想マシンがすでに作成されており、停止している場合は、これを起動します。既存の仮想マシンでオファリングを変更する場合は、タスクに force: yes
を追加する必要があります。これにより、仮想マシンが停止し、オファリングを変更して仮想マシンを再度起動します。
次のタスクでは、仮想マシンにパブリック IP を付与した場合にポートを開くようにします。
3 番目のタスクでは、パブリック IP が定義されている仮想マシンに静的 NAT を追加します。
Note
パブリック IP アドレスは事前に取得している必要があります。cs_ip_address
も参照してください。
Note
一部のモジュール (cs_sshkeypair
など)の場合、これはすべての仮想マシンに対してではなく、通常 1 回のみ実行するようにします。そのため、ローカルホストをターゲットとする別のプレイを作成します。以下のユースケースの例があります。
ユースケース: Basic Networking CloudStack 設定へのプロビジョニング¶
基本的なネットワーク CloudStack 設定は若干異なります。すべての仮想マシンにはパブリック IP が直接割り当てられ、セキュリティーグループはアクセス制限ポリシーに使用されます。
インベントリーは以下のようになります。
[cloud-vm:children]
webserver
[webserver]
web-01.example.com
web-02.example.com
仮想マシンのデフォルトは以下のようになります。
# file: group_vars/cloud-vm
---
cs_offering: Small
cs_securitygroups: [ 'default']
また、Web サーバーはセキュリティーグループ Web
にも存在します。
# file: group_vars/webserver
---
cs_securitygroups: [ 'default', 'web' ]
Playbook は以下のようになります。
# file: infra.yaml
---
- name: cloud base setup
hosts: localhost
tasks:
- name: upload ssh public key
cs_sshkeypair:
name: defaultkey
public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- name: ensure security groups exist
cs_securitygroup:
name: "{{ item }}"
loop:
- default
- web
- name: add inbound SSH to security group default
cs_securitygroup_rule:
security_group: default
start_port: "{{ item }}"
end_port: "{{ item }}"
loop:
- 22
- name: add inbound TCP rules to security group web
cs_securitygroup_rule:
security_group: web
start_port: "{{ item }}"
end_port: "{{ item }}"
loop:
- 80
- 443
- name: install VMs in the cloud
hosts: cloud-vm
tasks:
- delegate_to: localhost
block:
- name: create and run VMs on CloudStack
cs_instance:
name: "{{ inventory_hostname_short }}"
template: Linux Debian 7 64-bit 20GB Disk
service_offering: "{{ cs_offering }}"
security_groups: "{{ cs_securitygroups }}"
ssh_key: defaultkey
state: Running
register: vm
- name: show VM IP
debug: msg="VM {{ inventory_hostname }} {{ vm.default_ip }}"
- name: assign IP to the inventory
set_fact: ansible_ssh_host={{ vm.default_ip }}
- name: waiting for SSH to come up
wait_for: port=22 host={{ vm.default_ip }} delay=5
最初のプレイでは、セキュリティーグループを設定し、次のプレイで、作成される仮想マシンがこれらのグループに割り当てられます。さらに、モジュールから返されたパブリック IP をホストインベントリーに割り当てることが確認できます。これは、事前に取得している IP が分からないため必要になります。次の手順では、この IP を使用して DNS サーバーを設定し、DNS 名を使用して仮想マシンにアクセスします。
最後のタスクでは、SSH がアクセス可能になるのを待ちます。したがって、後でプレイしても、SSH で仮想マシンにアクセスする際に失敗せずに実行できます。