えんでぃの技術ブログ

えんでぃの技術ブログ

ネットワークエンジニアの視点で、IT系のお役立ち情報を提供する技術ブログです。

Ansibleによるネットワークステータス確認101

お伝えしたいこと

この記事はAnsible Advent Calendar 2024の11日目の記事です。

AnsibleでLinuxやクラウド、ネットワーク機器の設定変更を自動化できるのは周知のとおりですが、情報取得の機能も充実しています。
充実...していますが、機能が多すぎて「やりたいこと1つに対して実現手段が2つも3つも存在する」状況になっています。

一体私たちはどの機能を使いたいのでしょうか?
私自身あまり理解できていなかったので、この場でまとめてみたいと思います。

サマリ表

下表にNW機器のステータス情報を取得する方法をまとめます。
取得できる情報は大きく分けて4種類あります。
もっと大きく分けると、(1)の文字列データと(2-1)〜(2-3)の構造化データの2つに大別できます。

network_configuration_gathering_pattern

(※) 本記事では例示にArista EOSを使います

自分が使いたい機能を見つける

以降のセクションでは、いくつかの具体的なユースケースに基づいて上表の機能を選択し、実行結果を示していきます。
少しでもイメージが湧きやすくなれば幸いです。

未加工のshowコマンドログを取得する

showコマンドの出力をそのまま見たりファイルに保存したいときは、#サマリ表の 「(1) showコマンドそのまま」 の機能を使用します。

ユースケース (1) showコマンドを未加工で保存したいのはどんな場面?

ネットワーク機器のshowコマンド出力結果を加工せずそのままファイルに保存したいケースとして、私の中では以下の2点が思い当たります。

  1. 作業やメンテナンス前後で対象機器にshowコマンドをAnsibleで一括実行し、実行結果をファイル保存する。ファイルを目視で確認して作業の成否を判断する (コマンド実行のみ自動化、確認はマニュアル)
  2. Ansibleでコンフィグを定期的に一括取得・ファイル保存する。作業者は必要なときにコンフィグを参照し、設計業務などに活用する

これらのユースケースを満たすAnsibleの具体的な実装方法を次のセクションで見ていきましょう。

実行例 (1) arista.eos.eos_command module

arista.eos.eos_command moduleでshowコマンドを実行し、結果を記録する例を示します。
今回はshow running-configを実行し、ネットワーク機器のコンフィグを表示します。

例示ではansible.builtin.debugモジュールでコマンド出力を画面表示していますが、実際に業務で使う際はansible.builtin.copyモジュールなどに置き換えてファイル保存する想定です。

- name: Retrieve Arista EOS config
  hosts: eos
  gather_facts: false
  tasks:
    - name: Execute show running-config
      arista.eos.eos_command:
        commands:
          - show running-config
      register: _eos_show_running_config_result

    - name: Debug _eos_show_running_config_result
      ansible.builtin.debug:
        msg: '{{ _eos_show_running_config_result.stdout }}'

以下に実行結果を示します。

TASK [Debug _eos_show_running_config_result] ***
ok: [veos1] => 
  msg:
  - |-
    ! Command: show running-config
    ! device: veos1 (vEOS-lab, EOS-4.26.5M)
    !
    ! boot system flash:/vEOS-lab.swi
    !
    enable password sha512 $6$xxxxxx # マスクしました
    no aaa root
# ...

showコマンドログを構造化データに変換し、活用する

showコマンドの実行結果を構造化データに変換したいときは、#サマリ表の(2-1)〜(2-3)の機能を使用します。

  • (2-1) パーサ利用
  • (2-2) network resource module
  • (2-3) gather_subset

(参考) 構造化データへの変換のイメージ

「構造化データへの変換」のイメージを補足として説明します。
既に知っている方は読み飛ばしてください。

「構造化データへの変換」がどのようなものかを理解するには、実際に動いているところを見るのが一番です。

以下のネットワーク構成を例にします。
Arista vEOSスイッチが3台接続されています。

nw_diagram1

veos1でshow interface descriptionを実行し、インターフェースのステータスを確認します。

Interface  Status  Protocol  Description
Et1        up      up        veos2 Et1
Et2        up      up        veos3 Et1

これを構造化データに変換すると、以下のようなデータ構造になります。
利用するパーサによってデータ構造は変わりますが、基本的にはlistとdictのネスト構造になります。
例えばntc_templatesやTextFSMを利用した場合は以下のようなデータ構造になります。
(※) パーサとは、文字列を構造化データとして解釈するプログラムのことです。本記事の文脈では文字列を構造化するプログラムと思って差し支えありません。ntc_templatesやTextFSMは正規表現で実装されています

interfaces:
  - port: Et1
    status: up
    protocol: up
    description: veos2 Eth1

  - port: Et2
    status: up
    protocol: up
    description: veos3 Eth1

構造化することで「特定の値を取り出す」ことが非常に容易になります。
例えばEt1のstatusは{{ interfaces.0.status }}や{{ (interfaces.selectattr("port", "eq", "Et1"))["status"] }}で取り出せます。

後者の参照方法は一見すると難しく思えるかもしれません。
しかし「同じパーサを使う限りどのshowコマンドでも基本的に同じ方法でデータを取り出せる」ので、分析対象のshowコマンドが今後増えた場合も同じフィルタを使い回せます。
構造化されていないデータを都度grepやansible.builtin.regex_search filterで都度整形するよりも遥かに少ない手間でデータを構造化できます。

...話が少し逸れましたが、データを構造化できれば夢がかなり広がります。
構造化されたデータを変数に格納して追加のロジックを組めるのです。

例えば、以下のような処理が考えられます。

  1. Et1がupなら何もせず、downならエラーメッセージを出力する (→ showコマンドの実行だけでなく確認まで自動化できる)
  2. ansible.builtin.templateモジュールで表やレポートを自動生成 (→ ステータス可視化、レポート自動生成)

2の具体例を挙げます。
上述のlist of dict形式に構造化されたデータをinputに、templateモジュールを使えば以下のmarkdownを容易に生成できます。
(※) 余談ですが、list of dictは本質的には表と同じ構造のデータなのです。なので表形式に変換することは本当に簡単です

| port | status | protocol | description |
| ---- | ------ | -------- | ----------- |
| Et1 | up | up | veos2 Eth1 |
| Et2 | up | up | veos3 Eth1 |

適切なツールでmarkdownをhtml化すると、以下のような見た目の表になります。

interface_list

showコマンドログを構造化し、整形することで見やすい表を生成できました。

ユースケース (2) showコマンドを構造化したいのはどんな場面?

#構造化データへの変換のイメージで既に触れたとおり、私が思いつくユースケースは以下の2点です。

  1. コマンド実行だけでなく、実行結果の確認まで自動化する
  2. コマンド実行結果を整形してレポートや表形式で出力する

実行例 (2-1) パーサを使う場合

さて、Ansibleでネットワーク機器のステータス情報をパースする手段は3つあります。
順番に説明していきますが、まずは私が個人的に一番好んでいる「(2) パーサ利用」について説明します。

パーサを使う場合、基本的にはansible.utils.cli_parseモジュールを使います。

以下にサンプルを示します。
show interfaces descriptionをパースするplaybookです。
今回はntc_templatesパーサを利用しているので、動作にはntc_templates Pythonパッケージが必要です。

- name: Parse EOS show commands
  hosts: eos
  gather_facts: false
  tasks:
    - name: Parse show interfaces description
      ansible.utils.cli_parse:
        command: show interfaces description
        parser:
          name: ansible.netcommon.ntc_templates
        set_fact: _show_interfaces_description_parsed

    - name: Debug _show_interfaces_description_parsed
      ansible.builtin.debug:
        msg: '{{ _show_interfaces_description_parsed }}'

実行結果は以下のようなイメージになります。
TextFSMは必ずlist[dict] (list of dicts) というデータ型に構造化します。
したがって、showコマンドが変わってもそこそこ画一的な方法でデータを加工できることが利点だと私は考えています。

TASK [Debug _show_interfaces_description_parsed] ***
ok: [veos1] => 
  msg:
  - description: veos2 Et1
    port: Et1
    protocol: up
    status: up
  - description: ''
    port: Et2
    protocol: up
    status: up
  # ...

ご参考までに、show interfaces descriptionの実行ログも再掲します。

Interface  Status  Protocol  Description
Et1        up      up        veos2 Et1
Et2        down    down      veos3 Et1

ansible.utils.cli_parse module以外にも、似た機能を持つフィルタとしてansible.netcommon.parse_cli filterやansible.netcommon.cli_parse_textfsm filterが存在します。
これらのフィルタはcli_parseモジュールよりも先にリリースされた経緯があり使われたこともありますが、対応しているパーサも限定的ですし現在ではあまり使う理由がないと思います。
フィルタについては実行例を割愛します。

実行例 (2-2) network resource moduleを使う場合

network resource moduleが存在するOSの場合、この方法が使えます。
#実行例 (2-1) パーサを使う場合と比較するとパーサ導入が不要であるため、お手軽に使い始めることができます。
ntc_templatesやTextFSMは「CLIで得られる情報であれば全て構造化できる」汎用性と、「必ずlist[dict]形式でデータを返す」統一感があるので、私個人としてはパーサ利用に統一するのが好きです。
このあたりは宗教戦争です。

同じパース結果を得られる書き方が私の知る限り3通り存在するので、順番に挙げていきます。

1つ目の書き方はarista.eos.eos_facts moduleを呼び出す方法です。
Factsを収集すると、ansible_facts変数に自動的に格納されます。

- name: Test gather facts on EOS
  hosts: eos
  gather_facts: false
  tasks:
    - name: Gather facts
      arista.eos.eos_facts:
        gather_network_resources:
          - interfaces
          - l2_interfaces
          - l3_interfaces

    - name: Debug _eos_facts_result
      ansible.builtin.debug:
        msg: '{{ ansible_facts }}'

実行結果は以下の通りです。
network_resourcesの配下がnetwork resource moduleの機能で収集した情報です。 Factsを使うと、network_resource_module以外のFacts情報も勝手に収集されます。
gather_subsetパラメータに!allを指定してもminに相当する情報は最低限収集されます。

TASK [Debug _eos_facts_result] ***
ok: [veos1] => 
  msg:
    net_api: cliconf
    net_fqdn: veos1
# ...
    net_system: eos
    net_version: 4.26.5M
    network_resources:
      interfaces:
      - description: veos2 Et1
        enabled: true
        name: Ethernet1
# ...
      l2_interfaces:
      - mode: trunk
        name: Ethernet1
        trunk:
          trunk_allowed_vlans:
          - '2'
# ...
      l3_interfaces:
# ...
      - ipv4:
        - address: 192.168.0.11/24
        name: Management1

2つ目の書き方は、network resource moduleのstate: gatheredを指定する方法です。
変数格納するにはregisterキーワードが必要です。

1つのFactsだけを取得するときはこの書き方でも良いと思います。
複数のFactsを収集する場合は、arista.eos.eos_factsの方がコンパクトに書けると思います。

- name: Gather EOS Facts
  hosts: eos
  gather_facts: false
  tasks:
    - name: Gather interfaces Facts
      arista.eos.eos_interfaces:
        state: gathered
      register: _eos_interfaces_result

    - name: Debug _eos_facts_result
      ansible.builtin.debug:
        msg: '{{ _eos_interfaces_result.gathered }}'

3つ目の書き方は、gather_factsを指定する方法です。
書き方がやや特殊で、個人的に覚えにくいです。
またFactsの収集タイミングがPlayの冒頭に固定されます。
私の環境では実機検証できていませんが、module_defaultsの配下にeos以外のOSについてもデフォルト値を指定することで複数OS分のデータ取得を1つのPlayでスッキリ表現できることがこの書き方のメリットなのだと推測します。
Gathering facts from network devices

- name: Test gather facts on EOS
  hosts: eos
  gather_facts: true
  module_defaults:
    arista.eos.eos_facts:
      gather_network_resources:
        - interfaces
        - l2_interfaces
        - l3_interfaces
  tasks:
    - name: Debug _eos_facts_result
      ansible.builtin.debug:
        msg: '{{ ansible_facts }}'

(参考) cli_parseモジュールの概要説明

cli_parseモジュールは、文字列をパースして構造化データを変数格納する機能を持ちます。
cli_parseモジュールを実行するには以下のような情報が必要となります。

cli_module_data_structure

構造化に使用するパーサ名をパラメータに指定する必要があり、選択可能なパーサとして以下の選択肢があります。

  1. ntc_templates
  2. TextFSM
  3. TTP (dmulyalin/ttp_templatesにテンプレートサンプルあり)
  4. PyATS
  5. Ansible Native Parsing Engine

parsers

パーサが複数あるとどれを使うか迷うと思います。
一概には言えませんが、「使い慣れたパーサを使いたい」、「日本語情報が多いものを使いたい」、「自分の現場にはCisco機器が多い」など様々な事情を総合して選定するものと想像します。

ご参考までに、私個人としてはansible.netcommon.ntc_templatesとansible.utils.textfsmを好んで使います。

ntc_templatesについては主要なネットワークOSのパーサ定義は既にある程度揃っていて、GitHub上に公開されています (networktocode/ntc-templates - /ntc_templates/templates)。
自分の欲しいパーサテンプレートがGitHub上に公開されていれば、まずはそれを使ってみます。

もしntc-templatesのリポジトリに既存のパーサ定義が存在しなかったり、既存のパーサ定義とは異なるデータ構造が欲しかった場合にはTextFSMテンプレートを自分で記述しつつansible.utils.textfsmを使います。
テンプレートファイルの文法はntc-templatesと同様なので、他のテンプレートファイルの書き方を参考にできます。
テンプレートファイルの文法を調べる際は、TextFSMのWiki情報やるつぼっとの記事がおすすめです。

その他、使い方の詳細はansible.utils.cli_parseのパラメータ一覧や実行例が参考になります。

実行例 (2-3) gather_subsetを使う場合

network resource moduleがAnsibleに登場する前から、eos_factsモジュールなどネットワーク機器からFactsを収集する機能は存在していました。
ややこしいですが、この機能はgather_subsetというキーワードとしてまだ残っています。
network resource moduleの方が機能としては後発ですし、恐らくgather_subset周りの機能が今後拡充されることはないと思います。
かといって廃止の予告は今のところないので、network resource moduleで取得できない情報の中でgather_subsetで取れる情報があれば、選択肢に入れてみても良いかもしれません。

くどいようですが私個人としては#実行例 (2-1) パーサを使う場合で全て賄ってしまうのが今のところは好きです。
とはいえパーサの使い方を学習するコストもありますし、一概にそれが正義だとは言えません (宗教戦争です)。

今回もFacts機能のため、書き方としてはeos_factsとgather_factsの2通りがあります。
1つずつ紹介していきます。

まずは1つ目のarista.eos.eos_factsを利用したplaybookのサンプルです。

- name: Test gather facts on EOS
  hosts: eos
  gather_facts: false
  tasks:
    - name: Gather facts
      arista.eos.eos_facts:
        gather_subset:
          - interfaces

    - name: Debug _eos_facts_result
      ansible.builtin.debug:
        msg: '{{ ansible_facts }}'

実行結果は以下の通りです。
なんだかshow interfacesをパースした感がありますね。

TASK [Debug _eos_facts_result] ***
ok: [veos1] => 
  msg:
# ...
    net_interfaces:
      Ethernet1:
        bandwidth: 1000000000
        description: veos2 Et1
        duplex: duplexFull
        ipv4: {}
        lineprotocol: up
        macaddress: 0c:65:34:fe:00:01
        mtu: 9214
        operstatus: connected
        type: bridged
# ...
    network_resources: {}

続いて2つ目のgather_factsを利用した書き方です。
Factsの取得タイミングがPlayの冒頭に固定されるものの、ネットワーク機器のOSの差分を吸収できる書き方にはなってそうです。
「AnsibleをOSごとの操作手順の違いを吸収する抽象化レイヤーとして使用する」考え方、昔は流行ってましたね。
抽象化の利点について聞くことは最近減ってきましたが、gather_factsを使用する唯一のモチベーションはそこなんじゃないかと思っています。

- name: Test gather facts on EOS
  hosts: eos
  gather_facts: true
  gather_subset:
    - interfaces
  tasks:

    - name: Debug _eos_facts_result
      ansible.builtin.debug:
        msg: '{{ ansible_facts }}'

おわりに

Ansibleのネットワーク機器の情報を集める方法は本当にたくさんあります。

showコマンドログを保存するだけなら迷いませんが、パースの手段は本当にたくさんあります。
ですが、迷ったらパーサかnetwork resource module系の機能を使いましょう。
言い換えると、#サマリ表の(2-3)は理由がなければ使わなくて良いと思います。

(Aristaのnetwork resource moduleはlldp_interfacesの情報をなぜか収集できないので、show lldp neighbors相当の情報をパースしたいときはcli_parseかgather_subsetのどちらかを使う必要があるという話はありますがそれはそのうち修正される小さなissueです)

結局のところは宗教戦争ですが、この記事がパース手段の選択の一助となれば幸いです。

Fedora41の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora 41のリリースノートを読んで、個人的に気になった項目をまとめます。

公式情報の見方

Fedora 41の変更点は、以下のリンクに載っています。
概要はリリースノートに、詳細情報はChange Setsのページに書いてあります。

Change Setの各サブタイトルのリンクから詳細情報に飛べるようになっています (下図赤枠部)。
詳細を知りたい時に便利なので、こちらも活用ください。

fedora_change_sets

Fedora 41の既知の問題は、以下にまとめられています。

他バージョンのFedoraについて知りたい場合は、以下のリンクを参照してください。

Release Notes & Changes

DNF5がデフォルトに

Fedora40まではDNFのバージョンが4系でしたが、Fedora41以降は5系になります。
RPMパッケージの名称もdnfからdnf5に変わります。

(DNF4)

dnf --version | head -1
# 4.19.2

ls -l /usr/bin/dnf
# lrwxrwxrwx. 1 root root 5 Mar 29  2024 /usr/bin/dnf -> dnf-3

rpm -qa | grep -P '^dnf(5|)-\d'
# dnf-4.19.2-1.fc40.noarch

(DNF5)

dnf --version | head -1
# dnf5 version 5.2.6.2

ls -l /usr/bin/dnf
# lrwxrwxrwx. 1 root root 4 Sep 20 09:00 /usr/bin/dnf -> dnf5

rpm -qa | grep -P '^dnf(5|)-\d'
# dnf5-5.2.6.2-1.fc41.x86_64

DNF5の改善点を一部抜粋します。

  • DNFプログラム本体のファイルサイズ軽量化 (コンテナ環境において、dnf関連ファイルのサイズが60%減)
  • クエリの高速化 (以下の例では実行時間が2-4秒短縮されていることがわかる)

(DNF4)

dnf clean all
# 17 files removed

# キャッシュ無し
time dnf repoquery > /dev/null 2>&1
# real  0m14.801s
# user  0m10.556s
# sys   0m0.540s

# キャッシュ有り
time dnf repoquery > /dev/null 2>&1
# real  0m2.878s
# user  0m2.692s
# sys   0m0.156s

(DNF5)

dnf clean all
# Removed 20 files, 9 directories. 0 errors occurred.

# キャッシュ無し
time dnf repoquery > /dev/null 2>&1
# real  0m10.151s
# user  0m5.554s
# sys   0m0.371s

# キャッシュ有り
time dnf repoquery > /dev/null 2>&1
# real  0m0.590s
# user  0m0.528s
# sys   0m0.095s
  • APIメソッドが変わる。古いAPIは一部廃止される (Ansibleでdnfとdnf5でモジュールが分かれている背景が理解できました)
  • UIの統合。サブコマンドやコマンドラインオプションのaliasが整備されており、新しいコマンド体系と従来のコマンドの両方をサポートする
    • 例: dnf repoquery -l <file>はdnf repoquery --files <file>のalias。DNF4の-lとDNF5の--filesはどちらも動作する
    • 詳しい説明はman dnf5-aliasesを参照

その他気づいたこととしては、以下が挙げられます。

  • manページがサブコマンド別に分割されて可読性が向上した
    • DNF4時点ではman dnfにdnf listã‚„dnf installなどのサブコマンドが全て書かれていて縦長なmanになっていた
    • DNF5ではman dnf5-listã‚„man dnf5-installなどサブコマンド別に分割されて見やすくなった
    • man dnf-listのように5を省略してもヒットしてくれる
  • 標準出力が細かく変更されている。dnf listを例にすると...
    • DNF4は画面横幅いっぱいに使うよう列幅が自動調整されていた。DNF5は列幅がコンパクトに (個人的にはこれが一番うれしいです)
    • DNF5はサブセクションの手前に空行が挿入されるようになった
    • 色分けが変わった。DNF4ではパッケージ名がオレンジ色と水色に塗り分けられていた (基準はわかりません)。DNF5ではインストール済みが緑、他は白とシンプルに

(DNF4)

dnf4_list

(DNF5)

dnf5_list

NetworkManagerのifcfg形式設定ファイルの提供終了

NetworkManagerの設定ファイル形式としてifcfg形式がFedora 41以降でサポートされなくなります。
以下のrpmパッケージがFedora 41以降のリポジトリでは提供されなくなりました。

  • NetworkManager-initscripts-ifcfg-rh
  • NetworkManager-dispatcher-routing-rules
  • NetworkManager-initscripts-updown

Fedora 41以降ifcfgがサポートされなくなることは、Fedora 39リリース時点で広報されていました。
Fedora39の変更点 - NetworkManager-initscripts-ifcfg-rhパッケージはFedora 41以降提供されない

本変更点は、NetworkManagerの設定ファイルを直接編集してnmcli connection load <file-name>で設定読み込みするような運用をしている場合に影響する可能性があります。
設定ファイルを直接いじらず、GUIやnmcli, nmtuiで運用している方には影響有りません。

設定ファイルの形式について詳細が気になる方は Fedora36の変更点 - /etc/sysconfig/network-scripts/ifcfg-* がデフォルト無効に をご覧ください。

network-scriptsの提供終了

RHEL6などで使われていたnetwork-scriptsというネットワーク設定/ステータス管理のツール群がFedora 41以降で提供されなくなります。
network-scriptsは既にアクティブな開発が停止している状況です。

「今後はNetworkManagerなど別のツールでネットワーク設定を管理していきましょう」ということだと思います。
Fedora 41以降の実機で確認すると、dnf list *network-scripts*でRPMパッケージを検索しても何もヒットしませんでした。

Kubernetestの複数バージョンがRPMリポジトリで提供されるようになった

Fedora 40までは、kubernetesパッケージの指し示すKubernetesのバージョンはFedoraのバージョンと1:1対応していました。
例えば、Fedora 40のRPMで提供されるKubernetesのバージョンは1.29に固定されていました。
Kubernetes 1.31が最新バージョンだったとしても、Fedora 40の公式リポジトリからインストールできるのはKubernetes 1.29のみです。
RPMS - kubernetes

一方で、Kubernetesは4ヶ月ごとにリリースされ、各リリースは1年間サポートされるというリリースサイクルです。
つまり、Kubernetesは常に3つのバージョンが同時に提供されています。

したがって、Fedora 40までは以下のような課題がありました。

  • 最新版のKubernetesをインストールできるとは限らない。ある時点で最新のKubernetesを使うために、半年に一度のFedoraリリースを待たなければならない。しかしFedoraがリリースされる頃には更に新しいKubernetesがリリースされているのでは...
  • Kubernetesのアップグレード時、前後でマイナーリリースバージョンが連続したアップグレードパスしかサポートされない (Kubernetes Documentationより)。Fedoraを使い続けているとどこかでKubernetesのバージョンが不連続になり、アップグレードできなくなる懸念があった

Fedora41以降はサポートされているKubernetesバージョン全てについてRPMを配布するようになりました。
それに伴い、パッケージ名も若干変わりました。
詳しくは以下の実機コマンド出力をご覧ください。

(Fedora 40)

dnf list kubernetes*
# Last metadata expiration check: 0:49:18 ago on Sun 03 Nov 2024 03:00:11 PM JST.
# Available Packages
# kubernetes.x86_64                         1.29.9-2.fc40                  updates
# kubernetes-client.x86_64                  1.29.9-2.fc40                  updates
# kubernetes-kubeadm.x86_64                 1.29.9-2.fc40                  updates
# kubernetes-systemd.x86_64                 1.29.9-2.fc40                  updates

(Fedora 41)

dnf list kubernetes*
# Updating and loading repositories:
#   Repositories loaded.
# Available packages
# kubernetes.x86_64             1.29.9-1.fc41  fedora
# kubernetes-client.x86_64      1.29.9-1.fc41  fedora
# kubernetes-kubeadm.x86_64     1.29.9-1.fc41  fedora
# kubernetes-systemd.x86_64     1.29.9-1.fc41  fedora
# kubernetes1.29.x86_64         1.29.10-2.fc41 updates
# kubernetes1.29-client.x86_64  1.29.10-2.fc41 updates
# kubernetes1.29-kubeadm.x86_64 1.29.10-2.fc41 updates
# kubernetes1.29-systemd.x86_64 1.29.10-2.fc41 updates
# kubernetes1.30.x86_64         1.30.6-1.fc41  updates
# kubernetes1.30-client.x86_64  1.30.6-1.fc41  updates
# kubernetes1.30-kubeadm.x86_64 1.30.6-1.fc41  updates
# kubernetes1.30-systemd.x86_64 1.30.6-1.fc41  updates
# kubernetes1.31.x86_64         1.31.2-1.fc41  updates
# kubernetes1.31-client.x86_64  1.31.2-1.fc41  updates
# kubernetes1.31-kubeadm.x86_64 1.31.2-1.fc41  updates
# kubernetes1.31-systemd.x86_64 1.31.2-1.fc41  updates

今後はバージョン番号付きのkubernetesパッケージを明確に指定してインストールすることが推奨されています。
そうすることでKubernetesのバージョンアップ作業もシンプルになります。 Fedora Quick Docs - Versioned rpm update recommendations

例えば、現時点でkubernetes1.30をインストール済みだったとします。
1.30系の中でパッチを更新する場合は、単純にsudo dnf upgradeを実行します。
1.30から1.31にバージョンアップしたい場合は、以下のコマンドを実行します。

# Remove and replace with kubernetes 1.30 and 1.31 as an example
sudo dnf remove kubernetes1.30 kubernetes1.30-kubeadm kubernetes1.30-client
sudo dnf install kubernetes1.31 kubernetes1.31-kubeadm kubernetes1.31-client

fedora-repoqueryコマンド

fedora-repoqueryパッケージがリリースされました。
他のディストリビューションのパッケージを検索するのに使えます。
(後述の実例を見たほうがイメージがつきやすいと思います)

fedora-repoqueryを使うには、以下のコマンドでインストールする必要があります。

sudo dnf install fedora-repoquery

では実際に使ってみます。

CentOS Stream 9で提供されているOpenSSHクライアントのバージョンを調べます。
c9がCentOS Stream 9を表します。

fedora-repoquery c9 openssh-clients
# openssh-clients-8.7p1-38.el9.x86_64 (c9s-BaseOS)
# openssh-clients-8.7p1-41.el9.x86_64 (c9s-BaseOS)
# openssh-clients-8.7p1-42.el9.x86_64 (c9s-BaseOS)
# openssh-clients-8.7p1-43.el9.x86_64 (c9s-BaseOS)
# openssh-clients-8.7p1-44.el9.x86_64 (c9s-BaseOS)

ディストリビューション名を省略すると、今のディストリビューションになります。

fedora-repoquery openssh-clients
# openssh-clients-9.8p1-3.fc41.1.x86_64 (fedora)
# openssh-clients-9.8p1-3.fc41.2.x86_64 (updates)

ディストリビューションやパッケージを同時に指定することも可能です。
以下の例では、CentOS Stream 9とEPEL 9 NEXTの両方を検索しています。
(補足: EPEL9はRHEL9用、EPEL9 NEXTはCentOS Steam9用のリポジトリです)

fedora-repoquery epel9-next c9 nodejs nodejs-devel
# nodejs-devel-16.18.1-5.el9.next.x86_64 (epel9-next)
# nodejs-16.20.2-3.el9.x86_64 (c9s-AppStream)
# nodejs-16.20.2-8.el9.x86_64 (c9s-AppStream)

ディストリビューション名として指定できるのは以下のキーワードです。
現時点でFedora, CentOS Stream, EPEL, EPEL NEXT, ELNに対応しています。
そのうちCoprにも対応するかもとのことです。

fedora-repoquery -l
# epel8 current
# epel9 current
# epel9-next current
# f39 current
# f40 current
# f41 current
# eln pending
# epel10 pending
# f41 pending
# rawhide pending
# f42 pending

以上、実際にLinuxをインストールしたりググったりすることなく他ディストリビューションのパッケージ構成を手軽に検索できるツール、fedora-repoqueryの紹介でした。

(参考) fedora-repoquery -lの細かい話

上記fedora-repoquery -lの出力について気になった部分があったので、軽く調べてみました。

確実な情報はないものの、currentやpendingはリポジトリのリリースステータスと思われます (Release.hs)。
pendingだからといってfedora-repoqueryの実装が仮であるという意味ではなく、あくまでリポジトリのステータスがpendingであると理解しています。
安心して使いましょう。

リリース済みのf42 (Fedora 42) のステータスがpendingである点が気になりましたが、こちらもおそらく正しいです。
fedora-repoqueryはBodhi ServerのREST APIから得られたjsonデータをパースしてリポジトリ名やステータス情報を取得しているようでした (Release.hs)。
おそらくAPIで取得している情報は、Bodhi Server上で動いているFedora Update System - Active Releasesなのではないかと思います。
2024/11/3時点でFedora 42が"Pending Releases"の配下にかかれていたので、fedora-repoquery -lはそれを忠実に反映したものと思われます。

iptablesからnftablesへの移行

Fedora 41以降、NetavarkとLibvirtのバックエンドがiptablesからnftablesに移行されました。
nftablesはiptablesの後継です。
netfilter.org - nftables

NetavarkとLibvirtとは何かについてそれぞれ補足します。

NetavarkはPodmanコンテナのネットワーク実装を担うプログラムのようです。

Libvirtは仮想化アプリケーションやハイパーバイザを操作するための抽象化レイヤーを提供するプログラムで、ライブラリやデーモンプロセスとして存在します (QEMU、KVM、libvirtの基礎知識まとめ - libvirt とは)。
LibvirtはKVM仮想マシンを管理するCLI (virshやvirt-install)、GUI (virt-manager, virt-viewer)、そして仮想化基盤であるKubeVirt (->OpenShift Virtualization), OpenStackなどに使われています (Applications using libvirt)。

iptablesからnftablesへの動きはFedora 32頃から段階的に進められてきました。
その背景について、後続の2セクションに詳しく書きました。
Fedora 41のアップデートから少し話が脱線するので、興味のある方のみお読みください。

(背景) ebtables, arptables, iptablesの話

元々以下のようなソフトウェアがありましたが、netfilterは全ての後継に当たるという位置づけです。
いずれのツールも同じような操作感でルール設定できるCLIになっています。

ソフトウェア名 動作タイミング 機能
ebtables Ethernet bridgeインターフェースにフレームが届いたとき フィルタ、NAT、brouteを設定できる (※)
arptables ARPを送受信したとき ARP送受信のフィルタを行う
iptables IPパケットを送受信するとき フィルタ (L4 Firewall)、NAT、その他の制御ができる

(※) フィルタとは、パケットの通過/ドロップを制御する機能のこと。NATとはアドレス変換 (ebtablesならMACアドレス変換)。brouteとは、bridgingせずそのままnetwork stackに処理を移行してL3以上の制御を行うこと

(※) broutingの参考リンク。brouterとは。brouterの実装例1。実装例2。実装例1より、brouterでL3スイッチを再現するには結構な量のルール記述が必要とわかる

(背景) 後継ツールであるnftablesへの段階的な移行

nftablesは、ebtables, arptables, iptablesの後継に当たるツールです。
nftというCLIでnftablesを操作できますが、文法が従来のebtables, arptables, iptablesとは全く異なります。

そこで、ebtables, arptables, iptablesと全く同じCLIを使いつつも、Linux Kernel側に実装されたAPIをnftables互換に寄せたプログラムが用意されました。
nftablesへの移行措置としてです。
nftablesに寄せたプログラムを含むRPMパッケージはiptables-nftという名前です。
iptables-nftにはebtables, arptables, iptablesの実行ファイルが全て含まれています。
併せて従来どおりの古いLinux Kernel APIに基づいて実装されたプログラムを含むRPMパッケージがebtables-legacy, arptables-legacy, iptables-legacyに名称変更されました。
この変更はFedora 32時点で行われました。
Fedora Wiki - Changes/iptables-nft-default

IPフィルタ機能について言うと、iptables-legacy, iptables-nft, nftという3つのCLIがあるということになります。
比較的新しいディストリビューションであればnftかiptables-nftを使っているはずです。
これら3つのツールの実装の違いについて詳しく説明したブログがあります。
読んでみると面白いので、ご参考までに掲載しておきます。
Red Hat Developer - iptables: The two variants and their relationship with nftables

併せて、firewalldのバックエンドもiptablesからnftablesに変更されました。
firewalldはL4ファイアウォール機能を提供するCLIフロントエンドです。
Fedora Wiki - Changes/firewalld default to nftables

そして今回、Fedora 42にてNatavarkとlibvirtのバックエンドもiptablesからnftablesへ移行されました。

RHELやFedoraに付属するツールの中で主だったものはiptablesからnftablesへ移行されてきた印象です。
もちろん、Dockerなど引き続きiptablesを使っているソフトウェアもまだまだ存在します。
Docker Docs - Packet filtering and firewalls

RedisをValkeyに置き換えた

「RedisのライセンスがRASLv2/SSPLに変わったことで、FedoraとしてRedisを提供することが厳しくなった」というのが経緯のようです。
ライセンスの詳しい話は理解しきれませんでしたので、詳しいところはリンク先を参照してください。

ValkeyはRedisのforkであり、Valkey 7.2.5時点ではRedisとの互換性が100%とのことです。

(参考) valkey-compat-redis

RedisからValkeyに移行するにあたり、valkey-compat-redisというRPMパッケージが用意されています。
中身は以下の通りシンプルです。

dnf repoquery -l valkey-compat-redis
# /usr/bin/redis-benchmark
# /usr/bin/redis-check-aof
# /usr/bin/redis-check-rdb
# /usr/bin/redis-cli
# /usr/bin/redis-sentinel
# /usr/bin/redis-server
# /usr/libexec/migrate_redis_to_valkey.sh

実行ファイルは全てvalkeyへのシンボリックリンクです。

ls -l usr/bin
# total 0
# lrwxrwxrwx. 1 root root 16 Oct  7 09:00 redis-benchmark -> valkey-benchmark
# lrwxrwxrwx. 1 root root 16 Oct  7 09:00 redis-check-aof -> valkey-check-aof
# lrwxrwxrwx. 1 root root 16 Oct  7 09:00 redis-check-rdb -> valkey-check-rdb
# lrwxrwxrwx. 1 root root 10 Oct  7 09:00 redis-cli -> valkey-cli
# lrwxrwxrwx. 1 root root 15 Oct  7 09:00 redis-sentinel -> valkey-sentinel
# lrwxrwxrwx. 1 root root 13 Oct  7 09:00 redis-server -> valkey-server

/usr/libexec/migrate_redis_to_valkey.shは、RedisからValkeyへの移行ツールです。
元々Redisで運用して設定ファイル等をカスタマイズしているときに、このスクリプトを実行すると移行できるようです (もちろんスクリプトの過信は禁物です。ダブルチェックしましょう)。
中身は既存のRedis設定ファイルやライブラリをValkeyのディレクトリに移動するmvや、redisをvalkeyに置換するsedコマンドが主でした。

Python 3.13

Fedora 40ではPython 3.12系でしたが、Fedora 41ではPython 3.13系になります。
Fedoraが最新バージョンのPythonに追従するのはいつもどおりの動きです。
他のプログラミング言語も同様に最新化されているはずです。

Pythonバージョンアップ時、毎回ユーザー権限でインストールしたPythonパッケージ (venvを含む) の移行が必要になります。
移行手順の差分が上述のFedora 41 Release Notesのリンクに書いてあるので、参考にすると良いと思います。

Python2系のサポート終了

Python公式ではPython2系がEnd of Lifeになって久しいですが、いよいよFedoraでも互換性のために残っていたPython2.7のRPMパッケージ提供を終了しました。
RHELやCentOS Streamでも既にRPMの提供が終了しています。

Bugs

f41タグ付きのCommon Issuesを確認しましたが、特に気になるものはありませんでした。

...が、手元の環境で別のバグを踏んだので紹介しておきます。

Cockpit MachinesからVMの表示・操作ができない

Fedora 41においてCockpitからVM操作ができない不具合が発生しています。
原因はSELinuxによる拒否です。
今後バグが対処され、selinux-policyパッケージが更新されれば解消される見込みです。
GitHub - cockpit-project/cockpit-machines - issue#1818
Bugzilla - 2316474 - SELinux is preventing pool-libvirt-db from 'connectto' accesses on the unix_stream_socket /run/libvirt/libvirt-sock.

バグを踏んでいる間はvirshコマンドやvirt-managerで代替することで何とか乗り切りましょう。
これらのツールは正しく動作することを確認できています。

Fedora40の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora 40のリリースノートを読んで、個人的に気になった項目をまとめます。

公式情報の見方

Fedora 40の変更点は、以下のリンクに載っています。
概要はリリースノートに、詳細情報はChange Setsのページに書いてあります。

Change Setの各サブタイトルのリンクから詳細情報に飛べるようになっています (下図赤枠部)。
詳細を知りたい時に便利なので、こちらも活用ください。

fedora_change_sets

Fedora 40の既知の問題は、以下にまとめられています。

他バージョンのFedoraについて知りたい場合は、以下のリンクを参照してください。

Release Notes & Changes

dnf実行時、filelistsを必要なときのみダウンロードするようになった

dnfでリポジトリを参照する際、操作内容によってメタデータをダウンロードします。
このメタデータの中にfilelistsと呼ばれるものがあります。

filelistsとは、そのリポジトリ内に含まれているrpmパッケージと、パッケージに含まれるファイル名すべてをxml形式で記録したファイルのことです。
見た目のサンプルとして、以下にzipパッケージの部分を抜粋します。

<package pkgid="feafa5144f815ab92fca16446ec7eea763e116a27e3c5716f7308a314e8138ba" name="zip" arch="x86_64">
  <version epoch="0" ver="3.0" rel="40.fc40"/>
  <file>/usr/bin/zip</file>
  <file>/usr/bin/zipcloak</file>
  <file>/usr/bin/zipnote</file>
  <file>/usr/bin/zipsplit</file>
  <file type="dir">/usr/lib/.build-id</file>
  <file type="dir">/usr/lib/.build-id/29</file>
  <file>/usr/lib/.build-id/29/bb2d05a3cf4baa7462a94a29ed39b97b44884b</file>
  <file type="dir">/usr/lib/.build-id/30</file>
  <file>/usr/lib/.build-id/30/ee0623bc9369b448a820bad6a65babf8e7e93f</file>
  <file type="dir">/usr/lib/.build-id/32</file>
  <file>/usr/lib/.build-id/32/57caf91e8de8514f0e3ba270d940e61f38b60d</file>
  <file type="dir">/usr/lib/.build-id/38</file>
  <file>/usr/lib/.build-id/38/7b7e0ad52e0c77ac310531fdc6f558841fccaa</file>
  <file type="dir">/usr/share/doc/zip</file>
  <file>/usr/share/doc/zip/CHANGES</file>
  <file>/usr/share/doc/zip/README</file>
  <file>/usr/share/doc/zip/README.CR</file>
  <file>/usr/share/doc/zip/TODO</file>
  <file>/usr/share/doc/zip/WHATSNEW</file>
  <file>/usr/share/doc/zip/WHERE</file>
  <file>/usr/share/doc/zip/algorith.txt</file>
  <file type="dir">/usr/share/licenses/zip</file>
  <file>/usr/share/licenses/zip/LICENSE</file>
  <file>/usr/share/man/man1/zip.1.gz</file>
  <file>/usr/share/man/man1/zipcloak.1.gz</file>
  <file>/usr/share/man/man1/zipnote.1.gz</file>
  <file>/usr/share/man/man1/zipsplit.1.gz</file>
</package>

このfilelistsですが、多くのdnf操作において必要とされません。
従来のdnfでは、dnf list <パッケージ名>やdnf repoquery <パッケージ名>のようにrpmに含まれるファイル名を必要としない操作においてもfilelistsをダウンロードしていました。

Fedora 40以降 (dnf 4.19.0以降) では、必要な場合を除いてデフォルトでfilelistsをダウンロードしないようになりました。
この変更により余分なメタデータのダウンロードが抑止され、キャッシュが効いていないときのdnf実行速度が大幅に向上しました。

(検証) メタデータダウンロードにかかる時間の比較

試しに私の環境のFedora 40 VMで実行速度とダウンロードサイズを比較してみました。

まず、従来どおりのfilelistsをダウンロードしたときの結果を示します。
事前にsudo dnf clean metadataでメタデータのキャッシュをクリアした上で試験しました。
メタデータのダウンロードサイズが合計87 MB、コマンド実行時間は約41秒です。
このデータは、filelistsをダウンロードするようわざわざ設定変更したFedora 40で取得したものです。

# time sudo dnf repoquery rpm
Fedora 40 - x86_64                             5.4 MB/s |  75 MB     00:14    
Fedora 40 openh264 (From Cisco) - x86_64       2.3 kB/s | 2.6 kB     00:01    
Fedora 40 - x86_64 - Updates                   8.6 MB/s |  12 MB     00:01    
rpm-0:4.19.1.1-1.fc40.x86_64

real    0m41.338s
user    0m27.085s
sys 0m1.616s

filelistsをダウンロードしないときの結果を示します。
一度sudo dnf clean metadataでメタデータのキャッシュをクリアし、filelistsをダウンロードしない設定に切り替えてから同じコマンドを実行しました。
ダウンロードしたファイルサイズは23.4 MB、実行時間は10.5秒まで短縮されました。

# time sudo dnf repoquery rpm
Fedora 40 - x86_64                             13 MB/s |  20 MB     00:01    
Fedora 40 openh264 (From Cisco) - x86_64       1.0 kB/s | 1.8 kB     00:01    
Fedora 40 - x86_64 - Updates                   4.2 MB/s | 3.4 MB     00:00    
Last metadata expiration check: 0:00:01 ago on Tue 30 Apr 2024 04:39:06 PM JST.
rpm-0:4.19.1.1-1.fc40.x86_64

real    0m10.500s
user    0m7.043s
sys 0m0.432s

(検証) filelistsはどこに存在するのか?

/var/cache/dnf/リポジトリ名-英数字/repodata/英数字-filelists.xml.拡張子にありました。

それぞれ圧縮されているので、中身を見るにはunzckやgunzipといったコマンドで解凍してから開く必要があります。
unzckコマンドは、Fedoraであればsudo dnf install zchunkでインストールできます。

ファイルの中身については先ほどのセクションですでに示したので割愛します。

# find /var/cache/dnf/ -name '*filelists*' | xargs du -h
56M /var/cache/dnf/fedora-6c3a9e5977a00788/repodata/a07f2d719480923d5a2af772eed004eef5c1c6c1032258b740c9515fba82c173-filelists.xml.zck
8.2M   /var/cache/dnf/updates-02a32a5ce99e20ab/repodata/42fba8b75ea15274d85d9c5ea56242b341628e2c04bfad2979d390c535f80a57-filelists.xml.zck
8.0K   /var/cache/dnf/fedora-cisco-openh264-3e5cc8d7297aea85/repodata/c339739d50e2ae7ff271d6987aa9d95f37cec4da942afa0dc96bbe977e5cd333-filelists.xml.gz

(検証) Fedora 39とFedora 40の挙動を比較してみる

以下の手順を様々なパターンで試しつつ、挙動を比較してみました。

  1. sudo dnf clean metadataを実行し、メタデータのキャッシュを削除する
  2. dnfコマンド (A) を実行する
  3. find /var/cache/dnf/ -name '*filelists*'を実行し、filelistsが生成したかどうかを確認する (B)

結果は以下の通りです。
※/var/cache/dnf/配下にキャッシュ格納するのはrootユーザのみなので、本試験はすべてrootユーザで実施しました (一般ユーザは/var/tmp/dnf-ユーザ名-乱数/配下にキャッシュ格納します)

試験ID Fedoraバージョン dnfコマンド (A) filelistsは生成したか (B)
1 Fedora 39 sudo dnf repoquery rpm 生成した
2 Fedora 39 sudo dnf repoquery -l rpm 生成した
3 Fedora 40 sudo dnf repoquery rpm 生成しなかった
4 Fedora 40 sudo dnf repoquery -l rpm 生成した

結果 (B) から、全てこれまでに説明した仕様通りになっていることが読み取れました。

最下行の試験4について補足すると、dnf repoquery -lはRPMパッケージ内に含まれるファイルを列挙するコマンドです。
このコマンドはfilelists相当の情報を要求するため、filelistsが生成することは想定どおりです。
(今回のケースでは全パッケージの情報を取得する必要はないのですが、そこはdnfの仕様がそうなっているのだと理解しました)

(補足) filelistsを常にダウンロードする方法

従来どおりfilelistsを常にダウンロードしたい場合は、/etc/dnf/dnf.confにおいて、以下の行を[main]セクションの配下に追記します。

optional_metadata_types=filelists

wgetがwget2に置き換わった

Fedora 40ではwgetがwget2に置き換えられました。
wget2は従来のwgetとは異なるライブラリを利用していて、より活発に開発が行われているとのことです。

Fedora 40の公式リポジトリでは、従来バージョンのwgetのRPMファイルは提供されなくなりました。

wgetとwget2の機能差分

以下のページにwgetとwget2の機能差分がまとめられています。
GitLab - gnuwget/wget2 - Wiki - #Different behavior of Wget2

wget2ではFTP、WARC (Web Archive)関連のオプションが今のところサポートされないようです。
代わりにhttp2, hsts, 統計値の表示など多くの機能が追加されています。

パッケージ構成の違い

従来のwgetパッケージが以下2つのパッケージに置き換えられました。

パッケージ名 内容
wget2 wget2実行ファイルを含むwget2本体
wget2-wget wgetをwget2に差し替えるファイル群。
/usr/bin/wget -> wget2というシンボリックリンクなど

これにより、wgetコマンドを実行するとwget2コマンドが実行されます。
また、man wgetを実行するとman wget2が参照されます。

NetworkManagerにて、IPv4のアドレス重複検知がデフォルト有効に

Fedora 39以前ではIPv4のアドレス重複検知機能がデフォルト無効でしたが、Fedora 40以降ではデフォルト有効になります。

内部的には、ipv4.dad-timeoutのデフォルト値が変更されました。
とはいっても、nmcli connection show <connection-name>で表示されるipv4.dad-timeoutの値はFedora 39でもFedora 40でも-1のままです。
-1とは、「デフォルト値に従う」ことを意味します。
nmcliの出力やNetworkManager.confなどの設定ファイルには更新がありませんが、デフォルトの挙動が変わったのが今回の差分です。

ちなみにipv4.dad-timeoutの値が0の場合は無効化、1〜30000の場合はミリ秒単位でDAD (Duplicate Address Detection) のために実行されるARP Probeのタイムアウト値が指定されます。
man nm-settings-nmcliに記載の通り、実際には指定した値の等倍〜半分の間の値が乱数で決定されてタイムアウト値として使用されるとのことです。

(補足) DADとは、Duplicate Address Detectionの略です。インターフェースがupしたときにARP Probeと呼ばれる「自分のIPアドレスをセットしたARP Request」をブロードキャストで送信し、万が一応答があった場合にIPアドレス重複として検知する仕組みです。次セクションの検証結果を先にお伝えすると、Fedora 40においてIPアドレス重複を検知した場合、静的なIPアドレスであればインターフェースをupせず、動的なIPアドレスであれば別の利用可能なIPアドレスを代わりにアサインするという動きになりました。

(検証) 実際にIPv4アドレス重複させてみる

以下3台のVMを予め用意しておきます。

Fedoraバージョン ホスト名 IPv4アドレス割当方式 IPv4アドレス
Fedora 40 fedora40-dhcp dhcp 192.168.122.158/24
Fedora 40 fedora40-manual manual 未設定
Fedora 39 fedora39-manual manual 未設定

fedora40-manualに対して以下のコマンドを実行し、fedora40-dhcpとIPアドレスを重複させてみます。
すると、30秒前後経過した後にエラーメッセージが出てConnectionの有効化に失敗します。

fedora40-manual# sudo nmcli connection add ifname enp1s0 con-name test type ethernet ipv4.method manual ipv4.addresses 192.168.122.158/24

# Connectionの有効化に失敗する
fedora40-manual# time sudo nmcli connection up test
# Error: Connection activation failed: IP configuration could not be reserved (no available address, timeout, etc.)
# Hint: use 'journalctl -xe NM_CONNECTION=0e08924a-c79c-4672-b148-31d0d492aec5 + NM_DEVICE=enp1s0' to get more details.
# real 0m32.095s
# user 0m0.032s
# sys  0m0.019s

# 元々のConnectionのまま
fedora40-manual# nmcli connection show
# NAME    UUID                                  TYPE      DEVICE 
# enp1s0  f4d9f489-6247-383a-9fb2-0b7c84e762ec  ethernet  enp1s0 
# lo      5077f790-ccff-4a25-9f6b-4cfdfad2df57  loopback  lo     
# test    0e08924a-c79c-4672-b148-31d0d492aec5  ethernet  --   

# ログを抜粋。IPアドレス重複のエラーが出ていた
fedora40-static:~# journalctl --no-pager -eu NetworkManager.service
# May 01 01:31:12 fedora40-static NetworkManager[897]: <warn>  [1714494672.4948] device (enp1s0): IP address 192.168.122.158 cannot be configured because it is already in use in the network by host 52:54:00:4B:B9:2A

fedora39-manualでも同様の操作を行い、IPv4アドレスを重複させてみます。
今度は一瞬でIPアドレス設定が完了し、容赦なくIPアドレス重複が発生します。

fedora39-manual# sudo nmcli connection add ifname enp1s0 con-name test type ethernet ipv4.method manual ipv4.addresses 192.168.122.158/24

# Connectionの有効化に成功する
fedora39-manual# time sudo nmcli connection up test
# Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)

# real 0m0.112s
# user 0m0.010s
# sys  0m0.011s

更にIPアドレス重複が発生させた状態で、fedora40-dhcpのインターフェースを一度downさせ、その後upさせてみます。
すると元の192.168.122.158/24ではなく、別の192.168.122.159/24が動的にアサインされます。

fedora40-dhcp# sudo nmcli connection down enp1s0
fedora40-dhcp# time sudo nmcli connection up enp1s0
# Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)

# real 0m13.406s
# user 0m0.015s
# sys  0m0.016s

今回の検証結果をまとめると、以下のようになりました。

  • Fedora 40以降、IPv4アドレス重複検知機能がデフォルトで有効化された (Fedora 39以前ではデフォルト無効だった)
  • 静的なIPアドレス設定で重複を検知した場合、30秒程度でConnectionの有効化に失敗した
  • DHCP構成でlease期限内のIPアドレスが重複していることを検知した場合、13秒程度で次の空きIPアドレスを利用した
    • (補足) RFC5227ではDHCP ClientがDHCP DECLINEを送付することまで規定されているものの、IPアドレス設定のエラーを返すか次の空きIPアドレスを使うかの判断は実装に委ねられていた

Python 3.7のRPM提供終了

python3.7パッケージがFedora 40のリポジトリで配布されなくなりました。
dnf provides python3.7と検索してもRPMが見つからなくなりました。

なお、Python 3.7は2023/6/27にEnd of lifeになりました。
(Python Developer's Guide - Status of Python versions)

背景には以下の事情があったとのことです。

  • End of lifeになってからもDebian 10 "Buster" LTSのテストのためにPython3.7を残しておいた
  • Fedora 40がリリースされる頃にはDebian 10ã‚‚End of lifeになるため残しておく理由がなくなった

RHEL 8のサポートが継続していることを理由として、Python 3.6についてはFedora 40でも引き続き提供されるとのことでした。

Bugs

f40タグ付きのCommon Issuesを確認しましたが、特に気になるものはありませんでした。

Fedora39の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora39のリリースノートを読んで、個人的に気になった項目をまとめます。

私目線では、今回のFedora39リリースにはあまり大きな変更がありませんでした。

公式情報の見方

Fedora 39の変更点は、以下のリンクに載っています。
概要はリリースノートに、詳細情報はChange Setsのページに書いてあります。

Change Setの各サブタイトルのリンクから詳細情報に飛べるようになっています (下図赤枠部)。
詳細を知りたい時に便利なので、こちらも活用ください。

fedora_change_sets

Fedora39の既知の問題は、以下にまとめられています。

他バージョンのFedoraについて知りたい場合は、以下のリンクを参照してください。

Release Notes & Changes

Bashプロンプトに色がついた

Fedora 38以前ではBashプロンプトには色がついていませんでしたが、Fedora 39以降では色がつくようになりました。
また、直前のコマンドのExit Statusが0以外の場合にプロンプト文字列として表示されるようになりました。

↓従来のプロンプト

monochrome-bash-prompt

↓Fedora 39以降のプロンプト

colored-bash-prompt

なお、この色付けはログインシェルに対してしか適用されません。

具体的には、SSHでログインした場合には適用されません。
SSHでログインしたあと、更に手動でbashコマンドを実行すると適用されます。

login_to_colorize_bash

PROMPT_COLOR変数にカラーコードを入れることで、任意の色に変更できる作りになっています。
カラーコードの書き方はbash:tip_colors_and_formattingが参考になります。
以下の例では35がPurple、96がLight Syan、33がYellow、1がBold (太字) という意味になります。

prompt_color_to_customize

SSHログイン時も反映したい場合は、以下のスクリプトを~/.bashrcに追記します。
sourceコマンドの後にPROMPT_COLORを変更してもしっかり反映される作りになっています。

source /etc/profile.d/bash-color-prompt.sh
# PROMPT_COLOR=33

Bashプロンプト色付けの詳細

今回の変更は、Fedora39以降に初期インストールされているbash-color-promptというRPMパッケージによって導入されました。

rpm -ql bash-color-prompt、またはdnf repoquery -l bash-color-promptによってインストールされたファイル群を確認すると、/etc/profile.d/bash-color-prompt.shというシェルスクリプトが追加されていることがわかります。
シェルスクリプトの中身を見てみましょう。

if [ "$PS1" = "[\u@\h \W]\\$ " -a "${TERM: -5}" = "color" -o -n "${prompt_color_force}" ]; then
    PS1='\[\e[${PROMPT_COLOR:-32}m\]\u@\h\[\e[0m\]:\[\e[${PROMPT_COLOR:-32}m\]\w\[\e[0;31m\]${?#0}\[\e[0m\]\$ '
fi

ちょっと読むのが辛いかもしれませんが、最初のif文は以下の意味です。

  • PS1変数が初期値かつ、TERM変数がcolorで終わる場合 (手元の環境ではTERM=xterm-256colorでした)
  • または、prompt_color_force変数が空ではない場合

そして条件にマッチしたとき、PS1を書き換えています。
PS1はBashの中で特殊な意味を持つ変数であり、この変数を書き換えることでプロンプト文字列を変更できます。
(参考) Bash Reference Manual - Controlling the Prompt

以上より、Bashにログインしたときに特定の条件を満たしていればプロンプトがカスタマイズされることがわかりました。

上記スクリプトは/etc/profile.d/配下に書かれているので、「bashログイン時」のみに実行されます。
そのためSSHログイン時も含めてbash起動時もプロンプト文字列を変更したい場合には、~/.bashrcをカスタマイズする必要がありました。

KickstartにDNS関連のオプションが追加された

Kickstartで以下のオプションを追加で使えるようになりました。
いずれもネットワークインターフェースに紐づけて設定するDNS関連のオプションです。

オプション名 意味
--ipv4-dns-search
  • NetworkManagerのipv4.dns-searchに相当
  • 通信の宛先にDNSショートネームを指定した場合に
    自動補完するドメイン名を指定する
  • IPv4に対してのみ有効
--ipv6-dns-search
  • 同上
  • ただしIPv6に対してのみ有効
--ipv4-ignore-auto-dns
  • DHCPによるDNSサーバ自動設定を無効化する
  • IPv4に対してのみ有効
--ipv6-ignore-auto-dns
  • 同上
  • ただしIPv6に対してのみ有効

EFIファイルシステムの最小サイズが200 MiBから500 MiBに拡張

マザーボードのファームウェアにBIOSではなくUEFIを使っている方に該当します。
ESP (EFI System Partition) という先頭に作られるパーティションのサイズが最小200 MiBから500 MiBに引き上げられました。
ファームウェア更新時に必要な空き容量が近い将来引き上げられることが背景にあります。

ESPの最大サイズは従来の600 MiBのまま変更ありません。
また、BIOSをお使いの方には影響ありません。

NetworkManager-initscripts-ifcfg-rhパッケージはFedora 41以降提供されない

この変更はNetworkManagerをGUI、nmcli、nmtuiなどで操作している方には影響ありません。
RHEL6時代まで続いたnetwork-scripts形式の設定ファイルを編集して運用している方に影響があります。

NetworkManager-initscripts-ifcfg-rhパッケージについて、詳細はFedora36の変更点 - /etc/sysconfig/network-scripts/ifcfg-* がデフォルト無効にを参照してください。

Python 3.12

Fedora 38ではPython 3.11系でしたが、Fedora 39系ではPython 3.12系が提供されるようになります。

Fedoraはリリースのたびに最新のPythonバージョンに追従することが基本ポリシーのようです。
(おそらく他の言語も同様ですが、Python以外はチェックしていません)

Bugs

f39タグ付きのCommon Issuesを確認しましたが、特に気になるものはありませんでした。

まとめ

興味を持ったトピック限定ですが、Fedora39の更新点をまとめました。

Fedora38の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora38のリリースノートを読んで、個人的に気になった項目をまとめ...ようと思いましたが、今回は私目線で気になる更新点は1つもありませんでした。

リリースノートの読み方や不具合情報の探し方については、以下の過去記事を参照してください。
Fedora37の変更点 - #公式情報の見方

以上。

Fedora37の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora37のリリースノートを読んで、個人的に気になった項目をまとめます。

私目線では、今回のFedora37リリースにはあまり大きな変更がありませんでした。

公式情報の見方

Fedora 37の変更点は、以下のリンクに載っています。
概要はリリースノートに、詳細情報はChange Setsのページに書いてあります。

Change Setの各サブタイトルのリンクから詳細情報に飛べるようになっています (下図赤枠部)。
詳細を知りたい時に便利なので、こちらも活用ください。

fedora_change_sets

Fedora37の既知の問題は、以下にまとめられています。

他バージョンのFedoraについて知りたい場合は、以下のリンクを参照してください。

Release Notes & Changes

Python 3.11

Fedora36時点ではPython3.10が同梱されていましたが、Fedora37以降はPython3.11が同梱されます。

Bugs

f37タグ付きのCommon Issuesを確認しましたが、特に気になるものはありませんでした。

強いて言うなら、GNOME Desktopをお使いの方はざっとタイトルをチェックしてみると良いと思います。

その他

Kickstartのオプション

LinuxなどのOSインストールを自動化するKickstart処理のオプションとして、rootユーザーのパスワードを指定するrootpwというコマンドがあります。
このrootpwコマンドに、Fedora37から--allow-sshオプションが追加されました。

このオプションを指定すると、rootユーザーに対してSSHによるパスワードログインが許可されます。

なお、--allow-sshオプションはRHEL9でも利用可能です。
RHEL9 - Performing an advanced RHEL 9 installation - #rootpw

本件はFedora 37のRelease Notesには掲載されていませんでしたが、--allow-ssh付きのKickstartファイルでFedora36をインストールしようとしたときにエラーになったことでたまたま気づきました。

まとめ

興味を持ったトピック限定ですが、Fedora37の更新点をまとめました。

Fedora36の変更点

Fedoraの変更点シリーズ

過去リリース分の記事は、以下のリンクを参照してください。

Fedoraの変更点シリーズ

お伝えしたいこと

Fedora36のリリースノートを読んで、個人的に気になった項目をまとめます。

公式情報の見方

Fedora 36の変更点は、以下のリンクに載っています。
概要はリリースノートに、詳細情報はChange Setsのページに書いてあります。

Change Setの各サブタイトルのリンクから詳細情報に飛べるようになっています (下図赤枠部)。
詳細を知りたい時に便利なので、こちらも活用ください。

fedora_change_sets

Fedora36の既知の問題は、以下にまとめられています。

他バージョンのFedoraについて知りたい場合は、以下のリンクを参照してください。

Release Notes & Changes

remove-retired-packagesコマンドがインストール可能に

Fedora公式リポジトリでremove-retired-packagesというパッケージの配布が開始されました。

remove-retired-packagesコマンドを使うと、その名の通りretired packagesを自動的に検出してアンインストールを提案してくれます。

retired packagesとは、Fedora公式リポジトリで配布されなくなったパッケージのことです。
retired packagesになる主な理由は、アップストリームの更新が停止したことが挙げられます。

デフォルトでは1世代前のFedoraバージョンからretired packagesを検出して、対象のパッケージに対してdnf removeを実行します。
remove-retired-packages 34のように引数を指定することで、検索範囲を広げてくれます。

更新が停止したパッケージを残しておくとセキュリティリスクがありますので、Fedoraをバージョンアップするたびにこのコマンドを実行することが推奨されます。

過去記事のFedoraのOSバージョンアップ手順にremove-retired-packagesの使い方を追記しましたので、詳細はこちらをご覧ください。

/etc/sysconfig/network-scripts/ifcfg-* がデフォルト無効に

Fedora36以降、NetworkManagerはデフォルトで/etc/sysconfig/network-scripts/ifcfg-*ファイルを一切使わなくなります。
それどころか、/etc/sysconfig/network-scripts/フォルダ自体存在しなくなります。
追加のRPMパッケージをインストールすれば従来の構成に戻すことは可能ですが、ifcfg-*は今後なくなっていく流れですので、それに逆行することは推奨しません。

Connectionの定義ファイルを直接見ることがない方にとっては、この変更点はほぼ影響ありません。
例えば、普段nmcliを使っている方に取ってはあまり気にならないと思います。
もしもifcfg-*ファイルを編集してnmcli reloadやsystemctl restart NetworkManager.serviceなどで設定を再読込する運用をしている方がいれば、今回の変更は重要なものになります。
少数派だと思いますが...。

では、詳細に移ります。
この先は興味のある方のみお読みください。

全体像を理解するために、今までのLinuxのネットワーク設定変更の主だった動きを追ってみます。
私の知識の偏りにより、RHELとFedoraが混在した時系列になっていますがご了承ください。

RHEL6の頃、ネットワーク設定変更といえば以下の流れが主流でした。

  • /etc/sysconfig/network-scripts/ifcfg-*ファイルを編集する
  • service network restartによって反映する

RHEL7以降は、NetworkManagerを常時有効化することが主流となりました。
NetworkManager利用した設定変更の方法は複数ありますが、nmcliコマンドによる変更が最も基本的だと思います。

NetworkManagerには、/etc/NetworkManager/NetworkManager.confという設定ファイルがあります。
この設定ファイルにはpluginsという設定項目があり、デフォルトではコメントアウトされています。

#plugins=keyfile,ifcfg-rh

nmcliなどで変更したconnection設定はOS再起動後ももちろん残ります。
その裏では、NetworkManagerが設定内容をファイルに保存しています。

私はあまりやったことがないのですが、NetworkManagerを使っている環境においてもこの設定ファイルを書き換えて、nmcli connection reloadコマンドによって設定ファイルを再読込させることが可能です。
ファイルを書き換えるよりも、nmcli connection modifyコマンドを使うほうが一般的だと思いますが...。

さて、この「Connection設定が保存されたファイル」がどのような形式で、どういったファイルパスに保存されるかを指定するのが上述のplugins設定です。
plugins設定はNetworkManager.confで明示的に指定することが可能ですが、コメントアウトされている場合にはディストリビューション固有のデフォルト値を取ります。

pluginsの取りうる値は、man NetworkManager - #PLUGINSに書いてあります。

ここで紹介するpluginsは以下の2つのみです。

plugins 説明
keyfile
  • 最も基本形のフォーマット
  • NetworkManagerと必ず同梱される
  • INI形式
  • /etc/NetworkManager/system-connections/*に格納される
ifcfg-rh
  • RHEL系のレガシーなフォーマット
  • /etc/sysconfig/network-scripts/ifcfg-*に格納される

ここでFedoraバージョン依存の話が出てきます。

Fedoraのバージョンが上がるにつれて、pluginsのデフォルト値は以下のように変遷しました。1

バージョン pluginsのデフォルト値
Fedora32以前 ifcfg-rh,keyfile
Fedora33以降 keyfile,ifcfg-rh

ifcfg-rh,keyfileは、「基本的にifcfg-rhを優先するが、もしこのPluginが利用不可だった場合にはkeyfileを使う」という意味です。
keyfile,ifcfg-rhはその逆で、「keyfileを優先し、次にifcfg-rhを使う」という意味になります。

keyfile Pluginは、NetworkManagerのRPMファイルに必ず同梱されます。
一方で、ifcfg-rhについてはFedoraのバージョンによって以下のように構成が変わりました。
これがFedora36の差分です。

バージョン RPMパッケージ
Fedora35以下
Fedora36以降
  • NetworkManager RPMパッケージに同梱されない
  • 初期状態ではifcfg-rhプラグインを利用不可
  • NetworkManager-initscripts-ifcfg-rh
    RPMパッケージを別途インストールすれば使える

Fedora36以降は、ifcfg-rhプラグインがデフォルトでインストールされません。
また、/etc/sysconfig/network-scripts/ディレクトリもデフォルトで存在しません。

レガシーなifcfg-rhは今後なくなっていく流れですので、今後はkeyfileを使うことを前提に考えると良いと思います。

NetworkManager-initscripts-ifcfg-rh RPMパッケージを導入してifcfg-rhを使い続けるという選択肢もありますが、恐らくあまり良い選択ではありません。
このパッケージが今後提供されなくなる可能性が少なくないためです。

Bugs

Bugsの中から気になる情報を拾います。

Fedora36にアップデートした後SELinuxの不具合が出る

タイトルのとおりです。
投稿された事例では、dnf upgrade, flatpak update, setseboolなどのコマンドを実行した時にWarningが出たとのことです。

回避策は、Fedoraをバージョンアップする前にsudo dnf upgradeでパッケージを最新化しておくことです。
これはFedoraバージョンアップの公式手順にも記載されていることですので、マニュアル通りに作業していれば問題ありません。

Fedora36で事象が発生してしまったときのワークアラウンドとしては、以下が紹介されています。

  1. SELinux関連パッケージを再インストールする
  2. 1で直らなかった場合は以下を実施
    1. SELinuxの関連モジュールを停止する
    2. SELinux関連パッケージを再インストールする
    3. SELinuxのrelabelを行う

サイト上で紹介されているコマンドは一例です。
環境に応じて実行するコマンドを変更する必要があると思います。

ちなみに、私がもし事象を踏んだときは以下の手順で対処すると思います。
私は事象を踏んでおらず、未検証の手順なのでご参考までに...。

まず、事象を踏んだときのコマンドを覚えておきます (sudo dnf upgradeなど)。

続いて、SELinux関連パッケージを再インストールします。
この時、再インストールすべきパッケージは以下のコマンドで洗い出します (※)。
(※) SELinuxのコアなパッケージはselinux-policyとselinux-policy-targetedの2つです。そして、製品に対応したSELinuxの追加ルール (Security Policy) をインストールするパッケージは、製品名-selinuxというパッケージ名であることが多いです。したがって、以下のコマンドで必要なパッケージは一通り洗い出せます

dnf list installed *selinux*

上記を実施後、事象が継続しているかを確認します (例えば、sudo dnf upgradeを実行し、Warningが発生するかを確認します)。

事象が継続している場合、以下の手順を実施します。

個人的には、sudo fixfiles onbootに-Fを指定する必要はないかなと思います。
-Fを指定しても害はありませんが、通常の環境 (targeted policy) では指定してもしなくても差はありません。

まとめ

興味を持ったトピック限定ですが、Fedora36の更新点をまとめました。