てんこ

ブログ名は愛猫(てん)の愛称です。中身は個人のIT系学習記録です。

AnsibleでFortigateのHA構成を組んでみた。

この記事は、Ansible 2 Advent Calender 2019の15日目の記事です。

昨日の…というか、先週一週間は、@sky_jokerxxさん「Ansible2 Advent Calender 一週間全部俺」の無双をやっていただいてまして、あれだけ引き出しが多いのすごいなあと、ただただ尊敬する次第です。

昨日の記事はこちらです。

さて、私はいつもの通り、AnsibleでFortigateを操作してみた話を書かせていただきます。今回はHAを組むモジュールである、fortios_system_haを使ってみました。

Ansible関連の実践記事一覧はこちら


目的

fortigateを冗長構成(HA)を組むためのPlaybookの書き方や、<your_own_value>を明らかにするため

…そろそろ<your_own_value>との戦いから卒業せねば(汗)

先に結論

  • FortigateのHA設定用モジュールを利用して、HA構成を組むことができた
    • 初回設定のときはfailedになるが、設定は成功している
    • HeartBeat用のインターフェースを指定する場合は注意する
  • internalを分離させるためのvirtual-switchを扱うモジュールは現時点では存在しない。

環境

構成図

このような感じの構成で確認を行いました。

前提条件として、初期設定でFortigate側は初期状態からDMZポートに各々の管理用IPを付与した状態を前提としています。

f:id:tatematsu_san:20191215132941p:plain

構成上の注意点

検証で利用しているFortigateは60Dなのですが、スイッチ用のポートとして、「internal」というポートが備わっています。(1-7番ポートまで存在)

HA構成を組む場合、このスイッチポートを分離させて独立したポートにすることが多いです。 実機の設定では、「config system virtual-switch」というConfigで定義されているのがその箇所なのですが、残念ながら現時点では、Ansibleのfortios用のモジュールには、このvirtual-switchに関連するモジュールが存在しません。

今回は可能な限りPlaybookのみで実施しようとしていますので手動での分離などは行っていませんが、手動で分離した場合などについては、また別途記事にしたいと思います。

参考までに、実機で全ポートを独立したポートに分離する場合には、以下の通りのコマンドで実施可能です。

config system virtual-switch
delete 1
end

作成したinventory、group_vars、host_vars、Playbook

モジュールリファレンスを参考にしつつ、まずは以下のような環境設定を定義。

■inventory

[fortigate]
fg_fw01 ansible_host=192.168.10.61
fg_fw02 ansible_host=192.168.10.62

■group_vars

---
ansible_user: admin
ansible_password: password
ansible_network_os: fortios
ansible_connection: httpapi
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no
timeout: 600

■FW01用(host_vars/fg_fw01.yml)

---
fw_hostname: fw01
ha_manage_if: dmz
ha_manage_gw: 192.168.10.254
vc1_node_role: master
vc1_priority: 200
vc1_monitor_if: wan1

■FW02用(host_vars/fg_fw02.yml)

---
fw_hostname: fw02
ha_manage_if: dmz
ha_manage_gw: 192.168.10.254
vc1_node_role: backup
vc1_priority: 100
vc1_monitor_if: wan1

基本的には、単純なHA構成だけであれば、Priorityの値だけをホスト毎に変えれば問題ないと思います。

本当はもうちょっとvarsに入れたほうがいいものもあるんですが、時間も足りなくて未整理です。申し訳ありません。 そして、作成したPlaybookがこちら。

■Playbook

---
- hosts: fortigate
  gather_facts: false
  vars:
    vdom: "root"

  tasks:
  - name: Fortigate Hostname Setting # ホスト名の定義
    fortios_system_global:
      system_global:
        hostname: "{{ fw_hostname }}"
        alias: "{{ fw_hostname }}"

  - name: Fortigate HA VC1 Setting # 実際のHA設定
    fortios_system_ha:
      system_ha:
        group_id: "10"
        group_name: "FG_TEST"
        mode: "a-p"
        authentication: "enable"
        password: "hogehoge"
        ha_direct: "enable"
        ha_mgmt_status: "enable"
        ha_mgmt_interfaces:
          - 
            id: "1"
            interface: "{{ ha_manage_if }}"
            dst: "0.0.0.0 0.0.0.0"
            gateway: "{{ ha_manage_gw }}"
        priority: "{{ vc1_priority }}"
        monitor: "{{ vc1_monitor_if }}"
        hbdev: "\"wan2\" 128" # 注意点(後述)
        session_sync_dev: "wan2"
        sync_config: "enable"
        vcluster2: "disable"
        schedule: "none"
        override: "disable"
        vcluster_id: 0
        vdom: "{{ vdom }}"

冗長を組むと、さすがにホスト名を定義しないと区別が難しくなるため、ha設定を行う前に、hostnameの定義などを行っています。

このPlaybookを実行すると、以下のようにHA設定の部分はfailedになります。

f:id:tatematsu_san:20191215135112p:plain

しかしながら、WebUIなどで覗いてみると、意図した通りの設定になっていることが確認できます。

f:id:tatematsu_san:20191215135431p:plain

なぜfailedになるのに設定は完了しているのかについてですが、failedの要因は応答待ちのtimeoutです。 この辺りは機器の仕様もあると思いますが、HAの設定操作を行ったHTTPコネクションでは、HA設定に関しては応答を返せないのかな、と推測しています。

ちなみに、すでにHA構成が組まれているホストに対しての設定変更を行うPlaybookであれば、応答は返ってきます。

Playbook作成上の注意点

このあたりが<your_own_value>との戦いである所以なのですが、Playbook上にコメントした、hddev: のところで少しハマりました。

以下の画像は、モジュールリファレンスのサンプルの記述です。

f:id:tatematsu_san:20191215135845p:plain

hbdev:の部分は、目的は「Heart Beat パケットをやりとりするインターフェース(デバイス)を指定する」箇所です。

CLIなどで設定している人は良くご存じかもしれませんが、この設定においては、インターフェース名だけを指定するだけではなく、その「プライオリティ」を定義する必要があります。

記述方法が ”<インターフェース名>" <プライオリティ値> という指定をする必要があるため、ダブルクォーテーションもパラメータとして必要になります。

そのため、エスケープ文字を挟み、このように書く必要があります。

        hbdev: "\"wan2\" 128" # 注意点(後述)

まとめ

「先に結論」の個所でも書きましたが、以下のような結果になりました。

  • FortigateのHA設定用モジュールを利用して、HA構成を組むことができた
    • 初回設定のときはfailedになるが、設定は成功している
    • HeartBeat用のインターフェースを指定する場合は注意する
  • internalを分離させるためのvirtual-switchを扱うモジュールは現時点では存在しない。

リファレンスの<your_own_value>と戦いは、以下のような流れでやっています。

  • とりあえずCLIで最低ラインを探してみる
  • WebUIでも設定を実施してみる
  • uriモジュールを利用した汎用Playbookで設定後の状態をJSONで取得する
    • 今回のものは、cmdb/system/haで取得が可能
  • Playbookに落としこむ

楽しくはあるんですが、時間が限られたときにやるものではないですね…

また今度、今回作成したPlaybookを生かして、この構成を使った運用のつらみだったり、複数のVDOM Cluster構成を組むようなPlaybookにチャレンジしたいと思います。

バトンリレー

なんとか前走者から渡されたバトンを落とさず、ブログを書くことができました。

お次のssato1138さんにバトンをつなぎます。

よろしくお願いいたします!