自動化を実際に動かすための3つの技術要素

前の記事「ネットワーク自動化とコントローラベースネットワーキング」では、コントローラがノースバウンドAPIを通じて上位の自動化プログラムとやり取りすることを説明しました。本記事では、その具体的な中身にあたる3つの技術要素、REST API(コントローラと通信する方法)・JSON(やり取りするデータの形式)・設定管理メカニズム(Ansible等、実際に設定を配布するツール)を扱います。

REST APIとは

REST(Representational State Transfer)は、Webシステムでよく使われるAPI(Application Programming Interface)の設計方式の1つです。この設計方式に従って作られたAPIをREST API(RESTfulなAPIとも呼ばれます)と呼びます。ネットワークのコントローラ製品(Cisco Catalyst Center、旧Cisco DNA Center等)の多くも、ノースバウンドAPIとしてREST APIを提供しています。

REST APIの主な特性

  • リソースをURIで表す:操作の対象となるもの(デバイス一覧、インターフェイス情報など)を「リソース」と呼び、それぞれに一意なURI(URL)が割り当てられます。例えばhttps://controller.example.com/api/v1/network-deviceのようなURLが「ネットワーク機器一覧」というリソースを表す、という考え方です。
  • 統一されたインターフェイス(HTTPメソッド):リソースに対する操作は、HTTPが元々持っている決まった種類のメソッド(動詞)を使って表現します。同じURIでも、どのメソッドを使うかによって操作の意味が変わります。
  • ステートレス(stateless):サーバー側は、リクエストとリクエストの間でクライアントの状態(前回何をしたか等)を保持しません。各リクエストは、それ単体で処理に必要な情報をすべて含んでいる必要がありますこのステートレス性により、サーバー側の実装がシンプルになり、負荷分散(複数のサーバーでリクエストを分担すること)もしやすくなるという利点があります。[1]。
  • クライアント/サーバーモデル:リクエストを送る側(クライアント、自動化プログラム等)と、処理する側(サーバー、コントローラ等)の役割が明確に分離されています。

代表的なHTTPメソッド

メソッド主な意味
GETリソースの情報を取得する(読み取りのみ、対象を変更しない)
POST新しいリソースを作成する
PUT指定したリソースの内容を、送信した内容で丸ごと置き換える
PATCH指定したリソースの一部分だけを更新する
DELETE指定したリソースを削除する

HTTPステータスコード

REST APIのレスポンスには、処理結果を表すHTTPステータスコード(3桁の数値)が含まれます。先頭の桁によって、おおまかな意味が決まっています。

  • 2xx(成功):リクエストが正常に処理されたことを示します(例:200 OK=成功、201 Created=新規作成成功)。
  • 4xx(クライアント側のエラー):リクエストの内容に問題があったことを示します(例:400 Bad Request=リクエスト内容の誤り、401 Unauthorized=認証情報が無い・誤っている、404 Not Found=指定したリソースが存在しない)。
  • 5xx(サーバー側のエラー):サーバー側で処理中に問題が発生したことを示します(例:500 Internal Server Error)。

自動化プログラムを書く際は、レスポンスの中身(本文)だけでなく、このステータスコードを確認して、リクエストが正常に処理されたかどうかを判定するのが基本です。

JSONエンコードされたデータ

REST APIのリクエスト・レスポンスでやり取りされるデータの形式として、現在最もよく使われているのがJSON(JavaScript Object Notation)です。名前に「JavaScript」と付いていますが、特定のプログラミング言語に依存しない、汎用的なテキストベースのデータ形式です。

JSONの基本構文

JSONは、次のような要素の組み合わせで構成されます。

  • オブジェクト(object):波括弧{ }で囲み、"キー": 値という組(ペア)をカンマ区切りで並べたものです。
  • 配列(array):角括弧[ ]で囲み、複数の値をカンマ区切りで並べたものです。
  • 値(value)として使える型:文字列(ダブルクォートで囲む)、数値、真偽値(true/false)、null(値が無いことを表す)、そしてオブジェクトや配列自身(入れ子にできます)。

ネットワーク機器のインターフェイス情報をJSONで表現した例を示します。

{
  "hostname": "SW1",
  "interfaces": [
    {
      "name": "GigabitEthernet0/1",
      "status": "up",
      "vlan": 10,
      "trunk": false
    },
    {
      "name": "GigabitEthernet0/2",
      "status": "down",
      "vlan": null,
      "trunk": true
    }
  ]
}

この例では、hostname(文字列)とinterfaces(配列)というキーを持つオブジェクトが最上位にあり、interfaces配列の中に、各インターフェイスの情報を表すオブジェクトがさらに入れ子になっています。vlanの値には数値(10)のほか、該当するVLANが無いことを表すnullも使われています。このように、JSONはキーと値の組み合わせを入れ子にすることで、階層構造を持つデータを表現できます。

他のデータ形式との違い(概要)

XML(Extensible Markup Language)も同様に構造化データを表現できる形式ですが、開始タグ・終了タグを使う分、記述が冗長になりがちです。JSONは記号({ }・[ ]・,・:)が少なく簡潔なため、REST APIのデータ形式として広く採用されています本記事シリーズで扱う設定管理ツールのうち、Ansibleのプレイブックの記述にはJSONではなくYAML(YAML Ain't Markup Language)という別の形式が使われます。YAMLはインデント(字下げ)で階層構造を表す、人間にとってさらに読みやすいことを重視した形式です。JSONとYAMLは相互に変換可能な情報を表現でき、実際に多くのツールが両方の形式を読み書きできます。YAMLの詳しい構文自体はCCNA 200-301の出題範囲外のため、本記事では立ち入りません。[2]。

設定管理メカニズム

設定管理(configuration management)ツールは、多数の機器(サーバー・ネットワーク機器等)に対して、あるべき設定状態を定義しておき、その状態を自動的に適用するためのソフトウェアです。ツールによっては、その状態を継続的に監視・維持します。CCNA 200-301の出題範囲は試験バージョンにより異なります。旧v1.0では代表例としてAnsible・Puppet・Chefが挙げられており、現行v1.1ではAnsible・Terraformが例示されています。

エージェント方式とエージェントレス方式

  • エージェント方式(agent-based):管理対象の各機器に、専用の常駐プログラム(エージェント)を事前にインストールしておく方式です。
  • エージェントレス方式(agentless):管理対象の機器に専用プログラムを追加でインストールする必要が無い方式です。既存の仕組み(SSH等)を使って設定を配布します。

プッシュ型とプル型

  • プッシュ型(push):管理する側(サーバー・管理ステーション)が、対象の機器へ能動的に設定を送り込む方式です。
  • プル型(pull):管理される側(各機器のエージェント)が、一定間隔で自発的に中央のサーバーへ最新の設定を取りに行く方式です。

4つのツールの比較

ツールエージェント方式通信方式設定の記述形式中央サーバーの名称
Ansibleエージェントレス(SSH等の既存の仕組みを利用)プッシュ型YAML(Playbookと呼ばれるファイル)専用の中央サーバーは不要
Puppetエージェントベース(各機器にエージェントをインストール)プル型Ruby系の独自言語(Manifestと呼ばれるファイル)Puppet Server(旧称:Puppet master)
Chefエージェントベース(各機器にChef clientをインストール)プル型Ruby(Recipe/Cookbookと呼ばれるファイル)Chef server
Terraformエージェントレスプッシュ型HCL(HashiCorp Configuration Language)専用の中央サーバーは不要

Ansibleのプレイブック(Playbook)は、次のようにYAML形式で「あるべき状態」を記述します。

- name: NTPサーバーを設定する
  hosts: switches
  tasks:
    - name: NTPサーバーのアドレスを設定
      ios_ntp:
        server: 192.0.2.1
        state: present

このプレイブックは「switchesというグループに属する機器に対して、NTPサーバー192.0.2.1が設定されている状態(state: present)にする」という意図を宣言的に記述したものです。1台ずつ手作業でコマンドを打つのではなく、この定義ファイルを実行することで、対象の全機器へ一貫した設定を適用できます。なお、ここで使用しているios_ntpモジュールはAnsible 2.9系の例です。現行のAnsibleでは通常cisco.iosコレクションのモジュールを使用し、モジュール名や記述構文が異なります。


補足

  1. このステートレス性により、サーバー側の実装がシンプルになり、負荷分散(複数のサーバーでリクエストを分担すること)もしやすくなるという利点があります。 ↩
  2. 本記事シリーズで扱う設定管理ツールのうち、Ansibleのプレイブックの記述にはJSONではなくYAML(YAML Ain't Markup Language)という別の形式が使われます。YAMLはインデント(字下げ)で階層構造を表す、人間にとってさらに読みやすいことを重視した形式です。JSONとYAMLは相互に変換可能な情報を表現でき、実際に多くのツールが両方の形式を読み書きできます。YAMLの詳しい構文自体はCCNA 200-301の出題範囲外のため、本記事では立ち入りません。 ↩