From 0c6697eaeda2d1ed0c91c86c77440be54add5dcf Mon Sep 17 00:00:00 2001 From: chen21019 Date: Mon, 14 Sep 2026 06:17:50 +0800 Subject: [PATCH] release: publish network integration fixes in v0.3.10 --- README.md | 9 +- catalog-images.json | 39 ++++++++ .../layer-2-flat-network/4/README.md | 26 +++++ .../layer-2-flat-network/4/README.zh-TW.md | 23 +++++ .../4/docker-compose.yml.tpl | 70 ++++++++++++++ .../4/rancher-compose.yml | 96 +++++++++++++++++++ .../layer-2-flat-network/config.yml | 2 +- infra-templates/network-services/6/README.md | 39 ++++++++ .../network-services/6/README.zh-TW.md | 30 ++++++ .../network-services/6/docker-compose.yml.tpl | 95 ++++++++++++++++++ .../network-services/6/rancher-compose.yml | 77 +++++++++++++++ infra-templates/network-services/config.yml | 2 +- integration/core/test_catalog.py | 14 +-- scripts/audit_deployable_images.py | 4 +- scripts/test | 3 + 15 files changed, 516 insertions(+), 13 deletions(-) create mode 100644 infra-templates/layer-2-flat-network/4/README.md create mode 100644 infra-templates/layer-2-flat-network/4/README.zh-TW.md create mode 100644 infra-templates/layer-2-flat-network/4/docker-compose.yml.tpl create mode 100644 infra-templates/layer-2-flat-network/4/rancher-compose.yml create mode 100644 infra-templates/network-services/6/README.md create mode 100644 infra-templates/network-services/6/README.zh-TW.md create mode 100644 infra-templates/network-services/6/docker-compose.yml.tpl create mode 100644 infra-templates/network-services/6/rancher-compose.yml diff --git a/README.md b/README.md index b26d62b6..fcb81c0b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ PastureStack is an independent community effort to preserve, audit, and moderniz Earlier prerelease coordinates are retired from current release references; their reviewed source commits remain in Git history. This source tree targets -the pure numeric coordinate `v0.3.9`; the GitHub tag and Release, rather than +the pure numeric coordinate `v0.3.10`; the GitHub tag and Release, rather than this README, determine when it is published. Product identity is carried by the repository, catalog metadata, and provenance rather than the version tag. @@ -68,9 +68,12 @@ health-reporting, and encrypted-workload gates. The scheduler passed source, build, security, public distribution, live Metadata, idempotent reservation, managed allocation, and restart gates. Version `v0.8.15` additionally remained healthy through repeated Metadata long-poll windows in production without a -second container start. Network Services version `5` moves to `v0.8.17`, +second container start. Network Services version `6` moves to `v0.8.18`, rejects malformed per-host subnet labels before applying host firewall rules, -and preserves routed container source IPs between validated active peers. +and preserves routed container source IPs between validated active peers. It +also fixes bidirectional VXLAN traffic when published host ports coexist with +the overlay. Layer 2 Flat Network version `4` moves to `v0.14.36` so the CNI +preserves an operator-configured bridge address. Restored-data provisioning, complete multi-host scheduler lifecycle, and complete project-template upgrade and rollback remain release-candidate gates. The two alternative network drivers passed packaged diff --git a/catalog-images.json b/catalog-images.json index 7be4ff0a..0492c126 100644 --- a/catalog-images.json +++ b/catalog-images.json @@ -242,6 +242,25 @@ "secrets": 0 } }, + { + "reference": "ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.36", + "manifestDigest": "sha256:50c93f759fd1d2881701ae9d4ef17d91eaaeac715750c1d3ad6f586cd9fd658d", + "sourceRepository": "https://github.com/PastureStack/ipsec-vxlan-overlay-network", + "sourceCommit": "f754bab6dc63c4e51b849a106fcdc792f644b9ef", + "sourcePath": "package/Dockerfile", + "registryPage": "https://github.com/orgs/PastureStack/packages/container/package/ipsec-vxlan-overlay-network", + "licenseBoundary": "Apache-2.0 source and image; bundled Ubuntu, strongSwan, CNI, Weave, and other packages retain their upstream licenses and notices", + "reviewedAt": "2026-09-14", + "platforms": ["linux/amd64"], + "vulnerabilityScan": { + "scanner": "Trivy 0.74.0", + "reportCreatedAt": "2026-09-14", + "scope": "published runtime image", + "high": 0, + "critical": 0, + "secrets": 0 + } + }, { "reference": "ghcr.io/pasturestack/network-plugin-manager:v0.6.34", "sourceRepository": "https://github.com/PastureStack/network-plugin-manager", @@ -319,6 +338,26 @@ "critical": 0 } }, + { + "reference": "ghcr.io/pasturestack/network-plugin-manager:v0.8.18", + "manifestDigest": "sha256:1f5d44de03648a771ec9e7bc448e456ef6b21a5fcd4cc51f59f99df96a804822", + "sourceRepository": "https://github.com/PastureStack/network-plugin-manager", + "sourceCommit": "b52eddfa948a3f862c4d9ed78bce0fe1fe5dc22b", + "sourcePath": "package/Dockerfile", + "registryPage": "https://github.com/orgs/PastureStack/packages/container/package/network-plugin-manager", + "licenseBoundary": "Apache-2.0 source and image; bundled Alpine, Docker CLI, and other packages retain their upstream licenses and notices", + "reviewedAt": "2026-09-14", + "platforms": [ + "linux/amd64" + ], + "vulnerabilityScan": { + "scanner": "Trivy 0.74.0", + "reportCreatedAt": "2026-09-14", + "scope": "published runtime image", + "high": 0, + "critical": 0 + } + }, { "reference": "ghcr.io/pasturestack/network-diagnostics-agent:v0.2.0", "sourceRepository": "https://github.com/PastureStack/network-diagnostics-agent", diff --git a/infra-templates/layer-2-flat-network/4/README.md b/infra-templates/layer-2-flat-network/4/README.md new file mode 100644 index 00000000..0d21a7fe --- /dev/null +++ b/infra-templates/layer-2-flat-network/4/README.md @@ -0,0 +1,26 @@ +# PastureStack Layer 2 Flat Network + +This infrastructure template connects managed workloads directly to a shared +physical Layer 2 subnet. Every participating host must reach the same subnet +and gateway, and the selected workload range must not overlap DHCP, host, or +infrastructure addresses. + +Automatic bridge setup is disabled by default because moving a host's physical +interface into a bridge can interrupt remote access when the interface, subnet, +or gateway is wrong. Prepare the bridge through the operating system first, or +verify out-of-band console access before enabling automatic setup. + +The template uses +`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.36`, which contains the +reviewed `pasture-bridge` and `flat-cni-ipam` executables. The image source is +[`PastureStack/ipsec-vxlan-overlay-network@f754bab6dc63c4e51b849a106fcdc792f644b9ef`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/f754bab6dc63c4e51b849a106fcdc792f644b9ef); +the Flat CNI IPAM source is +[`PastureStack/flat-cni-ipam@047eb2ffc5a985810fbc8a9a25150698facc6ae6`](https://github.com/PastureStack/flat-cni-ipam/tree/047eb2ffc5a985810fbc8a9a25150698facc6ae6). + +The template files and icon are MIT licensed. The runtime projects are +Apache-2.0; operating-system packages and bundled components retain their own +upstream licenses and notices. + +This version packages a bridge CNI that honors `skipBridgeConfigureIP`, leaving a preconfigured bridge address unchanged. It does not change host bridge +ownership or enable automatic physical-interface migration. Verify the real +Layer 2 path and rollback before enabling this optional driver on a host. diff --git a/infra-templates/layer-2-flat-network/4/README.zh-TW.md b/infra-templates/layer-2-flat-network/4/README.zh-TW.md new file mode 100644 index 00000000..5503b7e9 --- /dev/null +++ b/infra-templates/layer-2-flat-network/4/README.zh-TW.md @@ -0,0 +1,23 @@ +# PastureStack 第 2 層平面網路 + +此基礎架構範本會透過主機網橋,將受管工作負載直接連接到共用的實體 +第 2 層子網路。每台參與主機都必須能連上相同的子網路與閘道,而且 +選定的工作負載位址範圍不得與 DHCP、主機或基礎架構位址重疊。 + +自動設定網橋預設為停用。若實體介面、子網路或閘道設定錯誤,把主機 +實體介面移入網橋可能會中斷遠端連線。請優先透過作業系統準備網橋; +若要啟用自動設定,請先確認具備頻外主控台存取方式。 + +此範本使用 +`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.36`, +其中包含經審核的 `pasture-bridge` 與 `flat-cni-ipam` 執行檔。 +映像原始碼位於 +[`PastureStack/ipsec-vxlan-overlay-network@f754bab6dc63c4e51b849a106fcdc792f644b9ef`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/f754bab6dc63c4e51b849a106fcdc792f644b9ef), +Flat CNI IPAM 原始碼位於 +[`PastureStack/flat-cni-ipam@047eb2ffc5a985810fbc8a9a25150698facc6ae6`](https://github.com/PastureStack/flat-cni-ipam/tree/047eb2ffc5a985810fbc8a9a25150698facc6ae6)。 + +範本檔案與圖示採 MIT 授權;執行專案採 Apache-2.0 授權。作業系統 +套件及隨附元件保留各自的上游授權及聲明。 + +此版隨附會遵守 `skipBridgeConfigureIP` 的橋接 CNI,保留已設定的網橋位址;不改變主機網橋權責,也不自動搬移實體網路 +介面。啟用此選用驅動程式前,仍須驗證真實第 2 層連線及回復方式。 diff --git a/infra-templates/layer-2-flat-network/4/docker-compose.yml.tpl b/infra-templates/layer-2-flat-network/4/docker-compose.yml.tpl new file mode 100644 index 00000000..2cd9d389 --- /dev/null +++ b/infra-templates/layer-2-flat-network/4/docker-compose.yml.tpl @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + layer-2-flat-cni: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.36 + privileged: true + network_mode: host + pid: host +{{- if eq .Values.AUTO_SETUP_LAYER_2_BRIDGE "true" }} + command: + - /bin/bash + - -ceu + - start-flat.sh && exec start-cni-driver.sh +{{- else }} + command: start-cni-driver.sh +{{- end }} + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + PASTURESTACK_METADATA_ADDRESS: '${PASTURESTACK_METADATA_ADDRESS}' + FLAT_IF: '${FLAT_INTERFACE}' + FLAT_BRIDGE: '${LAYER_2_BRIDGE}' + MTU: '${MTU}' + labels: + io.pasturestack.component: layer-2-flat-cni + io.rancher.network.cni.binary: pasture-bridge + io.rancher.container.dns: 'true' + io.rancher.scheduler.global: 'true' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - rancher-cni-driver:/opt/cni-driver + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + network_driver: + name: PastureStack Layer 2 Flat Network + default_network: + name: layer-2-flat + host_ports: {{ .Values.HOST_PORTS }} + subnets: + - network_address: ${SUBNET} + start_address: ${START_ADDRESS} + end_address: ${END_ADDRESS} + dns: + - 169.254.169.250 + dns_search: + - pasture.internal + cni_config: + '10-pasturestack-layer-2-flat.conf': + name: pasturestack-layer-2-flat-network + type: pasture-bridge + bridge: ${LAYER_2_BRIDGE} + bridgeSubnet: ${SUBNET} + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: ${PASTURESTACK_DEBUG} + hostNat: false + mtu: ${MTU} + skipBridgeConfigureIP: true + skipFastPath: true + ipam: + type: flat-cni-ipam + metadataURL: http://169.254.169.250/2015-12-19 + metadataAddress: 169.254.169.250 + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: ${PASTURESTACK_DEBUG} + routes: + - dst: 0.0.0.0/0 + gw: ${GATEWAY} diff --git a/infra-templates/layer-2-flat-network/4/rancher-compose.yml b/infra-templates/layer-2-flat-network/4/rancher-compose.yml new file mode 100644 index 00000000..7685b583 --- /dev/null +++ b/infra-templates/layer-2-flat-network/4/rancher-compose.yml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Layer 2 Flat Network + version: v0.3.2 + description: Connect managed workloads directly to a shared Layer 2 subnet through a host bridge. + minimum_rancher_version: v1.6.26-rc1 + labels: + io.pasturestack.catalog.question.layer_2_bridge.label.zh-tw: '第 2 層網橋' + io.pasturestack.catalog.question.layer_2_bridge.description.zh-tw: '共用第 2 層網路使用的既有或自動設定主機網橋。' + io.pasturestack.catalog.question.flat_interface.label.zh-tw: '實體網路介面' + io.pasturestack.catalog.question.flat_interface.description.zh-tw: '只有啟用自動網橋設定時,才會把此主機實體介面加入網橋。' + io.pasturestack.catalog.question.auto_setup_layer_2_bridge.label.zh-tw: '自動設定網橋' + io.pasturestack.catalog.question.auto_setup_layer_2_bridge.description.zh-tw: '把實體介面的位址移到第 2 層網橋;啟用前請先確認可使用主控台連線。' + io.pasturestack.catalog.question.subnet.label.zh-tw: '共用子網路' + io.pasturestack.catalog.question.subnet.description.zh-tw: '主機、網橋、閘道與受管工作負載共用的 IPv4 子網路。' + io.pasturestack.catalog.question.start_address.label.zh-tw: '第一個工作負載位址' + io.pasturestack.catalog.question.start_address.description.zh-tw: '控制平面可分配給受管工作負載的第一個 IPv4 位址。' + io.pasturestack.catalog.question.end_address.label.zh-tw: '最後一個工作負載位址' + io.pasturestack.catalog.question.end_address.description.zh-tw: '控制平面可分配給受管工作負載的最後一個 IPv4 位址。' + io.pasturestack.catalog.question.gateway.label.zh-tw: '預設閘道' + io.pasturestack.catalog.question.gateway.description.zh-tw: '共用子網路中受管工作負載使用的 IPv4 閘道。' + io.pasturestack.catalog.question.mtu.label.zh-tw: '網路 MTU' + io.pasturestack.catalog.question.mtu.description.zh-tw: '實體第 2 層網路端對端支援的 MTU。' + io.pasturestack.catalog.question.host_ports.label.zh-tw: '啟用主機連接埠' + io.pasturestack.catalog.question.host_ports.description.zh-tw: '允許受管工作負載在主機上公開連接埠。' + io.pasturestack.catalog.question.pasturestack_metadata_address.label.zh-tw: '中繼資料服務位址' + io.pasturestack.catalog.question.pasturestack_metadata_address.description.zh-tw: '相容中繼資料服務使用的連結本機 IPv4 位址。' + io.pasturestack.catalog.question.pasturestack_debug.label.zh-tw: '啟用除錯日誌' + io.pasturestack.catalog.question.pasturestack_debug.description.zh-tw: '記錄較詳細的網橋設定與 CNI 操作診斷資訊。' + questions: + - variable: LAYER_2_BRIDGE + label: Layer 2 bridge + description: Existing or automatically configured host bridge used by the shared Layer 2 network. + type: string + default: flatbr0 + required: true + - variable: FLAT_INTERFACE + label: Physical interface + description: Physical host interface to attach to the bridge only when automatic bridge setup is enabled. + type: string + default: eth0 + required: true + - variable: AUTO_SETUP_LAYER_2_BRIDGE + label: Configure the bridge automatically + description: Move the physical interface address onto the Layer 2 bridge. Verify console access before enabling this option. + type: boolean + default: 'false' + required: true + - variable: SUBNET + label: Shared subnet + description: IPv4 subnet shared by the hosts, bridge, gateway, and managed workloads. + type: string + default: 192.0.2.0/24 + required: true + - variable: START_ADDRESS + label: First workload address + description: First IPv4 address that the control plane may assign to a managed workload. + type: string + default: 192.0.2.100 + required: true + - variable: END_ADDRESS + label: Last workload address + description: Last IPv4 address that the control plane may assign to a managed workload. + type: string + default: 192.0.2.199 + required: true + - variable: GATEWAY + label: Default gateway + description: IPv4 gateway for managed workloads on the shared subnet. + type: string + default: 192.0.2.1 + required: true + - variable: MTU + label: Network MTU + description: MTU supported end to end by the physical Layer 2 network. + type: int + default: 1500 + required: true + - variable: HOST_PORTS + label: Enable host ports + description: Allow managed workloads to publish ports on their hosts. + type: boolean + default: 'true' + required: true + - variable: PASTURESTACK_METADATA_ADDRESS + label: Metadata address + description: Link-local IPv4 address of the compatible metadata service. + type: string + default: 169.254.169.250 + required: true + - variable: PASTURESTACK_DEBUG + label: Enable debug logs + description: Enable verbose diagnostics for bridge setup and CNI operations. + type: boolean + default: 'false' + required: true diff --git a/infra-templates/layer-2-flat-network/config.yml b/infra-templates/layer-2-flat-network/config.yml index 39004c0a..1f94656e 100644 --- a/infra-templates/layer-2-flat-network/config.yml +++ b/infra-templates/layer-2-flat-network/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: Layer 2 Flat Network description: Connect managed workloads directly to a shared Layer 2 subnet through a host bridge. -version: v0.3.1 +version: v0.3.2 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and bundled component licenses apply diff --git a/infra-templates/network-services/6/README.md b/infra-templates/network-services/6/README.md new file mode 100644 index 00000000..a0ddd0b5 --- /dev/null +++ b/infra-templates/network-services/6/README.md @@ -0,0 +1,39 @@ + + +# PastureStack Network Services + +Version 6 uses Network Plugin Manager `v0.8.18`. It retains single-backend selection and unchanged Metadata Service and Internal DNS images. It also restores bidirectional VXLAN forwarding when published host ports coexist with the overlay. The manager rejects malformed per-host subnet labels before touching host firewall rules; the optional per-host-subnet network preserves container source IPs across active peers and permits only peer-to-local-subnet forwarding. The image's release provenance and digest are recorded in `catalog-images.json`. + +## Firewall backend + +`FIREWALL_BACKEND` defaults to `auto`. It reads Docker's actual firewall driver: Docker's native `nftables` driver uses native nft rules, while Docker's `iptables` driver selects the frontend that owns Docker's active NAT chain. That may be `iptables-nft` or `iptables-legacy` on **any supported host**, including Ubuntu 26.04 and later. The OS release, installed executable, or unloaded kernel module alone never selects a backend. To pin one path, choose: + +- `nftables`: Docker's native nftables firewall backend. This is **not** the same as the iptables-nft compatibility CLI. +- `iptables-nft`: xtables compatibility CLI backed by nf_tables, for Docker's iptables firewall driver. +- `iptables-legacy`: legacy xtables, only when the running Docker daemon actually owns the active rules through that frontend. + +The manager refuses a mismatched or ambiguous selection and does not fall back, switch Docker's backend, or load legacy modules. An Ubuntu 26.04+ host already using `iptables-legacy` or `iptables-nft` must keep its live Docker path; do not turn on native nftables merely because the OS is new. A deliberate migration requires a separate host change, rollback point, and network lifecycle test. + +This manager alone owns the host NAT and host-port `CATTLE_*` chains. Its +masquerade rules exclude destinations inside the managed overlay subnet in +all three backends; the IPsec host-XFRM router must not patch these chains. +For the per-host-subnet driver, the manager also excludes other active hosts' +validated subnets from masquerade and adds a bounded forwarding exception. +Inactive registrations are ignored; missing or overlapping labels on an active +host fail closed. This is a routed, unencrypted network; protect the host +transport separately. +Upgrade Network Services first and verify manager health on every host before +upgrading the matching IPsec Overlay version. + +For Docker's native nftables driver, configure Docker itself with `"firewall-backend": "nftables"` and `"bridge-accept-fwmark": "0x1068/0x1068"` before upgrading this stack. Persist `net.ipv4.ip_forward=1` on the host and verify it remains enabled after a reboot: Docker's native nftables backend does not enable IPv4 forwarding for you. The mark allows Docker's bridge forwarding rules to accept the manager's published-host-port traffic; the template cannot configure the host daemon or kernel settings. Check and explicitly migrate any stale `iptables-nft` `FORWARD DROP` policy or previous platform hooks before switching Docker. The manager refuses that mixed state rather than changing the host's global firewall policy. Docker's native nftables backend remains an experimental Docker feature; qualify it against the installed Docker release before production use. + +## Other configuration + +- `DOCKER_BRIDGE`: host bridge for managed workload traffic. +- `DNS_RECURSER_TIMEOUT`, `TTL`: upstream DNS timeout and service-discovery cache time. +- `CPU_PERIOD`, `CPU_QUOTA`: Metadata Service CPU scheduling limits. +- `RELOAD_INTERVAL_LIMIT`, `ARP_SYNC_INTERVAL`: metadata reload and host ARP reconciliation intervals. + +Network Plugin Manager still requires host networking, host PID visibility, the Docker socket, Docker state, kernel-module and runtime mounts, and the shared CNI volume. Metadata Service starts as root only to assign its link-local address, then drops to UID/GID 10001. Internal DNS shares its namespace. The `rancher-compose.yml` filename, `io.rancher.*` labels, `CATTLE_*` fallback variables, `/var/lib/rancher` CA path, and `rancher-cni-driver` volume are compatibility contracts, not a request to use legacy firewall rules. + +These template files are MIT-licensed. The manager, metadata service, and internal DNS retain their Apache-2.0 licenses and bundled dependency notices. Verify image source and the recorded manifest digest in `catalog-images.json` before deployment. diff --git a/infra-templates/network-services/6/README.zh-TW.md b/infra-templates/network-services/6/README.zh-TW.md new file mode 100644 index 00000000..f7d4e80a --- /dev/null +++ b/infra-templates/network-services/6/README.zh-TW.md @@ -0,0 +1,30 @@ + + +# PastureStack 網路服務 + +第 6 版使用網路外掛管理器 `v0.8.18`,保留單一防火牆後端的選擇方式,以及相同的中繼資料服務與內部 DNS 映像;並修正發布主機連接埠與 VXLAN 並存時的雙向轉送。管理器會在修改主機防火牆規則前拒絕格式錯誤的每主機子網路標籤;選用每主機子網路時,會保留跨主機容器來源位址,並只允許已驗證的對端子網路轉送至本機子網路。映像發布來源與 digest 記錄於 `catalog-images.json`。 + +## 防火牆後端 + +`FIREWALL_BACKEND` 預設為 `auto`,依 Docker 實際防火牆驅動程式選擇單一路徑:Docker 原生 `nftables` 使用原生 nft 規則;Docker `iptables` 驅動程式則辨識哪一套前端擁有 Docker 現役 NAT 鏈。任何受支援主機(包括 Ubuntu 26.04 及更新版)都可能使用 `iptables-nft` 或 `iptables-legacy`;作業系統版本、執行檔存在或尚未載入的核心模組,均不足以決定後端。需要固定路徑時可選: + +- `nftables`:Docker 原生 nftables 防火牆後端,**不是** iptables-nft 相容命令。 +- `iptables-nft`:由 nf_tables 支援的 xtables 相容命令,搭配 Docker 的 iptables 防火牆驅動程式。 +- `iptables-legacy`:只在現役 Docker 確實透過這套前端持有規則時選用。 + +選擇與 Docker 實際後端不符或無法判定時,管理器會拒絕啟動,不會自動降級、切換 Docker 後端或載入 legacy 模組。Ubuntu 26.04 及更新版若已使用 `iptables-legacy` 或 `iptables-nft`,就應維持現役 Docker 路徑;不能只因系統較新便替它切成原生 nftables。刻意遷移須另外準備主機變更、回復點及網路生命週期驗收。 + +主機 NAT 與主機連接埠的 `CATTLE_*` 規則鏈只由此管理器維護;三種後端的來源位址轉換規則都排除受管 overlay 子網路內的目的位址。每主機子網路還會排除其他有效主機的已驗證子網路,並加入限定來源與目的子網路的轉送例外;非現役主機不列入,現役主機若缺少標籤或子網路重疊則安全地拒絕套用。此網路只提供路由、不加密,須另行保護主機間傳輸。IPsec 主機 XFRM 路由器不得再插入補丁規則。升級時應先升級網路服務,逐台確認管理器健康,再升級相符的 IPsec 加密網路版本。 + +使用 Docker 原生 nftables 前,必須先在主機 Docker 設定加入 `"firewall-backend": "nftables"` 及 `"bridge-accept-fwmark": "0x1068/0x1068"`,再升級此堆疊。還須在主機持久設定 `net.ipv4.ip_forward=1`,並於重開機後確認仍啟用;Docker 原生 nftables 後端不會代為啟用 IPv4 轉送。此標記讓 Docker 網橋轉送規則接受管理器發布的主機連接埠流量;範本無法替主機設定 Docker daemon 或核心參數。切換前還須檢查並明確遷移殘留的 `iptables-nft FORWARD DROP` 全域政策與舊平台掛鉤。管理器遇到混用狀態會拒絕啟動,不會自行修改主機全域防火牆政策。Docker 原生 nftables 目前仍屬實驗性功能,正式環境使用前應針對安裝的 Docker 版本完成驗收。 + +## 其他設定 + +- `DOCKER_BRIDGE`:受管工作負載使用的主機網橋。 +- `DNS_RECURSER_TIMEOUT`、`TTL`:上游 DNS 逾時與服務探索快取時間。 +- `CPU_PERIOD`、`CPU_QUOTA`:中繼資料服務的 CPU 排程限制。 +- `RELOAD_INTERVAL_LIMIT`、`ARP_SYNC_INTERVAL`:中繼資料重新載入與主機 ARP 協調間隔。 + +網路外掛管理器仍需主機網路、主機 PID、Docker Socket、Docker 狀態、核心模組與執行環境掛載,以及共用 CNI 磁碟區。中繼資料服務僅在指派連結本機位址時以 root 啟動,之後切換為 UID/GID 10001;內部 DNS 與其共用網路命名空間。`rancher-compose.yml`、`io.rancher.*`、`CATTLE_*` 備援變數、`/var/lib/rancher` CA 路徑及 `rancher-cni-driver` 磁碟區是既有協定的相容契約,不代表必須使用 legacy 防火牆規則。 + +範本檔案採 MIT 授權;管理器、中繼資料服務與內部 DNS 保留 Apache-2.0 授權及隨附相依套件聲明。部署前應以 `catalog-images.json` 核對映像來源與記錄的 manifest digest。 diff --git a/infra-templates/network-services/6/docker-compose.yml.tpl b/infra-templates/network-services/6/docker-compose.yml.tpl new file mode 100644 index 00000000..be38425b --- /dev/null +++ b/infra-templates/network-services/6/docker-compose.yml.tpl @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + network-plugin-manager: + image: ghcr.io/pasturestack/network-plugin-manager:v0.8.18 + privileged: true + network_mode: host + pid: host + command: + - network-plugin-manager + - --metadata-url + - http://169.254.169.250/2016-07-29 + - --arpsync-interval + - '${ARP_SYNC_INTERVAL}' + - --firewall-backend + - '${FIREWALL_BACKEND}' + environment: + DOCKER_BRIDGE: '${DOCKER_BRIDGE}' + METADATA_IP: 169.254.169.250 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker:/var/lib/docker + - /lib/modules:/lib/modules:ro + - /run:/run + - /var/run:/var/run + - rancher-cni-driver:/etc/cni + - rancher-cni-driver:/opt/cni + labels: + io.pasturestack.component: network-plugin-manager + io.rancher.scheduler.global: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + + metadata: + image: ghcr.io/pasturestack/metadata-service:v0.9.11 + user: root + cap_add: + - NET_ADMIN + network_mode: bridge + command: + - /bin/bash + - -ec + - | + export PLATFORM_URL="$${PLATFORM_URL:-$${CATTLE_URL:-}}" + export PLATFORM_ACCESS_KEY="$${PLATFORM_ACCESS_KEY:-$${CATTLE_ACCESS_KEY:-}}" + export PLATFORM_SECRET_KEY="$${PLATFORM_SECRET_KEY:-$${CATTLE_SECRET_KEY:-}}" + exec metadata-service --reload-interval-limit="${RELOAD_INTERVAL_LIMIT}" --subscribe + environment: + PLATFORM_CA_ROOT: /var/lib/rancher/etc/ssl/ca.crt + labels: + io.pasturestack.component: metadata-service + io.rancher.sidekicks: dns + io.rancher.container.create_agent: 'true' + io.rancher.scheduler.global: 'true' + io.rancher.container.agent_service.metadata: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + sysctls: + net.ipv4.conf.all.send_redirects: '0' + net.ipv4.conf.default.send_redirects: '0' + cpu_period: ${CPU_PERIOD} + cpu_quota: ${CPU_QUOTA} + + dns: + image: ghcr.io/pasturestack/internal-dns:v0.17.11 + network_mode: container:metadata + command: + - internal-dns + - --listen + - 169.254.169.250:53 + - --recurser-timeout + - '${DNS_RECURSER_TIMEOUT}' + - --ttl + - '${TTL}' + environment: + PLATFORM_METADATA_ENABLED: 'true' + PLATFORM_METADATA_URL: http://localhost/2016-07-29 + PLATFORM_METADATA_ANSWER: 169.254.169.250 + NEVER_RECURSE_TO: 169.254.169.250 + PLATFORM_DNS_ANSWERS_FILE: /etc/internal-dns/answers.json + labels: + io.pasturestack.component: internal-dns + io.rancher.scheduler.global: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' diff --git a/infra-templates/network-services/6/rancher-compose.yml b/infra-templates/network-services/6/rancher-compose.yml new file mode 100644 index 00000000..a66d31f9 --- /dev/null +++ b/infra-templates/network-services/6/rancher-compose.yml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Network Services + version: v0.3.4 + description: Install host networking, metadata, and internal DNS services required by managed workloads. + minimum_rancher_version: v1.6.26-rc1 + labels: + io.pasturestack.catalog.question.docker_bridge.label.zh-tw: 'Docker 網橋' + io.pasturestack.catalog.question.docker_bridge.description.zh-tw: '受管工作負載流量使用的主機網橋。' + io.pasturestack.catalog.question.firewall_backend.label.zh-tw: '主機防火牆後端' + io.pasturestack.catalog.question.firewall_backend.description.zh-tw: '依 Docker 現役後端自動選擇;不論 Ubuntu 版本,原生 nftables、iptables-nft 與 iptables-legacy 互不混用。切換原生 nftables 前須先設定 Docker bridge-accept-fwmark。' + io.pasturestack.catalog.question.dns_recurser_timeout.label.zh-tw: 'DNS 遞迴查詢逾時' + io.pasturestack.catalog.question.dns_recurser_timeout.description.zh-tw: '等待上游 DNS 查詢回應的秒數。' + io.pasturestack.catalog.question.ttl.label.zh-tw: '服務探索 DNS 紀錄存留時間' + io.pasturestack.catalog.question.ttl.description.zh-tw: '內部服務探索 DNS 回應可保留的秒數。' + io.pasturestack.catalog.question.cpu_period.label.zh-tw: '中繼資料服務 CPU 週期' + io.pasturestack.catalog.question.cpu_period.description.zh-tw: '分配給每個中繼資料服務執行個體的 CPU 排程週期。' + io.pasturestack.catalog.question.cpu_quota.label.zh-tw: '中繼資料服務 CPU 配額' + io.pasturestack.catalog.question.cpu_quota.description.zh-tw: '分配給每個中繼資料服務執行個體的 CPU 配額。' + io.pasturestack.catalog.question.reload_interval_limit.label.zh-tw: '中繼資料重新載入間隔' + io.pasturestack.catalog.question.reload_interval_limit.description.zh-tw: '兩次中繼資料設定重新載入之間的最短毫秒數。' + io.pasturestack.catalog.question.arp_sync_interval.label.zh-tw: 'ARP 同步間隔' + io.pasturestack.catalog.question.arp_sync_interval.description.zh-tw: '兩次主機 ARP 協調作業之間的秒數。' + questions: + - variable: DOCKER_BRIDGE + label: Docker bridge + description: Host bridge used for managed workload traffic. + type: string + default: docker0 + required: true + - variable: FIREWALL_BACKEND + label: Host firewall backend + description: Follow Docker's active firewall backend on any supported Ubuntu version, or explicitly select native nftables, iptables-nft, or iptables-legacy. A mismatch fails safely; native nftables requires Docker bridge-accept-fwmark on the host. + type: enum + default: auto + required: true + options: + - auto + - nftables + - iptables-nft + - iptables-legacy + - variable: DNS_RECURSER_TIMEOUT + label: DNS recursion timeout + description: Seconds allowed for an upstream DNS query. + type: int + default: 2 + required: true + - variable: TTL + label: Service discovery TTL + description: Seconds that internal service-discovery answers remain valid. + type: int + default: 1 + required: true + - variable: CPU_PERIOD + label: Metadata CPU period + description: CPU scheduler period assigned to each metadata service instance. + type: int + default: 400000 + required: true + - variable: CPU_QUOTA + label: Metadata CPU quota + description: CPU quota assigned to each metadata service instance. + type: int + default: 200000 + required: true + - variable: RELOAD_INTERVAL_LIMIT + label: Metadata reload interval + description: Minimum milliseconds between metadata configuration reloads. + type: int + default: 1000 + required: true + - variable: ARP_SYNC_INTERVAL + label: ARP synchronization interval + description: Seconds between host ARP reconciliation passes. + type: int + default: 5 + required: true diff --git a/infra-templates/network-services/config.yml b/infra-templates/network-services/config.yml index 0a0d30e8..e59738d9 100644 --- a/infra-templates/network-services/config.yml +++ b/infra-templates/network-services/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: Network Services description: Install host networking, metadata, and internal DNS services required by managed workloads. -version: v0.3.3 +version: v0.3.4 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 images and third-party package licenses apply diff --git a/integration/core/test_catalog.py b/integration/core/test_catalog.py index 3985ff93..d1d921fc 100644 --- a/integration/core/test_catalog.py +++ b/integration/core/test_catalog.py @@ -211,10 +211,10 @@ def test_catalog_list(): assert by_folder[('infra', 'layer-2-flat-network')]['name'] == ( 'Layer 2 Flat Network') assert by_folder[('infra', 'layer-2-flat-network')][ - 'defaultVersion'] == 'v0.3.1' + 'defaultVersion'] == 'v0.3.2' assert by_folder[('infra', 'layer-2-flat-network')][ 'links']['defaultVersion'].endswith( - ':3') + ':4') assert by_folder[('infra', 'network-diagnostics')]['name'] == ( 'Network Diagnostics') assert by_folder[('infra', 'network-diagnostics')][ @@ -232,10 +232,10 @@ def test_catalog_list(): assert by_folder[('infra', 'network-services')]['name'] == ( 'Network Services') assert by_folder[('infra', 'network-services')][ - 'defaultVersion'] == 'v0.3.3' + 'defaultVersion'] == 'v0.3.4' assert by_folder[('infra', 'network-services')][ 'links']['defaultVersion'].endswith( - ':5') + ':6') assert by_folder[('infra', 'nfs-storage')][ 'name'] == 'NFS Storage' assert by_folder[('infra', 'nfs-storage')][ @@ -623,8 +623,10 @@ def test_catalog_compose_shapes_are_runtime_compatible(): layer_2_files = layer_2_version['files'] layer_2_docker = layer_2_files['docker-compose.yml.tpl'] layer_2_platform = layer_2_files['rancher-compose.yml'] + flat_network_image = ( + 'ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.36') assert layer_2_docker.count( - 'image: {}'.format(alternative_network_image)) == 1 + 'image: {}'.format(flat_network_image)) == 1 assert '\n layer-2-flat-cni:\n' in layer_2_docker assert 'command: start-cni-driver.sh' in layer_2_docker assert 'start-flat.sh && exec start-cni-driver.sh' in layer_2_docker @@ -715,7 +717,7 @@ def test_catalog_compose_shapes_are_runtime_compatible(): network_docker = network_files['docker-compose.yml.tpl'] network_platform = network_files['rancher-compose.yml'] network_manager_image = ( - 'ghcr.io/pasturestack/network-plugin-manager:v0.8.17') + 'ghcr.io/pasturestack/network-plugin-manager:v0.8.18') metadata_image = 'ghcr.io/pasturestack/metadata-service:v0.9.11' dns_image = 'ghcr.io/pasturestack/internal-dns:v0.17.11' assert network_docker.count( diff --git a/scripts/audit_deployable_images.py b/scripts/audit_deployable_images.py index 5f27639d..be278c25 100644 --- a/scripts/audit_deployable_images.py +++ b/scripts/audit_deployable_images.py @@ -54,10 +54,10 @@ "ecr-credential-sync": ("2", "3"), "healthcheck": ("0", "1"), "ipsec-overlay": ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"), - "layer-2-flat-network": ("2", "3"), + "layer-2-flat-network": ("2", "3", "4"), "network-diagnostics": ("1", "2"), "network-policy-manager": ("1", "2"), - "network-services": ("1", "2", "3", "4", "5"), + "network-services": ("1", "2", "3", "4", "5", "6"), "nfs-storage": ("1", "2"), "per-host-subnet-network": ("2", "3"), "resource-scheduler": ("1", "2", "3", "4"), diff --git a/scripts/test b/scripts/test index 45261ac6..fce1c2aa 100755 --- a/scripts/test +++ b/scripts/test @@ -119,6 +119,8 @@ for version_id in \ network-services:2 \ network-services:3 \ network-services:4 \ + network-services:5 \ + network-services:6 \ nfs-storage:1 \ nfs-storage:2 \ resource-scheduler:1 \ @@ -127,6 +129,7 @@ for version_id in \ resource-scheduler:4 \ secret-volume-driver:1 \ secret-volume-driver:2 \ + layer-2-flat-network:4 \ vxlan-overlay-network:2 \ vxlan-overlay-network:3; do version_url="http://localhost:8088/v1-catalog/templateversions/library:infra*${version_id}"