てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] Playbook の実装ポリシーをチェックできる ansible-policy(開発進行中)をためした

はじめに

2024年5月の AnsibleFest 2024 のキーノートでたびたび「Policy as Code」という言葉が出てきました。Policy as Code 自体はほかでも耳にしますが、Ansible の場合は例えば、Playbook 中で指定するAWS インスタンスタイプを制限する、のようなことができるという話でした。コンセプトはふんわり分かったものの、当時はどういう実装の仕方になるのかまではわかりませんでした。

最近、ansible/ansible-policy という、Policy as Code を実現するための実装のリポジトリが公開されたため、実装面の情報がで始めてきました。

Playbook に対するポリシーを YAML で定義するファイルのことを「Policybook」と呼びます。Policybook のサンプルリポジトリも公開されました。

ansible-policy はリポジトリの説明にもあるとおり、現状はプロトタイプとしての実装で、破壊的な変更が起きる可能性も十分あります。バージョン管理もされておらず、PyPi にもありません。そのため、まだ導入する段階ではありません。

README.md にも冒頭に以下の説明があります。

Note: This repository is in prototype phase and under active development with subject to breaking changes.

とはいえ、ちょっと触ってみたい欲があったので触ってみました。あくまで、現時点でこうやったらこうなった、程度です。

ためしたのは、モジュールのオプションのポリシーチェックと、利用コレクションのポリシーチェックです。

  • 検証環境
    • ansible-policy 2024/06/20 の コミットハッシュ f9a80faf2a55aed7d67f368303076b5a8f44b03b 時点
      • 本記事内の各種リンクもこのコミット時点です。どんどん古くなるのでご注意ください
    • ansible-core 2.17.1
    • Python 3.11.3
    • macOS 13.6

環境の準備

前述の通り、まだ PyPi に公開されていないため、リポジトリを clone してからインストールします。

% git clone https://github.com/ansible/ansible-policy.git
% cd ansible-policy
% pip install -e .

また、ansible-poilcy は内部的に OPA (Open Policy Agent) と使っているらしいので、インストールしておきます。

% brew install opa

おためし1: モジュールのオプションのポリシーチェック

このモジュールのこのオプションは、この値しか指定しちゃだめ、のようなポリシーの実現です。

Policybook の作成

Playbook に対するポリシーの定義を Policybook として作成します。

あとででてきますが、ポリシーチェックの実行時は、複数(もちろん1つでも)の Policybook を含んだディレクトリを指定します。そのため、適当(今回は policies ディレクトリの中に Policybook を作成します。

あまり凝ったことを試しても後で変わるかもしれないので、シンプルなポリシーで雰囲気だけつかむようにします。

今回は、examples ディレクトリにあるcheck_pkg.ymlを参考にし、以下のポリシーとします。

  • ansible.builtin.packges モジュールでインストールするパッケージは httpd のみ許可

これを実現する Policybook は以下のとおりです。

pollicies/check_packages.yml:

---
- name: Check for httpd package installation
  hosts: localhost 

  vars:
    allowed_packages:
      - httpd

  policies:
    - name: Check for package name
      target: task
      condition: input["ansible.builtin.package"].name not in allowed_packages
      actions:
        - deny:
            msg: The package {{ input["ansible.builtin.package"].name }} is not allowed, allowed packages are one of {{ allowed_packages }}
      tags:
        - compliance

policies 配下にポリシー(複数可)を指定し、各ポリシーで targettaskplayrole)や、条件、そのときのアクションを指定します。

ansible_policy/policybook/README.md に説明があります。ただ、hosts が一番ピンときていません・・。

condition が一番肝ですかね。 input が唐突に感じましたが、おそらく targettask の場合はタスクを指すという感じだと思います。

Playbook の作成とポリシーチェック(違反あり)

チェック対象の Playbook は以下のとおりです。あえて許可されていないパッケージ git を指定しています。

playbook.yml:

---
- name: Test Play
  hosts: sv
  gather_facts: false

  vars:
    package_list:
      - git     # 許可されていない
      - httpd

  tasks:
    - name: Install Packages
      ansible.builtin.package:
        name: "{{ package_list }}"
        state: present

それでは、ansible-policy コマンドでポリシーチェックを実行します。-p で Playbook、--policy-dir で Policybook を格納したディレクトリを指定します。

% ansible-policy -p playbook.yml --policy-dir policies
TASK [Install Packages] playbook.yml L12-17 ************************************************************************
... Check_for_package_name Not Validated
    The package ["git", "httpd"] is not allowed, allowed packages are one of ["httpd"]

------------------------------------------------------------------------------------------------------------------------------
SUMMARY
... Total files: 1, Validated: 0, Not Validated: 1

Violations are detected! in 1 task

違反(Not Validated)が検出されて、actions 配下で指定したメッセージが表示されました。

Playbook の変数も評価してるのは良いですね。ただし、現時点で試した限り ansible.builtin.import_tasks`ansible.builtin.include_tasks で読み込んだ先の違反は検出できませんでした。

なお、ansible-policy コマンドに --format json をつけると、結果が JSON で表示されます。機械処理させたいときに便利ですね。

% ansible-policy -p playbook.yml --policy-dir policies --format json | jq .
{
  "summary": {
    "policies": {
      "total": 1,
      "violation_detected": 1,
      "list": [
        "Check_for_package_name"
      ]
    },
    "files": {
      "total": 1,
      "validated": 0,
      "not_validated": 1,
      "list": [
        "playbook.yml"
      ]
    }
  },
  "files": [
    {
      "path": "playbook.yml",
      "violation": true,
      "policies": [
        {
          "policy_name": "Check_for_package_name",
          "target_type": "task",
          "violation": true,
          "targets": [
            {
              "name": "Install Packages",
              "lines": {
                "begin": 12,
                "end": 17
              },
              "validated": false,
              "action_type": "deny",
              "message": "The package [\"git\", \"httpd\"] is not allowed, allowed packages are one of [\"httpd\"]\n"
            }
          ]
        }
      ],
      "metadata": {}
    }
  ]
}

Playbook の作成とポリシーチェック(違反なし)

つづいて、違反なしの Playbook で試します。

---
- name: Test Play
  hosts: sv
  gather_facts: false

  vars:
    package_list:
      - httpd

  tasks:
    - name: Install Packages
      ansible.builtin.package:
        name: "{{ package_list }}"
        state: present

ポリシーチェックを実行します。

% ansible-policy -p playbook.yml --policy-dir policies                     
------------------------------------------------------------------------------------------------------------------------------
SUMMARY
... Total files: 1, Validated: 1, Not Validated: 0

No violations are detected

違反がなくなりました。

おためし2: モジュールのオプションのポリシーチェック

今度は、使っていいコレクションのポリシーの実現です。

Policybook の作成

今回は、examples ディレクトリにあるcheck_collection.ymlをベースにします。

ansible.builtinamazon.aws のみの利用を許可することにします。

policies/check_collection.yml:

---
- name: Check for using collection
  hosts: localhost
  vars:
    allowed_collections:  # 利用を許可するコレクション
      - ansible.builtin
      - amazon.aws
  policies:
    - name: Check for collection name
      target: task
      condition: input._agk.task.module_info.collection not in allowed_collections
      actions:
        - deny:
            msg: The collection {{ input._agk.task.module_info.collection }} is not allowed, allowed collection are one of {{ allowed_collections }}
      tags:
        - compliance

condition の条件の書き方が先ほどとは異なりますね。

Playbook の作成とポリシーチェック(違反あり)

examples/check_project/playbook.yml をベースにして、唐突に azure.azcollection コレクションの利用を混ぜます。

---
- name: Provision EC2 instance and set up MySQL
  hosts: localhost
  gather_facts: false
  become: True
  vars:
    region: "your_aws_region"
    instance_type: "t2.micro"
    ami_id: "your_ami_id"
    key_name: "your_key_name"
    security_group: "your_security_group_id"
    subnet_id: "your_subnet_id"
    mysql_root_password: "your_mysql_root_password"
    package_list:
    - unauthorized-app
  tasks:
    - name: Create EC2 instance
      amazon.aws.ec2_instance:
        region: "{{ region }}"
        key_name: "{{ key_name }}"
        instance_type: "{{ instance_type }}"
        image_id: "{{ ami_id }}"
        security_group: "{{ security_group }}"
        subnet_id: "{{ subnet_id }}"
        assign_public_ip: true
        wait: yes
        count: 1
        instance_tags:
          Name: "MySQLInstance"
      register: ec2

    - name: Create a resource group
      azure.azcollection.azure_rm_resourcegroup:     # 許可されていないコレクション
        name: myrg
        state: present

ポリシーチェックを実行します。

% ansible-policy -p playbook2.yml --policy-dir policies 
TASK [Create a resource group] playbook2.yml L32-36 ****************************************************************
... Check_for_collection_name Not Validated
    The collection azure.azcollection is not allowed, allowed collection are one of ["ansible.builtin", "amazon.aws"]

------------------------------------------------------------------------------------------------------------------------------
SUMMARY
... Total files: 1, Validated: 0, Not Validated: 1

Violations are detected! in 1 task

違反が検出されました。

他にできそうなこと

サンプルを見る限り、become を禁止(タスクレベル、プレイレベル) などのポリシーチェックもできるようです。

サンプル

つまりポリシーチェックってどういうこと?

現時点での私の浅い理解ではありますが、「Playbook の実装ポリシーをチェックできる。ポリシーはYAMLで定義でき、Policybookと呼ぶ」ということなのかなと思います。

似たようなものだと ansible-lint を連想しますが、私なりに比較すると以下の通りです。

私が誤解しているかもしれないですし、今後仕様が変わるかもしれない点はご了承ください。

ansible-policy ansible-lint
チェックレベル 実装 文法
ルールの定義 YAML (Policybook) Python

おわりに

まだまだ発展途上ですが、今後もチェックしていきたいと思います。

参考

[Ansible] ansible-core 2.17.0 で マネージドノード側の Python 2 系全部と Python 3.6 のサポートがなくなった

はじめに

いよいよ、という感じですが、ansible-core 2.17.0 で、マネージドノード(自動化対象)側での Python 2系と Python 3.6 のサポートがなくなりました。

テスト対象からも外されているため、サポートされているバージョンよりバグが起こる可能性が大きいでしょうし、バージョンに起因するバグの場合はissue も対応されなくなっていると思います。

Releases and maintenance — Ansible Community Documentation

2.17 の Target Python 欄に Python 2 系がなくなった

Changelog

2.17.0 の Chaneglog には以下の記載があります。

Removed Python 2.7 and Python 3.6 as a supported remote version. Python 3.7+ is now required for target execution.

少しややこしいですが、ここの「target execution」は managed node (マネージドノード: 自動化対象)のことです。

記載の通り Python 3.6 のサポートもなくなりました。デフォルトが Python 3.6 の Linux ディストリビューションのバージョンもあった気がします。

Python 2 系の環境に対しておためし(エラー)

デフォルト Python 2.6.6 のままの CentOS 6.8 の環境に ansible-core 2.17.0 から接続してみます。 (CentOS 6 はだいぶ古いです。ここでは本記事の検証用途なので、利用を推奨する意図はありません。)

さくっと、アドホックコマンドで試します。

% ansible -i inventory.ini centos6 -m ping     
[WARNING]: No python interpreters found for host centos6 (tried ['python3.12', 'python3.11', 'python3.10',
'python3.9', 'python3.8', 'python3.7', '/usr/bin/python3', 'python3'])
centos6 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "module_stderr": "Shared connection to 192.168.1.141 closed.\r\n",
    "module_stdout": "/bin/sh: /usr/bin/python3: そのようなファイルやディレクトリはありません\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 127
}

この現象は Python 2のサポートがなくなり、Interpreter Discovery で探す Python のパスとしても python2 系のパスを探さなくなったことによるものです。最終的には /usr/bin/python3 がないというエラーになっています。

では、次にインタープリターのパスを、マネージドノード上に実際にあるパス(Python2)を指定するとどうでしょうか。

 % ansible -i inventory.ini centos6 -m ping -e ansible_python_interpreter=/usr/bin/python
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: SyntaxError: invalid syntax
centos6 | FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to 192.168.1.141 closed.\r\n",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/sakana/.ansible/tmp/ansible-tmp-1718715820.50483-30749-84959101405755/AnsiballZ_ping.py\", line 107, in <module>\r\n    _ansiballz_main()\r\n  File \"/home/sakana/.ansible/tmp/ansible-tmp-1718715820.50483-30749-84959101405755/AnsiballZ_ping.py\", line 99, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/home/sakana/.ansible/tmp/ansible-tmp-1718715820.50483-30749-84959101405755/AnsiballZ_ping.py\", line 44, in invoke_module\r\n    from ansible.module_utils import basic\r\n  File \"/tmp/ansible_ping_payload_4nYFEq/ansible_ping_payload.zip/ansible/module_utils/basic.py\", line 17\r\n    msg=f\"ansible-core requires a minimum of Python version {'.'.join(map(str, _PY_MIN))}. Current version: {''.join(sys.version.splitlines())}\",\r\n                                                                                                                                               ^\r\nSyntaxError: invalid syntax\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

Python の構文レベルでのエラーになりました。これは初見だと理解が難しいかもしれませんね。

(おまけ) ansible-core 2.16 だと

2.16 では、Python 2系としてぎりぎりPython 2.7 がサポートされていました。2.16 で Python 2.6 の環境に実行すると、以下のように親切なエラーになりました。

%  ansible -i inventory.ini centos6 -m ping 
centos6 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "msg": "ansible-core requires a minimum of Python2 version 2.7 or Python3 version 3.6. Current version: 2.6.6 (r266:84292, Jul 23 2015, 15:22:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]"
}

これまでエラーハンドリングができていたところが、Python2 系のサポートがバッサリなくなったことで、ハンドリングもできなくなったのだと思います。

おわりに

開発に携わっている方の目線に立つと、Pyrhon 2 対応のコードが一式消せて、今後の負担もかるくなったのではないでしょうか。

INTERPRETER_PYTHON_DISTRO_MAP の実質的な廃止の件を含め、ansible-core 2.17 は Pythonインタプリター周りの変更が大きめな印象です。

これまで、どのインタープリタが利用されていたか意識せずなんとなく動いていた環境は、このタイミングで注意が必要になったと思います。

参考

関連PR: Drop Python 2.7 and Python 3.6 support by mattclay · Pull Request #81866 · ansible/ansible · GitHub

また、Python 2 のサポートがなくなった影響で、ansible.builtin.yum モジュールがなくなりました

tekunabe.hatenablog.jp

Interop Tokyo 2024 参加レポート(主に ShowNet)

はじめに

2024/06/12-14(現地展示期間として)に開催されたInterop Tokyo 2024に参加してきました。

ShowNet の展示やセッションを見てきましたので、いくつかまとめます。

※ 口頭で聞いた内容を思い出しながら書いた記述が含まれます。正確な情報は一次ソースをあたっていただくようお願いします。

■ ShowNet

Interop といえば ShowNet。ShowNet は、多くのベンダーの最新鋭の機器を実施に動作させる検証の側面と、来場者や展示ブースからのインターネット接続性を提供する環境の側面がある環境です。

一時的な小さな ISP、という表現も耳にしました。小さな、と入っても技術的には非常に濃いものがぎゅっと詰まっている印象です。

新しくて分からないものが満載ですが、気になったトピックをピックアップします。

現地のホワイトボードやウォーキングツアーでの説明のほか、YouTube の動画の説明などをインプットにしています。

エクスターナル(対外接続) (#N-4 ラック)

#N-4 ラック

ShowNet と外を接続する回線は例年どおり以下の 3つ、合計 2Tbps。

  • SoftBank/BBIX (100Gbps)
  • KDDI (100Gbps)
  • NTT コミュニケーションズ (1.8Tbps)

3回線

IOWN Open APN(よくわかってない)のところは、今年もトポロジー図(PDF)上では虹色で表現されていました。6波だそうです。

External 部(トポロジー図から)

ルーターとしては、シスコ、ジュニパー、ファーウェイの 3社。

解説:

www.youtube.com

光配線切替ロボット (#N-2 ラック)

ROME minii(写りが・・・

毎年ついつい目が行く、配線切替ロボット「ROME mini」。光の配線を切り替える物理作業を自動でやってくれる機械です。

テストなどで、配線を切り替えるときに人が直接抜き指しする必要がないので便利なのだそうです。

運が良いと実際にガシャガシャ切り替えて動くところが見えるそうですが、今年も動いているところはお目にかかれませんでした。

製品紹介: https://keytech.ntt-at.co.jp/network/index_rome.html

テスト自動化 (#N-2 ラック)

ネットワークテスト自動化

弊社のネットワークテスト自動化ツール NEEDLEWORKが、今年は ShowNet で使っていただいていました(コントリビューター)。

おそらく、ShowNet の今年のポイントの一つの「複雑なテスター操作を必要としない試験自動化の取り組み」がこちらではないかと思います。

他部署の製品ではありますが、20年以上前に学生の頃初めてShowNetをみてなんかすごそうと思って、今、自社の製品が使われているというのは個人的に感慨深いものがありました。

トポロジー図(PDF)にも、needllework-1..8 という表記で載っていました。

「 フロー監視/UX品質分析」「統合監視/パケット解析」ラックの解説動画:   www.youtube.com

SN コネクタ (#N-5 ラック)

SN コネクタ

光ファイバーの終端としてさまざまなコネクタがあって、高密度化が進んでいるようです。

今回始めて見かけた気がするのが、こちらの SENKO Advanced 社の SN コネクタ

ここまでコンパクトだと、人間の指で抜き差しにくそうですが、抜き差ししやすいように工夫が。あとで X で教えていただきましたが、やわらかく曲がるようになっているようです。

他にも、両脇のポートの部品が避けてくれるような製品もあるそうです

物理レベルでもさまざまな工夫がなされているのだなと思いました。

Wi-Fi 6E / Wi-Fi 7 (#N-6 ラックほか)

#N-6 ラック

さまざまなベンダーのアクセスポイントが会場に設置されていたようです(写真は撮りそこねました)。

Wi-Fi 6E、Wi-Fi 7 は、私のスマホは非対応・・。そろそろ買い替えようかなと思います。

OpenRoaming も提供されていたようです。

解説:

www.youtube.com

ユーザ収容ネットワーク (#N-7 ラック)

#N-7 ラック

EVPN Type 5 VXLAN で構築。私自身は EVPN を通ってこなかったので、そもそもルートタイプと言う概念自身を知りませんでした。

バックボーン

解説:

www.youtube.com

出展社向けセキュリティ (#N-8 ラック)

#N-8 ラック

出展しているブース向けに、セキュリティのサービスを提供する機器がありました。

出典の申込時に、セキュリティ的に守ってほしいか、野ざらしにしてほしいかの選択があるそうです。セキュリティ製品のデモをするブースの場合、あえての野ざらしのままのほうが都合がいいから、とのことでおもしろいなと思いました。

緑の SRX (#N-8 ラック)

緑の SRX

Juniper 社の最近のコーポレートカラーは緑色ですが、緑の SRX の筐体が ShowNet に入ったのは、これが初なんだそうです。

SRX2300: https://www.juniper.net/jp/ja/products/security/srx-series/srx2300-enterprise-firewall.html

SYNESIS パケットキャプチャ装置 (#N-9 ラック)

パケットキャプチャ装置

何かあったときに後で調べられるように、ShowNet 内のパケットキャプチャと取り続ける装置。

高性能でコンパクトな 1U ってところがポイントです。

SYNESIS: https://www.synesis.tech/technology/

Zabbix アプライアンス・サーバー (#N-11 ラック)

Zabbix

Zabbix Enterprise Appliance ZS-7700 と、Zabbix 7.0 が入ったサーバーがありました。

Zabbix 7.0 はリリースされたばかりですね。ラックの話とは別ですが、Zabbix のブースはセッション含めて盛り上がっていて、人気の根強さを感じました。

時刻供給 (#N-12 ラック)

#N-12 ラック

ローカル 5G や Media over IP の世界では、NTP よりも高精度な時刻同期が求められるそうです。そのために利用されるプロトコルが PTP(Precision Time Protocol)。

このラック内の機器には PTP のグランドマスタがありました。Media over IP や ローカル 5G へ高精度な時刻を提供する役割です。

PTP グランドマスタ

屋上に 設置した GPS アンテナからひっぱてきているそうです。去年屋上のGPSアンテナが1つだったから雷こないでくれと祈っていたけど、今年は冗長化したとのこと。

GPSからグランドマスタ、各機器へ

ちなみに GPS アンテナも ShowNet 用、つまり仮設で、終わったら撤去するそうです。

ローカル 5G では、時刻のズレが大きくなると停波してしまうそうです。

時の番人

PTP の用途自体は、去年あたりに知ったのですが、今年は「テレコム」などプロファイルという概念があることを知りました。ローカル 5G ではテレコムプロファイルを利用。

ローカル5G (#N-14 ラックほか)

アンテナは会場の別のところにあって、関連機器(よくわかってないです・・)がラックにありました。

オンプレのAWS である AWS Outposts が今年もありました。

AWS のロゴが見える

さまざまな装置を内製開発のオーケストレーター Qmonus SDK で制御しているそうです。Qmonus SDK は以前 JANOG の発表で聞いたことがありました。

今年は実験試験局免許に加えて、実用局免許というものを取得し、会場を利用可能なエリアにしているそうです。数年前は、確か黒い幕のなかで「この中でローカル5Gをやっています」という感じだったので、年々広がっておますね。

免許

解説: https://engineers.ntt.com/entry/2024/06/13/141312

また、ShowNet の機器をラックごとに NOC の方に解説していただけるウォーキングツアーでは、今回ローカル5Gを活用されていました。具体的には、各ラックで説明していただくときに後ろの方だと機器が見えにくいのですが、カメラで映した映像をローカル5G経由で配布端末で見れるようにする、という取り組みです。遅延が少なく安定した通信になるようです。実際は物理的に近い距離にあるのに、ちょっと不思議な図ですね。

人[端末]    人人人人 [ラック]
    ↑映像             △ カメラで撮影
    |------------------|

マルチクラスタコンテナ基盤 (#D-4 ラック)

#D-4 ラック

会場内のインターネット接続提供の一環で、DNSサーバーもコンテナで構築されていて、DoH (DNS over HTTPS) にも対応していたようです。利用の割合としては、普通の DNS が6割、DoH が 4割とのことでした。

隣のラック #D-3 のディスプレイには、OpenShift の画面が映っていました。

OpenShift

解説:

www.youtube.com

Media over IP (#D-1 ラック、MOC、Stages)

#D-1 ラック

去年から少し興味が出てきたこの分野。今年は大きな目玉の一つになっていました。

デモ構成図

ShowNet ステージ側に、プロ用機材で撮影できるステージ、IP 化された放送設備、スイッチ、MOC (Media Operation Center) があり、ステージの映像を、テレビ北海道日本テレビNHK に届けるという試みです。

MOC の説明

放送業界は全く詳しくないのですが、通常であれば放送設備は同軸(SDI)ケーブルで接続されるところ、IP 化されると光ファイバーで通信できる距離の制約が緩和される、とのことです。

印象的だったのは MOC 付近のホワイトボードにあった以下の言葉です。「リモプロ」は「リモートプロダクション」のこと。

リモプロ

放送業界として、いままでできなかったことができるようになったり、いい意味で常識が覆えったりすることが起きているのかもしれません、おそらくは、巡り巡って視聴者にとっても、いい事がある話なのだと思います。

距離のアドバテージだけでなく、ケーブルの軽量化、通信の効率化、などのさまざまな良い点があるようです。

なぜ IP か

解説:

www.youtube.com

www.youtube.com

その他

詳細をおえませんでしたが、印象的だったもののキーワードだけ載せておきます。

  • SRv6 L3VPN over 衛星回線
    • ホール3の海側に衛星車がきていたそうです
  • 衛星インターネットとメディア配信技術の詳細分析

■ セッション

あらかじめ登録しておいたセッションを見に行きました。

自動化されたGenerative AIによるNetOPSの高度化について

セッション説明ページ: https://forest.f2ff.jp/introduction/9010?project_id=20240601

Aviz Networks による、Network Copilot の紹介でした。ざっくり「ネットワーク運用における ChatGPT」ということのようです。

たとえば、ネットワークOSのアップグレード前後で問題が発生していないか、ネットワークのコンプライアンスに問題がないかなどの確認や、トラブルシューティング自然言語ベースで進められるシステムです。回答は文章だったり、グラフだったりします。英語も日本語も対応。

データの観点での準備は主に2点。ベンダー依存はないそうです。

  1. ネットワーク機器側では SNMP や、gMNI、API などを有効にしておき、情報を収集できるようにしておく
  2. 判断材料として自社の運用基準(正常の閾値はいくつかなど。Excelでも可)や、ナレッジベースを食わせておく

ユースケース(いただいたパンフレットから)

ネットワークは多数の機器で構成されるため、全体を把握するには各機器の状態や関係性の確認が必要ですが、それがチャットというインターフェースで実現できるのであれば便利だなと思いました。

オンプレミス側で、相応のハードウェア要件(特に GPU)がある点は留意点かなと思います。

■ 各社ブース

今年は時間配分をミスってしまい、あまり回れませんでした・・・。

ヤマハ さん

ブース紹介ページ: https://f2ff.jp/2024/interop/exhibitor/show.php?id=2246&lang=ja

知識が RTX1200 くらいで止まっているため、最近の情報を知りたくて訪れました。

あの機器の後継がこれ、と各ルーターのご説明いただきました。ありがとうございます。

RTX3510のように 10G ポートを備えた機器も増えてきているのですね。

LAN マップで、YAMAHA ルーター配下の IPアドレスを設定していない YAMAHA スイッチがマップに表示されるところも実際の画面で見せていただきました。

参考: https://cloud.watch.impress.co.jp/docs/event/1600082.html


おわりに

毎年見ていると、同じテーマでも去年との差分を差分がわかるので、進化に少し敏感になれるなと思いました。

ShowNet の構築、運用に関わった NOC、STM のみなさま、ブースでご対応いただいたみなさま、ありがとうございました。

まお、ShowNet のより詳しい説明がされる shownet.conf_ が 2024/09/25 - 26 に開催されるそうです。数年前までは 有料でしたが確か去年あたりから無料で、今年も無料。かなり濃いお話が聞けるのではないかともいます。

https://f2ff.jp/event/shownetconf/2024

参考

開催後しばらくは、さまざまな情報が上がってくると思いますので、随時リンクを追加予定です。

www.interop.jp

cloud.watch.impress.co.jp

cloud.watch.impress.co.jp

www.itmedia.co.jp

xtech.nikkei.com

[Ansible] vyos.vyos や frr.frr コレクションなどが Deprecated (非推奨)になった

3つのネットワーク系コレクションが Deprecated

ネットワーク系のコレクションのうち、以下のコレクションが Deprecated (非推奨)になっていました。

例えば vyos.vyos コレクション README.md には以下のような説明があります。

The vyos.vyos collection has been deprecated and will reach it's end-of-life on December, 2025. We are no longer accepting new pull requests, except for ones that fix critical bugs or security vulnerabilities. This collection is not supported with ansible-core>2.17.

2025年12月に EOL を向かえ、クリティカルなバグや脆弱性についてのプルリクしか受け付けないようになっているそうです。

確かにコミュニティ向けニュースレター Bullhorn の #123 (2023年11月)では、

The frr.frr, vyos.vyos and openvswitch.openvswitch collections have been deprecated and will not have any more major releases.

とありました。で、REAMDE.md に反映されたのが 2024年6月です。

ただ、理由と今後については私は追いきれませんでした。

ちょと注視しておこおうかなと思います。

Ansible Community Package から外す動きは始まっているようです。

参考

forum.ansible.com

forum.ansible.com

github.com

CLI ベースのコレクションとは別の、API 版のコレクションについての議論も。

[Ansible/Terraform] terraform モジュールが2つのコレクションにある事情(cloud.terraform、community.general)

はじめに

Ansible から Terraform を呼ぶ terraform モジュールですが、現状 cloud.terraform コレクションと community.general コレクションの2つにあります。

ここまでの経緯や、現在の状況になっている理由をまとめます。

経緯

もともと terraform モジュールは community.general コレクションにありました。

そこから独立する形で、cloud.terraform コレクションができました。バージョン 1.0.0 のリリースは 2022年のことでした。

コレクション単位で比較すると以下の特徴があります。

community.general cloud.terraform
内容 いろいろ Terraform 用
Terraform 関連のモジュール類 terraform モジュール terraform モジュール 、terraform_state インベントリプラグインterraform.provider インベントプラグインなど
配布元 Ansible Galaxy Ansible Galaxy、Automation Hub

まだ2つのコレクションにある事情

cloud.terraform.terraform の方が後発ですが、 community.general.terraform は Deprecated (非推奨)になっていません。直近だと 2024年2月のコミットがありました。

どういうことだろうと思って、Forum で聞いてみました。以下のような事情があるそうです。

  • cloud.terraform コレクションは Ansible Community Package (いろいろコレクションがセットのもの)に含まれていない
  • community.general コレクションはもともと Ansible Community Package に含まれている
  • ルール上、Ansible Community Package に含まれるものを外に移動することはできない

おわりに

開発者にとっても利用者にとっても 1つに統一されてメンテナンスされる方が、好ましいと思います。

が、すでに差分が出てしまっている状態で、互換性などを考慮して統一させていくのは難しいのかもしれません。見守りたいと思います。

参考

[Ansible/Terraform] cloud.terraform.terraform モジュールでどんな terraform コマンドが実行される確認する

はじめに

Ansible の cloud.terraform.terraform モジュールは、Ansible から Terraform を呼べるモジュールです。

モジュールで指定するオプションに応じて、さまざま terraform コマンドが実行されます。

で、「このときは実際にどういうコマンドが実行されるんだろう?」と気になることがあります。

調べてみると、Ansible 本体の AnsibleModule クラスの run_command メソッド経由でコマンドが実行されることがわかりました。

このメソッドの中ではログを出力する処理があるので、このログを見ればどんなコマンドが実行されるかが確認できることになります。

ということで、試してみました。

  • 環境
    • ansible-core 2.16.6
    • cloud.terraform コレクション 3.0.0
      • 挙動説明、コードへのリンクも 3.0.0
    • macOS 13.6.7
    • Ansible と Terraform は同一マシンに入れて hosts: localhost で実行

基本的なお作法

run_command メソッド内で実行されるコマンドをデバッグするは、設定項目 DEFAULT_DEBUGデバッグを有効にします(デフォルト無効)。環境変数で設定する場合は ANSIBLE_DEBUG です。

このデバッグを有効にすると、Playbook 実行時にデバッグ情報が no_log: true にしたもの含めて大量に表示されるので注意してください。

(このデバッグほどしなくてもいい方法があれば教えてください)

デフォルトでは、ファシリティ INFO として出力されます。ファシリティを変更する場合は、設置項目 DEFAULT_SYSLOG_FACILITY で変更します。

今回は macOS を使うので、log コマンドで確認します。process はざっくり Python にしておきます。

(確認方法は各環境に合わせてください)

log コマンドは、こちらのページを参考にさせていただきました。ありがとうございます!

ログ出力の待機

% log stream --info --predicate 'process == "Python"'
Filtering the log data using "process == "Python""
(出力待ち)

Playbook 実行:

ANSIBLE_DEBUG=True ansible-playbook -i localhost, ansible_terraform.yml

すると以下のようにログが表示されます。

% log stream --info --predicate 'process == "Python"'
Filtering the log data using "process == "Python""
Timestamp                       Thread     Type        Activity             PID    TTL 
2024-06-09 14:38:02.930838+0900 0xdbbd6    Info        0x0                  18358  0    Python: (syslog.cpython-311-darwin.so) Invoked with project_path=./ state=present force_init=True workspace=default purge_workspace=False complex_vars=False targets=[] lock=True init_reconfigure=False overwrite_init=True check_destroy=False provider_upgrade=False binary_path=None plugin_paths=None variables=None variables_files=None plan_file=None state_file=None lock_timeout=None backend_config=None backend_config_files=None parallelism=None
2024-06-09 14:38:02.932716+0900 0xdbbd6    Info        0x0                  18358  0    Python: (syslog.cpython-311-darwin.so) Executing: /usr/local/bin/terraform version -json
2024-06-09 14:38:06.268688+0900 0xdbbd6    Info        0x0                  18358  0    Python: (syslog.cpython-311-darwin.so) Executing: /usr/local/bin/terraform init -input=false -no-color
2024-06-09 14:38:11.463882+0900 0xdbbd6    Info        0x0                  18358  0    Python: (syslog.cpython-311-darwin.so) Executing: /usr/local/bin/terraform providers schema -json
2024-06-09 14:38:15.128367+0900 0xdbbd6    Info        0x0                  18358  0    Python: (syslog.cpython-311-darwin.so) Executing: /usr/local/bin/terraform show -json

Executing: のあとに各種 terraform コマンドが確認できます。

おためし

いつくかのパターンで試してみます。

見やすさのため、以下からはログのうち Executing: /usr/local/bin/terraformterraform 以降の文字列のみを乗せます。

また、途中でコードの解説を含みますが、ざっと読んだ程度ですので、詳細、正確なところはコードをあたってください。

パターン1: リソースがない状態から作成

ほしいリソースがまだない状態から、terraform init 含めてリソースを作成するパターンです。

Playbook は以下のとおり。

    - name: Call Terraform
      cloud.terraform.terraform:
        project_path: ./
        state: present
        force_init: true

表示された terraform コマンドは以下のとおりです。結構いろいろ表示されますね。

terraform version -json
terraform init -input=false -no-color
terraform providers schema -json -no-color
terraform show -json
terraform workspace list -no-color
terraform plan -lock=true -input=false -no-color -detailed-exitcode -out /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmphxtb7o8u.tfplan
terraform validate
terraform show -json /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmphxtb7o8u.tfplan
terraform apply -no-color -input=false -auto-approve -lock=true /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmphxtb7o8u.tfplan
terraform show -json
terraform output -no-color -json

最初に terraform version を実行しています。これはあとで、バージョンによってオプションを切り替えるために取得しているようです。見つけた範囲ですと、apply 時に自動で yes して進めるオプションを -auto-approve にするか -auto-approve=true にするか、の判断に使われていました。

force_init: true を指定していて overwrite_init もデフォルトの true のままなので、init が実行されています(参考)。他のコマンド含め、-input=false が指定されているので、変数の値を入力するプロンプトは表示されず、未割り当ての変数があっても処理を続行します。Ansible から見ると terraform コマンド実行後の対話処理はないほうがいいのでこうなっているのだと思います。

いきなり terraform applyするのではなく terraform plan.tfplan ファイルを作成してから terraform applyしているのが特徴でしょうか。plan_file の指定がない場合は、一時ファイルとして作成されます。

validate が実行されるのは意外でした。project_pathbin_path妥当性をチェックする流れで validate もするようです。

3回 terraform show を実行しているのは、事前事後で diff を取得するためのようです。 それぞれの概要は以下のとおりです。

  • 1回目は、事前状態の取得
  • 2回目は、事前に terraform plan -out して生成した .tfplan ファイルからの状態の取得
    • 通常(チェックモードでない)は、ここの情報はその後とくに利用されないように見える
  • 3回目は、事後(apply後)状態の取得
    • 後述のチェックモードの場合は、2回目の結果が事後結果として扱われる

terraform apply にある -detailed-exitcode オプションは、終了コードによって、変更有無を判断するためのオプションです。

パターン2: リソース作成済みから再実行

最後は、リソースがある状態から再度同じ Playbook を実行するパターンです。タスクのステータス的には OK です。

表示された terraform コマンドは以下のとおりです。

terraform version -json
terraform init -input=false -no-color
terraform providers schema -json
terraform show -json
terraform workspace list -no-color
terraform plan -lock=true -input=false -no-color -detailed-exitcode -out /var/folders/2s/h6djr0fn3773tj1zy4smg442c0000gn/T/tmpscohbatx.tfplan
terraform validate
terraform show -json /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpscohbatx.tfplan
terraform show -json
terraform output -no-color -json

terraform applyコマンドがないですね。

コード的には terraform applyを担当するメソッドは呼ばれますが、terraform plan 時に変更が検出されなかったため、terraform apply不要(needs_applicationfalse)という扱いで処理されているようです。

パターン3: チェックモード

ドキュメントに terraform plan したいときは Playbook をチェックモードで実行してね、と記載があります。

リソースがまだない状態から試してみます。

terraform version -json
terraform init -input=false -no-color
terraform providers schema -json
terraform show -json
terraform workspace list -no-color
terraform plan -lock=true -input=false -no-color -detailed-exitcode -out /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpr0m76lku.tfplan
terraform validate
terraform show -json /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpr0m76lku.tfplan
terraform output -no-color -json

やはり terraform applyがないですね。

3回目の terraform show(事後状態) がないのも特徴です。チェックモードだと実行されないようになっています。

パターン4: リソースの削除

最後は、リソースがある状態からリソースを削除するパターンです。

Playbook は以下のとおりです。

    - name: Call Terraform
      cloud.terraform.terraform:
        project_path: ./
        state: absent     # destroy 相当

表示された terraform コマンドは以下のとおりです。

terraform version -json
terraform init -input=false -no-color
terraform providers schema -json
terraform show -json
terraform workspace list -no-color
terraform plan -lock=true -input=false -no-color -detailed-exitcode -out /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpu74d8r3v.tfplan -destroy
terraform validate
terraform show -json /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpu74d8r3v.tfplan
terraform apply -no-color -input=false -auto-approve -lock=true /var/folders/2s/h6djr0fn3773tj1zy4mg442c0000gn/T/tmpu74d8r3v.tfplan
terraform show -json
terraform output -no-color -json

直接 terraform destroyするのではなく、terraform plan 時に -destroy オプションを付けてできた .tfplan ファイルを terraform applyしています。

Ansible としては、変更の有無を検出しながら段階をおって処理するための工夫なのかなと思います。

おわりに

実際にどんなコマンドが実行されているかわかるとスッキリしますね。

今回はとてもシンプルなPlaybookで試しましたが、例えば、variables を指定したり workspace を指定があるときは色々変化があって、確認するとおもしろいかもしれません。

[Ansible/AAP] Automation Controller の API エンドポイントは末尾のスラッシュ(trailing slash)を付けるのが吉

はじめに

タイトルがほぼ全てです。

Automation Controlle の API エンドポイントには、末尾のスラッシュ(trailing slash)があります。

developers.redhat.com

ドキュメント通り末尾のスラッシュを付けるべきですが、付けなくて問題なく見えることがあるので、うっかり忘れてしまうかもしれません。

末尾のスラッシュを付けなくても問題なく見えるパターン

試した限り GET のパターンです。

  • GET で /api/v2/ping をリクエストする
  • 301 が返ってくる
  • GET で /api/v2/ping/ をリクエストしなおす

試せていませんが、DjangoAPPEND_SLASH という設定による(デフォルト True)のではないかと思います。

末尾のスラッシュを付けないとまずいケース

GET 以外、たとえば POST をするケースです。

  • POST で /api/v2/job_templates/99/launch をリクエストする
  • 301 が返ってくる
  • GET/api/v2/job_templates/99/launch/ をリクエストしなおす
  • GET の結果が返ってくる

リクエスト時に元のメソッドを維持するかどうかは、クライアント側の設定次第のようですが、GET になることが結構多いようです。

Postman での挙動

デフォルトでは前述の通り、GET でリクエストし直していました。

Settingの Follow original HTTP Method を有効にすると、 POST のままにしてくれました。(Automatically follow redirects はデフォルト有効のまま)

Follow original HTTP Method

curl での挙動

curl-L, --location オプションには以下の説明がありました。

              When curl follows a redirect and if the request is a POST, it sends the following request with a GET if the HTTP
              response was 301, 302, or 303. If the response code was any other 3xx code, curl resends the following request
              using the same unmodified method.

              You can tell curl to not change POST requests to GET after a 30x response by using the dedicated options for
              that: --post301, --post302 and --post303.

ただ、

curl --location -X POST 'https://192.168.1.99/api/v2/job_templates/99/launch' --header 'Authorization: Basic xxxxxxxxxx' -k -v

のように、POST で trailing slash なし(body もなし)で確認すると、以下のように POST のままリクエストしていました。なにか気の利いた機能が効いてるのかもしれません。

> POST /api/v2/job_templates/99/launch HTTP/1.1
...(略)...
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Fri, 07 Jun 2024 12:27:31 GMT
< Content-Type: text/html
< Content-Length: 162
< Location: https://192.168.1.99/api/v2/job_templates/99/launch/
...(略)...
< 
* Ignoring the response-body
* Connection #0 to host 192.168.1.99 left intact
* Issue another request to this URL: 'https://192.168.1.99/api/v2/job_templates/99/launch/'
* Found bundle for host: 0x7fc96f106460 [serially]
* Can not multiplex, even if we wanted to
* Re-using existing connection with host 192.168.1.99
> POST /api/v2/job_templates/56/launch/ HTTP/1.1
...(略)...
> 
< HTTP/1.1 201 Created

まとめ

ドキュメント通り、末尾のスラッシュ(trailing slash)を付けるのが吉です。

参考

qiita.com

docs.djangoproject.com

qiita.com