From 38496efe859474bb6cdf0502f2350201d71dd23a Mon Sep 17 00:00:00 2001 From: chen21019 Date: Mon, 14 Sep 2026 15:05:44 +0800 Subject: [PATCH 1/3] Release backend-aware network catalog 0.3.12 --- COMPATIBILITY.md | 9 ++ README.md | 19 ++- catalog-images.json | 20 +++ infra-templates/ipsec-overlay/11/README.md | 34 ++++++ .../ipsec-overlay/11/README.zh-TW.md | 85 +++++++++++++ .../ipsec-overlay/11/docker-compose.yml.tpl | 115 ++++++++++++++++++ .../ipsec-overlay/11/rancher-compose.yml | 97 +++++++++++++++ infra-templates/ipsec-overlay/config.yml | 2 +- .../layer-2-flat-network/5/README.md | 29 +++++ .../layer-2-flat-network/5/README.zh-TW.md | 26 ++++ .../5/docker-compose.yml.tpl | 70 +++++++++++ .../5/rancher-compose.yml | 96 +++++++++++++++ .../layer-2-flat-network/config.yml | 2 +- .../network-policy-manager/3/README.md | 48 ++++++++ .../network-policy-manager/3/README.zh-TW.md | 40 ++++++ .../3/docker-compose.yml | 35 ++++++ .../3/rancher-compose.yml | 9 ++ .../network-policy-manager/config.yml | 2 +- infra-templates/network-services/8/README.md | 44 +++++++ .../network-services/8/README.zh-TW.md | 32 +++++ .../network-services/8/docker-compose.yml.tpl | 95 +++++++++++++++ .../network-services/8/rancher-compose.yml | 77 ++++++++++++ infra-templates/network-services/config.yml | 2 +- .../per-host-subnet-network/4/README.md | 37 ++++++ .../per-host-subnet-network/4/README.zh-TW.md | 35 ++++++ .../4/docker-compose.yml.tpl | 78 ++++++++++++ .../4/rancher-compose.yml | 88 ++++++++++++++ .../per-host-subnet-network/config.yml | 2 +- .../vxlan-overlay-network/5/README.md | 44 +++++++ .../vxlan-overlay-network/5/README.zh-TW.md | 44 +++++++ .../5/docker-compose.yml.tpl | 97 +++++++++++++++ .../5/rancher-compose.yml | 56 +++++++++ .../vxlan-overlay-network/config.yml | 2 +- integration/core/test_catalog.py | 35 +++--- scripts/audit_deployable_images.py | 12 +- scripts/check-firewall-backend-contract.py | 5 + scripts/test | 8 +- 37 files changed, 1495 insertions(+), 36 deletions(-) create mode 100644 infra-templates/ipsec-overlay/11/README.md create mode 100644 infra-templates/ipsec-overlay/11/README.zh-TW.md create mode 100644 infra-templates/ipsec-overlay/11/docker-compose.yml.tpl create mode 100644 infra-templates/ipsec-overlay/11/rancher-compose.yml create mode 100644 infra-templates/layer-2-flat-network/5/README.md create mode 100644 infra-templates/layer-2-flat-network/5/README.zh-TW.md create mode 100644 infra-templates/layer-2-flat-network/5/docker-compose.yml.tpl create mode 100644 infra-templates/layer-2-flat-network/5/rancher-compose.yml create mode 100644 infra-templates/network-policy-manager/3/README.md create mode 100644 infra-templates/network-policy-manager/3/README.zh-TW.md create mode 100644 infra-templates/network-policy-manager/3/docker-compose.yml create mode 100644 infra-templates/network-policy-manager/3/rancher-compose.yml create mode 100644 infra-templates/network-services/8/README.md create mode 100644 infra-templates/network-services/8/README.zh-TW.md create mode 100644 infra-templates/network-services/8/docker-compose.yml.tpl create mode 100644 infra-templates/network-services/8/rancher-compose.yml create mode 100644 infra-templates/per-host-subnet-network/4/README.md create mode 100644 infra-templates/per-host-subnet-network/4/README.zh-TW.md create mode 100644 infra-templates/per-host-subnet-network/4/docker-compose.yml.tpl create mode 100644 infra-templates/per-host-subnet-network/4/rancher-compose.yml create mode 100644 infra-templates/vxlan-overlay-network/5/README.md create mode 100644 infra-templates/vxlan-overlay-network/5/README.zh-TW.md create mode 100644 infra-templates/vxlan-overlay-network/5/docker-compose.yml.tpl create mode 100644 infra-templates/vxlan-overlay-network/5/rancher-compose.yml diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 4baa3bd16..f4bf1e69d 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -31,6 +31,15 @@ The `PastureStack IPsec Overlay` release candidate keeps the literal `rancher-co The `PastureStack Network Services` release candidate keeps the same catalog filename and version gate, required `io.rancher.*` orchestration labels, `CATTLE_*` credential fallbacks, `/var/lib/rancher` CA path, and `rancher-cni-driver` shared volume. These values are produced or consumed by the compatible control plane and existing host-network contract. Public service names, image coordinates, executables, primary environment variables, and user-facing metadata use PastureStack-neutral identifiers. +Fixed-subnet IPsec and VXLAN CNI revisions explicitly set +`allowSharedSubnetIngress: true`. Network Plugin Manager alone consumes that +metadata and owns the bounded host-forwarding rule: both addresses must be +inside the configured shared subnet and the output interface must be the exact +managed bridge. Host-label-based per-host subnets cannot enable this path and +continue to trust only validated active peer ranges. IPsec owns XFRM and +routes; VXLAN owns its data-plane namespace; neither may patch the manager's +host firewall chains merely to make an integration test pass. + The `PastureStack Network Diagnostics` release candidate keeps only the catalog filename, version gate, and global scheduling label required by the compatible control plane. Its images, services, variables, persisted volume, diff --git a/README.md b/README.md index 666c46bb8..17d1d8f40 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.11`; the GitHub tag and Release, rather than +the pure numeric coordinate `v0.3.12`; 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,13 +68,13 @@ 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 `7` moves to `v0.8.19`, +second container start. Network Services version `8` moves to `v0.8.20`, rejects malformed per-host subnet labels before applying host firewall rules, and preserves routed container source IPs between validated active peers. It -also fixes bidirectional VXLAN traffic when published host ports coexist with -the overlay, binds forwarding rules to the exact managed bridge, and protects -bridge traffic from `route_localnet` loopback routing while preserving and -restoring the operator's original per-bridge setting. Layer 2 Flat Network +also restores bounded inbound forwarding for fixed shared overlay subnets, +binds every forwarding rule to the exact configured subnet and managed bridge, +and protects bridge traffic from `route_localnet` loopback routing while +preserving and restoring the operator's original per-bridge setting. 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 @@ -131,6 +131,13 @@ firewall ownership or backend selection. The image digest is recorded in `catalog-images.json`; live Catalog activation and two-host lifecycle remain separate acceptance gates. +IPsec Overlay version `11` and VXLAN Overlay Network version `5` explicitly +declare the fixed shared-subnet ingress contract consumed by Network Plugin +Manager `v0.8.20`. The rule is limited to traffic whose source and destination +are both inside the configured `10.42.0.0/16` subnet and whose output interface +is the exact managed bridge. Overlay routers retain their existing data-plane +responsibilities and do not take ownership of host firewall chains. + Deployable Compose files use semantic version tags only. A published version tag must never be replaced. Manifest digests remain release-verification evidence and are not inserted into Catalog, Compose, API, or user-interface diff --git a/catalog-images.json b/catalog-images.json index cc20b07bd..f89624d1d 100644 --- a/catalog-images.json +++ b/catalog-images.json @@ -378,6 +378,26 @@ "critical": 0 } }, + { + "reference": "ghcr.io/pasturestack/network-plugin-manager:v0.8.20", + "manifestDigest": "sha256:b66e4a7188c52d4ff970d450e2086c726e5895f3c5881599c24f5b020953d337", + "sourceRepository": "https://github.com/PastureStack/network-plugin-manager", + "sourceCommit": "75d7957d36a7f0079b2335c6a9060a592596b72a", + "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/ipsec-overlay/11/README.md b/infra-templates/ipsec-overlay/11/README.md new file mode 100644 index 000000000..ad3e6bee8 --- /dev/null +++ b/infra-templates/ipsec-overlay/11/README.md @@ -0,0 +1,34 @@ + + +# PastureStack IPsec Overlay 0.3.9 + +This infrastructure template is a candidate for the IPsec overlay data plane on every eligible host. A network-holder service owns the managed namespace, the router applies host XFRM and route state, the connectivity sidecar exposes the control-plane health contract, and the CNI sidecar supplies the bridge and address-management executables. + +## Candidate template — published image + +- Image: `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35` is recorded with its published manifest digest in `catalog-images.json`. The GitHub Release itself is not immutable. +- Version `11` explicitly declares `allowSharedSubnetIngress: true` for the fixed `10.42.0.0/16` CNI network. Network Plugin Manager `v0.8.20` uses that contract to restore cross-host workload forwarding without granting traffic outside the configured subnet or managed bridge. Version `10` remains available for existing stacks. +- Version `10` gives the connectivity-check sidecar a bounded TCP 80 handoff during rolling upgrades. It waits only when the prior sidecar still owns its listener and fails clearly after 90 seconds or on another bind error; firewall rules and router port 8111 remain under their existing owners. Version `9` remains available for existing stacks. +- Version `9` updates the bundled CNI host-label adapter to the control plane's plain-text `/self/host/labels/` contract. This lets per-host subnet workloads receive the host-specific bridge and IPAM ranges instead of failing CNI setup. Version `8` remains available for existing stacks. +- Version `8` retains the port-8111 handoff and peer-retry behavior. It lets the IPsec module, rather than strongSwan's CHILD close action, own missing-SA recovery. After a quiet period it removes only a zero-traffic established duplicate when one other installed SA for the same managed peer has traffic; ambiguous pairs remain untouched. Version `7` remains available for existing stacks but did not converge after a live rolling upgrade. +- Source license: Apache-2.0; Ubuntu, strongSwan, CNI, Weave, and bundled dependencies retain their upstream licenses and notices. + +## Privilege and secret boundary + +The router is privileged and uses host PID and network namespaces. In all three firewall backends it synchronizes IPsec XFRM state and routes, but does not write host firewall chains. Network Plugin Manager alone owns the overlay bridge-subnet forward mark, NAT exclusion, and host-port rules. The router does not create a second nftables mark table, patch the manager's `CATTLE_*` chains, or change Docker's tables. The router receives a read-only Docker socket mount to query the actual firewall driver; Unix socket access still grants a powerful Docker API capability, so it remains confined to this trusted privileged system service. The CNI sidecar also accesses the Docker socket. These permissions are required by this compatibility architecture and must not be copied to ordinary workloads. + +The router receives a scoped create-agent credential from the compatible control plane and downloads the generated IPsec pre-shared key through the authenticated `configcontent/psk` contract. This template does not accept a user-supplied key and never places a key in the public Catalog repository, Compose variables, image, or logs. + +## Compatibility boundary + +The literal `rancher-compose.yml` filename, `minimum_rancher_version` key, required `io.rancher.*` orchestration labels, `rancher-cni-driver` shared volume, and `ipsec` agent-service marker are consumed by the compatible control plane and network plugin manager. They are protocol identifiers, not PastureStack branding. User-facing names, image coordinates, commands, environment variables, CNI names, log paths, and the `pasture.internal` search suffix use current PastureStack identifiers. + +The data plane currently supports the compatibility network `10.42.0.0/16`; the template intentionally does not expose a subnet selector that the runtime cannot safely honor. Its explicit `allowSharedSubnetIngress` contract is consumed only by Network Plugin Manager. The IPsec router continues to own XFRM and routes without writing host firewall rules. + +The host firewall backend is selected explicitly or left at `auto`. The four supported choices are `auto`, native `nftables`, `iptables-nft`, and `iptables-legacy`. The selection is passed only to `overlay-router` through `PASTURESTACK_FIREWALL_BACKEND`. The router checks Docker's actual driver and live rule owner, not the Ubuntu version: even on Ubuntu 26.04 and later, an existing `iptables-legacy` or `iptables-nft` deployment keeps that active path. An explicit mismatch or ambiguous state fails safely without switching backends or activating unloaded legacy modules. Align the choice with the Network Services template on the same environment. + +The Native project definition lists Network Services before IPsec, but list order alone does not establish a health dependency. Before creating or upgrading this overlay, apply the matching Network Services version and wait until Network Plugin Manager is healthy on every target host. In native `nftables` mode, first satisfy that template's Docker firewall-backend, bridge-accept-fwmark, and persistent IPv4-forwarding prerequisites; an IPsec router alone cannot provide the manager-owned forwarding and NAT rules. + +## Release boundary + +The published `v0.14.35` image is recorded with its real manifest digest. The isolated native nftables, iptables-nft, and iptables-legacy gates must remain green. Managed upgrade and peer-restart evidence must be checked separately; a successful CNI address allocation alone does not prove the encrypted multi-host lifecycle. diff --git a/infra-templates/ipsec-overlay/11/README.zh-TW.md b/infra-templates/ipsec-overlay/11/README.zh-TW.md new file mode 100644 index 000000000..7d37432dc --- /dev/null +++ b/infra-templates/ipsec-overlay/11/README.zh-TW.md @@ -0,0 +1,85 @@ + + +# PastureStack IPsec 加密網路 0.3.9 + +此候選基礎架構範本預計在每台符合條件的主機上安裝 IPsec 加密 +網路資料平面。網路持有服務負責受管命名空間;路由器套用主機 XFRM +與路由狀態;連線檢查相關容器提供控制平面健康狀態契約;CNI 相關 +容器則提供網橋與位址管理執行檔。 + +## 候選範本:映像已發布 + +- 映像 `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35` 已正式發布; + 真實 manifest digest、來源 revision 與執行映像安全掃描已記錄於 + `catalog-images.json`。GitHub Release 並未標示為不可變。 +- 第 `11` 版為固定的 `10.42.0.0/16` CNI 網路明確設定 + `allowSharedSubnetIngress: true`。網路外掛管理器 `v0.8.20` 依此契約 + 恢復跨主機工作負載轉送,且不放行設定子網路或受管網橋以外的流量。 + 第 `10` 版仍供既有堆疊使用。 +- 第 `10` 版在滾動升級時,若舊版連線檢查容器尚占用 TCP 80, + 新版只對此埠占用情況等待,最多 90 秒;其他監聽錯誤或逾時仍會 + 明確失敗。此處不更動防火牆規則或路由器的 8111 連接埠責任。 + 第 `9` 版仍供既有堆疊使用。 +- 第 `8` 版保留對等主機重試與 8111 連接埠交接。IPsec 模組統一負責 + 缺失 SA 的重建;超過觀察期間且同一對等主機恰有一條已使用的健康 + SA 時,才清除另一條零流量的重複 SA。無法明確判斷的連線不動。 + 第 `7` 版仍供既有堆疊參照,但真機滾動升級後曾留下兩條已建立 SA。 +- 第 `9` 版將隨附 CNI 的主機標籤查詢改為控制平面實際提供的純文字 + `/self/host/labels/` 契約,讓每主機子網路可正確取得網橋與 IPAM + 位址範圍。第 `8` 版仍供既有堆疊使用。 +- 原始碼採 Apache-2.0 授權;Ubuntu、strongSwan、CNI、Weave 與 + 隨附相依套件保留各自的上游授權及聲明。 + +## 權限與機密資料界線 + +路由器使用特權模式並加入主機 PID 與網路命名空間。在三種防火牆 +後端,它只同步 IPsec XFRM 狀態與路由,不寫入主機防火牆規則。 +網路外掛管理器獨自維護 overlay 網橋子網路的轉送標記、NAT 排除及 +主機連接埠規則。路由器不另建 nftables 標記表、不修改管理器的 +`CATTLE_*` 規則鏈,也不修改 Docker 的規則表。路由器以唯讀掛載 Docker Socket 查詢 +實際防火牆驅動程式;唯讀掛載仍賦予強大的 Docker API 存取能力, +只限此受信任的特權系統服務使用。CNI 相關容器也存取 Docker Socket。 +這些權限是相容架構所需, +不得套用到一般工作負載。 + +路由器會從相容控制平面取得範圍受限的代理程式登入資訊,再透過已驗證 +的 `configcontent/psk` 契約下載 IPsec 預先共用金鑰。此範本不接受 +使用者提供的金鑰,也不會把金鑰放入公開商店、Compose 變數、映像或 +日誌。 + +## 相容性界線 + +`rancher-compose.yml`、`minimum_rancher_version`、必要的 +`io.rancher.*` 編排標籤、`rancher-cni-driver` 共用磁碟區及 +`ipsec` 代理程式服務標記是相容控制平面與網路外掛管理器使用的協定 +識別名稱。使用者可見名稱、映像位置、命令、環境變數、CNI 名稱、 +日誌路徑及 `pasture.internal` 搜尋後綴均採用 PastureStack 名稱。 + +資料平面目前支援 `10.42.0.0/16` 相容網路。執行環境無法安全套用 +任意子網路,因此範本不提供無效的子網路選項。 +明確的 `allowSharedSubnetIngress` 契約只由網路外掛管理器處理;IPsec +路由器仍只負責 XFRM 與路由,不寫入主機防火牆規則。 + +主機防火牆後端可選 `auto`、原生 `nftables`、`iptables-nft` 或 +`iptables-legacy`。選擇會透過 `PASTURESTACK_FIREWALL_BACKEND` 傳給 +`overlay-router`。路由器檢查 Docker 實際驅動程式與現役規則擁有者, +不以 Ubuntu 版本推斷;Ubuntu 26.04 及更新版若已使用 `iptables-legacy` +或 `iptables-nft`,仍維持該現役路徑。明確指定與實際後端不符或狀態 +無法判定時安全停止,不切換後端,也不載入尚未啟用的 legacy 模組。 +同環境的 Network Services 範本應使用一致的選項。 + +Native 專案定義將 Network Services 排在 IPsec 前面,但清單順序 +本身不保證健康狀態相依。建立或升級加密網路前,應先套用相符版本 +的 Network Services,等待每台目標主機上的網路外掛管理器恢復 +健康。使用原生 `nftables` 時,須先完成該範本列出的 Docker +防火牆後端、`bridge-accept-fwmark` 與持久 IPv4 轉送前置設定; +只有 IPsec 路由器無法提供管理器負責的轉送及 NAT 規則。 + +## 發布界線 + +已發布的 `v0.14.35` 映像已記錄真實 manifest digest。原生 nftables、 +iptables-nft 與 iptables-legacy 的隔離驗收必須保持通過;受管升級及 +對等主機重啟還須確認暫時離線的主機不會拆掉其他健康連線、同一對等 +主機收斂為一條可用 IKE SA,新路由器 +仍等待 8111 埠釋放,且不越界修改網路外掛管理器的防火牆規則。 +本版實機結果須另行記錄;單純完成 CNI 位址分配不能代替加密跨主機生命週期驗收。 diff --git a/infra-templates/ipsec-overlay/11/docker-compose.yml.tpl b/infra-templates/ipsec-overlay/11/docker-compose.yml.tpl new file mode 100644 index 000000000..6fdff1ec6 --- /dev/null +++ b/infra-templates/ipsec-overlay/11/docker-compose.yml.tpl @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + overlay-network: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35 + command: + - /bin/bash + - -c + - 'mkfifo /tmp/overlay-log; exec cat /tmp/overlay-log' + network_mode: ipsec + labels: + io.pasturestack.component: ipsec-overlay + io.rancher.sidekicks: overlay-router,connectivity-check + io.rancher.scheduler.global: 'true' + io.rancher.cni.link_mtu_overhead: '0' + io.rancher.network.macsync: 'true' + io.rancher.network.arpsync: 'true' + + overlay-router: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35 + command: start-ipsec.sh + privileged: true + network_mode: container:overlay-network + pid: host + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + PASTURESTACK_FIREWALL_BACKEND: '${FIREWALL_BACKEND}' + PASTURESTACK_NETWORK_XFRM_NETNS_PATH: /proc/1/ns/net + PASTURESTACK_NETWORK_XFRM_TUNNEL_SOURCE: host + PASTURESTACK_NETWORK_RUN_IN_HOST_NETNS: 'true' + PASTURESTACK_NETWORK_ARP_INTERFACE: '${DOCKER_BRIDGE}' + PASTURESTACK_NETWORK_SYNC_HOST_ROUTES: 'true' + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + labels: + io.pasturestack.component: ipsec-overlay-router + io.rancher.container.create_agent: 'true' + io.rancher.container.agent_service.ipsec: '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' + + connectivity-check: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35 + command: + - ipsec-vxlan-connectivity-check + - --connectivity-check-interval + - '${CONNECTIVITY_CHECK_INTERVAL}' + - --peer-connection-timeout + - '${PEER_CONNECTION_TIMEOUT}' + network_mode: container:overlay-network + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + PASTURESTACK_METADATA_ADDRESS: 169.254.169.250 + labels: + io.pasturestack.component: ipsec-overlay-connectivity + + cni-driver: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.35 + command: start-cni-driver.sh + privileged: true + network_mode: host + pid: host + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + labels: + io.pasturestack.component: ipsec-overlay-cni + io.rancher.scheduler.global: 'true' + io.rancher.network.cni.binary: pasture-bridge + io.rancher.container.dns: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - rancher-cni-driver:/opt/cni-driver + network_driver: + name: PastureStack IPsec Overlay + default_network: + name: ipsec + host_ports: {{ .Values.HOST_PORTS }} + subnets: + - network_address: 10.42.0.0/16 + dns: + - 169.254.169.250 + dns_search: + - pasture.internal + cni_config: + '10-pasturestack.conf': + name: pasturestack-cni-network + type: pasture-bridge + bridge: $DOCKER_BRIDGE + bridgeSubnet: 10.42.0.0/16 + allowSharedSubnetIngress: true + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' + isDefaultGateway: true + hostNat: true + hairpinMode: {{ .Values.PASTURESTACK_HAIRPIN_MODE }} + promiscMode: {{ .Values.PASTURESTACK_PROMISCUOUS_MODE }} + mtu: ${MTU} + linkMTUOverhead: 98 + ipam: + type: metadata-cni-ipam + subnetPrefixSize: /16 + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' diff --git a/infra-templates/ipsec-overlay/11/rancher-compose.yml b/infra-templates/ipsec-overlay/11/rancher-compose.yml new file mode 100644 index 000000000..ad3233db1 --- /dev/null +++ b/infra-templates/ipsec-overlay/11/rancher-compose.yml @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack IPsec Overlay + version: v0.3.9 + description: Provide an encrypted host-to-host network for managed workloads. + minimum_rancher_version: v1.6.19-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 分開使用。指定不符時安全停止,不會自動切換後端。' + io.pasturestack.catalog.question.mtu.label.zh-tw: '網路 MTU' + io.pasturestack.catalog.question.mtu.description.zh-tw: '請與主機網路 MTU 一致;GCE 常用 1460,一般乙太網路常用 1500。' + io.pasturestack.catalog.question.pasturestack_debug.label.zh-tw: '啟用除錯日誌' + io.pasturestack.catalog.question.pasturestack_debug.description.zh-tw: '記錄較詳細的加密網路元件診斷資訊。' + io.pasturestack.catalog.question.host_ports.label.zh-tw: '啟用主機連接埠' + io.pasturestack.catalog.question.host_ports.description.zh-tw: '允許受管工作負載在主機上公開連接埠。' + io.pasturestack.catalog.question.pasturestack_hairpin_mode.label.zh-tw: '啟用 Hairpin 模式' + io.pasturestack.catalog.question.pasturestack_hairpin_mode.description.zh-tw: 'Hairpin 模式與混雜模式不可同時啟用。' + io.pasturestack.catalog.question.pasturestack_promiscuous_mode.label.zh-tw: '啟用混雜模式' + io.pasturestack.catalog.question.pasturestack_promiscuous_mode.description.zh-tw: '混雜模式與 Hairpin 模式不可同時啟用。' + io.pasturestack.catalog.question.connectivity_check_interval.label.zh-tw: '對等主機檢查間隔' + io.pasturestack.catalog.question.connectivity_check_interval.description.zh-tw: '兩次加密對等主機連線檢查之間的毫秒數。' + io.pasturestack.catalog.question.peer_connection_timeout.label.zh-tw: '對等主機連線逾時' + io.pasturestack.catalog.question.peer_connection_timeout.description.zh-tw: '每次嘗試連線對等主機可使用的毫秒數。' + 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. An explicit mismatch fails safely; legacy is never a fallback. + type: enum + default: auto + required: true + options: + - auto + - nftables + - iptables-nft + - iptables-legacy + - variable: MTU + label: Network MTU + description: Match the host network MTU; common values are 1460 for GCE and 1500 for Ethernet. + type: int + default: 1500 + required: true + - variable: PASTURESTACK_DEBUG + label: Enable debug logs + description: Enable verbose diagnostic logging for the overlay components. + type: boolean + default: 'false' + 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_HAIRPIN_MODE + label: Enable hairpin mode + description: Hairpin mode and promiscuous mode must not both be enabled. + type: boolean + default: 'false' + required: true + - variable: PASTURESTACK_PROMISCUOUS_MODE + label: Enable promiscuous mode + description: Promiscuous mode and hairpin mode must not both be enabled. + type: boolean + default: 'true' + required: true + - variable: CONNECTIVITY_CHECK_INTERVAL + label: Peer check interval + description: Milliseconds between encrypted peer-connectivity checks. + type: int + default: 10000 + required: true + - variable: PEER_CONNECTION_TIMEOUT + label: Peer connection timeout + description: Milliseconds allowed for each peer connection attempt. + type: int + default: 60000 + required: true + +overlay-network: + health_check: + request_line: GET "/connectivity" "HTTP/1.0" + port: 80 + interval: 5000 + initializing_timeout: 60000 + reinitializing_timeout: 60000 + response_timeout: 2000 + healthy_threshold: 2 + unhealthy_threshold: 3 + strategy: none diff --git a/infra-templates/ipsec-overlay/config.yml b/infra-templates/ipsec-overlay/config.yml index 63dc9c3ad..0b639fe31 100644 --- a/infra-templates/ipsec-overlay/config.yml +++ b/infra-templates/ipsec-overlay/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: IPsec Overlay description: Provide an encrypted host-to-host network for managed workloads. -version: v0.3.8 +version: v0.3.9 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and third-party package licenses apply diff --git a/infra-templates/layer-2-flat-network/5/README.md b/infra-templates/layer-2-flat-network/5/README.md new file mode 100644 index 000000000..0619ab9f2 --- /dev/null +++ b/infra-templates/layer-2-flat-network/5/README.md @@ -0,0 +1,29 @@ +# 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. + +Version 5 preserves `PASTURESTACK_DEBUG` as a string in the generated CNI JSON, +matching the CNI schema when the Catalog answer is a boolean. It 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/5/README.zh-TW.md b/infra-templates/layer-2-flat-network/5/README.zh-TW.md new file mode 100644 index 000000000..9611e41ca --- /dev/null +++ b/infra-templates/layer-2-flat-network/5/README.zh-TW.md @@ -0,0 +1,26 @@ +# 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 授權。作業系統 +套件及隨附元件保留各自的上游授權及聲明。 + +第 5 版會把 Catalog 的布林除錯選項明確保留為 CNI JSON 所要求的字串, +避免受管工作負載建立時發生型別解析錯誤。此版隨附會遵守 +`skipBridgeConfigureIP` 的橋接 CNI,保留已設定的網橋位址;不改變主機 +網橋權責,也不自動搬移實體網路 +介面。啟用此選用驅動程式前,仍須驗證真實第 2 層連線及回復方式。 diff --git a/infra-templates/layer-2-flat-network/5/docker-compose.yml.tpl b/infra-templates/layer-2-flat-network/5/docker-compose.yml.tpl new file mode 100644 index 000000000..154184070 --- /dev/null +++ b/infra-templates/layer-2-flat-network/5/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/5/rancher-compose.yml b/infra-templates/layer-2-flat-network/5/rancher-compose.yml new file mode 100644 index 000000000..5b272994e --- /dev/null +++ b/infra-templates/layer-2-flat-network/5/rancher-compose.yml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Layer 2 Flat Network + version: v0.3.3 + 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 1f94656e4..8c3a10905 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.2 +version: v0.3.3 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and bundled component licenses apply diff --git a/infra-templates/network-policy-manager/3/README.md b/infra-templates/network-policy-manager/3/README.md new file mode 100644 index 000000000..f20653845 --- /dev/null +++ b/infra-templates/network-policy-manager/3/README.md @@ -0,0 +1,48 @@ + + +# PastureStack Network Policy Manager + +This infrastructure entry installs one policy agent on every eligible managed +host. Each agent reads the established link-local Metadata endpoint, compiles +the active network policy, and atomically replaces only +`table inet pasturestack_policy`. + +## Runtime behavior + +The agent checks Metadata every 20 seconds. Valid policy changes preserve +established and related connections, allow required system traffic, and apply +the configured default action to local application workloads. A transient +Metadata or policy error keeps the last-known-good table. If valid Metadata +remains unavailable for ten minutes, the agent enters a visible availability- +safe fail-open state and restores enforcement after reconciliation succeeds. + +The diagnostic readiness endpoint listens on host port `8092`. Rancher 1.6 +cannot address a health target for a host-network container without a container +IP, so this revision deliberately does not declare a Rancher health check that +would remain indefinitely in `initializing`. Operators can query `/readyz` +directly on each managed host; failures omit identifiers, addresses, labels, +selectors, and policy documents. + +## Security boundary + +The container uses host networking and only `NET_ADMIN`. It drops every other +capability, runs with a read-only root filesystem and +`no-new-privileges`, and does not use privileged mode, host PID, a +container-engine socket, host filesystem mounts, API credentials, or secret +input. + +Graceful stack removal stops reconciliation and deletes only the independently +owned nftables table. An unexpected container or host failure leaves the +last-known-good table in place. Review the source repository before changing +the polling, stale-data, or shutdown behavior. + +## License and provenance + +The template files and original icon are MIT-licensed PastureStack +contributions. The image source retains its Apache License 2.0, preserved +upstream history, authorship, and notices. Ubuntu, nftables, and bundled +dependencies retain their respective upstream licenses. + +PastureStack is an independent community effort to preserve, audit, and +modernize the Rancher 1.6 ecosystem. It is not affiliated with or endorsed by +Rancher Labs or SUSE. diff --git a/infra-templates/network-policy-manager/3/README.zh-TW.md b/infra-templates/network-policy-manager/3/README.zh-TW.md new file mode 100644 index 000000000..6676036f3 --- /dev/null +++ b/infra-templates/network-policy-manager/3/README.zh-TW.md @@ -0,0 +1,40 @@ + + +# PastureStack 網路政策管理器 + +此基礎架構範本會在每台符合條件的受管主機上安裝一個政策代理程式。 +每個代理程式都會讀取既有的連結本機中繼資料端點、編譯有效的網路 +政策,並以不可分割方式只替換 `table inet pasturestack_policy`。 + +## 執行方式 + +代理程式每 20 秒檢查一次中繼資料。有效政策變更會保留已建立及相關 +連線、允許必要系統流量,並把設定的預設動作套用到本機應用程式工作 +負載。暫時性中繼資料或政策錯誤會保留最後一份有效規則。若有效中繼 +資料持續無法使用十分鐘,代理程式會進入畫面可見、以維持可用性為主 +的開放狀態;協調成功後會自動恢復政策強制執行。 + +診斷用就緒狀態端點使用主機連接埠 `8092`。Rancher 1.6 無法為沒有 +容器 IP 的主機網路容器定位健康檢查目標,因此本版刻意不宣告會永遠 +停在「初始化中」的 Rancher 健康檢查。管理者可直接查詢每台受管主機 +的 `/readyz`;失敗回報不含識別碼、位址、標籤、選取條件或政策內容。 + +## 安全性界線 + +容器使用主機網路,且只保留 `NET_ADMIN`。其他 Capability 全部移除; +根檔案系統為唯讀並啟用 `no-new-privileges`。容器不使用特權模式、 +主機 PID、容器引擎 Socket、主機檔案掛載、API 登入資訊或機密資料 +輸入。 + +正常移除堆疊時會停止協調,並只刪除自己擁有的 nftables 表。非預期 +的容器或主機故障會保留最後一份有效規則。變更輪詢、過期資料或停止 +行為前,請先審查原始碼儲存庫。 + +## 授權與出處 + +範本檔案與原創圖示是 PastureStack 依 MIT 授權提供的新貢獻。映像 +原始碼保留 Apache License 2.0、上游歷史、作者與聲明。Ubuntu、 +nftables 及隨附相依套件保留各自的上游授權。 + +PastureStack 是獨立的社群計畫,目的在保存、稽核與現代化 Rancher +1.6 生態系;本計畫與 Rancher Labs 或 SUSE 無隸屬或背書關係。 diff --git a/infra-templates/network-policy-manager/3/docker-compose.yml b/infra-templates/network-policy-manager/3/docker-compose.yml new file mode 100644 index 000000000..197713391 --- /dev/null +++ b/infra-templates/network-policy-manager/3/docker-compose.yml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + network-policy-manager: + image: ghcr.io/pasturestack/network-policy-manager:v0.3.1 + command: + - serve + - --poll-interval + - 20s + - --fail-open-after + - 10m + - --health-listen + - 0.0.0.0:8092 + - --cleanup-on-exit + network_mode: host + cap_drop: + - ALL + cap_add: + - NET_ADMIN + read_only: true + tmpfs: + - /tmp:rw,noexec,nosuid,size=8m + security_opt: + - 'no-new-privileges:true' + labels: + io.pasturestack.component: network-policy-manager + io.rancher.scheduler.global: 'true' + cpu_shares: 128 + mem_limit: 64m + logging: + driver: json-file + options: + max-size: 10m + max-file: '2' diff --git a/infra-templates/network-policy-manager/3/rancher-compose.yml b/infra-templates/network-policy-manager/3/rancher-compose.yml new file mode 100644 index 000000000..3825f5ec2 --- /dev/null +++ b/infra-templates/network-policy-manager/3/rancher-compose.yml @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Network Policy Manager + version: v0.3.3 + description: Enforce metadata-defined network policy on every managed host with independently owned nftables rules. + minimum_rancher_version: v1.6.26-rc1 + +network-policy-manager: + start_on_create: true diff --git a/infra-templates/network-policy-manager/config.yml b/infra-templates/network-policy-manager/config.yml index ea0f160a5..a59ee9474 100644 --- a/infra-templates/network-policy-manager/config.yml +++ b/infra-templates/network-policy-manager/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: Network Policy Manager description: Enforce metadata-defined network policy on every managed host with independently owned nftables rules. -version: v0.3.2 +version: v0.3.3 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and bundled dependency licenses apply diff --git a/infra-templates/network-services/8/README.md b/infra-templates/network-services/8/README.md new file mode 100644 index 000000000..71a3e14d2 --- /dev/null +++ b/infra-templates/network-services/8/README.md @@ -0,0 +1,44 @@ + + +# PastureStack Network Services + +Version 8 uses Network Plugin Manager `v0.8.20`. It retains single-backend selection and unchanged Metadata Service and Internal DNS images. It restores bounded inbound forwarding for fixed shared overlay subnets such as the IPsec and VXLAN `10.42.0.0/16` network. The rule accepts only new or established traffic whose source and destination are both inside that configured subnet and whose output interface is the exact managed bridge. Per-host-subnet networks keep their separate peer-to-local-subnet rules. The manager rejects malformed or conflicting bridge metadata before touching host firewall rules, binds every managed forwarding rule to that exact bridge, and protects bridge traffic from `route_localnet` loopback routing. It records the original per-bridge setting under `/run`, applies the guard before enabling it, and restores the original value when that bridge no longer needs a host port. 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. + +Shared-subnet ingress is enabled only when CNI metadata explicitly sets +`allowSharedSubnetIngress: true`, or for the legacy fixed-subnet contract that +already declares both `bridgeSubnet` and `hostNat: true`. It is rejected for +host-label-based subnets, where only validated active peer ranges are trusted. + +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/8/README.zh-TW.md b/infra-templates/network-services/8/README.zh-TW.md new file mode 100644 index 000000000..c346f8044 --- /dev/null +++ b/infra-templates/network-services/8/README.zh-TW.md @@ -0,0 +1,32 @@ + + +# PastureStack 網路服務 + +第 8 版使用網路外掛管理器 `v0.8.20`,保留單一防火牆後端的選擇方式,以及相同的中繼資料服務與內部 DNS 映像;並恢復固定共用 overlay 子網路(例如 IPsec 與 VXLAN 的 `10.42.0.0/16`)有限制的輸入轉送。規則只接受來源與目的都位於該設定子網路、輸出介面為正確受管網橋的新連線或既有連線;每主機子網路仍使用另一套對端至本機子網路規則。管理器會在修改主機防火牆規則前拒絕格式錯誤或互相衝突的網橋中繼資料,並把所有受管轉送規則限制在正確網橋。啟用 `route_localnet` 前會先阻擋來自該網橋、目的為 `127.0.0.0/8` 的流量;原始的每網橋設定會保存於 `/run`,不再需要主機連接埠時則恢復原值。映像發布來源與 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 加密網路版本。 + +只有 CNI 中繼資料明確設定 `allowSharedSubnetIngress: true` 時才啟用共用子網路輸入轉送;為維持既有固定子網路契約相容性,同時具有 `bridgeSubnet` 與 `hostNat: true` 的舊設定也會採用相同行為。使用主機標籤決定子網路時會拒絕此選項,只信任已驗證的現役對端範圍。 + +使用 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/8/docker-compose.yml.tpl b/infra-templates/network-services/8/docker-compose.yml.tpl new file mode 100644 index 000000000..b65dccd31 --- /dev/null +++ b/infra-templates/network-services/8/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.20 + 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/8/rancher-compose.yml b/infra-templates/network-services/8/rancher-compose.yml new file mode 100644 index 000000000..07e9b7235 --- /dev/null +++ b/infra-templates/network-services/8/rancher-compose.yml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Network Services + version: v0.3.6 + 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 732e1b199..8f11ad9dc 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.5 +version: v0.3.6 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 images and third-party package licenses apply diff --git a/infra-templates/per-host-subnet-network/4/README.md b/infra-templates/per-host-subnet-network/4/README.md new file mode 100644 index 000000000..c5533bac5 --- /dev/null +++ b/infra-templates/per-host-subnet-network/4/README.md @@ -0,0 +1,37 @@ +# PastureStack Per-Host Subnet Network + +This infrastructure template assigns a different workload subnet to each host +and maintains marked host-gateway routes between those subnets. Before +deployment, add a unique label to every participating host: + +```text +io.pasturestack.network.per-host-subnet.subnet=10.50.1.0/24 +``` + +Use a different, non-overlapping subnet on each host. Optional allocation +bounds use +`io.pasturestack.network.per-host-subnet.range-start` and +`io.pasturestack.network.per-host-subnet.range-end`. The controller accepts +`io.pasturestack.network.per-host-subnet.override-agent-ip` only when metadata +does not advertise the address that other hosts can route through. + +The template uses +`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34`. The image source is +[`PastureStack/ipsec-vxlan-overlay-network@db5a506346f521c6947b21a1a60cef6dd546f983`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/db5a506346f521c6947b21a1a60cef6dd546f983); +the bundled controller is from +[`PastureStack/per-host-subnet@babe7d7f2b7f67a18883b9ed99d17483c8854315`](https://github.com/PastureStack/per-host-subnet/tree/babe7d7f2b7f67a18883b9ed99d17483c8854315), +and the bundled IPAM executable is from +[`PastureStack/host-local-cni-ipam@e79e1721f78a9579145cd89d8ad5083ae24633f5`](https://github.com/PastureStack/host-local-cni-ipam/tree/e79e1721f78a9579145cd89d8ad5083ae24633f5). + +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. + +Version 4 preserves `PASTURESTACK_DEBUG` as a string in the generated CNI JSON, +matching the CNI schema when the Catalog answer is a boolean. Version 3 resolves +host-specific bridge and IPAM labels through the control +plane's plain-text `/self/host/labels/` endpoint. The previous version's +JSON assumption prevented managed workload creation on a real host. A subnet +label must be valid and non-overlapping; Network Plugin Manager validates it +before applying host firewall rules. This driver is optional, not a second +Catalog vendor or an automatic replacement for the encrypted IPsec overlay. diff --git a/infra-templates/per-host-subnet-network/4/README.zh-TW.md b/infra-templates/per-host-subnet-network/4/README.zh-TW.md new file mode 100644 index 000000000..86218f1aa --- /dev/null +++ b/infra-templates/per-host-subnet-network/4/README.zh-TW.md @@ -0,0 +1,35 @@ +# PastureStack 每台主機獨立子網路 + +此基礎架構範本會為每台主機分配不同的工作負載子網路,並維護這些 +子網路之間帶有專用標記的主機閘道路由。部署前,請為每台參與主機 +新增唯一標籤: + +```text +io.pasturestack.network.per-host-subnet.subnet=10.50.1.0/24 +``` + +每台主機必須使用互不重疊的子網路。可用 +`io.pasturestack.network.per-host-subnet.range-start` 與 +`io.pasturestack.network.per-host-subnet.range-end` 限制分配範圍。 +只有中繼資料沒有提供其他主機可路由的位址時,控制器才會接受 +`io.pasturestack.network.per-host-subnet.override-agent-ip`。 + +此範本使用 +`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34`。 +映像原始碼位於 +[`PastureStack/ipsec-vxlan-overlay-network@db5a506346f521c6947b21a1a60cef6dd546f983`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/db5a506346f521c6947b21a1a60cef6dd546f983), +隨附控制器來自 +[`PastureStack/per-host-subnet@babe7d7f2b7f67a18883b9ed99d17483c8854315`](https://github.com/PastureStack/per-host-subnet/tree/babe7d7f2b7f67a18883b9ed99d17483c8854315), +隨附 IPAM 執行檔來自 +[`PastureStack/host-local-cni-ipam@e79e1721f78a9579145cd89d8ad5083ae24633f5`](https://github.com/PastureStack/host-local-cni-ipam/tree/e79e1721f78a9579145cd89d8ad5083ae24633f5)。 + +範本檔案與圖示採 MIT 授權;執行專案採 Apache-2.0 授權。作業系統 +套件及隨附元件保留各自的上游授權及聲明。 + +第 4 版會把 Catalog 的布林除錯選項明確保留為 CNI JSON 所要求的字串, +避免受管工作負載建立時發生型別解析錯誤。第 3 版透過控制平面實際提供的 +純文字 `/self/host/labels/` +端點解析主機專屬網橋及 IPAM 標籤;舊版將回應誤當 JSON,會使真機 +受管工作負載建立失敗。子網路標籤必須有效且互不重疊,網路外掛管理器 +會在套用主機防火牆規則前驗證。本驅動程式為選用功能,不會另外建立 +商店供應者,也不會自動取代加密的 IPsec 覆疊網路。 diff --git a/infra-templates/per-host-subnet-network/4/docker-compose.yml.tpl b/infra-templates/per-host-subnet-network/4/docker-compose.yml.tpl new file mode 100644 index 000000000..3f50b09cf --- /dev/null +++ b/infra-templates/per-host-subnet-network/4/docker-compose.yml.tpl @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + per-host-subnet-controller: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34 + command: per-host-subnet + privileged: true + network_mode: host + pid: host + environment: + PLATFORM_DEBUG: '${PASTURESTACK_DEBUG}' + PLATFORM_METADATA_URL: http://169.254.169.250/2016-07-29 + PLATFORM_METADATA_STARTUP_TIMEOUT: '${METADATA_STARTUP_TIMEOUT}' + PLATFORM_WATCH_INTERVAL: '${WATCH_INTERVAL}' + PLATFORM_ENABLE_ROUTE_UPDATE: '${ENABLE_ROUTE_UPDATE}' + PLATFORM_ROUTE_UPDATE_PROVIDER: host-gateway + labels: + io.pasturestack.component: per-host-subnet-controller + io.rancher.scheduler.global: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + + per-host-subnet-cni: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34 + command: start-cni-driver.sh + privileged: true + network_mode: host + pid: host + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + labels: + io.pasturestack.component: per-host-subnet-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 Per-Host Subnet Network + default_network: + name: per-host-subnet + host_ports: {{ .Values.HOST_PORTS }} + dns: + - 169.254.169.250 + dns_search: + - pasture.internal + cni_config: + '10-pasturestack-per-host-subnet.conf': + name: pasturestack-per-host-subnet-network + type: pasture-bridge + bridge: ${BRIDGE} + bridgeSubnet: '__host_label__: io.pasturestack.network.per-host-subnet.subnet' + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' + isDefaultGateway: true + hostNat: {{ .Values.HOST_NAT }} + hairpinMode: {{ .Values.HAIRPIN_MODE }} + promiscMode: {{ .Values.PROMISCUOUS_MODE }} + mtu: ${MTU} + ipam: + type: host-local-cni-ipam + subnet: '__host_label__: io.pasturestack.network.per-host-subnet.subnet' + rangeStart: '__host_label__: io.pasturestack.network.per-host-subnet.range-start' + rangeEnd: '__host_label__: io.pasturestack.network.per-host-subnet.range-end' + dataDir: /opt/cni/state + metadataURL: http://169.254.169.250/2016-07-29 + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' diff --git a/infra-templates/per-host-subnet-network/4/rancher-compose.yml b/infra-templates/per-host-subnet-network/4/rancher-compose.yml new file mode 100644 index 000000000..84a5e8db6 --- /dev/null +++ b/infra-templates/per-host-subnet-network/4/rancher-compose.yml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Per-Host Subnet Network + version: v0.3.2 + description: Assign a distinct workload subnet to each host and maintain host-gateway routes between hosts. + minimum_rancher_version: v1.6.26-rc1 + labels: + io.pasturestack.catalog.question.bridge.label.zh-tw: '工作負載網橋' + io.pasturestack.catalog.question.bridge.description.zh-tw: '每台主機的受管工作負載子網路使用的主機網橋。' + io.pasturestack.catalog.question.mtu.label.zh-tw: '網路 MTU' + io.pasturestack.catalog.question.mtu.description.zh-tw: '所有參與主機之間端對端支援的 MTU。' + io.pasturestack.catalog.question.enable_route_update.label.zh-tw: '維護主機路由' + io.pasturestack.catalog.question.enable_route_update.description.zh-tw: '維護前往其他主機工作負載子網路且帶有專用標記的主機閘道路由。' + io.pasturestack.catalog.question.host_nat.label.zh-tw: '啟用主機 NAT' + io.pasturestack.catalog.question.host_nat.description.zh-tw: '對離開各主機專用工作負載子網路的流量套用主機 NAT。' + io.pasturestack.catalog.question.host_ports.label.zh-tw: '啟用主機連接埠' + io.pasturestack.catalog.question.host_ports.description.zh-tw: '允許受管工作負載在主機上公開連接埠。' + io.pasturestack.catalog.question.hairpin_mode.label.zh-tw: '啟用 Hairpin 模式' + io.pasturestack.catalog.question.hairpin_mode.description.zh-tw: 'Hairpin 模式與混雜模式不可同時啟用。' + io.pasturestack.catalog.question.promiscuous_mode.label.zh-tw: '啟用混雜模式' + io.pasturestack.catalog.question.promiscuous_mode.description.zh-tw: '混雜模式與 Hairpin 模式不可同時啟用。' + io.pasturestack.catalog.question.metadata_startup_timeout.label.zh-tw: '中繼資料服務啟動逾時' + io.pasturestack.catalog.question.metadata_startup_timeout.description.zh-tw: '控制器結束前,等待中繼資料服務可用的最長時間。' + io.pasturestack.catalog.question.watch_interval.label.zh-tw: '中繼資料監看間隔' + io.pasturestack.catalog.question.watch_interval.description.zh-tw: '協調主機路由時使用的重試及長輪詢間隔。' + io.pasturestack.catalog.question.pasturestack_debug.label.zh-tw: '啟用除錯日誌' + io.pasturestack.catalog.question.pasturestack_debug.description.zh-tw: '記錄較詳細的子網路、路由與 CNI 操作診斷資訊。' + questions: + - variable: BRIDGE + label: Workload bridge + description: Host bridge used for each host's managed workload subnet. + type: string + default: docker0 + required: true + - variable: MTU + label: Network MTU + description: MTU supported end to end between all participating hosts. + type: int + default: 1500 + required: true + - variable: ENABLE_ROUTE_UPDATE + label: Maintain host routes + description: Maintain marked host-gateway routes for the other hosts' workload subnets. + type: boolean + default: 'true' + required: true + - variable: HOST_NAT + label: Enable host NAT + description: Apply host NAT to traffic leaving each host-specific workload subnet. + type: boolean + default: 'true' + 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: HAIRPIN_MODE + label: Enable hairpin mode + description: Hairpin mode and promiscuous mode must not both be enabled. + type: boolean + default: 'false' + required: true + - variable: PROMISCUOUS_MODE + label: Enable promiscuous mode + description: Promiscuous mode and hairpin mode must not both be enabled. + type: boolean + default: 'true' + required: true + - variable: METADATA_STARTUP_TIMEOUT + label: Metadata startup timeout + description: Maximum time to wait for the metadata service before the controller exits. + type: string + default: 2m + required: true + - variable: WATCH_INTERVAL + label: Metadata watch interval + description: Retry and long-poll interval used while reconciling host routes. + type: string + default: 5s + required: true + - variable: PASTURESTACK_DEBUG + label: Enable debug logs + description: Enable verbose diagnostics for subnet, route, and CNI operations. + type: boolean + default: 'false' + required: true diff --git a/infra-templates/per-host-subnet-network/config.yml b/infra-templates/per-host-subnet-network/config.yml index c615ed2a3..8ebfb9b4d 100644 --- a/infra-templates/per-host-subnet-network/config.yml +++ b/infra-templates/per-host-subnet-network/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: Per-Host Subnet Network description: Assign a distinct workload subnet to each host and maintain host-gateway routes between hosts. -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/vxlan-overlay-network/5/README.md b/infra-templates/vxlan-overlay-network/5/README.md new file mode 100644 index 000000000..a24853b2a --- /dev/null +++ b/infra-templates/vxlan-overlay-network/5/README.md @@ -0,0 +1,44 @@ + + +# PastureStack VXLAN Overlay Network 0.3.3 + +This optional infrastructure template installs an unencrypted VXLAN data +plane across managed hosts. It publishes UDP port `4789`, runs one router +sidecar per network holder, and installs the reviewed CNI executables on each +eligible host. + +## Reviewed image + +- Image: `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34` +- Template version `5` explicitly declares `allowSharedSubnetIngress: true` for the fixed `10.42.0.0/16` CNI network. Network Plugin Manager `v0.8.20` uses this bounded contract for cross-host workload forwarding; version `4` remains available for existing stacks. +- Source: [`PastureStack/ipsec-vxlan-overlay-network@db5a506346f521c6947b21a1a60cef6dd546f983`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/db5a506346f521c6947b21a1a60cef6dd546f983) +- Source license: Apache-2.0; Ubuntu, CNI, Weave, and bundled dependencies retain their upstream licenses and notices +- Security gate: Trivy HIGH 0, CRITICAL 0, image secrets 0, and personal-marker scan passed +- Runtime gate: the earlier version passed isolated two-node VXLAN forwarding; repeat the managed lifecycle gate for this new image before treating it as production-ready + +## Security and network boundary + +VXLAN encapsulates traffic but does not encrypt or authenticate it. Use this +driver only on a trusted host network. Every participating host must allow +inbound and outbound UDP port `4789`. Select the IPsec template when encrypted +host-to-host traffic is required. + +The router receives `NET_ADMIN` in the network-holder namespace. The CNI +sidecar is privileged, joins the host network and PID namespaces, and accesses +the Docker socket so it can install and operate the compatibility CNI path. +These permissions must not be copied to ordinary workloads. + +The managed network is `10.42.0.0/16`. This release intentionally does not +expose a subnet selector because the reviewed startup path does not safely +honor arbitrary subnets. Network Plugin Manager alone consumes the explicit +shared-subnet ingress contract and owns the corresponding host forwarding +rule; the VXLAN router remains confined to its data-plane namespace. + +## Compatibility boundary + +The literal `rancher-compose.yml` filename, `minimum_rancher_version` key, +required `io.rancher.*` orchestration labels, and `rancher-cni-driver` shared +volume are consumed by the compatible control plane. They are protocol +identifiers, not PastureStack branding. User-facing names, image coordinates, +environment variables, CNI names, log paths, and the `pasture.internal` search +suffix use current PastureStack identifiers. diff --git a/infra-templates/vxlan-overlay-network/5/README.zh-TW.md b/infra-templates/vxlan-overlay-network/5/README.zh-TW.md new file mode 100644 index 000000000..d836ffc2f --- /dev/null +++ b/infra-templates/vxlan-overlay-network/5/README.zh-TW.md @@ -0,0 +1,44 @@ + + +# PastureStack VXLAN 覆疊網路 0.3.3 + +此選用基礎架構範本會在受管主機間安裝未加密的 VXLAN 資料平面。 +範本會公開 UDP `4789`、為每個網路持有服務執行一個路由相關容器, +並在每台符合條件的主機上安裝經審核的 CNI 執行檔。 + +## 已審核映像 + +- 映像:`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34` +- 第 `5` 版為固定的 `10.42.0.0/16` CNI 網路明確設定 + `allowSharedSubnetIngress: true`。網路外掛管理器 `v0.8.20` 依此有限 + 契約處理跨主機工作負載轉送;第 `4` 版仍供既有堆疊使用。 +- 原始碼: + [`PastureStack/ipsec-vxlan-overlay-network@db5a506346f521c6947b21a1a60cef6dd546f983`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/db5a506346f521c6947b21a1a60cef6dd546f983) +- 原始碼採 Apache-2.0 授權;Ubuntu、CNI、Weave 及隨附相依套件 + 保留各自的上游授權及聲明。 +- Trivy 結果為 HIGH 0、CRITICAL 0,映像機密資料與個人識別標記 + 掃描均已通過。 +- 舊版已通過隔離雙節點 VXLAN 轉送;此新版映像仍須重新完成受管生命週期驗收,才能宣稱適合正式環境。 + +## 安全性與網路界線 + +VXLAN 只封裝流量,不提供加密或身分驗證。此驅動程式只能用於受信任 +的主機網路,每台參與主機都必須允許 UDP `4789` 的輸入及輸出流量。 +需要主機間加密時,請改用 IPsec 加密網路範本。 + +路由器在網路持有服務的命名空間中使用 `NET_ADMIN`。CNI 相關容器 +使用特權模式、加入主機網路與 PID 命名空間,並存取 Docker Socket +以安裝及操作相容 CNI 路徑。這些權限不得套用到一般工作負載。 + +受管網路為 `10.42.0.0/16`。經審核的啟動流程無法安全套用任意 +子網路,因此此版本不提供無效的子網路選項。只有網路外掛管理器會 +處理明確的共用子網路輸入契約及相對應的主機轉送規則;VXLAN 路由器 +仍只在自己的資料平面命名空間內運作。 + +## 相容性界線 + +`rancher-compose.yml`、`minimum_rancher_version`、必要的 +`io.rancher.*` 編排標籤及 `rancher-cni-driver` 共用磁碟區是相容 +控制平面使用的協定識別名稱,不是目前的產品品牌。使用者可見名稱、 +映像位置、環境變數、CNI 名稱、日誌路徑及 `pasture.internal` +搜尋後綴均採 PastureStack 名稱。 diff --git a/infra-templates/vxlan-overlay-network/5/docker-compose.yml.tpl b/infra-templates/vxlan-overlay-network/5/docker-compose.yml.tpl new file mode 100644 index 000000000..8ebef72b9 --- /dev/null +++ b/infra-templates/vxlan-overlay-network/5/docker-compose.yml.tpl @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: MIT +version: '2' + +services: + vxlan-network: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34 + command: + - /bin/bash + - -c + - 'mkfifo /tmp/overlay-log; exec cat /tmp/overlay-log' + network_mode: vxlan + ports: + - 4789:4789/udp + labels: + io.pasturestack.component: vxlan-overlay + io.rancher.sidekicks: vxlan-router + io.rancher.scheduler.global: 'true' + io.rancher.cni.link_mtu_overhead: '0' + io.rancher.internal.service.vxlan: 'true' + io.rancher.service.selector.link: io.rancher.internal.service.vxlan=true + io.rancher.network.macsync: 'true' + io.rancher.network.arpsync: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + + vxlan-router: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34 + command: start-vxlan.sh + cap_add: + - NET_ADMIN + network_mode: container:vxlan-network + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + 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' + + cni-driver: + image: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.34 + command: start-cni-driver.sh + privileged: true + network_mode: host + pid: host + environment: + PASTURESTACK_DEBUG: '${PASTURESTACK_DEBUG}' + labels: + io.pasturestack.component: vxlan-overlay-cni + io.rancher.scheduler.global: 'true' + io.rancher.network.cni.binary: pasture-bridge + io.rancher.container.dns: 'true' + logging: + driver: json-file + options: + max-size: 25m + max-file: '2' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - rancher-cni-driver:/opt/cni-driver + network_driver: + name: PastureStack VXLAN Overlay Network + default_network: + name: vxlan + host_ports: {{ .Values.HOST_PORTS }} + subnets: + - network_address: 10.42.0.0/16 + dns: + - 169.254.169.250 + dns_search: + - pasture.internal + cni_config: + '10-pasturestack-vxlan.conf': + name: pasturestack-cni-network + type: pasture-bridge + bridge: $DOCKER_BRIDGE + bridgeSubnet: 10.42.0.0/16 + allowSharedSubnetIngress: true + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' + isDefaultGateway: true + hostNat: true + hairpinMode: {{ .Values.PASTURESTACK_HAIRPIN_MODE }} + promiscMode: {{ .Values.PASTURESTACK_PROMISCUOUS_MODE }} + mtu: ${MTU} + linkMTUOverhead: 50 + ipam: + type: metadata-cni-ipam + subnetPrefixSize: /16 + logToFile: /var/log/pasturestack-cni.log + isDebugLevel: '${PASTURESTACK_DEBUG}' diff --git a/infra-templates/vxlan-overlay-network/5/rancher-compose.yml b/infra-templates/vxlan-overlay-network/5/rancher-compose.yml new file mode 100644 index 000000000..a8c14bebe --- /dev/null +++ b/infra-templates/vxlan-overlay-network/5/rancher-compose.yml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack VXLAN Overlay Network + version: v0.3.3 + description: Provide an unencrypted UDP VXLAN network across managed hosts. + minimum_rancher_version: v1.6.11-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.mtu.label.zh-tw: '網路 MTU' + io.pasturestack.catalog.question.mtu.description.zh-tw: '請與主機網路 MTU 一致;GCE 常用 1460,一般乙太網路常用 1500。' + io.pasturestack.catalog.question.pasturestack_debug.label.zh-tw: '啟用除錯日誌' + io.pasturestack.catalog.question.pasturestack_debug.description.zh-tw: '記錄較詳細的 VXLAN 元件診斷資訊。' + io.pasturestack.catalog.question.host_ports.label.zh-tw: '啟用主機連接埠' + io.pasturestack.catalog.question.host_ports.description.zh-tw: '允許受管工作負載在主機上公開連接埠。' + io.pasturestack.catalog.question.pasturestack_hairpin_mode.label.zh-tw: '啟用 Hairpin 模式' + io.pasturestack.catalog.question.pasturestack_hairpin_mode.description.zh-tw: 'Hairpin 模式與混雜模式不可同時啟用。' + io.pasturestack.catalog.question.pasturestack_promiscuous_mode.label.zh-tw: '啟用混雜模式' + io.pasturestack.catalog.question.pasturestack_promiscuous_mode.description.zh-tw: '混雜模式與 Hairpin 模式不可同時啟用。' + questions: + - variable: DOCKER_BRIDGE + label: Docker bridge + description: Host bridge used for managed workload traffic. + type: string + default: docker0 + required: true + - variable: MTU + label: Network MTU + description: Match the host network MTU; common values are 1460 for GCE and 1500 for Ethernet. + type: int + default: 1500 + required: true + - variable: PASTURESTACK_DEBUG + label: Enable debug logs + description: Enable verbose diagnostic logging for the VXLAN components. + type: boolean + default: 'false' + 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_HAIRPIN_MODE + label: Enable hairpin mode + description: Hairpin mode and promiscuous mode must not both be enabled. + type: boolean + default: 'false' + required: true + - variable: PASTURESTACK_PROMISCUOUS_MODE + label: Enable promiscuous mode + description: Promiscuous mode and hairpin mode must not both be enabled. + type: boolean + default: 'true' + required: true diff --git a/infra-templates/vxlan-overlay-network/config.yml b/infra-templates/vxlan-overlay-network/config.yml index da1b8f2de..3d6e96fd2 100644 --- a/infra-templates/vxlan-overlay-network/config.yml +++ b/infra-templates/vxlan-overlay-network/config.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT name: VXLAN Overlay Network description: Provide an unencrypted UDP VXLAN network across managed hosts. -version: v0.3.2 +version: v0.3.3 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and third-party package licenses apply diff --git a/integration/core/test_catalog.py b/integration/core/test_catalog.py index c1398a45a..d461e627b 100644 --- a/integration/core/test_catalog.py +++ b/integration/core/test_catalog.py @@ -204,17 +204,17 @@ def test_catalog_list(): assert by_folder[('infra', 'ipsec-overlay')]['name'] == ( 'IPsec Overlay') assert by_folder[('infra', 'ipsec-overlay')][ - 'defaultVersion'] == 'v0.3.8' + 'defaultVersion'] == 'v0.3.9' assert by_folder[('infra', 'ipsec-overlay')][ 'links']['defaultVersion'].endswith( - ':10') + ':11') assert by_folder[('infra', 'layer-2-flat-network')]['name'] == ( 'Layer 2 Flat Network') assert by_folder[('infra', 'layer-2-flat-network')][ - 'defaultVersion'] == 'v0.3.2' + 'defaultVersion'] == 'v0.3.3' assert by_folder[('infra', 'layer-2-flat-network')][ 'links']['defaultVersion'].endswith( - ':4') + ':5') assert by_folder[('infra', 'network-diagnostics')]['name'] == ( 'Network Diagnostics') assert by_folder[('infra', 'network-diagnostics')][ @@ -225,17 +225,17 @@ def test_catalog_list(): assert by_folder[('infra', 'network-policy-manager')]['name'] == ( 'Network Policy Manager') assert by_folder[('infra', 'network-policy-manager')][ - 'defaultVersion'] == 'v0.3.2' + 'defaultVersion'] == 'v0.3.3' assert by_folder[('infra', 'network-policy-manager')][ 'links']['defaultVersion'].endswith( - ':2') + ':3') assert by_folder[('infra', 'network-services')]['name'] == ( 'Network Services') assert by_folder[('infra', 'network-services')][ - 'defaultVersion'] == 'v0.3.5' + 'defaultVersion'] == 'v0.3.6' assert by_folder[('infra', 'network-services')][ 'links']['defaultVersion'].endswith( - ':7') + ':8') assert by_folder[('infra', 'nfs-storage')][ 'name'] == 'NFS Storage' assert by_folder[('infra', 'nfs-storage')][ @@ -260,10 +260,9 @@ def test_catalog_list(): assert by_folder[('infra', 'per-host-subnet-network')]['name'] == ( 'Per-Host Subnet Network') assert by_folder[('infra', 'per-host-subnet-network')][ - 'defaultVersion'] == 'v0.3.1' + 'defaultVersion'] == 'v0.3.2' assert by_folder[('infra', 'per-host-subnet-network')][ - 'links']['defaultVersion'].endswith( - ':3') + 'links']['defaultVersion'].endswith(':4') assert by_folder[('infra', 'resource-scheduler')][ 'name'] == 'Resource Scheduler' assert by_folder[('infra', 'resource-scheduler')][ @@ -288,10 +287,10 @@ def test_catalog_list(): assert by_folder[('infra', 'vxlan-overlay-network')]['name'] == ( 'VXLAN Overlay Network') assert by_folder[('infra', 'vxlan-overlay-network')][ - 'defaultVersion'] == 'v0.3.2' + 'defaultVersion'] == 'v0.3.3' assert by_folder[('infra', 'vxlan-overlay-network')][ 'links']['defaultVersion'].endswith( - ':4') + ':5') assert by_folder[('infra', 'windows-container-networking')][ 'name'] == 'Windows Container Networking' assert by_folder[('infra', 'windows-container-networking')][ @@ -585,6 +584,7 @@ def test_catalog_compose_shapes_are_runtime_compatible(): assert 'PASTURESTACK_NETWORK_XFRM_NETNS_PATH' in overlay_docker assert 'ipsec-vxlan-connectivity-check' in overlay_docker assert 'type: pasture-bridge' in overlay_docker + assert 'allowSharedSubnetIngress: true' in overlay_docker assert 'type: metadata-cni-ipam' in overlay_docker assert 'pasture.internal' in overlay_docker assert 'RANCHER_' not in overlay_docker @@ -611,6 +611,7 @@ def test_catalog_compose_shapes_are_runtime_compatible(): assert 'io.rancher.sidekicks: vxlan-router' in vxlan_docker assert 'io.rancher.internal.service.vxlan' in vxlan_docker assert 'type: pasture-bridge' in vxlan_docker + assert 'allowSharedSubnetIngress: true' in vxlan_docker assert 'type: metadata-cni-ipam' in vxlan_docker assert 'pasture.internal' in vxlan_docker assert 'RANCHER_' not in vxlan_docker @@ -707,9 +708,9 @@ def test_catalog_compose_shapes_are_runtime_compatible(): assert 'pid: host' not in policy_docker assert '@sha256:' not in policy_docker assert 'minimum_rancher_version: v1.6.26-rc1' in policy_platform - assert 'request_line: GET /readyz HTTP/1.0' in policy_platform - assert 'port: 8092' in policy_platform - assert 'strategy: none' in policy_platform + assert '--health-listen' in policy_docker + assert 'health_check:' not in policy_platform + assert 'port: 8092' not in policy_platform network_version = _get_json( by_folder[('infra', 'network-services')]['links']['defaultVersion']) @@ -717,7 +718,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.19') + 'ghcr.io/pasturestack/network-plugin-manager:v0.8.20') 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 372d243b5..724ffd33c 100644 --- a/scripts/audit_deployable_images.py +++ b/scripts/audit_deployable_images.py @@ -53,16 +53,16 @@ RETAINED_VERSION_LAYOUTS = { "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", "4"), + "ipsec-overlay": ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"), + "layer-2-flat-network": ("2", "3", "4", "5"), "network-diagnostics": ("1", "2"), - "network-policy-manager": ("1", "2"), - "network-services": ("1", "2", "3", "4", "5", "6", "7"), + "network-policy-manager": ("1", "2", "3"), + "network-services": ("1", "2", "3", "4", "5", "6", "7", "8"), "nfs-storage": ("1", "2"), - "per-host-subnet-network": ("2", "3"), + "per-host-subnet-network": ("2", "3", "4"), "resource-scheduler": ("1", "2", "3", "4"), "secret-volume-driver": ("1", "2"), - "vxlan-overlay-network": ("2", "3", "4"), + "vxlan-overlay-network": ("2", "3", "4", "5"), } RETAINED_VERSION_HASHES = { "infra-templates/healthcheck/0/README.md": "1b18863d98ba3c042676f81daf6d6fc510c255cd1df275495985ed41f3b13aaa", diff --git a/scripts/check-firewall-backend-contract.py b/scripts/check-firewall-backend-contract.py index 48c70f028..dc3549b33 100644 --- a/scripts/check-firewall-backend-contract.py +++ b/scripts/check-firewall-backend-contract.py @@ -47,6 +47,11 @@ def check_cni_ownership(template: str, expected_host_nat: str) -> None: cni = compose.split(" cni_config:\n", 1)[1] assert f" hostNat: {expected_host_nat}\n" in cni, template assert "ipMasq:" not in cni, template + # Catalog boolean answers are rendered through YAML before this embedded + # CNI document is parsed. Keep the CNI schema's string field quoted. + assert compose.count( + "isDebugLevel: '${PASTURESTACK_DEBUG}'" + ) == 2, template if template == "vxlan-overlay-network": router = compose.split(" vxlan-router:\n", 1)[1].split( diff --git a/scripts/test b/scripts/test index cd1bd7f44..9b01f57f0 100755 --- a/scripts/test +++ b/scripts/test @@ -111,10 +111,12 @@ for version_id in \ ipsec-overlay:2 \ ipsec-overlay:3 \ ipsec-overlay:4 \ + ipsec-overlay:11 \ network-diagnostics:1 \ network-diagnostics:2 \ network-policy-manager:1 \ network-policy-manager:2 \ + network-policy-manager:3 \ network-services:1 \ network-services:2 \ network-services:3 \ @@ -122,6 +124,7 @@ for version_id in \ network-services:5 \ network-services:6 \ network-services:7 \ + network-services:8 \ nfs-storage:1 \ nfs-storage:2 \ resource-scheduler:1 \ @@ -131,8 +134,11 @@ for version_id in \ secret-volume-driver:1 \ secret-volume-driver:2 \ layer-2-flat-network:4 \ + layer-2-flat-network:5 \ + per-host-subnet-network:4 \ vxlan-overlay-network:2 \ - vxlan-overlay-network:3; do + vxlan-overlay-network:3 \ + vxlan-overlay-network:5; do version_url="http://localhost:8088/v1-catalog/templateversions/library:infra*${version_id}" if ! curl -fsS "$version_url" >/dev/null; then echo "catalog-service version lookup failed: ${version_id} (${version_url}), pinned commit ${source_commit}" >&2 From ad34381ade1070e03714f5aa7d6247bebd6b4e6a Mon Sep 17 00:00:00 2001 From: chen21019 Date: Mon, 14 Sep 2026 16:51:17 +0800 Subject: [PATCH 2/3] Release Flat network IPAM fix as template version 6 --- COMPATIBILITY.md | 11 +++ README.md | 10 +- catalog-images.json | 19 ++++ .../layer-2-flat-network/6/README.md | 31 ++++++ .../layer-2-flat-network/6/README.zh-TW.md | 26 +++++ .../6/docker-compose.yml.tpl | 70 ++++++++++++++ .../6/rancher-compose.yml | 96 +++++++++++++++++++ .../layer-2-flat-network/config.yml | 2 +- integration/core/test_catalog.py | 6 +- scripts/audit_deployable_images.py | 2 +- scripts/test | 1 + 11 files changed, 265 insertions(+), 9 deletions(-) create mode 100644 infra-templates/layer-2-flat-network/6/README.md create mode 100644 infra-templates/layer-2-flat-network/6/README.zh-TW.md create mode 100644 infra-templates/layer-2-flat-network/6/docker-compose.yml.tpl create mode 100644 infra-templates/layer-2-flat-network/6/rancher-compose.yml diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index f4bf1e69d..a4c1f453f 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -40,6 +40,17 @@ continue to trust only validated active peer ranges. IPsec owns XFRM and routes; VXLAN owns its data-plane namespace; neither may patch the manager's host firewall chains merely to make an integration test pass. +Host firewall selection follows the installed system instead of rewriting it. +In `auto` mode, Network Plugin Manager distinguishes Docker's native nftables +backend from the iptables compatibility backend, then resolves the host's +active iptables implementation as iptables-nft or iptables-legacy. It does not +change `update-alternatives`, load a legacy kernel module, create rules in an +inactive backend, or silently fall back after an error. An explicit backend +answer is accepted only when it matches the detected host and Docker rule +owner; a mismatch fails closed before existing hooks are replaced. This is the +same contract on Ubuntu 26.04 and later: a newer operating system is not enough +reason to override an operator's existing firewall choice. + The `PastureStack Network Diagnostics` release candidate keeps only the catalog filename, version gate, and global scheduling label required by the compatible control plane. Its images, services, variables, persisted volume, diff --git a/README.md b/README.md index 17d1d8f40..203e2b42e 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,11 @@ and preserves routed container source IPs between validated active peers. It also restores bounded inbound forwarding for fixed shared overlay subnets, binds every forwarding rule to the exact configured subnet and managed bridge, and protects bridge traffic from `route_localnet` loopback routing while -preserving and restoring the operator's original per-bridge setting. Layer 2 Flat Network -version `4` moves to `v0.14.36` so the CNI -preserves an operator-configured bridge address. +preserving and restoring the operator's original per-bridge setting. Layer 2 +Flat Network version `6` moves to `v0.14.37`. Its Flat IPAM keeps an explicitly +configured host bridge address, but when `bridgeSubnet` is a network prefix it +deterministically selects the first usable address only if that address is +actually present. Ambiguous multi-address bridges still fail closed. 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 @@ -161,7 +163,7 @@ corresponding current definition. Historical definitions are restored exactly from reviewed immutable source snapshots; their original commits and contents remain available in Git history without making prerelease tag names part of the current operator workflow. Taiwan Traditional Chinese readmes are added without -changing those workload definitions. The integration gate is configured to resolve all 26 +changing those workload definitions. The integration gate is configured to resolve all 27 retained and current version IDs through Catalog Service so an existing stack cannot regress to a version-detail 404. diff --git a/catalog-images.json b/catalog-images.json index f89624d1d..f601dbcf0 100644 --- a/catalog-images.json +++ b/catalog-images.json @@ -261,6 +261,25 @@ "secrets": 0 } }, + { + "reference": "ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.37", + "manifestDigest": "sha256:1b3451edc5f338e13edb14a434bf68d51febdcfd25dc94de73b9a2421656014f", + "sourceRepository": "https://github.com/PastureStack/ipsec-vxlan-overlay-network", + "sourceCommit": "20eb898da1b24ed3b8ab2c0ad212d6523adeddeb", + "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", diff --git a/infra-templates/layer-2-flat-network/6/README.md b/infra-templates/layer-2-flat-network/6/README.md new file mode 100644 index 000000000..317628d88 --- /dev/null +++ b/infra-templates/layer-2-flat-network/6/README.md @@ -0,0 +1,31 @@ +# 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.37`, which contains the +reviewed `pasture-bridge` and `flat-cni-ipam` executables. The image source is +[`PastureStack/ipsec-vxlan-overlay-network@20eb898da1b24ed3b8ab2c0ad212d6523adeddeb`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/20eb898da1b24ed3b8ab2c0ad212d6523adeddeb); +the Flat CNI IPAM source is +[`PastureStack/flat-cni-ipam@4676b320a03fec53ae68899fdf18c7e7f7340356`](https://github.com/PastureStack/flat-cni-ipam/tree/4676b320a03fec53ae68899fdf18c7e7f7340356). + +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. + +Version 6 retains version 5's correctly typed `PASTURESTACK_DEBUG` value and +bridge ownership boundary. Flat IPAM now distinguishes an explicit host +address from a network prefix: it keeps the explicit address, or selects the +first usable address only when that address is present on the bridge. If a +multi-address bridge remains ambiguous, allocation fails instead of guessing. +The change does not alter firewall, IPsec, VXLAN, or physical-interface setup. +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/6/README.zh-TW.md b/infra-templates/layer-2-flat-network/6/README.zh-TW.md new file mode 100644 index 000000000..648b36c4f --- /dev/null +++ b/infra-templates/layer-2-flat-network/6/README.zh-TW.md @@ -0,0 +1,26 @@ +# PastureStack 第 2 層平面網路 + +此基礎架構範本會透過主機網橋,將受管工作負載直接連接到共用的實體 +第 2 層子網路。每台參與主機都必須能連上相同的子網路與閘道,而且 +選定的工作負載位址範圍不得與 DHCP、主機或基礎架構位址重疊。 + +自動設定網橋預設為停用。若實體介面、子網路或閘道設定錯誤,把主機 +實體介面移入網橋可能會中斷遠端連線。請優先透過作業系統準備網橋; +若要啟用自動設定,請先確認具備頻外主控台存取方式。 + +此範本使用 +`ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.37`, +其中包含經審核的 `pasture-bridge` 與 `flat-cni-ipam` 執行檔。 +映像原始碼位於 +[`PastureStack/ipsec-vxlan-overlay-network@20eb898da1b24ed3b8ab2c0ad212d6523adeddeb`](https://github.com/PastureStack/ipsec-vxlan-overlay-network/tree/20eb898da1b24ed3b8ab2c0ad212d6523adeddeb), +Flat CNI IPAM 原始碼位於 +[`PastureStack/flat-cni-ipam@4676b320a03fec53ae68899fdf18c7e7f7340356`](https://github.com/PastureStack/flat-cni-ipam/tree/4676b320a03fec53ae68899fdf18c7e7f7340356)。 + +範本檔案與圖示採 MIT 授權;執行專案採 Apache-2.0 授權。作業系統 +套件及隨附元件保留各自的上游授權及聲明。 + +第 6 版保留第 5 版的除錯選項型別與網橋權責。Flat IPAM 現在會區分 +明確的主機位址與網路前綴:明確位址會原樣保留;若設定的是網路前綴, +只有當第一個可用位址確實存在於網橋時才會選用。多位址網橋若仍有歧義, +會停止配置而不擅自猜測。此變更不改動防火牆、IPsec、VXLAN 或實體介面 +設定。啟用此選用驅動程式前,仍須驗證真實第 2 層連線及回復方式。 diff --git a/infra-templates/layer-2-flat-network/6/docker-compose.yml.tpl b/infra-templates/layer-2-flat-network/6/docker-compose.yml.tpl new file mode 100644 index 000000000..7178c691c --- /dev/null +++ b/infra-templates/layer-2-flat-network/6/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.37 + 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/6/rancher-compose.yml b/infra-templates/layer-2-flat-network/6/rancher-compose.yml new file mode 100644 index 000000000..ec3fe882a --- /dev/null +++ b/infra-templates/layer-2-flat-network/6/rancher-compose.yml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Layer 2 Flat Network + version: v0.3.4 + 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 8c3a10905..9c3294aad 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.3 +version: v0.3.4 category: Networking maintainer: PastureStack contributors license: MIT template; Apache-2.0 image and bundled component licenses apply diff --git a/integration/core/test_catalog.py b/integration/core/test_catalog.py index d461e627b..943177803 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.3' + 'defaultVersion'] == 'v0.3.4' assert by_folder[('infra', 'layer-2-flat-network')][ 'links']['defaultVersion'].endswith( - ':5') + ':6') assert by_folder[('infra', 'network-diagnostics')]['name'] == ( 'Network Diagnostics') assert by_folder[('infra', 'network-diagnostics')][ @@ -625,7 +625,7 @@ def test_catalog_compose_shapes_are_runtime_compatible(): 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') + 'ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.37') assert layer_2_docker.count( 'image: {}'.format(flat_network_image)) == 1 assert '\n layer-2-flat-cni:\n' in layer_2_docker diff --git a/scripts/audit_deployable_images.py b/scripts/audit_deployable_images.py index 724ffd33c..34b140cb0 100644 --- a/scripts/audit_deployable_images.py +++ b/scripts/audit_deployable_images.py @@ -54,7 +54,7 @@ "ecr-credential-sync": ("2", "3"), "healthcheck": ("0", "1"), "ipsec-overlay": ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"), - "layer-2-flat-network": ("2", "3", "4", "5"), + "layer-2-flat-network": ("2", "3", "4", "5", "6"), "network-diagnostics": ("1", "2"), "network-policy-manager": ("1", "2", "3"), "network-services": ("1", "2", "3", "4", "5", "6", "7", "8"), diff --git a/scripts/test b/scripts/test index 9b01f57f0..7d6c0d30e 100755 --- a/scripts/test +++ b/scripts/test @@ -135,6 +135,7 @@ for version_id in \ secret-volume-driver:2 \ layer-2-flat-network:4 \ layer-2-flat-network:5 \ + layer-2-flat-network:6 \ per-host-subnet-network:4 \ vxlan-overlay-network:2 \ vxlan-overlay-network:3 \ From 349ea62bbb571b79c7aa3750d78a5a2bed6a361d Mon Sep 17 00:00:00 2001 From: chen21019 Date: Mon, 14 Sep 2026 21:08:34 +0800 Subject: [PATCH 3/3] Release Network Services v0.3.7 with NPM v0.8.21 --- README.md | 11 ++- SUPPORTED.md | 58 ++++++----- catalog-images.json | 20 ++++ infra-templates/network-services/9/README.md | 50 ++++++++++ .../network-services/9/README.zh-TW.md | 38 ++++++++ .../network-services/9/docker-compose.yml.tpl | 95 +++++++++++++++++++ .../network-services/9/rancher-compose.yml | 77 +++++++++++++++ infra-templates/network-services/config.yml | 2 +- integration/core/test_catalog.py | 6 +- scripts/audit_deployable_images.py | 2 +- scripts/test | 1 + 11 files changed, 328 insertions(+), 32 deletions(-) create mode 100644 infra-templates/network-services/9/README.md create mode 100644 infra-templates/network-services/9/README.zh-TW.md create mode 100644 infra-templates/network-services/9/docker-compose.yml.tpl create mode 100644 infra-templates/network-services/9/rancher-compose.yml diff --git a/README.md b/README.md index 203e2b42e..19df1d3d7 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,14 @@ 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 `8` moves to `v0.8.20`, +second container start. Network Services version `9` moves to `v0.8.21`, +keeps the host's actual Docker firewall path, and adds deterministic CNI +provider selection, exact immutable-container wrapper binding, symlink-safe +atomic wrapper repair, and a managed-subnet fallback for the short interval +before Metadata reports a new container address. The fallback accepts exactly +one address from the selected running container and revalidates its PID before +installing host-port rules; ambiguity preserves the last known-good rules. +Version `8` introduced the `v0.8.20` forwarding contract that rejects malformed per-host subnet labels before applying host firewall rules, and preserves routed container source IPs between validated active peers. It also restores bounded inbound forwarding for fixed shared overlay subnets, @@ -90,7 +97,7 @@ isolated Ubuntu 26.04.1 / Docker 29.8 hosts, the source-equivalent candidate passed bidirectional workload ping and TCP, service DNS, egress, a published host port, Docker restart, and both host reboots. The peer was explicitly tested with native nftables, iptables-nft, and iptables-legacy, then restored -to its original iptables-legacy configuration. This does not qualify every +to its pre-test firewall frontend. This does not qualify every existing deployment's upgrade or rollback path. The alternative drivers are not installed automatically by the project template. diff --git a/SUPPORTED.md b/SUPPORTED.md index 6f963b1d0..592093a84 100644 --- a/SUPPORTED.md +++ b/SUPPORTED.md @@ -13,7 +13,7 @@ or out-of-scope templates from being presented as deployable software. | PastureStack System Image Preloader | Infrastructure image-cache service | v0.3.0 | Public PastureStack GHCR image with an explicit version tag | Mock compatibility API discovery, real Docker pull/cache lifecycle, anonymous distribution, and HIGH/CRITICAL scan passed | | PastureStack Amazon ECR Credential Sync | Infrastructure registry service | v3.1.0 | Public PastureStack GHCR image with an explicit version tag | Source tests, anonymous distribution, and credential lifecycle gates passed | | Metadata Healthcheck | Infrastructure stack | v0.3.16 | Public PastureStack GHCR image with a non-overwritten version tag | Link-local Metadata integration and stdout/stderr routing passed; production rolling upgrade pending | -| PastureStack Network Services | Infrastructure system stack | v0.3.2 candidate | Network Plugin Manager v0.8.13 published; official manifest digest, source revision, and release scan recorded; Metadata Service and Internal DNS unchanged | Earlier isolated native-nft VM gates passed; the official image still requires formal multi-host lifecycle verification before catalog publication | +| PastureStack Network Services | Infrastructure system stack | v0.3.7 candidate | Network Plugin Manager v0.8.21; Metadata Service and Internal DNS unchanged | Two-host Ubuntu 26.04 gates passed native nftables, iptables-nft, and iptables-legacy across all four supported Linux network drivers; the exact official image and both host reboots passed; Catalog activation and removal remain release gates | | PastureStack Network Diagnostics | Infrastructure diagnostics service | v0.2.1 | Two public PastureStack GHCR images with explicit version tags | Reproducible builds, anonymous distribution, full snapshot and bundle lifecycle, persistence, localization, and HIGH/CRITICAL scan passed | | PastureStack Network Policy Manager | Infrastructure network-policy agent | v0.3.2 | Public PastureStack GHCR image with an explicit version tag | Five consecutive two-host default-deny, directed TCP allow, rollback, cleanup, and zero-restart gates passed | | PastureStack IPsec Overlay | Infrastructure network driver | v0.3.2 candidate | v0.14.27 published and manifest digest locked | Isolated VM two-container XFRM and encrypted-packet check passed; formal two-host control-plane lifecycle pending | @@ -405,35 +405,43 @@ release blockers. ## PastureStack Network Services evidence -- Network Plugin Manager: `ghcr.io/pasturestack/network-plugin-manager:v0.6.34` -- Network Plugin Manager source: [`PastureStack/network-plugin-manager@b4b61856d38a9410319688144ff635868571e35f`](https://github.com/PastureStack/network-plugin-manager/tree/b4b61856d38a9410319688144ff635868571e35f) +- Network Plugin Manager: `ghcr.io/pasturestack/network-plugin-manager:v0.8.21` +- Network Plugin Manager manifest: `sha256:aab4c05b0801feeca40fa9cb82a52fbfbfe506c609d3df2024fbc07ef4b968e9` +- Network Plugin Manager source: [`PastureStack/network-plugin-manager@2f2418423022264695f90960f4a80b9d20c5826f`](https://github.com/PastureStack/network-plugin-manager/tree/2f2418423022264695f90960f4a80b9d20c5826f) - Metadata Service: `ghcr.io/pasturestack/metadata-service:v0.9.11` - Metadata Service source: [`PastureStack/metadata-service@2096eb100a6c900ab70a952483306965c2278fe9`](https://github.com/PastureStack/metadata-service/tree/2096eb100a6c900ab70a952483306965c2278fe9) - Internal DNS: `ghcr.io/pasturestack/internal-dns:v0.17.11` - Internal DNS source: [`PastureStack/internal-dns@5459f857cb7ead00888e900d77e4dc713107fef1`](https://github.com/PastureStack/internal-dns/tree/5459f857cb7ead00888e900d77e4dc713107fef1) - License: Apache-2.0 for each project; Ubuntu, Docker CLI, and bundled packages retain their upstream licenses and notices -- Reviewed: 2026-07-23 -- Vulnerability gate: all three releases report 0 HIGH and 0 CRITICAL findings with Trivy 0.70.0 - -This is a privileged release candidate. On isolated hosts, credential delivery, -per-host scheduling, CNI installation, Metadata and DNS access, control-plane -return traffic, NAT reconciliation, restart, and health reporting passed -together with Metadata Healthcheck and IPsec Overlay. Multi-host upgrade, -rollback, and complete infrastructure-stack removal remain required before -production approval. - -The new Network Services `v0.3.2` definition in directory `4` is not yet -published as a deployable release. It selects one host firewall backend and -references published Network Plugin Manager `v0.8.13`; its official manifest -digest, merged source revision, and runtime-image release scan are recorded in -`catalog-images.json`. Metadata -Service and Internal DNS are unchanged from directory `3`. The 2026-07-23 -evidence above applies to the earlier released image and must not be presented -as host lifecycle validation of `v0.8.13`. -An isolated VM using Docker native nftables has since passed backend detection, -both watcher readiness checks, host-NAT egress, DNS, HTTPS, and same-bridge and -cross-bridge host-port checks before and after reboot. This does not replace a -formal two-host control-plane create, upgrade, rollback, and coexistence gate. +- Reviewed: 2026-09-14 +- Vulnerability gate: Network Plugin Manager source, binary, and image report 0 detected vulnerabilities and 0 image/source secrets with Trivy 0.74.0; govulncheck, CodeQL, race tests, reproducible build, SBOM, checksums, and provenance attestation passed + +Directory `9` is the Network Services `v0.3.7` candidate. It follows Docker's +active native nftables, iptables-nft, or iptables-legacy path without switching +the host, loading legacy modules, or writing both backends. Network Plugin +Manager alone owns host NAT, forwarding marks, and host-port `CATTLE_*` chains; +the IPsec, VXLAN, per-host-subnet, and Flat providers retain only their own +data-plane responsibilities. + +On two isolated Ubuntu 26.04 / Docker 29.1.3 hosts, the exact official image +passed bidirectional cross-host workload traffic, published host ports, DNS, +Metadata, platform egress, and component health for all four Linux network +drivers. One host used Docker native nftables; the other passed both +iptables-nft and iptables-legacy with Docker's iptables backend and was restored +to iptables-nft. Docker restart recovery passed. Both hosts were then rebooted +one at a time; after each reboot and after both had rebooted, all four drivers +again passed the complete bidirectional data-path gate. Wrapper content, mode, and +symbolic-link drift were repaired to the selected provider's exact SHA-256 and +regular `0700` file without modifying the link target. + +The manager binds each wrapper to one eligible immutable provider ID, prefers +the highest numeric OCI image version, and prevents a nonnumeric development +label from replacing a numeric release. During the short interval before +Metadata publishes a container IP, host-port recovery accepts exactly one IPv4 +address in that network's managed subnet and revalidates the same Docker PID; +missing, ambiguous, or raced state preserves the previous working rules. +Official Catalog activation, rollback, and complete test-stack removal remain +gates before this candidate is called production-approved. ## PastureStack IPsec Overlay evidence diff --git a/catalog-images.json b/catalog-images.json index f601dbcf0..4270be4eb 100644 --- a/catalog-images.json +++ b/catalog-images.json @@ -417,6 +417,26 @@ "critical": 0 } }, + { + "reference": "ghcr.io/pasturestack/network-plugin-manager:v0.8.21", + "manifestDigest": "sha256:aab4c05b0801feeca40fa9cb82a52fbfbfe506c609d3df2024fbc07ef4b968e9", + "sourceRepository": "https://github.com/PastureStack/network-plugin-manager", + "sourceCommit": "2f2418423022264695f90960f4a80b9d20c5826f", + "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/network-services/9/README.md b/infra-templates/network-services/9/README.md new file mode 100644 index 000000000..8223e4ada --- /dev/null +++ b/infra-templates/network-services/9/README.md @@ -0,0 +1,50 @@ + + +# PastureStack Network Services + +Version 9 uses Network Plugin Manager `v0.8.21`. It retains single-backend selection and unchanged Metadata Service and Internal DNS images. It restores bounded inbound forwarding for fixed shared overlay subnets such as the IPsec and VXLAN `10.42.0.0/16` network. The rule accepts only new or established traffic whose source and destination are both inside that configured subnet and whose output interface is the exact managed bridge. Per-host-subnet networks keep their separate peer-to-local-subnet rules. The manager rejects malformed or conflicting bridge metadata before touching host firewall rules, binds every managed forwarding rule to that exact bridge, and protects bridge traffic from `route_localnet` loopback routing. It records the original per-bridge setting under `/run`, applies the guard before enabling it, and restores the original value when that bridge no longer needs a host port. The image's release provenance and digest are recorded in `catalog-images.json`. + +## Provider and lifecycle convergence + +The manager selects one eligible CNI provider per binary from the infrastructure-service metadata on the local host. The highest numeric OCI image version wins; an unversioned or nonnumeric development label cannot replace a numeric release, and ties use a deterministic immutable container-ID ordering. The generated wrapper stays bound to that exact provider and does not relist containers by service label at invocation time. It executes the provider's private `/opt/cni/bin` copy with a bounded compatibility fallback for older images. Wrapper replacement uses an exclusive temporary inode and atomic rename; content, file type, and mode drift are repaired without following a replacement symlink. + +When platform metadata temporarily reports a host-port container before its primary address, the manager may read the exact running container's network namespace. It accepts only one IPv4 address inside that network's configured managed subnet and revalidates the same Docker container PID after the namespace read. Missing, ambiguous, out-of-subnet, or lifecycle-raced results fail closed and retain the last known-good host-port rules until metadata and CNI converge. + +## 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. + +Shared-subnet ingress is enabled only when CNI metadata explicitly sets +`allowSharedSubnetIngress: true`, or for the legacy fixed-subnet contract that +already declares both `bridgeSubnet` and `hostNat: true`. It is rejected for +host-label-based subnets, where only validated active peer ranges are trusted. + +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/9/README.zh-TW.md b/infra-templates/network-services/9/README.zh-TW.md new file mode 100644 index 000000000..fed48bb61 --- /dev/null +++ b/infra-templates/network-services/9/README.zh-TW.md @@ -0,0 +1,38 @@ + + +# PastureStack 網路服務 + +第 9 版使用網路外掛管理器 `v0.8.21`,保留單一防火牆後端的選擇方式,以及相同的中繼資料服務與內部 DNS 映像;並恢復固定共用 overlay 子網路(例如 IPsec 與 VXLAN 的 `10.42.0.0/16`)有限制的輸入轉送。規則只接受來源與目的都位於該設定子網路、輸出介面為正確受管網橋的新連線或既有連線;每主機子網路仍使用另一套對端至本機子網路規則。管理器會在修改主機防火牆規則前拒絕格式錯誤或互相衝突的網橋中繼資料,並把所有受管轉送規則限制在正確網橋。啟用 `route_localnet` 前會先阻擋來自該網橋、目的為 `127.0.0.0/8` 的流量;原始的每網橋設定會保存於 `/run`,不再需要主機連接埠時則恢復原值。映像發布來源與 digest 記錄於 `catalog-images.json`。 + +## Provider 與生命週期收斂 + +管理器會依本機主機上的基礎架構服務中繼資料,為每個 CNI 執行檔選出唯一合格的 provider。數字型 OCI 映像版本以最高版為準;未標示版本或非數字的開發標籤不得取代正式數字版本,版本相同時再以不可變的容器 ID 做固定排序。產生的 wrapper 只綁定這個精確 provider,呼叫時不會再以服務標籤重新列舉容器。它優先執行 provider 私有的 `/opt/cni/bin` 程式,並只為舊映像保留有限的相容路徑。wrapper 以排他暫存 inode 與原子更名更新;內容、檔案型態或權限漂移時會安全修復,不會沿著遭置換的符號連結寫入。 + +若平台中繼資料暫時先出現主機連接埠容器、尚未填入主要位址,管理器可讀取該精確執行中容器的網路命名空間。只有該網路設定之受管子網路內恰好一個 IPv4 位址可被接受,讀取後還會再次確認同一 Docker 容器 PID。缺少、歧義、超出子網路或生命週期競態都會安全失敗,並保留上一份可用的主機連接埠規則,直到中繼資料與 CNI 完成收斂。 + +## 防火牆後端 + +`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 加密網路版本。 + +只有 CNI 中繼資料明確設定 `allowSharedSubnetIngress: true` 時才啟用共用子網路輸入轉送;為維持既有固定子網路契約相容性,同時具有 `bridgeSubnet` 與 `hostNat: true` 的舊設定也會採用相同行為。使用主機標籤決定子網路時會拒絕此選項,只信任已驗證的現役對端範圍。 + +使用 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/9/docker-compose.yml.tpl b/infra-templates/network-services/9/docker-compose.yml.tpl new file mode 100644 index 000000000..b0a3228bf --- /dev/null +++ b/infra-templates/network-services/9/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.21 + 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/9/rancher-compose.yml b/infra-templates/network-services/9/rancher-compose.yml new file mode 100644 index 000000000..46645ac14 --- /dev/null +++ b/infra-templates/network-services/9/rancher-compose.yml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: MIT +.catalog: + name: PastureStack Network Services + version: v0.3.7 + 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 8f11ad9dc..385117665 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.6 +version: v0.3.7 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 943177803..68c8617d2 100644 --- a/integration/core/test_catalog.py +++ b/integration/core/test_catalog.py @@ -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.6' + 'defaultVersion'] == 'v0.3.7' assert by_folder[('infra', 'network-services')][ 'links']['defaultVersion'].endswith( - ':8') + ':9') assert by_folder[('infra', 'nfs-storage')][ 'name'] == 'NFS Storage' assert by_folder[('infra', 'nfs-storage')][ @@ -718,7 +718,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.20') + 'ghcr.io/pasturestack/network-plugin-manager:v0.8.21') 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 34b140cb0..a3baefe24 100644 --- a/scripts/audit_deployable_images.py +++ b/scripts/audit_deployable_images.py @@ -57,7 +57,7 @@ "layer-2-flat-network": ("2", "3", "4", "5", "6"), "network-diagnostics": ("1", "2"), "network-policy-manager": ("1", "2", "3"), - "network-services": ("1", "2", "3", "4", "5", "6", "7", "8"), + "network-services": ("1", "2", "3", "4", "5", "6", "7", "8", "9"), "nfs-storage": ("1", "2"), "per-host-subnet-network": ("2", "3", "4"), "resource-scheduler": ("1", "2", "3", "4"), diff --git a/scripts/test b/scripts/test index 7d6c0d30e..c4dd32c24 100755 --- a/scripts/test +++ b/scripts/test @@ -125,6 +125,7 @@ for version_id in \ network-services:6 \ network-services:7 \ network-services:8 \ + network-services:9 \ nfs-storage:1 \ nfs-storage:2 \ resource-scheduler:1 \