Linux中國

NMState:一個聲明式網路配置工具

這篇文章描述並演示了 NMState,這是一個使用聲明式方法配置主機的網路管理器。這意味著你可以通過 API 定義所需的配置狀態,而工具則通過 提供者 provider 來應用配置。

配置方法:命令式與聲明式

網路管理有時候是一項非常複雜的任務,這取決於環境的規模和多樣性。在 IT 的早期,網路管理依賴於網路管理員在網路設備上手動執行命令。如今, 基礎設施即代碼 Infrastructure as Code (IaC)允許以不同的方式將這些任務自動化。z這基本上有兩種方法:命令式或聲明式。

在命令式方法中,你會定義「如何」達到所需的配置狀態。而在聲明式範式里則定義了「什麼」是所需的配置狀態,所以它不確定哪些步驟是必需的,也不確定它們必須以何種順序執行。這種方法目前正在聚集更多的人員參與,你可以在目前使用的大多數管理和編排工具上找到它。

NMState:一個聲明式的工具

NMState 是一個網路管理器,允許你按照聲明式方法配置主機。這意味著你通過一個北向的聲明式 API 定義所需的配置狀態,這個工具通過南向的 提供者 provider 應用配置。

目前 NMState 支持的唯一的提供者是 NetworkManager,它是為 Fedora Linux 提供網路功能的主要服務。不過,NMState 的開發計劃中將逐漸增加其他提供者。

關於 NMState 的進一步信息,請訪問其項目 站點 或 GitHub 倉庫

安裝

NMState 在 Fedora Linux 29+ 上可用,需要在系統上安裝並運行 NetworkManager 1.26 或更高版本。下面是在 Fedora Linux 34 上的安裝情況:

$ sudo dnf -y install nmstate
...
輸出節略
...
Installed:
  NetworkManager-config-server-1:1.30.4-1.fc34.noarch      gobject-introspection-1.68.0-3.fc34.x86_64      nispor-1.0.1-2.fc34.x86_64              nmstate-1.0.3-2.fc34.noarch
  python3-gobject-base-3.40.1-1.fc34.x86_64                python3-libnmstate-1.0.3-2.fc34.noarch          python3-nispor-1.0.1-2.fc34.noarch      python3-varlink-30.3.1-2.fc34.noarch

Complete!

這樣,你可以使用 nmstatectl 作為 NMState 的命令行工具。請參考 nmstatectl -helpman nmstatectl 以了解關於這個工具的進一步信息。

使用 NMstate

首先要檢查系統中安裝的 NMState 版本:

$ nmstatectl version
1.0.3

檢查一個網路介面的當前配置,例如 eth0 的配置:

$ nmstatectl show eth0
2021-06-29 10:28:21,530 root         DEBUG    NetworkManager version 1.30.4
2021-06-29 10:28:21,531 root         DEBUG    Async action: Retrieve applied config: ethernet eth0 started
2021-06-29 10:28:21,531 root         DEBUG    Async action: Retrieve applied config: ethernet eth1 started
2021-06-29 10:28:21,532 root         DEBUG    Async action: Retrieve applied config: ethernet eth0 finished
2021-06-29 10:28:21,533 root         DEBUG    Async action: Retrieve applied config: ethernet eth1 finished
dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 100
    next-hop-address: ''
    next-hop-interface: eth0
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 100
    next-hop-address: ''
    next-hop-interface: eth0
    table-id: 254
interfaces:
- name: eth0
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.238
      prefix-length: 24
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    dhcp: true
  ipv6:
    enabled: true
    address:
    - ip: fe80::c3c9:c4f9:75b1:a570
      prefix-length: 64
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    autoconf: true
    dhcp: true
  lldp:
    enabled: false
  mac-address: 52:54:00:91:E4:4E
  mtu: 1500

正如你在上面看到的,這個網路配置顯示了四個主要部分:

  • dns-resolver:這部分是這個介面的名字伺服器配置。
  • route-rules:它說明了路由規則。
  • routes:它包括動態和靜態路由。
  • interfaces:這部分描述了 ipv4 和 ipv6 設置。

修改配置

你可以在兩種模式下修改所需的配置狀態:

  • 互動式:通過 nmstatectl edit 編輯介面配置。這個命令調用環境變數 EDITOR 定義的文本編輯器,因此可以用 yaml 格式編輯網路狀態。完成編輯後,NMState 將應用新的網路配置,除非有語法錯誤。
  • 基於文件的:使用 nmstatectl apply 應用介面配置,它從先前創建的 yaml 或 json 文件中導入一個所需的配置狀態。

下面幾節告訴你如何使用 NMState 來改變網路配置。這些改變可能會對系統造成破壞,所以建議在測試系統或客戶虛擬機上執行這些任務,直到你對 NMState 有更好的理解。

這裡使用的測試系統有兩個乙太網介面,eth0eth1

$ ip -br -4 a
lo               UNKNOWN        127.0.0.1/8
eth0             UP             192.168.122.238/24
eth1             UP             192.168.122.108/24

互動配置模式的例子

使用 nmstatectl edit 命令將 eth0 介面的 MTU 改為 9000 位元組,如下所示:

$ sudo nmstatectl edit eth0

dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 100
    next-hop-address: ''
    next-hop-interface: eth0
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 100
    next-hop-address: ''
    next-hop-interface: eth0
    table-id: 254
interfaces:
- name: eth0
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.123
      prefix-length: 24
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    dhcp: true
  ipv6:
    enabled: true
    address:
    - ip: fe80::c3c9:c4f9:75b1:a570
      prefix-length: 64
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    autoconf: true
    dhcp: true
  lldp:
    enabled: false
  mac-address: 52:54:00:91:E4:4E
  mtu: 9000

在保存並退出編輯器後,NMState 應用新的網路期望狀態:

2021-06-29 11:29:05,726 root         DEBUG    Nmstate version: 1.0.3
2021-06-29 11:29:05,726 root         DEBUG    Applying desire state: {'dns-resolver': {'config': {}, 'running': {'search': [], 'server': ['192.168.122.1']}}, 'route-rules': {'config': []}, 'routes': {'config': [], 'running': [{'destination': 'fe80::/64', 'metric': 102, 'next-hop-address': '', 'next-hop-interface': 'eth0', 'table-id': 254}, {'destination': '0.0.0.0/0', 'metric': 102, 'next-hop-address': '192.168.122.1', 'next-hop-interface': 'eth0', 'table-id': 254}, {'destination': '192.168.122.0/24', 'metric': 102, 'next-hop-address': '', 'next-hop-interface': 'eth0', 'table-id': 254}]}, 'interfaces': [{'name': 'eth0', 'type': 'ethernet', 'state': 'up', 'ipv4': {'enabled': True, 'address': [{'ip': '192.168.122.238', 'prefix-length': 24}], 'auto-dns': True, 'auto-gateway': True, 'auto-route-table-id': 0, 'auto-routes': True, 'dhcp': True}, 'ipv6': {'enabled': True, 'address': [{'ip': 'fe80::5054:ff:fe91:e44e', 'prefix-length': 64}], 'auto-dns': True, 'auto-gateway': True, 'auto-route-table-id': 0, 'auto-routes': True, 'autoconf': True, 'dhcp': True}, 'lldp': {'enabled': False}, 'mac-address': '52:54:00:91:E4:4E', 'mtu': 9000}]}
--- output omitted 2021-06-29 11:29:05,760 root         DEBUG    Async action: Update profile uuid:2bdee700-f62b-365a-bd1d-69d9c31a9f0c iface:eth0 type:ethernet started
2021-06-29 11:29:05,792 root         DEBUG    Async action: Update profile uuid:2bdee700-f62b-365a-bd1d-69d9c31a9f0c iface:eth0 type:ethernet finished

現在,使用 ip 命令和 eth0 的配置文件來檢查 eth0MTU 是不是 9000 位元組。

$ ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:91:e4:4e brd ff:ff:ff:ff:ff:ff
    altname enp1s0

$ sudo cat /etc/NetworkManager/system-connections/eth0.nmconnection
[sudo] password for admin:
[connection]
id=eth0
uuid=2bdee700-f62b-365a-bd1d-69d9c31a9f0c
type=ethernet
interface-name=eth0
lldp=0
permissions=

[ethernet]
cloned-mac-address=52:54:00:91:E4:4E
mac-address-blacklist=
mtu=9000

[ipv4]
dhcp-client-id=mac
dhcp-timeout=2147483647
dns-search=
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-duid=ll
dhcp-iaid=mac
dhcp-timeout=2147483647
dns-search=
method=auto
ra-timeout=2147483647

[proxy]

基於文件的配置模式的例子

讓我們使用基於文件的方法來設置一個新的配置狀態。這裡我們禁用 eth1 介面的 IPv6 配置。

首先,創建一個 yaml 文件來定義 eth1 介面的期望狀態。使用 nmstatectl show 來保存當前設置,然後使用 nmstatectl edit 來禁用 IPv6。

$ nmstatectl show eth1 > eth1.yaml

$ vi eth1.yaml
dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 101
    next-hop-address: 192.168.122.1
    next-hop-interface: eth1
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
interfaces:
- name: eth1
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.108
      prefix-length: 24
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    dhcp: true
  ipv6:
    enabled: false
    address:
    - ip: fe80::5054:ff:fe3c:9b04
      prefix-length: 64
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    autoconf: true
    dhcp: true
  lldp:
    enabled: false
  mac-address: 52:54:00:3C:9B:04
  mtu: 1500

保存新的配置後,用它來應用新的狀態:

$ sudo nmstatectl apply eth1.yaml

2021-06-29 12:17:21,531 root         DEBUG    Nmstate version: 1.0.3
2021-06-29 12:17:21,531 root         DEBUG    Applying desire state: {&apos;dns-resolver&apos;: {&apos;config&apos;: {}, &apos;running&apos;: {&apos;search&apos;: [], &apos;server&apos;: [&apos;192.168.122.1&apos;]}}, &apos;route-rules&apos;: {&apos;config&apos;: []}, &apos;routes&apos;: {&apos;config&apos;: [], &apos;running&apos;: [{&apos;destination&apos;: &apos;fe80::/64&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}, {&apos;destination&apos;: &apos;0.0.0.0/0&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;192.168.122.1&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}, {&apos;destination&apos;: &apos;192.168.122.0/24&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}]}, &apos;interfaces&apos;: [{&apos;name&apos;: &apos;eth1&apos;, &apos;type&apos;: &apos;ethernet&apos;, &apos;state&apos;: &apos;up&apos;, &apos;ipv4&apos;: {&apos;enabled&apos;: True, &apos;address&apos;: [{&apos;ip&apos;: &apos;192.168.122.108&apos;, &apos;prefix-length&apos;: 24}], &apos;auto-dns&apos;: True, &apos;auto-gateway&apos;: True, &apos;auto-route-table-id&apos;: 0, &apos;auto-routes&apos;: True, &apos;dhcp&apos;: True}, &apos;ipv6&apos;: {&apos;enabled&apos;: False}, &apos;lldp&apos;: {&apos;enabled&apos;: False}, &apos;mac-address&apos;: &apos;52:54:00:3C:9B:04&apos;, &apos;mtu&apos;: 1500}]}
--- output omitted 2021-06-29 12:17:21,582 root         DEBUG    Async action: Update profile uuid:5d7244cb-673d-3b88-a675-32e31fad4347 iface:eth1 type:ethernet started
2021-06-29 12:17:21,587 root         DEBUG    Async action: Update profile uuid:5d7244cb-673d-3b88-a675-32e31fad4347 iface:eth1 type:ethernet finished
--- output omitted Desired state applied:
dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 101
    next-hop-address: 192.168.122.1
    next-hop-interface: eth1
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
interfaces:
- name: eth1
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.108
      prefix-length: 24
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    dhcp: true
  ipv6:
    enabled: false
  lldp:
    enabled: false
  mac-address: 52:54:00:3C:9B:04
  mtu: 1500

你可以檢查看到 eth1 介面沒有配置任何 IPv6:

$ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             192.168.122.238/24 fe80::5054:ff:fe91:e44e/64
eth1             UP             192.168.122.108/24

$ sudo cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
uuid=5d7244cb-673d-3b88-a675-32e31fad4347
type=ethernet
interface-name=eth1
lldp=0
permissions=

[ethernet]
cloned-mac-address=52:54:00:3C:9B:04
mac-address-blacklist=
mtu=1500

[ipv4]
dhcp-client-id=mac
dhcp-timeout=2147483647
dns-search=
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-duid=ll
dhcp-iaid=mac
dns-search=
method=disabled

[proxy]

臨時應用改變

NMState 的一個有趣的功能允許你臨時配置一個期望的網路狀態。如果你對這個配置感到滿意,你可以事後提交。否則,當超時(默認為 60 秒)過後,它將回滾。

修改前面例子中的 eth1 配置,使它有一個 IPv4 靜態地址,而不是通過 DHCP 動態獲得。

$ vi eth1.yaml

dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 101
    next-hop-address: 192.168.122.1
    next-hop-interface: eth1
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
interfaces:
- name: eth1
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.110
      prefix-length: 24
    auto-dns: true
    auto-gateway: true
    auto-route-table-id: 0
    auto-routes: true
    dhcp: false
  ipv6:
    enabled: false
  lldp:
    enabled: false
  mac-address: 52:54:00:3C:9B:04
  mtu: 1500

現在,使用選項 no-commit 臨時應用這個配置,讓它只在 30 秒內有效。這可以通過添加選項 timeout 來完成。同時,我們將運行 ip -br a 命令三次,看看配置在 eth1 介面的 IPv4 地址是如何變化的,然後配置就會回滾。

$ ip -br a && sudo nmstatectl apply --no-commit --timeout 30 eth1.yaml && sleep 10 && ip -br a && sleep 25 && ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             192.168.122.238/24 fe80::5054:ff:fe91:e44e/64
eth1             UP             192.168.122.108/24
2021-06-29 17:29:18,266 root         DEBUG    Nmstate version: 1.0.3
2021-06-29 17:29:18,267 root         DEBUG    Applying desire state: {&apos;dns-resolver&apos;: {&apos;config&apos;: {}, &apos;running&apos;: {&apos;search&apos;: [], &apos;server&apos;: [&apos;192.168.122.1&apos;]}}, &apos;route-rules&apos;: {&apos;config&apos;: []}, &apos;routes&apos;: {&apos;config&apos;: [], &apos;running&apos;: [{&apos;destination&apos;: &apos;fe80::/64&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}, {&apos;destination&apos;: &apos;0.0.0.0/0&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;192.168.122.1&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}, {&apos;destination&apos;: &apos;192.168.122.0/24&apos;, &apos;metric&apos;: 101, &apos;next-hop-address&apos;: &apos;&apos;, &apos;next-hop-interface&apos;: &apos;eth1&apos;, &apos;table-id&apos;: 254}]}, &apos;interfaces&apos;: [{&apos;name&apos;: &apos;eth1&apos;, &apos;type&apos;: &apos;ethernet&apos;, &apos;state&apos;: &apos;up&apos;, &apos;ipv4&apos;: {&apos;enabled&apos;: True, &apos;address&apos;: [{&apos;ip&apos;: &apos;192.168.122.110&apos;, &apos;prefix-length&apos;: 24}], &apos;dhcp&apos;: False}, &apos;ipv6&apos;: {&apos;enabled&apos;: False}, &apos;lldp&apos;: {&apos;enabled&apos;: False}, &apos;mac-address&apos;: &apos;52:54:00:3C:9B:04&apos;, &apos;mtu&apos;: 1500}]}
--- output omitted Desired state applied:
dns-resolver:
  config: {}
  running:
    search: []
    server:
    - 192.168.122.1
route-rules:
  config: []
routes:
  config: []
  running:
  - destination: fe80::/64
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
  - destination: 0.0.0.0/0
    metric: 101
    next-hop-address: 192.168.122.1
    next-hop-interface: eth1
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 101
    next-hop-address: &apos;&apos;
    next-hop-interface: eth1
    table-id: 254
interfaces:
- name: eth1
  type: ethernet
  state: up
  ipv4:
    enabled: true
    address:
    - ip: 192.168.122.110
      prefix-length: 24
    dhcp: false
  ipv6:
    enabled: false
  lldp:
    enabled: false
  mac-address: 52:54:00:3C:9B:04
  mtu: 1500
Checkpoint: NetworkManager|/org/freedesktop/NetworkManager/Checkpoint/7
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             192.168.122.238/24 fe80::5054:ff:fe91:e44e/64
eth1             UP             192.168.122.110/24
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             192.168.122.238/24 fe80::5054:ff:fe91:e44e/64
eth1             UP             192.168.122.108/24

從上面可以看到,eth1 的 IP 地址從 192.168.122.108 暫時變成了 192.168.122.110,然後在超時結束後又回到了 192.168.122.108

總結

NMState 是一個聲明式的網路配置工具,目前可以通過 NetworkManager API 在主機中應用所需的網路配置狀態。這種狀態既可以用文本編輯器互動式地定義,也可以用基於文件的方法創建一個 yaml 或 json 文件。

這種工具提供了「基礎設施即代碼」,它可以自動化網路任務,也減少了使用傳統配置方法可能出現的潛在錯誤配置或不穩定的網路情況。

via: https://fedoramagazine.org/nmstate-a-declarative-networking-config-tool/

作者:Maurizio Garcia 選題:lujun9972 譯者:wxy 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國