キャンセル
次の結果を表示 
次の代わりに検索 
もしかして: 
cancel
3987
閲覧回数
0
いいね!
0
コメント
takaochan
Cisco Employee
Cisco Employee

■現実的なACIの構成管理における自動化を実現するために

ACIはAPI-Firstで設計されており、Ansibleを用いた構成管理とも非常に相性が良い実装となっています。APICのGUIを通じた操作はバージョンアップに伴い改善が続けられており、最初に構成を実施してみる手段としては適していますが、大量のパラメータを構成管理する手段としては最適とは言えません。特に、繰り返し構成作業が発生する様な事項については、自動化する仕組みを用意することによって、作業工数を削減するとともに、操作ミスなどの発生を抑制することができます。

Ansibleはネットワークエンジニアも親しんでいるYAML形式で構成を定義し、Playbookとして構成を実行することで定義した構成を実現することができます。

Ansible 2.4〜2.9ではACIの管理に利用することができるモジュールが標準で含まれているため、Ansibleを導入するだけでACIの管理に利用することができます。Ansible 2.9では、65を超えるACIモジュールと30を超えるMulti-Site Orchestrator (MSO)モジュールが用意されており、日常的なACIの運用管理において必要とする構成の大半をパラメータの定義だけで非常に簡単に構成できるようになっています。

本ページでは、Ansible自体に対する解説は含めていません。Ansibleウェブサイト等の情報を合わせてご確認下さい。

 

■ Ansibleを通じたACIの構成管理方法

Ansibleを通じたACIの構成管理は、AnsibleからACIモジュールを通じてPythonによるcurlを持ちいたREST API操作となります。以下では、実行先のhostsとして "apic" を指定していますが、実際にはinventoryにおいては以下のようにlocalhostを指定しています。

[apic]
localhost

実際のAPIC IPの指定は、モジュール内の host パラメータで指定します。つまり、AnsibleからAPICに対する処理は、実際にはAnsibleホスト自身で実行されており、その結果としてREST/APIがAPICに対してPOST/GETされます。ネットワークとしてProxyを利用している環境では、APICに対する接続ではProxyを経由しないようno_proxyでAPIC IPを指定して下さい。

 

■Ansible 2.10〜 cisco.aci コレクションとしての提供

Ansible 2.10以降では Ansible 本体の配布ファイル肥大化を防止することやレポジトリとしての管理を分離するために、Collection機能を利用してAnsible本体のレポジトリから基本機能を除く全てのモジュールがコレクションとして分離されました。

ACI用のモジュールについても、cisco.aci コレクションとしてとして分離されたため、Ansible 2.10以降でACIを対象としてAnsibleを利用したい場合には、以下のようにansibleとは別にansible-galaxy コマンドを用いてcisco.aci コレクションの導入が必要となります。

 

pipを用いたAnsible 2.10.3の導入例

(ansible) root@tsmgmt2:~/ansible# pip install ansible
Collecting ansible
  Downloading ansible-2.10.3.tar.gz (28.0 MB)
(中略)
Successfully built ansible ansible-base PyYAML MarkupSafe
Installing collected packages: MarkupSafe, jinja2, PyYAML, six, pycparser, cffi, cryptography, pyparsing, packaging, ansible-base, ansible
Successfully installed MarkupSafe-1.1.1 PyYAML-5.3.1 ansible-2.10.3 ansible-base-2.10.3 cffi-1.14.3 cryptography-3.2.1 jinja2-2.11.2 packaging-20.4 pycparser-2.20 pyparsing-2.4.7 six-1.15.0
(ansible) root@tsmgmt2:~/ansible# ansible --version
ansible 2.10.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /root/.local/share/virtualenvs/ansible--ycPIPLU/lib/python3.9/site-packages/ansible
  executable location = /root/.local/share/virtualenvs/ansible--ycPIPLU/bin/ansible
  python version = 3.9.0 (default, Nov 18 2020, 07:53:34) [GCC 9.3.0]
(ansible) root@tsmgmt2:~/ansible# 
(ansible) root@tsmgmt2:~/ansible# pip freeze
ansible==2.10.3
ansible-base==2.10.3
cffi==1.14.3
cryptography==3.2.1
Jinja2==2.11.2
MarkupSafe==1.1.1
p1==1.0.1
packaging==20.4
pycparser==2.20
pyparsing==2.4.7
PyYAML==5.3.1
RPi.GPIO==0.7.0
six==1.15.0

ansible-galaxyを用いたcisco.aciコレクション1.1.0の導入例

(ansible) root@tsmgmt2:~/ansible# ansible-galaxy collection install cisco.aci
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Installing 'cisco.aci:1.1.0' to '/root/.ansible/collections/ansible_collections/cisco/aci'
Downloading https://galaxy.ansible.com/download/cisco-aci-1.1.0.tar.gz to /root/.ansible/tmp/ansible-local-30990gdisz9rb/tmp8jtzyibt
cisco.aci (1.1.0) was installed successfully

ansible-galaxyを用いたcisco.aciコレクション2.0.0へのアップグレード例

(ansible) root@tsmgmt2:~/ansible# ansible-galaxy collection install cisco.aci -f
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Installing 'cisco.aci:2.0.0' to '/root/.ansible/collections/ansible_collections/cisco/aci'
Downloading https://galaxy.ansible.com/download/cisco-aci-2.0.0.tar.gz to /root/.ansible/tmp/ansible-local-1121264su0xhbff/tmpylan67oc
cisco.aci (2.0.0) was installed successfully
(ansible) root@tsmgmt2:~/ansible# ansible-galaxy collection list

# /root/.ansible/collections/ansible_collections
Collection Version
---------- -------
cisco.aci  2.0.0  

■Ansible利用における認証方式

Ansibleを通じてACIを利用する場合にも認証が必要です。認証方式としてはパスワードを用いる方法と、署名された公開鍵認証を用いる方法が提供されていますが、パスワード認証の方法を利用した場合、大量の処理を一度にAPICに対して実行するとAPICのDoS対策機能によって接続が遮断(HTTP 503 errorが返される)されてしまう可能性があるため、運用環境においてACIの構成管理をAnsibleを用いて利用したい場合には署名方式を用いることが推奨されます。

署名方式を利用するための手順は以下のとおりです。

  1. 鍵の生成(公開鍵・秘密鍵)
  2. APICへの公開鍵の登録

1. 鍵の生成(公開鍵・秘密鍵)

Ansibleノード側でRSA鍵を生成します。

 

opensslコマンドによる生成例 

$ openssl req -new -newkey rsa:2048 -days 36500 -nodes -x509 -keyout admin_ansible.key -out admin_ansible.crt -subj '/CN=Admin/O=Cisco Systems/C=JP'

 

2. APICアカウントへの公開鍵の登録

署名された公開鍵をAPICの管理者権限を持ったアカウントに登録します。登録は様々な方法で実行可能ですが、APIC GUIを通じて行う方法と、Ansible Playbookを用いて行う方法を紹介します。

 

APIC GUIを通じた公開鍵の登録例

(1) APIC GUIにおいて、公開鍵を紐付けるアカウントを選択します([Admin] - [AAA] - [Users])。なお、署名形式の認証を利用できるアカウントはAPICのローカルアカウントに限られます。 2020-05-01 14.46.20.png

 

(2) [User Certificates] 欄において、[+]をクリックし、名前をつけた上で生成した公開鍵を貼り付けます。 2020-05-01 14.46.42.png

 

Ansible Playbookを使った公開鍵の登録例

※このPlaybook自体はパスワード形式での認証が必要です。

※実行ホストとして "apic" を指定していますが、APICに対する操作はAPI経由での実行となるため、実際の実行先はlocalhostです。そのため、自分自身にSSHする必要性はないため、"connection: local"を付加して実行します。

※APICのデフォルトの証明書は自己署名証明書となっているため、"gather_facts: no" を指定しないと接続に失敗します。

---
- name: ACI Sample - aci_aaa_user_certificate
  hosts: apic
  connection: local
  gather_facts: no

  tasks:
  - name: Add Certificate to APIC admin
    cisco.aci.aci_aaa_user_certificate:
      host: apic_url_or_ip
      username: admin
      password: password

      aaa_user: admin
      certificate_name: acihot_ansible
      certificate: "{{ lookup('file', 'admin_ansible.crt') }}"

      validate_certs: no
    delegate_to: localhost
    register: query_result

  - name: debug
    debug:
      var: query_result

ACI Collection 2.0.0から、cisco.aci.aci_aaa_user_certificate のパラメータ "certificate_name" は "name" に変更されました。そのため、上記 1.x 向けのPlaybookを実行すると以下のようにエラーとなります。

(ansible) root@tsmgmt2:~/ansible# ansible-playbook -i inventory.ini acilab-add-user-certificate.yaml 

PLAY [aci_aaa_user_certificate] ******************************************************************************************************************************************************************************************

TASK [Add Certificate to admin of APIC] **********************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "state is present but all of the following are missing: name"}

PLAY RECAP ***************************************************************************************************************************************************************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

cisco.aci コレクション 2.0.0 以降を利用する場合は以下の様に certificate_name を name に書き換える必要があります。

---
- name: ACI Sample - aci_aaa_user_certificate
  hosts: apic
  connection: local
  gather_facts: no

  tasks:
  - name: Add Certificate to APIC admin
    cisco.aci.aci_aaa_user_certificate:
      host: apic_url_or_ip
      username: admin
      password: password

      aaa_user: admin
      name: acihot_ansible
      certificate: "{{ lookup('file', 'admin_ansible.crt') }}"

      validate_certs: no
    delegate_to: localhost
    register: query_result

  - name: debug
    debug:
      var: query_result

 

上記Playbookの実行例

(ansible) root@tsmgmt2:~/ansible# ansible-playbook -i inventory.ini acilab-add-user-certificate.yaml 

PLAY [aci_aaa_user_certificate] ******************************************************************************************************************************************************************************************

TASK [Add Certificate to admin of APIC] **********************************************************************************************************************************************************************************
changed: [localhost]

TASK [debug] *************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "query_result": {
        "changed": true,
        "current": [
            {
                "aaaUserCert": {
                    "attributes": {
                        "annotation": "",
                        "data": "-----BEGIN CERTIFICATE-----(略)-----END CERTIFICATE-----",
                        "descr": "",
                        "dn": "uni/userext/user-admin/usercert-acilab_ansible",
                        "name": "acilab_ansible",
                        "nameAlias": "",
                        "ownerKey": "",
                        "ownerTag": "",
                        "userdom": ":all:common:"
                    }
                }
            }
        ],
        "failed": false,
        "mo": {
            "aaaUserCert": {
                "attributes": {
                    "data": "-----BEGIN CERTIFICATE-----(略)-----END CERTIFICATE-----",
                    "dn": "uni/userext/user-admin/usercert-acilab_ansible",
                    "name": "acilab_ansible"
                }
            }
        }
    }
}

PLAY RECAP ***************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

いずれの方法で登録した場合でも、APICローカルアカウントに正しく公開鍵が紐付けられたことを確認して下さい。 2020-05-01 14.46.59.png

 

Ansibleから署名形式の認証を利用する場合には、実際にREST/API経由でAPICに対して接続する際に鍵の署名をCookieにセットして通信を行います。

 

■Ansibleモジュールを用いたPlaybookサンプル

署名方式の認証を利用し、AnsibleのACIモジュールを使って全てのテナント情報を取得するAnsible Playbookです。各変数については別途Inventoryファイルなどで指定してください。

aci-query-tenant-sample.yaml

---
- name: ACI Tenant Query
  hosts: apic
  connection: local
  gather_facts: no

  tasks:
  - name: Query All Tenants
    cisco.aci.aci_tenant:
      host:"{{ apic_address }}"
      username:"{{ apic_username }}"
      certificate_name:"{{ apic_aaa_certificate }}"
      private_key:"{{ apic_aaa_private_key }}"
      state: query
      output_level: debug
      validate_certs: no
    delegate_to: localhost
    register: query_result
  
  - name: debug
    debug:
      var: query_result

cisco.aci コレクション 1.1.0 以降では、Playbookの中で環境変数を定義することによってタスク毎に認証情報を指定する必要性がなくなり、より簡潔でわかりやすいPlaybookを書くことが可能となりました。環境変数を利用することのメリットは、もちろんタスクの項目数を減らせることですが、モジュール側に指定があればそれを優先して利用しますので汎用性と厳密性を両立させられそうです。

 

以下が環境変数名とオプションの対比表となります。

項目 環境変数名 モジュールオプション 補足
ホスト名 ACI_HOST host  
ポート ACI_PORT port  
ユーザ名 ACI_USERNAME username  
パスワード ACI_PASSWORD password パスワード認証時のみ
証明書名 ACI_CERTIFICATE_NAME certificate_name (〜1.x.x)
name (2.0.0〜)
鍵認証時のみ
秘密鍵ファイル名 ACI_PRIVATE_KEY private_key 鍵認証時のみ
接続時の証明書の検証有無 ACI_VALIDATE_CERTS validate_certs  
SSL/TLS利用 ACI_USE_SSL use_ssl  
プロキシ利用 ACI_USE_PROXY use_proxy  
タイムアウト ACI_TIMEOUT timeout  

 

環境変数を利用して上記Playbookを書き直すと、以下の通りとなります。得られる結果は同一です。

 

---
- name: ACI Tenant Query
  hosts: apic
  connection: local
  gather_facts: no

  environment:
    ACI_HOST: "{{ apic_address }}"
    ACI_USERNAME: "{{ apic_username }}"
    ACI_CERTIFICATE_NAME: "{{ apic_aaa_certificate }}"
    ACI_PRIVATE_KEY:"{{ apic_aaa_private_key }}"
    ACI_VALIDATE_CERTS: no

  tasks:
  - name: Query All Tenants
    cisco.aci.aci_tenant:
      state: query
      output_level: debug
    delegate_to: localhost
    register: query_result
  
  - name: debug
    debug:
      var: query_result

上記ではDebugを含めているので行数が増えてしまっていますが、タスク内のモジュールでは必要最小限のパラメータのみを指定すれば良くなるため、格段にPlaybookが簡潔となり解りやすくなります。 

■aci_restモジュールを用いたPlaybookサンプル

ACIの運用管理において必要となる大半の操作対象に紐づくモジュールが提供されていますが、ACIモジュールが全てのパラメータの構成をサポートしてないケースや、そもそもACIモジュールが用意されていない項目も多く存在します。そうした場合には、aci_restモジュールを使用することで、AnsibleからAPICに対するあらゆるパラメータの構成管理を行うことが可能です。

ただし、冪等性の確保が通常のモジュールを利用する場合と比較して制限されるため、aci_restモジュールの利用は可能な限り最小限とすることを推奨します。

 

L3outをACIモジュールを使って構成し、OSPF基本パラメータの定義をaci_restモジュールを使って行う例

 

---
- name: ACILAB - L3out
  hosts: apic
  connection: local
  gather_facts: no

  tasks:

  - name: Create new L3out
    cisco.aci.aci_l3out:
      host: "{{ apic_address }}"
      username: "{{ apic_username }}"
      certificate_name: "{{ apic_aaa_certificate }}"
      private_key: acihot_ansible.key
      state: present
      tenant: "{{ tenant_name }}"
      vrf: "{{ vrf_name }}"
      name: "{{ l3out_name }}"
      domain: "{{ l3out_domain }}"
      l3protocol: ospf
      route_control: export
      validate_certs: no
    delegate_to: localhost

  - name: Modify L3out OSPF parameters
    cisco.aci.aci_rest:
      host: "{{ apic_address }}"
      username: "{{ apic_username }}"
      certificate_name: "{{ apic_aaa_certificate }}"
      private_key: acihot_ansible.key
      method: post
      path: "/api/node/mo/uni/tn-{{ tenant_name }}/out-{{ l3out_name }}/ospfExtP.json"
      content:
        {
          "ospfExtP": {
            "attributes": {
              "dn": "uni/tn-{{ tenant_name }}/out-{{ l3out_name }}/ospfExtP",
              "areaId": "0",
              "areaType": "regular"
            },
            "children": []
          }
        }
      validate_certs: no
    delegate_to: localhost

 

上記例では、ACI L3out自体は "aci_l3out" モジュールを使って構成していますが、aci_l3out モジュールでは 2020/04時点では使用するルーティングプロトコルの指定(この例では "ospf")は出来ても、そのパラメータとして Area ID や Area Type の指定ができないため、その範囲を "aci_rest" モジュールを使って構成しています。

 

パラメータとして利用する path や content の構造については、APIC GUI に用意されている API Inspector を利用することによってGUI操作を通じて簡単に確認することが可能です。他のパラメータと同様に、これらの構文の一部に変数を利用することが可能ですので、これによって汎用性を確保することができます。

 

上記 aci_rest 作成のためにAPIC GUI で実行した操作を API Inspector で取得した例

timestamp: 12:03:15 DEBUG 
method: POST
url: https://apic_url/api/node/mo/uni/tn-Tenant10/out-L3out_OSPF/ospfExtP.json
payload{"ospfExtP":{"attributes":{"dn":"uni/tn-Tenant10/out-L3out_OSPF/ospfExtP","areaId":"0","areaType":"regular","status":"created"},"children":[]}}
response: {"totalCount":"0","imdata":[]}

 

API Inspector の使用方法については、ACI How To - API Inspectorの活用 等を参照してください。

 

■参考情報

ACIとAnsibleを組合せた構成管理の詳細については、Cisco DevNet, Ansible Documentサイトなどを参照して下さい。 

 また、Cisco Liveセッションでも以下のセッションにおいて ACI と Ansible を組み合わせた運用管理ついて扱っています。

  • BRKACI-1619 Automating ACI with Ansible
  • DEVNET-1797 Introduction to Automating ACI with Ansible

Cisco Liveで行われた ACI のAPI活用に関するハンズオンのガイドが公開されており、Internet経由で参照可能となっていますが、こちらのBonus ContentsとしてAnsible連携についても解説されています。 
LTRACI-3225 ハンズオンガイド

以下に有益な情報が公開されています。

 

 

Getting Started

検索バーにキーワード、フレーズ、または質問を入力し、お探しのものを見つけましょう

シスコ コミュニティをいち早く使いこなしていただけるよう役立つリンクをまとめました。みなさんのジャーニーがより良いものとなるようお手伝いします