実行時間を約90%削減する Ansible パフォーマンスチューニング 基礎

by manabu.a.sato | August 04, 2020
infrastructure | #infrastructure #ansible

はじめに

IT 基盤部の佐藤です。
社内システムのインフラを担当しています。

前回は、Ansible で始める Linux 管理と題しまして、構成管理ツールの Ansible について、基本的な特徴と簡単なサンプルを紹介いたしました。 Ansible のパフォーマンスチューニングは、デプロイする対象(ネットワーク機器、仮想化ソフトウェア)によって様々な方法がありますが、今回は次の2つの観点でのパフォーマンスチューニングの方法を簡単にご紹介したいと思います。

  • タスク並列実行
  • 情報量の削減( Dyanmic Inventory)

Dyanmic Inventory とは、構成管理の対象となるサーバを動的に取得する機能です。
詳細は Ansible のマニュアル「Working with dynamic inventory 」を参照してください。

Ansible の環境情報

パフォーマンスチューニングを行うための環境情報について記載します。

前提条件

  • Ansible 2.9.11 がインストールされていること
  • Ansible を実行するサーバから構成管理の対象に、公開鍵認証で SSH 接続できていること
  • 構成管理の対象となる仮想サーバ
    • EC2: 20台
      • OS: Red Hat Enterprise Linux 8

ディレクトリ 構成

├── hosts
│   ├── ec2.ini
│   ├── ec2.py
│   └── group_vars
│       └── tag_server_rhel.yml
├── playbook.yml
└── ansible.cfg

ファイルの概要

下記のファイルを用意して、Ansible を実行します。

  • ec2.ini: Dynamic Inventory の設定ファイル
  • ec2.py: Dynamic Inventory の実行ファイル
  • tag_server_rhel.yml: Red Hat Enterprise Linux のデプロイを行う場合に使用する変数
  • playbook.yml: 構成管理する内容を記載する
    • Red Hat Enterprise Linux 8
      • SELinux を無効化する
      • SELinux を無効化して、OS の再起動が必要な場合、OS を再起動する
  • ansible.cfg: Ansible の設定ファイル

ファイルの設定値

ec2.ini

  ec2.ini をダウンロードして、hosts ディレクトリの配下に格納します。

ec2.py

  ec2.py をダウンロードします。hosts ディレクトリの配下に格納します。

tag_server_rhel.yml

---
# SSH setting
ansible_user: ec2-user

playbook.yml

---
- name: Red Hat Enterprise Linux 8 - Base Setting
  hosts: all
  gather_facts: true
  become: true
  tasks:
    - name: Disable SELinux
      selinux:
        state: disabled
      register: result
      when: ansible_distribution == 'RedHat'
    - name: Disable SELinux - Reboot
      reboot:
      when: ansible_distribution == 'RedHat' and result is defined and result.reboot_required

ansible.cfg

[defaults]

Ansible 実行コマンド

パフォーマンスチューニングの時間測定するために、ansible-playbook コマンドを実行しました。

$ ansible-playbook -i hosts/ playbook.yml

パフォーマンスチューニング - タスク並列実行

パフォーマンスチューニングの結果

パフォーマンスチューニングを実施した結果、Playbook の実行時間を短縮することができました。それでは、パフォーマンスチューニングとして、どのような対策を行ったのか説明します。

時間差 削減率
2分34秒 1分14秒 1分20秒 50%

列 “無” と “有” は、パフォーマンスチューニングが有り、無しの実行時間です。

パフォーマンスチューニングの実施

パフォーマンスチューニング前後の ansible.cfg の内容を記載します。

  • パフォーマンスチューニング無し

    [defaults]
    
  • パフォーマンスチューニング有り

    [defaults]
    forks = 20
    

パフォーマンスチューニングポイント

パフォーマンスチューニングを実施していない場合について説明します。
デプロイ対象が20台ですが、タスクの並列度はデフォルトの5でした。この状態で、Playbook を実行すると、5台ずつタスクを実行するため、タスクに待ち時間が発生します。そのため、Playbook の実行時間が長くなります。

この状況を改善するために、ansible.cfg の並列度を設定する forks というパラメータの値を20に設定しました。この状態でタスクを実行すると、20台すべてが並列で実行されるため、Playbook の実行時間を短縮することができました。

パフォーマンスチューニング - 情報量の削減

パフォーマンスチューニングの結果

並列化に続き、2つ目のパフォーマンスチューニングを実施した結果、Playbook の実行時間を短縮することができました。それでは、パフォーマンスチューニングとして、どのような対策を行ったのか説明します。

時間差 削減率
1分14秒 14秒 1分 81%

列 “無” と “有” は、パフォーマンスチューニングが有り、無しの実行時間です。

パフォーマンスチューニングの実施

パフォーマンスチューニング前後の ec2.ini の内容を記載します。

  • パフォーマンスチューニング無し

    [ec2]
    regions = all
    regions_exclude = us-gov-west-1, cn-north-1
    destination_variable = public_dns_name
    vpc_destination_variable = ip_address
    route53 = False
    all_instances = False
    all_rds_instances = False
    include_rds_clusters = False
    all_elasticache_replication_groups = False
    all_elasticache_clusters = False
    all_elasticache_nodes = False
    cache_path = ~/.ansible/tmp
    cache_max_age = 300
    nested_groups = False
    replace_dash_in_groups = True
    expand_csv_tags = False
    group_by_instance_id = True
    group_by_region = True
    group_by_availability_zone = True
    group_by_aws_account = False
    group_by_ami_id = True
    group_by_instance_type = True
    group_by_instance_state = False
    group_by_platform = True
    group_by_key_pair = True
    group_by_vpc_id = True
    group_by_security_group = True
    group_by_tag_keys = True
    group_by_tag_none = True
    group_by_route53_names = True
    group_by_rds_engine = True
    group_by_rds_parameter_group = True
    group_by_elasticache_engine = True
    group_by_elasticache_cluster = True
    group_by_elasticache_parameter_group = True
    group_by_elasticache_replication_group = True
    stack_filters = False
    [credentials]
    
  • パフォーマンスチューニング有り

    [ec2]
    regions = ap-northeast-1
    regions_exclude = us-gov-west-1, cn-north-1
    destination_variable = public_dns_name
    vpc_destination_variable = ip_address
    route53 = False
    all_instances = False
    all_rds_instances = False
    include_rds_clusters = False
    all_elasticache_replication_groups = False
    all_elasticache_clusters = False
    all_elasticache_nodes = False
    cache_path = ~/.ansible/tmp
    cache_max_age = 0
    nested_groups = False
    replace_dash_in_groups = True
    expand_csv_tags = False
    group_by_instance_id = False
    group_by_region = False
    group_by_availability_zone = False
    group_by_aws_account = False
    group_by_ami_id = False
    group_by_instance_type = False
    group_by_instance_state = False
    group_by_platform = False
    group_by_key_pair = False
    group_by_vpc_id = False
    group_by_security_group = False
    group_by_tag_keys = True
    group_by_tag_none = False
    group_by_route53_names = False
    group_by_rds_engine = False
    group_by_rds_parameter_group = False
    group_by_elasticache_engine = False
    group_by_elasticache_cluster = False
    group_by_elasticache_parameter_group = False
    group_by_elasticache_replication_group = False
    stack_filters = False
    [credentials]
    

パフォーマンスチューニングポイント

今回、EC2 のインスタンス情報を動的に取得する Dynamic Inventory の設定を変更しました。Dynamic Inventory は、デフォルトで全リージョン、数多くの AWS リソースの情報を取得することができます。ただ、全リージョン、多数の AWS リソースの情報を取得すると、非常に時間がかかります。今回は、EC2 の IP アドレスが取得できれば Playbook を実行できます。そのため、Dyanmic Inventory の設定ファイル ec2.ini を編集しました。

ec2.ini の変更点を一覧化して、どのような設定変更を行ったのか解説します。

項目名 変更理由
regions all ap-northeast-1 *1
cache_max_age 300 0 *2
group_by_instance_id True False *3
group_by_region True False *3
group_by_availability_zone True False *3
group_by_ami_id True False *3
group_by_instance_type True False *3
group_by_platform True False *3
group_by_key_pair True False *3
group_by_vpc_id True False *3
group_by_security_group True False *3
group_by_tag_none True False *3
group_by_route53_names True False *3
group_by_rds_engine True False *3
group_by_rds_parameter_group True False *3
group_by_elasticache_engine True False *3
group_by_elasticache_cluster True False *3
group_by_elasticache_parameter_group True False *3
group_by_elasticache_replication_group True False *3

一覧の列 “無” と “有” は、パフォーマンスチューニングが有り、無しの設定値です。

下記にパフォーマンスチューニングを実施するにあたり、変更した設定値を解説します。
*1 採集先を全リージョンから東京リージョンに変更することで、採集にかかる時間を大幅に減らすため
*2 Dynamic Inventory のキャッシュを無効にして、常に最新の情報を取得する
*3 多数の AWS リソースの情報を取得すると非常に時間がかかるが、EC2 の IP アドレスが取得できれば Playbook を実行できる。EC2 の IPアドレスのみ取得して時間を減らすため。

このように、Dyanmic Inventory の設定値を変えることで、実行時間を大幅に短縮することができました。 Dynamic Inventory を使用して、パフォーマンスが出ないと悩まれている方は、AWS リソース情報を絞り込んでみてください。

まとめ

今回は、Ansible のパフォーマンスチューニングについて、非常に簡単ではありますがご紹介しました。 二つのパフォーマンスチューニングを行った結果、実行時間の90%削減することができました。 パフォーマンスチューニングを行うことで、Playbook の待ち時間を減らすことができるため、工数の削減に繋がります。

時間差 削減率
2分34秒 14秒 2分20秒 90%

Playbook でデプロイする対象に合わせて、パフォーマンスチューニングが出来るポイントがないか確認しておくことをオススメします。今回とは異なるデプロイ対象のパフォーマンスチューニングについては、機会がありましたら記事にさせていただきます。

この機会に Ansible に触れていただけると幸いです。