## 問題 `playbooks/apply/os-patch-sla-apply.yml` 的 play vars 把 `target_group` 寫死成 `sandbox`,所以不管 `patch_stage` 是什麼,這個 play 都只會選 `sandbox` group 的主機。 以下行號以 main `540f736f` 為準: ```yaml # os-patch-sla-apply.yml:36-42 - name: OS patch SLA apply (stage={{ patch_stage }}, target={{ target_group | default(patch_stage) }}) hosts: "{{ target_group | default(patch_stage) }}" ... vars: patch_stage: sandbox target_group: sandbox ``` `hosts:` 的本意是「沒指定 `target_group` 時,用 `patch_stage` 這個 group」。但 `target_group` 在 play vars 裡已經有值,`default(patch_stage)` 永遠不會生效。 `pilot deploy`/`pilot reconcile` 帶 `--stage` 時,只會傳 `stage=` 和 `patch_stage=`(`cmd/pilot/cmd/deploy.go:3231`),不會傳 `target_group`。`site.yml:261` 匯入這支 playbook 時也沒有帶 vars。 ## 重現 ansible-core 2.19.2,假的 inventory,`--list-hosts` 不會連到任何主機: ```yaml # inv.yml all: vars: {ansible_connection: local} children: prod: {hosts: {prod1: {}}} staging: {hosts: {stg1: {}}} sandbox: {hosts: {sbx1: {}}} ``` | 指令 | play 選到的主機 | |---|---| | `-e patch_stage=sandbox` | `sandbox` → sbx1 | | `-e patch_stage=staging` | `sandbox` → sbx1 | | `-e patch_stage=prod` | `sandbox` → sbx1 | | `-e patch_stage=prod -e target_group=prod` | `prod` → prod1 | ## 影響 - **inventory 只有 staging 或 prod 主機時**(例如每個環境一個 workspace):`pilot deploy --stage prod` 的 site.yml 會印出 ``` PLAY [OS patch SLA apply (stage=prod, target=sandbox)] skipping: no hosts matched ``` run 仍然是成功,所以 staging/prod 主機**從來不會套用 patch SLA**,也沒有任何錯誤或警告。這是在一次真實的 site-wide prod preview 裡看到的。 - **inventory 同時有 sandbox 主機時**:`--stage prod` 會選到 sandbox 主機,再被「patch_stage must match this host's inventory environment group」這道 gate(`:85`)擋下,整次 run 失敗。 - `pilot deploy` 單一 playbook 模式在精靈裡填了 target_group 時,會用 `-e target_group=` 覆寫,所以不受影響。 其他 playbook 的 play vars 也有 `target_group`(docker、reverse-proxy、seaweedfs-s3 等),但寫的是它們自己的角色 group,跟 stage 無關,沒有這個問題。 ## 建議 1. 把 play vars 裡的 `target_group: sandbox` 拿掉,讓 `hosts:` 的 `default(patch_stage)` 生效。其他 playbook 也有刻意不在 play vars 宣告覆寫用變數的先例(例如 `prometheus-apply.yml` 的註解)。 2. 加一個 regression test:對 sandbox/staging/prod 各跑一次 `--list-hosts`,確認選到的是 `patch_stage` 對應的 group。也要確認修正前這個測試會失敗。 3. 可以考慮讓 site.yml 在非 sandbox stage 下,遇到「某個 play 一台主機都沒選到」時發出警告。這次 stage 一改,patch SLA 就整段沒套用,卻沒有任何提示。 ## 注意 修好之後,staging/prod 主機會**第一次**跑這支 playbook:安裝並啟用 unattended-upgrades、覆寫 `/etc/apt/apt.conf.d/50unattended-upgrades`。等 #172 也修好之後,就會真的安裝安全性更新。建議跟 #172 的「各 stage 要不要在 apply 時升級」政策一起決定。 相關:#172、#174、#167。
Activity
kjelly commentedon Oct 29, 2026
#174 的修正(spec §1 改成純環境 group)會在
docs/verification/os-patch-sla.md留下一段針對這個 bug 的 workaround 說明,修 #177 時請一起更新:-e target_group=,因為 play vars 的target_group: sandbox讓hosts:的default(patch_stage)永遠不會生效」,並列出 staging/prod 的vm-target test指令(含-e target_group=staging/-e target_group=prod)。拿掉target_group: sandbox之後,這段與指令中的-e target_group=要刪掉或改寫。ansible-playbook指令目前帶-e target_group=staging/-e target_group=prod,同樣要跟著修。playbooks/apply/os-patch-sla-apply.yml檔頭的 Usage 註解:staging/prod 範例目前只有-e patch_stage=…,在今天的 main 上會選到 0 台主機;bug(os-patch-sla): target_group 寫死成 sandbox,staging/prod stage 下 play 選不到主機,patch SLA 從未套用 #177 修好後這些範例就是正確的(不需要另外開 issue)。另外,#177 建議的 regression test 若對 sandbox/staging/prod 各跑一次
--list-hosts,可參考 #174 的實跑:在 vm-target 用--hosts staging/--hosts prod建 VM,帶-e patch_stage=… -e target_group=…時 play 能選到該 VM。Merge pull request #186 from kjelly/issue/177-os-patch-sla-target-group
docs(os-patch-sla): record fresh staging and prod runs of the #177 SO…
Merge pull request #197 from kjelly/docs/os-patch-sla-drop-target-gro…
feat(skills): issue-to-pr disputes Issue claims that do not hold