LoginSignup
6
3

More than 3 years have passed since last update.

Cisco NFVISをAnsibleから操作する

Last updated at Posted at 2019-12-09

はじめに

従来のエンタープライズ向けネットワークでは、ルータやファイアウォール等の機能毎に専用のハードウェアを用意して導入していました。一方ここ数年、身近でもNFV(Network Functions Virtualization)を利用してネットワーク機能を仮想化し、汎用デバイス上に構築するケースが少しずつ増えてきました。

Ciscoが提供するエンタープライズNFVを例にとると、NFVは以下のコンポートから構成されます。
(加えて、これらを管理するコントローラもあり。)

今回の記事でご紹介するCisco NFVISは、ハイパーバイザーとしての機能に加え、REST-APIを通じた仮想サービスの制御やゼロタッチ展開(PnP)機能も提供されています。

詳細は、Cisco DevNet Lerning Labsの以下セッションで分かりやすく説明されています。
NFVIS API を使用したネットワーク機能の仮想化の紹介
このセッションでは、後述するCisco dCloud環境上で、VNFのデプロイ・情報取得・削除をGUIやREST-API(Postman、Python)経由で行うハンズオンが体験できます。

本記事は、同様の内容をAnsibleのuriモジュールで行った時のメモになります。

~その他参考URL~

2. 用意した環境

以下のCisco dCloud環境を利用させて頂きました。
Cisco DevNet Express Cisco DNA Sandbox v3.0a
無題1208_12.png

dCloud接続方法の詳細は割愛しますが、以下の流れでセットアップしています。

  1. Cisco AnyConnectを使って、自分のPCからVPN経由で図中のcentos(DevBox)へリモートデスクトップ接続。
  2. DevBoxにインストールされていたPython3.6.5を使ってvenv仮想環境を構築し、その上でAnsible2.9.2をインストール。
  3. DevBoxからNFVISへWebアクセス or Ansible経由でREST-APIコール。

これ以降で、Ansible Inventory/Playbookの内容と実行結果をご紹介します。

3. Inventoryファイル

NFVISへのHTTPSアクセスに必要な情報を記載します。

inventory_nfvis.ini
[cisco]
nfvis ansible_host=[NFVISのIPアドレス] ansible_port=443

[cisco:vars]
username=[NFVISのユーザ名]
password=[NFVISのパスワード]

4. VNFのデプロイ

まずは、仮想ルータISRvのデプロイを行ってみます。

4-1. Ansible Playbook

内容は以下の通りです。

  • POSTメソッドで、Body内にISRvのデプロイ情報を定義。パラメーターはLearning Labsをそのまま流用。今回はYAML形式の変数body_dataを、フィルタープラグイン"{{ body_data | to_json }}"でJSON形式で変換し、Bodyに格納。(JSONファイルをlookupプラグイン"{{ lookup('file', 'body_data.json') }}"で読み込んでもOK。)
  • Basic認証を使用し、APIコール毎にユーザ名/パスワードを指定。
  • uriモジュールは、デフォルトでStatus Code200 (OK)をSuccessとするが、今回は201 (Created)が返ってくるため、明示的に201を指定。
playbook_nfvis_post.yml
---

- hosts: cisco
  gather_facts: no
  connection: local
  vars:
    body_data:
      deployment:
        name: "ISRv"
        vm_group:
          name: "ROUTER"
          image: "isrv-universalk9.16.06.02.tar.gz"
          flavor: "ISRv-small"
          bootup_time: 600
          recovery_wait_time: 0
          interfaces:
            interface:
              - nicid: 0
                network: "int-mgmt-net"
              - nicid: 1
                network: "wan-net"
              - nicid: 2
                network: "lan-net"
          kpi_data:
            kpi:
              event_name: "VM_ALIVE"
              metric_value: "1"
              metric_cond: "GT"
              metric_type: "UINT32"
              metric_collector:
                type: "ICMPPing"
                nicid: 0
                poll_frequency: 3
                polling_unit: "seconds"
                continuous_alarm: false
          rules: 
            admin_rules:
              rule:
                event_name: "VM_ALIVE"
                action:
                  - "ALWAYS log"
                  - "FALSE recover autohealing"
                  - "TRUE servicebooted.sh"
          config_data:
            configuration:
              dst: "bootstrap_config"
              variable:
                - name: "TECH_PACKAGE"
                  val: "ax"

  tasks:
    - name: Deploy ISRv
      uri:
        url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments
        method: POST
        headers:
          Content-Type: application/vnd.yang.data+json
          Accept: application/vnd.yang.data+json
        body_format: json
        body: "{{ body_data | to_json }}"
#        body: "{{ lookup('file', 'body_data.json') }}"
        status_code:
          - 201
        url_username: "{{ username }}"
        url_password: "{{ password }}"
        force_basic_auth: yes
        validate_certs: no
      ignore_errors: yes

4-2. Playbook実行ログ

特にエラーなく終了しました。

$ ansible-playbook -i inventory_nfvis.ini playbook_nfvis_post.yml 

PLAY [cisco] *************************************************************************************************

TASK [Deploy ISRv] *******************************************************************************************
ok: [nfvis]

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

4-3. GUI画面

ここでNFVISのGUI画面を見ると、Active状態のVNFが1つ表示され、ネットワークwan-netlan-netに論理接続されていました。

無題1208_11.png
無題1208_15.png

5. ステータス情報の取得

続いて、各種ステータス情報をGETメソッドで取得してみます。

5-1. Ansible Playbook

各タスクの内容は以下の通りです。

  1. イメージ情報を取得。Status Codeは200 (OK)に加え、情報がない場合204 (No Content)が返ってくる可能性があるため、2つをSuccess対象に指定。
  2. タスク1で取得した情報を表示。
  3. 起動中のVNF情報を取得。
  4. タスク3で取得した情報を表示。
  5. 起動中のVNF情報詳細を取得。
  6. タスク5で取得した情報を表示。
playbook_nfvis_get.yml
---

- hosts: cisco
  gather_facts: no
  connection: local

  tasks:
    - name: Get images   # (1)
      uri:
        url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/images
        method: GET
        headers:
          Content-Type: application/vnd.yang.data+json
          Accept: application/vnd.yang.data+json
        status_code:
          - 200
          - 204
        url_username: "{{ username }}"
        url_password: "{{ password }}"
        force_basic_auth: yes
        validate_certs: no
      register: result_images

    - name: Display images   # (2)
      debug:
        msg: "{{ result_images.json | default('None') }}"
      when: result_images.json is defined

    - name: Get running VNFs   # (3)
      uri:
        url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments
        method: GET
        headers:
          Content-Type: application/vnd.yang.data+json
          Accept: application/vnd.yang.data+json
        status_code:
          - 200
          - 204
        url_username: "{{ username }}"
        url_password: "{{ password }}"
        force_basic_auth: yes
        validate_certs: no
      register: result_vnfs

    - name: Display running VNFs   # (4)
      debug:
        msg: "{{ result_vnfs.json | default('None') }}"

    - name: Get running VNFs (detail)   # (5)
      uri:
        url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments?deep
        method: GET
        headers:
          Content-Type: application/vnd.yang.data+json
          Accept: application/vnd.yang.data+json
        status_code:
          - 200
          - 204
        url_username: "{{ username }}"
        url_password: "{{ password }}"
        force_basic_auth: yes
        validate_certs: no
      register: result_vnfs_detail

    - name: Display running VNFs   # (6)
      debug:
        msg: "{{ result_vnfs_detail.json | default('None') }}"

5-2. Playbook実行ログ

タスク2で、dCloud環境に元々存在しているASAvとISRvのイメージが表示されました。続いて、タスク4でVNFISRv、タスク6でその詳細情報が表示されてる事が分かります。

$ ansible-playbook -i inventory_nfvis.ini playbook_nfvis_get.yml 

PLAY [cisco] *************************************************************************************************

TASK [Get images] ********************************************************************************************
ok: [nfvis]

TASK [Display images] ****************************************************************************************
ok: [nfvis] => {
    "msg": {
        "vmlc:images": {
            "image": [
                {
                    "name": "asav961.tar.gz"
                },
                {
                    "name": "isrv-universalk9.16.06.02.tar.gz"
                }
            ]
        }
    }
}

TASK [Get running VNFs] **************************************************************************************
ok: [nfvis]

TASK [Display running VNFs] **********************************************************************************
ok: [nfvis] => {
    "msg": {
        "vmlc:deployments": {
            "deployment": [
                {
                    "name": "ISRv"
                }
            ]
        }
    }
}

TASK [Get running VNFs (detail)] *****************************************************************************
ok: [nfvis]

TASK [Display running VNFs] **********************************************************************************
ok: [nfvis] => {
    "msg": {
        "vmlc:deployments": {
            "deployment": [
                {
                    "name": "ISRv",
                    "vm_group": [
                        {
                            "bootup_time": 600,
                            "config_data": {
                                "configuration": [
                                    {
                                        "dst": "bootstrap_config",
                                        "variable": [
                                            {
                                                "name": "TECH_PACKAGE",
                                                "val": [
                                                    "ax"
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            },
                            "flavor": "ISRv-small",
                            "image": "isrv-universalk9.16.06.02.tar.gz",
                            "interfaces": {
                                "interface": [
                                    {
                                        "network": "int-mgmt-net",
                                        "nicid": 0
                                    },
                                    {
                                        "network": "wan-net",
                                        "nicid": 1
                                    },
                                    {
                                        "network": "lan-net",
                                        "nicid": 2
                                    }
                                ]
                            },
                            "kpi_data": {
                                "kpi": [
                                    {
                                        "event_name": "VM_ALIVE",
                                        "metric_collector": {
                                            "continuous_alarm": false,
                                            "nicid": 0,
                                            "poll_frequency": 3,
                                            "polling_unit": "seconds",
                                            "type": "ICMPPing"
                                        },
                                        "metric_cond": "GT",
                                        "metric_type": "UINT32",
                                        "metric_value": "1"
                                    }
                                ]
                            },
                            "name": "ROUTER",
                            "recovery_wait_time": 0,
                            "rules": {
                                "admin_rules": {
                                    "rule": [
                                        {
                                            "action": [
                                                "ALWAYS log",
                                                "FALSE recover autohealing",
                                                "TRUE servicebooted.sh"
                                            ],
                                            "event_name": "VM_ALIVE"
                                        }
                                    ]
                                }
                            }
                        }
                    ]
                }
            ]
        }
    }
}

PLAY RECAP ***************************************************************************************************
nfvis                      : ok=6    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

6. VNFの削除

最後に、作成したVNFをすべて削除してみます。

6-1. Ansible Playbook

各タスクの内容は以下の通りです。

  1. (事前)起動中のVNF情報を取得。
  2. (事前)タスク1で取得した情報を表示。
    ↓ これ以降はblockwhenを用いて、VNFが1つでもデプロイされている場合のみ実施。
  3. 起動中のVNF名一覧を変数running_vnfsに格納。
  4. loopを用いて、各VNFをDELETEメソッドで1つずつ削除。
  5. (事後)起動中のVNF情報を取得。
  6. (事後)タスク5で取得した情報を表示。
playbook_nfvis_delete.yml
---

- hosts: cisco
  gather_facts: no
  connection: local

  tasks:
    - name: Get running VNFs (before)   # (1)
      uri:
        url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments
        method: GET
        headers:
          Content-Type: application/vnd.yang.data+json
          Accept: application/vnd.yang.data+json
        status_code:
          - 200
          - 204
        url_username: "{{ username }}"
        url_password: "{{ password }}"
        force_basic_auth: yes
        validate_certs: no
      register: result_vnfs_before

    - name: Display running VNFs (before)   # (2)
      debug:
        msg: "{{ result_vnfs_before.json | default('None') }}"

    - block:
      - name: Set running VNFs   # (3)
        set_fact:
          running_vnfs: "{{ result_vnfs_before.json['vmlc:deployments']['deployment'] }}"

      - name: Delete running VNFs   # (4)
        uri:
          url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments/deployment/{{item.name}}
          method: DELETE
          headers:
            Content-Type: application/vnd.yang.data+json
            Accept: application/vnd.yang.data+json
          status_code:
            - 200
            - 204
          url_username: "{{ username }}"
          url_password: "{{ password }}"
          force_basic_auth: yes
          validate_certs: no
        loop: "{{ running_vnfs }}"

      - name: Get running VNFs (after)   # (5)
        uri:
          url: https://{{ansible_host}}:{{ansible_port}}/api/config/vm_lifecycle/tenants/tenant/admin/deployments
          method: GET
          headers:
            Content-Type: application/vnd.yang.data+json
            Accept: application/vnd.yang.data+json
          status_code:
            - 200
            - 204
          url_username: "{{ username }}"
          url_password: "{{ password }}"
          force_basic_auth: yes
          validate_certs: no
        register: result_vnfs_after

      - name: Display running VNFs (after)   # (6)
        debug:
          msg: "{{ result_vnfs_after.json | default('None') }}"
      when: result_vnfs_before.json is defined

6-2. Playbook実行ログ

タスク2で表示されていたVNFISRvが、タスク6で消えている事が分かります。

$ ansible-playbook -i inventory_nfvis.ini playbook_nfvis_delete.yml

PLAY [cisco] *************************************************************************************************

TASK [Get running VNFs (before)] *****************************************************************************
ok: [nfvis]

TASK [Display running VNFs (before)] *************************************************************************
ok: [nfvis] => {
    "msg": {
        "vmlc:deployments": {
            "deployment": [
                {
                    "name": "ISRv"
                }
            ]
        }
    }
}

TASK [Set running VNFs] **************************************************************************************
ok: [nfvis]

TASK [Delete running VNFs] ***********************************************************************************
ok: [nfvis] => (item={'name': 'ISRv'})

TASK [Get running VNFs (after)] ******************************************************************************
ok: [nfvis]

TASK [Display running VNFs (after)] **************************************************************************
ok: [nfvis] => {
    "msg": "None"
}

PLAY RECAP ***************************************************************************************************
nfvis                      : ok=6    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

6-3. GUI画面

NFVISのGUI画面でも、該当のVNFが削除されました。

無題1208_14.png

最後に

今回は汎用モジュールuri使いましたが、Cisco DevNetでansible-nvfisnfvis-opsも開発されているようです。Playbookもよりシンプルになりそうですので、実運用する場合はこちらも検討したいと思います。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3