はじめに
ここまで第2回と第3回でCUI版、第4回でGUI版の使い方を紹介してきました。Ansibleの基本的な使い方に関してはある程度理解できたのではないでしょうか?これまでは既に起動し、SSH接続が可能なLinuxサーバへのインストール手法を紹介してきましたが、最終回となる今回はAWSやVMware等、様々な環境を操作するための手法に関して紹介します。
REST APIとクライアントモジュール
Ansibleから様々な環境を操作するにあたって大きく以下2パターンの方式があります。
項番 | 方式 | 概要 |
---|---|---|
1 | API | API操作可能な機器の場合、AnsibleのサーバからAPIのリクエストをPOSTして操作を行います |
2 | クライアントモジュール | Ansibleのサーバにインストールされているモジュールを操作して、対象となる機器を操作します |
どちらの方式もAnsibleが直接操作する機器はlocalhost(Ansibleがインストールされているサーバ自身)となります。LocalhostにおいてAnsibleで生成したPythonのスクリプトを実行し、それぞれの操作対象機器に合わせた手法で接続、操作を行います。
①APIで操作する方式
Ciscoのスイッチやf5のロードバランサー、HPEのサーバやストレージ等の物理的な機器は昨今APIで操作可能となっています。これら機器に関してはAnsibleからAPIに対してリクエストをPOSTすることで操作します。
Ansibleで生成されたPythonのスクリプト内からAPIを操作するHTTP/HTTPSのリクエストが実行されます。なので、Playbook内ではURI作成に必要となる情報を記載することになります。
②クライアントモジュールで操作する方式
WindowsやAWS等はPythonでの操作を可能とするモジュールが用意されています。Ansibleにもこれらモジュールを使用するためのモジュールが用意されています。Playbook内で必要な情報を与えることで、操作するためのPythonスクリプトを作成、実行してくれるので、Pythonプログラミングの知識を必要とせずに操作することが可能となります。
また、DockerのようにPythonのモジュールではないが、クライアントソフトウェアをPythonスクリプト内から起動できるようにしたモジュールも用意されています。
項番 | 対象 | 概要 |
---|---|---|
1 | Windows | Pythonのpywinrmを使用してWinRMに接続、PowerShellコマンドでOSを操作します |
2 | VMware | PythonのPyvmomiを使用してvCenterServerに接続、仮想環境を構築します |
3 | AmazonWebService | PythonのBotoを使用してAWSに接続、NWやEC2の構築等基盤部分の操作を行います |
4 | Microsoft Azure | Azure-CLIを使用してAzureに接続、NWやOSの立ち上げ等基盤部分の操作を行います |
5 | Docker | DockerClientを使用してDocker環境に接続、コンテナの構築やコンテナ内の操作を行います |
使用例の紹介
以下に、現在よく使用されているケースとして、Windows環境、仮想環境(例としてVMware環境)、クラウド環境(例としてAWS環境)の構築に関して紹介します。なお、それぞれ一例となりますので、その他設定に関しては別途Ansibleのドキュメントを参照しながら実施していただければと思います。
項番 | 対象環境 | 実施内容 |
---|---|---|
1 | Windows | Windows環境を対象にした際のAnsibleの環境構築及びPlaybookの書き方を紹介します |
2 | VMware | VMwareで仮想マシンを作成する際のAnsibleの環境構築及びPlaybookの書き方を紹介します |
3 | AmazonWebServices | AWSでEC2を作成する際のAnsibleの環境構築及びPlaybookの書き方を紹介します |
なお、各Pythonモジュールの導入にあたり、pipがインストールされている必要があります。インストールされていない場合は事前にインストールを行います。
# yum install gcc python-devel # curl -L https://bootstrap.pypa.io/get-pip.py | python
1. Windows環境を操作する
AnsibleではWindows環境も操作する事が可能です。ここではWindows環境を操作する場合に必要となる環境の準備方法と、Playbookの書き方を紹介します。
1-1. 事前準備
Ansibleを使ってWindows環境を操作する場合、Ansibleのサーバに「Pywinrm」というPythonモジュールがインストールされている必要があります。
以下の通り、pipコマンドを使用し、「Pywinrm」をインストールします。
# pip install pywinrm
また、Windows環境を操作する場合には、操作対象のWindows環境にも準備が必要となります。WinRMの接続を受け付けるためのいくつかのコマンドをまとめた設定用スクリプト(公式)が提供されているため、ダウンロードして操作対象環境で実行します。
① PowerShellを管理者権限で起動します
②設定用スクリプトをダウンロードし、実行します
PS > mkdir C:\work PS > cd C:\work PS > Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile ConfigureRemotingForAnsible.ps1 PS > powershell -ExecutionPolicy RemoteSigned .\ConfigureRemotingForAnsible.ps1
1-2. Windows用インベントリファイル
Windows環境を操作する場合、インベントリファイル内に接続するPort番号とWinRMを使用する旨の記載が必要となります。また、Python2.7.9以降を使用する場合はHTTPSの証明書の検証が行われるため、無視するための設定を入れる必要があります。
[windows] Windows機IPアドレスorホスト名(Ansibleサーバから名前解決出来る事) [windows:vars] ansible_user=ユーザ名(Administratorグループのユーザ) ansible_password=パスワード ansible_port=5986 ansible_connection=winrm ansible_winrm_server_cert_validation=ignore
設定が正しく行えたことの確認はLinuxの時と違い、以下の通り、win_pingというオプションを使って行います。
# ansible -i hosts windows -m win_ping
1-3. Windows環境用Playbook
Windows環境用にはLinux用の物とは別に、win_○○ のようなモジュールが用意されているため、それらを用いてPlaybookを作成します。種類やそれぞれの詳しい使い方に関してはAnsibleドキュメントのWindows環境関連の箇所を確認します。
ここでは、Zabbix-AgentをWindows環境にインストールする際のRole用Playbook例を紹介します。以下モジュールを使用しています。
モジュール名 | 概要 |
---|---|
win_file | ファイルやディレクトリの作成を行います |
win_get_url | ファイルをダウンロードしてきます |
win_unzip | ZIP形式のファイルを解凍します |
win_template | テンプレートファイルをアップロードします |
win_command | コマンドを実行します |
win_firewall_rule | ファイアウォールのポリシー変更を行います |
--- - name: Create zabbix directory win_file: path: 'C:\Zabbix' state: directory - name: Download zabbix-agent.zip win_get_url: url: '{{ zabbix_agent_url }}' dest: C:\Zabbix\zabbix_agent.zip - name: Unzip zabbix-agent.zip win_unzip: src: C:\Zabbix\zabbix_agent.zip dest: C:\Zabbix\ delete_archive: yes - name: Create zabbix config directory win_file: path: 'C:\Zabbix\conf\conf.d' state: directory - name: Make config from template win_template: src: zabbix_agentd.win.conf.j2 dest: 'C:\Zabbix\conf\zabbix_agentd.win.conf' - name: Install zabbix-agent win_command: CMD /C "C:\Zabbix\bin\win64\zabbix_agentd.exe --config C:\Zabbix\conf\zabbix_agentd.win.conf --install"
- name: Start zabbix-agent win_command: CMD /C "C:\Zabbix\bin\win64\zabbix_agentd.exe --config C:\Zabbix\conf\zabbix_agentd.win.conf --start" - name: Add firewall rule for {{ zabbix_agent_port }} port win_firewall_rule: name: 'Zabbix-Agent' localport: '{{ zabbix_agent_port }}' action: allow direction: in protocol: tcp remoteip: '{{ zabbix_server_ip }}' state: present enabled: yes
モジュールとしてはwin_○○といった別の物を使用していますが、変数の設定やテンプレートファイル、トップレベルのPlaybookに関しての記載方法は同じです。
テンプレートファイル: zabbix_agentd.win.conf.j2
LogFile={{zabbix_log}} Server={{ zabbix_server_ip }} ListenPort={{ zabbix_agent_port }} ListenIP={{ zabbix_agent_ip }} ServerActive={{ zabbix_server_ip }} Hostname={{ ansible_hostname }} Timeout={{ zabbix_agent_timeout }} Include={{zabbix_include}}
デフォルト変数の設定: defaults/main.yml
zabbix_agent_url: https://www.zabbix.com/downloads/3.4.6/zabbix_agents_3.4.6.win.zip' zabbix_log: 'c:\Zabbix\zabbix_agentd.log' zabbix_agent_port: 10050 zabbix_include: 'c:\Zabbix\conf\conf.d\*.conf' zabbix_agent_timeout: '10' zabbix_agent_ip: '0.0.0.0'
トップレベルのPlaybook: zabbix_agentd_site.yml
--- - hosts: windows remote_user: Administrator vars: - zabbix_server_ip: '10.10.10.22' roles: - zabbix_agent
2. VMware環境を操作する
AnsibleではVMware環境も操作する事が可能です。ここではVMware環境を操作する場合に必要となる環境の準備方法と、Playbookの書き方を紹介します。 なお、VMwareを操作する場合はモジュールがvCenterServerに対してコマンドを発行して操作する事になります。vCenterServerが無い環境ではAnsibleから操作できません。
2-1. 事前準備
Ansibleを使ってVMware環境を操作する場合、Ansibleのサーバに「Pyvmomi」というPythonモジュールがインストールされている必要があります。
以下の通り、pipコマンドを使用し、「Pyvmomi」をインストールします。
# pip install pyvmomi
2-2. VMware環境用Playbook
VMware環境用にvmware_guestというモジュールとvsphere_guestというモジュールが用意されています。vsphere_guestであればvCenterServerが無くても操作が可能ですが、Ansibleのver2.9において削除される予定となっているモジュールであるため、vmware_guestを使用してPlaybookを作成します。詳しい使い方に関してはAnsibleドキュメントのvmware_guestの箇所を確認します。
ここでは、VMware環境に新しいLinux仮想マシンを構築する際のRole用Playbook例を紹介します。
--- - name: vmware deploy vmware_guest: datacenter: "{{ vc_datacenter }}" hostname: "{{ vc_hostname }}" username: "{{ admin_username }}" password: "{{ admin_password }}" esxi_hostname: "{{ esxhost }}" validate_certs: no name: "{{ item.guest_vm_name }}" state: poweredon template: "{{ guest_template }}" folder: /Datacenter/vm datastore: "{{ vc_datastore }}" disk: - size_gb: 65 type: thin hardware: memory_mb: "{{ guest_memory }}" num_cpus: "{{ guest_cpu_num }}" networks: - name: VM Network ip: "{{ item.guest_ip_addr }}" netmask: "{{ guest_netmask }}" gateway: "{{ guest_gateway }}" customization: dns_servers: - "{{ guest_dns }}" wait_for_ip_address: yes with_items: - "{{ guest_info }}"
トップレベルのPlaybookは次の通りとなります。接続先がlocalhostになり、connectionがlocalになっています。Ansibleサーバが自分自身に対してアクセスを行って操作することを示しています。
--- - name: vmware deploy hosts: localhost gather_facts: false connection: local vars: guest_dns: 172.17.144.1 vc_datacenter: Datacenter vc_hostname: 172.17.146.130 admin_username: administrator@vcenterl.local admin_password: パスワード esxhost: 172.17.146.110 vc_datastore: datastore1 guest_netmask: 255.255.248.0 guest_gateway: 172.17.144.1 guest_memory: 2048 guest_cpu_num: 1 guest_template: basetemp guest_info: - guest_vm_name: handsonclx guest_ip_addr: xxx.xxx.xxx.xxx roles: - vmware_deploy
3.AWS環境を操作する
AnsibleではAWS環境も操作する事が可能です。EC2の構築だけでなく、ネットワークの設定やS3の設定等多岐にわたる操作が可能です。ここではAWS環境を操作する場合に必要となる環境の準備方法と、Playbookの書き方を紹介します。
3-1. 事前準備
Ansibleを使ってAWS環境を操作する場合、Ansibleのサーバに「Boto」というPythonモジュールがインストールされている必要があります。また、Pythonのバージョンが2.6以上である必要があります。
以下の通り、「Boto」をインストールします。
# yum install python-boto
Botoを使ってAWSにアクセスするにあたって、実行ユーザのホームディレクトリにAWSのアクセスキー及びシークレットキーが記載されたBotoの環境設定ファイルが必要となるため、作成します。なおAWXの場合は認証情報設定画面で入力可能であるため本作業は必要ありません。
# vi ~/.boto
[Credentials] aws_access_key_id = アクセスキーを調べて入力します aws_secret_access_key = シークレットキーを調べて入力します [Boto] ec2_region_name = ap-northeast-1 ec2_region_endpoint = ec2.ap-northeast-1.amazonaws.com
3-2. AWS操作用Playbookの作成
ここではEC2のインスタンスを1つ作成するにあたって必要となるPlaybookを紹介します。EC2インスタンスを立ち上げるにあたって、VPC、セキュリティグループ、キーペアの作成といった作業が必要となります。これらを実施するにあたって使用する各モジュールの詳細やこれら以外の作業を行うにあたって必要となるモジュールに関してはAnsibleドキュメントのCloud moduleのページ、Amazonの項目を参照します。
3-2-1. VPC作成
VPC及びその周辺の新規設定する際に以下モジュールを使用します。
モジュール名 | 概要 |
---|---|
ec2_vpc_net | VPCを作成します |
ec2_vpc_igwec2 | インターネットゲートウェイを作成します |
ec2_vpc_subnet | VPCのサブネットを作成します |
ec2_vpc_route_table | 各サブネットのルーティング設定を行います |
AWSの設定を行なう際には、新規に設定した項目で新たに払い出されるIDを別の所でも使用することが必要となってきます。
このIDは事前に知ることや、特定の物を指定することが出来ません。このため、Ansibleの処理内で確認して、指定する必要があります。これを実現するためにregisterを使用し、取得したIDを一時的に保持、参照しています。
また、サブネット値のセットをリストで呼び出すことで複数のサブネットを設定する際に何度も同じ記載を行わなくても良いようにします。
--- - name: Set VPC ec2_vpc_net: name: "{{aws.common_env}}_{{aws.vpc_vpc_name_tags}}" cidr_block: "{{aws.vpc_cider_block}}" region: "{{aws.common_region}}" register: _vpc - debug: var=_vpc verbosity=1 - name: Set Internet gateway ec2_vpc_igw: vpc_id: "{{_vpc.vpc.id}}" region: "{{aws.common_region}}" register: _igw - debug: var=_igw verbosity=1
- name: Set Public Subnets ec2_vpc_subnet: vpc_id: "{{_vpc.vpc.id}}" region: "{{aws.common_region}}" cidr: "{{item.cider}}" az: "{{item.az}}" resource_tags: { "Name": "{{item.name}}" } with_items: "{{aws.vpc_subnets}}" register: _subnet - debug: var=_subnet verbosity=1 - name: Public Route ec2_vpc_route_table: vpc_id: "{{_vpc.vpc.id}}" region: "{{aws.common_region}}" subnets: "{{_subnet.results | selectattr('item.route','match', 'Public') | map(attribute='subnet.id') | list }}" routes: - dest: 0.0.0.0/0 gateway_id: "{{_igw.gateway_id}}" tags: Name: "{{aws.common_env}}_Public_{{aws.vpc_routetable_name_tags}}" register: _public_route - debug: var=_public_route verbosity=1 - name: Set Private Route ec2_vpc_route_table: vpc_id: "{{_vpc.vpc.id}}" region: "{{aws.common_region}}" subnets: "{{_subnet.results | selectattr('item.route','match', 'Private') | map(attribute='subnet.id') | list }}" tags: Name: "{{aws.common_env}}_Private_{{aws.vpc_routetable_name_tags}}" register: _private_route - debug: var=_private_route verbosity=1
VPC作成のトップレベルのPlaybookは次の通りとなります。接続先がlocalhostになり、connectionがlocalになっています。
--- - hosts: localhost connection: local gather_facts: False vars: aws: common_region: "ap-northeast-1" common_env: "Prd" vpc_profile: default vpc_vpc_name_tags: "sample-vpc" vpc_cider_block: "172.24.0.0/16" vpc_subnets: - name: "sample-subnet-a" cider: "172.24.0.0/24" az: "ap-northeast-1a" route: "Private" - name: "sample-subnet-c" cider: "172.24.1.0/24" az: "ap-northeast-1c" route: "Public" vpc_routetable_name_tags: "sample-public-rtb" roles: - aws_vpc2
3-2-2. セキュリティグループ作成
セキュリティグループの新規設定する際に以下モジュールを使用します。
モジュール名 | 概要 |
---|---|
ec2_group | セキュリティグループの設定を行います |
ec2_vpc_net_facts | VPCの設定を取得します |
ec2_vpc_net_factsを使用する事で、VPCの設定内容を取得する事ができるので、registerに入れて使用します。VPC作成時につけたタグの情報を元に対象の設定を検索します。
--- - name: Get VPC_ID for new Security Group ec2_vpc_net_facts: region: "{{aws.common_region}}" filters: "tag:Name": "{{aws.common_env}}_{{aws.vpc_vpc_name_tags}}" changed_when: False register: vpc_id - debug: var=vpc_id.vpcs[0].id - name: Make Security Group ec2_group: state: present name: "{{aws.securitygroup_name}}" description: "{{aws.securitygroup_description}}" vpc_id: "{{vpc_id.vpcs[0].id}}" region: "{{aws.common_region}}" rules: - proto: "{{item.proto}}" from_port: "{{item.from_port}}" to_port: "{{item.to_port}}" cidr_ip: "{{item.cider_ip}}" with_items: "{{aws.securitygroup_rules}}" register: _secg - debug: var=_secg
セキュリティグループ作成のトップレベルのPlaybookは次の通りとなります。こちらも接続先がlocalhostになり、connectionがlocalになっています。
--- - hosts: localhost connection: local gather_facts: False vars: aws: vpc_vpc_name_tags: "sample-vpc" securitygroup_name: "sample-ec2-sg" securitygroup_description: "ec2 security group" securitygroup_rules: - proto: "tcp" from_port: "22" to_port: "22" cider_ip: "0.0.0.0/0" roles: - aws_securitygroup
3-2-3. EC2インスタンス作成
EC2インスタンスの新規作成では以下に使用するモジュールを使用します。EC2インスタンスの作成と合わせてログイン時に必要となるキーペアの作成も行います。
モジュール名 | 概要 |
---|---|
ec2_key | EC2で使用するキーペアの作成を行います |
ec2_ami_find | AMIの情報を取得します |
ec2_vpc_net_facts | VPCの設定を取得します |
ec2_vpc_subnet_facts | VPCのサブネットの設定を取得します |
ec2 | EC2インスタンス作成を行います |
AMIのidとか普段は意識したこともないと思います。毎回ログインして確認する手間をかけないために、ここでは処理の中で併わせて確認する事としました。1つの際は特に問題ないのですが、複数台を構築する場合にはインスタンスによって使用したいAMIが異なる可能性がありますので、Playbook内で調べてきたIDとAMIの名前をJson形式の一覧にしています。
誰でもが読み書きしやすいというAnsibleのポリシーに反することになるので、あまり推奨はされませんがPlaybookの中でPythonのスクリプトを記載することができる(次Playbook内Ⓐの部分参照)ので、その機能を使用して一覧の作成を行います。
サブネットも同様に複数ある可能性があるため、一覧の作成を行います。
ec2作成の部分で exact_count: “1” という項目があります。既に同様の設定のインスタンスが作成されていた場合は新たに作成しないという制御を行なっています。
最後のWait_forにおいて、一定時間待ったうえでsshでのアクセスを確認しています。この結果の確認後にミドルウェアインストールを行なうという流れを作成することが出来ます。
- name: Make EC2 KeyPair ec2_key: region: "{{aws.common_region}}" state: present wait: yes wait_timeout: 300 name: "{{aws.common_key}}" register: _keypair_result - debug: var=_keypair_result - name: Save private key local_action: shell /bin/bash -lc "touch /root/{{_keypair_result.key.name}}.pem; echo '{{ _keypair_result.key.private_key }}' > /root/{{_keypair_result.key.name}}.pem;chmod 0600 /root/{{_keypair_result.key.name}}.pem" when: _keypair_result.changed - debug: var=ami_find
with_dict: "{{aws.ec2_vars}}" register: subnet_fact when: aws.ec2_vars is defined - name: Create subnet dict set_fact: subnet_dict: >- {%- set dict = {} -%} {%- for i in range(subnet_fact.results|length) -%} {%- set _ = dict.update({subnet_fact.results[i].subnets[0].tags.Name: subnet_fact.results[i].subnets[0].id}) -%} {%- endfor -%} {{ dict }} when: aws.ec2_vars is defined - name: Create ec2 instances. ec2: key_name: "{{aws.common_key}}" group: "{{item.value.ec2_securitygroup_name}}" instance_type: "{{item.value.ec2_instance_type}}" image: >- {%- set ami_id = ami_dict[item.value.ec2_ami_name] -%} {{ ami_id }} region: "{{aws.common_region}}" vpc_subnet_id: >- {%- set id = subnet_dict[item.value.ec2_vpc_subnet_tagname] -%} {{ id }} wait: true wait_timeout: 300 assign_public_ip: "{{item.value.ec2_public_ip}}" exact_count: "1" count_tag: Name: "{{item.value.ec2_tags.Name}}" Env: "{{aws.common_env}}" Role: "{{item.value.ec2_tags.Role}}" instance_tags: Name: "{{item.value.ec2_tags.Name}}" Env: "{{aws.common_env}}" Role: "{{item.value.ec2_tags.Role}}"
with_dict: "{{aws.ec2_vars}}" register: ec2 when: aws.ec2_vars is defined - debug: var=ec2 - debug: var=ec2.results[0].tagged_instances[0].private_ip - debug: var=ec2.results[0].tagged_instances[0].public_ip - name: Private IP dict作成 set_fact: pip_dict: >- {%- set dict = {} -%} {%- for i in range(ec2.results|length) -%} {%- set _ = dict.update({ec2.results[i].tagged_instances[0].tags.Name: ec2.results[i].tagged_instances[0].private_ip}) -%} {%- endfor -%} {{ dict }} when: aws.ec2_vars is defined - name: Public IP dict作成 set_fact: pubip_dict: >- {%- set dict = {} -%} {%- for i in range(ec2.results|length) -%} {%- set _ = dict.update({ec2.results[i].tagged_instances[0].tags.Name: ec2.results[i].tagged_instances[0].public_ip}) -%} {%- endfor -%} {{ dict }} when: aws.ec2_vars is defined - name: wait for ssh wait_for: host: >- {%- set pubip = pubip_dict[item.value.ec2_tags.Name] -%} {{ pubip }} port: 22 ignore_errors: true with_dict: "{{aws.ec2_vars}}"
EC2作成のトップレベルのPlaybookは次の通りとなります。ここまで紹介しましたトップレベルのPlaybookを1つにまとめることも可能で、その場合はVPCの作成からEC2の作成までを一気に行うことが出来ます。
--- - hosts: localhost connection: local gather_facts: False vars: aws: common_region: "ap-northeast-1" common_env: "Prd" vpc_vpc_name_tags: "sample-vpc" ec2_vars: instance1: ec2_key_name: "sample-ec2-key" ec2_ami_name: "RHEL-7.3_HVM_*-GP2" ec2_ami_architecture: "x86_64" ec2_ami_virtualization_type: "hvm" ec2_vpc_subnet_tagname: "bb-subnet-A" ec2_securitygroup_name: - default - fluentd-test ec2_instance_type: "t2.micro" ec2_device_name: /dev/xvda ec2_device_type: gp2 ec2_volume: "10" ec2_public_ip: "yes" ec2_tags: Name: "ec2testhost" Role: "web" roles: - aws_ec2
おわりに
Ansibleを使って様々な環境が操作できること、お分かりいただけましたでしょうか?今回紹介した環境以外にもDockerやAzure、GCP等様々な環境を操作することが出来きます。また日々そのためのモジュールも開発されています。
また、自分でモジュールを作成することも可能なので皆様が作成されたアプリケーションやハードウェアの操作や運用、テスト等を自動化するといった使い方もできるかと思います。日々の業務で使用している物がAnsibleで操作可能か今一度確認してみてはいかがでしょうか?
5回にわたり、お付き合いいただきありがとうございました。本企画は今回で最終回となります。Ansibleがどんなものか、どういった事が出来るようになるのかご理解いただけましたでしょうか?
今後皆様がAnsibleを活用するうえでの一助となれば幸いです。
- BACK
- 1
※Ansibleは、米国Red Hat, Inc. の米国およびその他の国における登録商標もしくは商標です。
その他、本コンテンツ内で利用させて頂いた各プロダクト名やサービス名などは、各社もしくは各団体の商標または登録商標です。