iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Kubernetes

防範軟體供應鏈攻擊:從零打造具備硬性阻擋能力的雲原生 CI/CD 流水線系列 第 13

Day 13:Workspace 的四層命名——同一顆 PVC,兩個 Pod 看到不一樣的路徑

  • 分享至 

  • xImage
  •  

今日目的

上一篇讓 Pipeline 跨 Namespace 引用了 openshift-pipelines 裡的 git-clone。接下來的問題是:git-clone 把 repo 抓下來之後,下一個 Task 怎麼讀得到。

答案是 workspace。這篇處理的不是「怎麼掛」,而是名字有幾個位置、哪些必須相同、哪些可以自訂,以及固定 PVC 這條路徑實際跑起來的樣子。

先備知識

  • ci namespace 與 pipeline ServiceAccount
  • cluster resolver 跨 namespace 引用 Task
  • PersistentVolumeClaim 與 StorageClass 的基本概念

四層命名

先給結論,其餘是驗證過程。

名稱 約束
PipelineRun spec.workspaces[].name shared-workspace 必須等於下一列
Pipeline 頂層 spec.workspaces[].name shared-workspace 必須等於上一列
git-clone Task 內部 output Task 作者定的,不能改
自訂 Task 內部 repo 自行決定

四個位置、三種字串。只有第 1、2 列必須對死,其餘各自獨立。

這篇的第一版草稿把每一層都取名 source,YAML 看起來整齊,但也讓映射關係看不出來。這一版刻意把三層取成不同的字。

本篇分成兩半。上半是快樂路徑:從建 PVC 到看到證據,一條線走完,過程中的行為不解釋。下半把值得說明的部分抽出來各自處理,上半會用〈A〉〈B〉這樣的標記指過去。最後是資料來源整理。


實測環境

項目
CRC 2.61.0
OpenShift 4.21.14
Kubernetes v1.34.6
OpenShift Pipelines Operator 1.23.1(Pipelines controller v1.12.2)
主機端 Windows + PowerShell 5.1,oc 4.21.14(未安裝 kubectl)

指令一律 & $OC --kubeconfig $kubeconfig ...

三個影響寫法的旗標:

& $OC --kubeconfig $kubeconfig get cm feature-flags -n openshift-pipelines -o jsonpath='{.data.coschedule}'
# workspaces

& $OC --kubeconfig $kubeconfig get cm feature-flags -n openshift-pipelines -o jsonpath='{.data.enable-concise-resolver-syntax}'
# false        → resolver 必須寫完整語法

& $OC --kubeconfig $kubeconfig get cm cluster-resolver-config -n openshift-pipelines -o jsonpath='{.data}'
# {"allowed-namespaces":"","blocked-namespaces":"","default-kind":"task","default-namespace":""}
#                                                                          ↑ 空的,namespace param 不能省

StorageClass:

crc-csi-hostpath-provisioner (default)   kubevirt.io.hostpath-provisioner
Retain   WaitForFirstConsumer   allowVolumeExpansion=false

RetainWaitForFirstConsumer 這兩項後面都會用到。


上半:快樂路徑

一、建立固定 PVC

Tekton 給 workspace 掛 PVC 有兩條路:volumeClaimTemplate(每跑一次自動建、跑完自動刪)與 persistentVolumeClaim(自行建立、自行管理)。上一篇走前者,這篇走後者,取捨見〈F〉。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pipeline-source-pvc
  namespace: ci
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
& $OC --kubeconfig $kubeconfig apply -f 01-pvc.yaml
# persistentvolumeclaim/pipeline-source-pvc created

建立後的狀態:

NAME                  STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS
pipeline-source-pvc   Pending                                      crc-csi-hostpath-provisioner

Pending 而非 Bound。這是這台 StorageClass 的 volumeBindingMode 造成的預期行為,要等 PipelineRun 送出才會 Bound;停多久、以及對 CI 腳本的影響見〈A〉。


二、四層命名的三份 YAML

Pipeline

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: d15-happy-path
  namespace: ci
spec:
  workspaces:
    - name: shared-workspace          # 第 2 層:Pipeline 頂層宣告
  tasks:
    - name: git-clone
      taskRef:
        resolver: cluster             # 簡寫語法已關閉,只能寫完整形式
        params:
          - name: kind
            value: task
          - name: name
            value: git-clone
          - name: namespace
            value: openshift-pipelines
      params:
        - name: URL
          value: http://gitea-http.gitea.svc.cluster.local:3000/gitea_admin/frontend-nx-mono.git
        - name: REVISION
          value: main
      workspaces:
        - name: output                # 第 3 層:git-clone 自己定的
          workspace: shared-workspace #   映射回第 2 層
    - name: workspace-probe
      runAfter:
        - git-clone
      taskRef:
        name: workspace-probe
      workspaces:
        - name: repo                  # 第 4 層:自訂
          workspace: shared-workspace #   一樣映射回第 2 層

workspaces 底下兩個欄位的意義相反:name 是 Task 內部的名字,workspace 是要對回 Pipeline 頂層的名字。這是最常寫反的位置。

自訂 Task

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: workspace-probe
  namespace: ci
spec:
  workspaces:
    - name: repo
  steps:
    - name: probe
      image: registry.redhat.io/openshift-pipelines/pipelines-git-init-rhel9@sha256:d8de2ba8...
      workingDir: $(workspaces.repo.path)
      script: |
        #!/usr/bin/env sh
        set -e
        echo "workspaces.repo.path = $(workspaces.repo.path)"
        pwd
        id
        ls -ld "$(workspaces.repo.path)"
        ls -la
        for f in nx.json package.json; do
          if [ -f "$f" ]; then echo "FOUND: $f"; else echo "MISSING: $f"; fi
        done

image 直接用 git-clone 那顆 digest:節點上已有快取,不必走公網,而且確定有 gitbashubi9/ubi-minimal 沒有 git,配上 set -e 會讓 TaskRun 失敗在與本題無關的地方。

PipelineRun

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: d15-happy-run-
  namespace: ci
spec:
  pipelineRef:
    name: d15-happy-path
  taskRunTemplate:
    serviceAccountName: pipeline
  workspaces:
    - name: shared-workspace          # 第 1 層:必須與 Pipeline 頂層相同
      persistentVolumeClaim:
        claimName: pipeline-source-pvc

三、送出

PVC、Task、Pipeline 都用 oc apply。PipelineRun 帶 generateNameapply 會被擋(含 --dry-run=server),只能用 create——原因見〈B〉。

& $OC --kubeconfig $kubeconfig create -f 04-pipelinerun.yaml -o name
# pipelinerun.tekton.dev/d15-happy-run-hf78d

四、執行過程

oc create 送出後立即返回,PipelineRun 非同步執行,前景輪詢即可。整條 53.6 秒。

送出後 0.325 秒的第一輪:

[17:28:44.511]
  STS : affinity-assistant-5f0843cf5a   0/1   0s
  POD : affinity-assistant-5f0843cf5a-0        Pending
        d15-happy-run-hf78d-git-clone-pod      Pending
  PVC : pipeline-source-pvc   Bound   pvc-d9718706-...   179Gi

三件事同時成立:

  1. 出現一個 affinity-assistant-* 的 StatefulSet
  2. PVC 已 Bound——前兩分鐘還是 Pending
  3. 兩顆 Pod 都還在 Pending

affinity assistant 是什麼、為什麼 PVC 在這一刻才 Bound,見〈D〉。

之後串接執行:

[17:28:51.207]  git-clone  Running
[17:28:55.580]  git-clone  Completed   probe  Init:1/3
[17:28:57.820]  probe      Running
[17:29:37.079]  PipelineRun = True / Succeeded
                STS : (無)

五、核心證據:同一顆 PVC,兩個路徑

probe 的輸出:

workspaces.repo.path = /workspace/repo
--- pwd (workingDir) ---
/workspace/repo
=== IDENTITY ===
uid=65532(nonroot) gid=65532(nonroot) groups=65532(nonroot),1000860000
=== WORKSPACE ROOT ls -ld ===
drwxrwsr-x. 5 root 1000860000 4096 /workspace/repo
=== ROOT LISTING ===
-rw-rw-r--. 1 nonroot 1000860000    1599 nx.json
-rw-rw-r--. 1 nonroot 1000860000    1681 package.json
drwxrwsr-x. 3 nonroot 1000860000      17 apps
drwxrwsr-x. 7 nonroot 1000860000     161 .git
...
FOUND: nx.json
FOUND: package.json

更直接的證據是兩顆 Pod 的 spec:

& $OC --kubeconfig $kubeconfig get pod -n ci -o json | ConvertFrom-Json
d15-happy-run-hf78d-git-clone-pod
  volume 'ws-79a94' -> PVC pipeline-source-pvc
  container step-prepare-and-run : ws-79a94 -> mountPath /workspace/output

d15-happy-run-hf78d-workspace-probe-pod
  volume 'ws-d3b4c' -> PVC pipeline-source-pvc
  container step-probe          : ws-d3b4c -> mountPath /workspace/repo

同一顆 PVC,不同的 volume 名,不同的 mountPath。git-clone 寫入 /workspace/output,probe 從 /workspace/repo 讀取,因為那是同一塊儲存。

路徑的來源:依 Workspaces 文件,未指定 mountPath 時,workspace 會掛在 /workspace/ 加上該 workspace 名稱的位置。查過 git-clone 的四個 workspace,mountPath 全部未設定,因此走預設。而決定路徑的那個名稱是「Task 內部的 workspace 名」,與 PVC 無關,也與 Pipeline 頂層的名稱無關。

這就是四個名字裡只有 PipelineRun ↔ Pipeline 必須對死的原因:那一組是綁定,其餘兩個是映射。

兩個 Task 都以 image 內建的 nonroot 執行,全程沒有權限問題,也沒有調整任何 SCC;目錄權限的細節見〈C〉。


收工前檢查清單

# 1. PipelineRun 成功
& $OC --kubeconfig $kubeconfig get pipelinerun -n ci

# 2. git-clone 抓到的 commit
$tr = (& $OC --kubeconfig $kubeconfig get taskrun <name> -n ci -o json | ConvertFrom-Json)
($tr.status.results | Where-Object { $_.name -eq 'COMMIT' }).value

# 3. PVC 仍為 Bound、未被刪除
& $OC --kubeconfig $kubeconfig get pvc pipeline-source-pvc -n ci

# 4. 沒有新增孤兒 PV
& $OC --kubeconfig $kubeconfig get pv --no-headers | Where-Object { $_ -match 'Released' }

# 5. affinity assistant 已清乾淨
& $OC --kubeconfig $kubeconfig get statefulset -n ci

預期:PipelineRun SucceededCOMMIT 與遠端 HEAD 相同、PVC BoundReleased 數量與執行前相同、ci 沒有殘留的 StatefulSet。


下半:值得說明的技術說明

上半沒有解釋的行為,在這裡各自處理。彼此獨立,可以只挑要看的。

A. PVC 為什麼停在 Pending 兩分鐘

接第一節建立 PVC 之後。oc describe 的 event:

Events:
  Type    Reason                From                         Message
  Normal  WaitForFirstConsumer  persistentvolume-controller  waiting for first consumer to be created before binding

這是 volumeBindingMode: WaitForFirstConsumer 的預期行為。依 Kubernetes Storage Classes 文件,這個模式會把 PV 的綁定與動態配置延後到有 Pod 使用該 PVC 為止;未設定時的預設是 Immediate,PVC 一建立就配置。

這顆 PVC 停在 Pending 2 分 9 秒,直到 PipelineRun 送出。期間 PV 總數未變。

若 CI 腳本裡寫「建完 PVC 就等 Bound,逾時報錯」,在這種 StorageClass 上會永遠逾時。


B. generateName 不能用 apply

PVC、Task、Pipeline 都用 oc apply。PipelineRun 照做會得到:

error: from d15-happy-run-: cannot use generate name with apply

--dry-run=server 同樣被擋。kubectl apply 的文件寫明 The resource name must be specified.——apply 需要靠名字比對既有物件,而 generateName 的名字要到伺服器端建立時才產生。Red Hat 的 KB 也記錄了這個錯誤,並提到 OCP 4.5 與 4.6 的訊息措辭不同。

所以:Task / Pipeline / PVC 用 apply,PipelineRun 用 create


C. workspace 根目錄的權限

workspace 根目錄由 root 所有、帶 setgid、group 1000860000 可寫;兩個 Task 都以 image 內建的 nonroot(65532) 執行,附屬群組包含 1000860000。因此 nonroot 寫得進去、下一顆 Pod 也讀得到。全程沒有權限問題,也沒有調整任何 SCC。


D. affinity assistant

執行期間出現、結束後消失的 affinity-assistant-5f0843cf5a,是 Tekton 用來讓共用同一顆 workspace 的 TaskRun 被排到同一個節點的機制。

它是一顆 pipelines-nop-* image 的 placeholder Pod,包在 StatefulSet 裡。原始實作的 commit 訊息記載了設計:TaskRun 的 Pod 被設上 podAffinity 指向這顆 assistant,assistant 之間彼此 podAntiAffinity(Best Effort),選用 StatefulSet 是為了 singleton 語意。

這裡的因果容易寫反:

RWO 確實只允許單一節點掛載。平行 Task 之所以能共用同一顆 PVC,是因為 affinity assistant 把它們排到同一個節點,不是 RWO 本身寬鬆。

在單節點的 CRC 上這兩種說法看起來相同。換到多節點叢集、或把 coschedule 關掉,寫反的那個會出問題。

跑完後 assistant 自動刪除,這一點 Affinity Assistants 文件有記載,實測時間戳落在同一秒:

18:32:39Z  PipelineRun/d15-happy-run-hf78d      Succeeded
18:32:39Z  Pod/affinity-assistant-5f0843cf5a-0  Killing  Stopping container affinity-assistant

誰是第一個 consumer

WaitForFirstConsumer 要等第一個 consumer。是 affinity assistant 的 Pod,還是 git-clone 的 Pod?

實測的答案是:分不出來,因為兩者在競爭。同一個叢集秒內的事件:

18:31:43Z  TaskRun/…-git-clone   Pending   pod status "PodScheduled":"False"
                                           message: "running PreBind plugin \"VolumeBinding\"…
18:31:43Z  PVC   ExternalProvisioning → Provisioning → ProvisioningSucceeded
18:31:43Z  Pod/…-git-clone-pod   FailedScheduling
                                 running PreBind plugin "VolumeBinding":
                                 Operation cannot be fulfilled on persistentvolumeclaims…
18:31:43Z  StatefulSet/affinity-assistant-5f0843cf5a   SuccessfulCreate
18:31:44Z  Pod/affinity-assistant-5f0843cf5a-0  Scheduled
18:31:45Z  Pod/…-git-clone-pod                  Scheduled

能確定的有三點:

  1. PVC 在兩顆 Pod 中任何一顆被 Scheduled 之前就配好並綁定
  2. 唯一出現在 VolumeBinding PreBind 的是 git-clone 的 Pod,而且撞上 Operation cannot be fulfilled——PVC 的樂觀鎖衝突,代表同一刻有另一個寫入者
  3. 1 秒的時間戳粒度分不出誰先

所以準確的說法是:WaitForFirstConsumer 的觸發者是這兩顆 Pod 的排程競爭。第 1 點與 WaitForFirstConsumer 的定義並不衝突——排程器的 PreBind 階段早於 Pod 被標記 Scheduled,綁定就是在那一步完成的。


E. 不需要 git 憑證

整條 pipeline 沒有綁任何 git 憑證。git-clone 有三個 optional workspace(ssh-directory / basic-auth / ssl-ca-directory),一個都沒綁。

原因有兩層。

前提:repo 是 public,走的是叢集內的純 http Service DNS(gitea-http.gitea.svc.cluster.local:3000)。沒有 TLS 就不需要 CA,沒有權限控管就不需要帳密。

Task 本身處理過:git-clone 的 stepTemplate 帶著三個變數:

WORKSPACES_SSH_DIRECTORY_BOUND    = $(workspaces.ssh-directory.bound)
WORKSPACES_BASIC_AUTH_BOUND       = $(workspaces.basic-auth.bound)
WORKSPACES_SSL_CA_DIRECTORY_BOUND = $(workspaces.ssl-ca-directory.bound)

script 裡三處都是 if [[ "${..._BOUND}" == "true" ]] 的顯式分支。執行時的 log 印出走過的 phase,那三個都沒出現:

---> Phase: Preparing the filesystem before cloning the repository...
---> Phase: Deleting all contents of checkout-dir '/workspace/output/'...
---> Phase: Setting output workspace as safe directory ('/workspace/output')...
---> Phase: Cloning 'http://gitea-http.gitea.svc.cluster.local:3000/...' into '/workspace/output/'...

沒有 Configuring Git authentication with 'basic-auth' Workspace files,也沒有 Copying '.ssh' from ssh-directory workspace

Tekton 的憑證機制是 annotation 驅動的。依 Authentication at Run Time,憑證用的 annotation key 必須以 tekton.dev/git-tekton.dev/docker- 開頭,未正確標註的 Secret 不會被採用。這個 namespace 裡沒有任何帶 tekton.dev/git-* annotation 的 secret,因此不會產生 git 憑證檔。

Pod 上仍然掛著一個 Secret:pipeline-dockercfg-*,型別 kubernetes.io/dockercfg,是 ServiceAccount 的 image pull secret,由 Tekton 自動注入。所以準確的敘述是「不需要 git 憑證」,而不是「不需要任何憑證」。


F. 固定 PVC 的取捨

不會每跑一次多一顆孤兒 PV

這台的 StorageClass 是 reclaimPolicy: Retain。依 Persistent Volumes 文件,這個回收策略在 PVC 被刪除後不會回收 PV,PV 會停在 Released,底層資料保留。

volumeClaimTemplate 時 PVC 由 Tekton 建立、跑完即刪,於是每跑一次就留下一顆 Released 的孤兒 PV。而 oc get pvc -n ci 看不到——PV 是叢集層級物件,要改看:

& $OC --kubeconfig $kubeconfig get pv --no-headers | Where-Object { $_ -match 'Released' }

用固定 PVC 跑了兩次,收工時:

PV 總數 = 10   Released = 3   Bound = 7

那 3 顆 Released 是先前留下的,這次沒有新增。新增的是一顆 Bound

pvc-d9718706-6f1c-4fa8-aef9-92390c363137   179Gi   Retain   Bound   ci/pipeline-source-pvc

沒有產生孤兒 PV 的原因是 PVC 沒被刪。刪掉 pipeline-source-pvc 之後,Retain 一樣會留下一顆 Released。差別在於「每跑一次一顆」變成「整條路線一顆」。

不會保留狀態

同一條 PipelineRun 跑第二次時,git-clone 的 DELETE_EXISTING 預設是 true,內部用 rm -rfv,所以把刪掉的檔案逐行印出:

---> Phase: Deleting all contents of checkout-dir '/workspace/output/'...
removed '/workspace/output//Dockerfile'
removed '/workspace/output//README.md'
removed '/workspace/output//apps/web/src/app/app.ts'
removed directory '/workspace/output//apps/web/src/app'
...
removed '/workspace/output//.editorconfig'
removed '/workspace/output//.git/description'
...

三點:

  1. 隱藏檔也在內——.editorconfig、整個 .git.git/ 底下就 120 行)
  2. 目錄本身保留——刪的是 /workspace/output//*。原始碼註解說明了理由:不能直接刪目錄,因為那可能是 / 或掛載點的根
  3. 雙斜線來自 checkout_dir="${WORKSPACES_ROOT_PATH}/${PARAMS_SUBDIRECTORY}"SUBDIRECTORY 為空,無影響

所以固定 PVC 提供的是 PV 層面的穩定,不是內容的延續。要做快取得自行指定 SUBDIRECTORY,或把 DELETE_EXISTING 設成 false 再自己處理衝突。


G. 一個 TaskRun 只能綁一顆 PVC-backed workspace

設計平行掃描 Task 時會撞到這條規則。Workspaces 文件說明,在 coscheduleworkspacesdisabled 時,不允許把多顆 PVC-backed workspace 綁到同一個 TaskRun,理由是可能的 Availability Zone 衝突。這兩個正好是兩個 stable 模式,另外兩個模式(pipelinerunsisolate-pipelinerun)是 alpha。

實測方式是把兩個 claimName 都填成不存在的 PVC。Tekton 只讀 WorkspaceBinding 裡的名稱、不檢查存在性,驗證會在任何東西被配置之前觸發,因此不會產生 PV。

webhook 不擋(--dry-run=server 會過),要實跑才看得到:

PipelineRun  Failed
             Tasks Completed: 1 (Failed: 1, Cancelled 0), Skipped: 0

子 TaskRun   TaskRunValidationFailed
             [User error] more than one PersistentVolumeClaim is bound

失敗形狀分兩層:PipelineRun 只給 Failed 加一句 Tasks Completed: 1 (Failed: 1…),真正的原因要往子 TaskRun 看。這在 Tekton 是通例。

這個錯誤字串與 tektoncd/pipeline#3480 裡使用者回報的一致,該 issue 也記載了同樣的不對稱:單獨跑 TaskRun 沒事,走 PipelineRun 就失敗。


H. 工具行為

與 Tekton 無關,但這次都實際踩到。

PowerShell 5.1 的 jsonpath 引號

-o jsonpath='{...}' 用單引號直傳,只在沒有內層雙引號時成立。一旦用到分隔符或 filter,PowerShell 會吃掉引號,而三種情境的錯誤訊息不同:

寫法 錯誤訊息
'{.a}{"|"}{.b}' unrecognized character in action: U+007C '|'
'{.status.conditions[?(@.type=="Ready")].status}' unrecognized identifier Ready
'{.a}{" x="}{.b}' unterminated quoted string

第二種最容易誤判——訊息看起來像 jsonpath 語意寫錯,而不是引號被吃掉。

解法:內層雙引號寫成 \";或任何多欄位、帶 filter 的查詢一律走 -o json | ConvertFrom-JsonWhere-Object

oc auth can-i use scc/... 要帶 -n

& $OC ... auth can-i use scc/pipelines-scc --as=system:serviceaccount:ci:pipeline
# Warning: resource 'securitycontextconstraints' is not namespace scoped
# no

& $OC ... auth can-i use scc/pipelines-scc --as=system:serviceaccount:ci:pipeline -n ci
# yes

SCC 物件是叢集層級的,但「能不能用」的授權來自 namespace 裡的 RoleBinding。那句 Warning 容易讀成「不用加 namespace」。

PVC 的 CAPACITY 與 request 無關

NAME                  STATUS   CAPACITY   ...
pipeline-source-pvc   Bound    179Gi      ← request 是 2Gi

kubevirt.io.hostpath-provisioner 回報的是配置當下節點檔案系統的容量。這是這個 provisioner 的實作行為,不是 CSI 通則;上游有對應的 issue(kubevirt/hostpath-provisioner#33,回報 request 4Gi、capacity 39Gi)。

在這種 provisioner 上,oc get pvc 的 CAPACITY 欄不能拿來做容量監控。


已知未測

  • affinity assistant 的節點親和作用:單節點 CRC 沒有第二個節點,結構上驗不了。〈D〉相關敘述來自上游設計文件。
  • coschedule=disabled 下的多 PVC 限制:文件說同樣不允許,這次只實測了 workspaces 那一半。要驗得改全叢集的 feature-flags
  • 併發兩條 PipelineRun:這次跑的兩條是串行,第一條結束才送第二條。
  • 刪掉 pipeline-source-pvc 是否留下 Released PVRetain 是 StorageClass 層的設定,理論上必然,但沒有為此製造第 4 顆孤兒 PV。

收尾

workspace 有四個名字的位置,只有 PipelineRun ↔ Pipeline 那一組必須對死,另外兩個各自獨立。驗證方式是把三層取成不同的字,再去看兩顆 Pod 的 volumeMounts——/workspace/output/workspace/repo 指向同一顆 PVC。

其餘是過程中確認的行為:WaitForFirstConsumer 讓 PVC 停在 Pending 是預期的、Retain 讓孤兒 PV 從「每跑一次一顆」變成「總共一顆」、固定 PVC 不等於保留狀態、generateName 不能 apply

明天處理下一段:把抓下來的 repo 真的建起來。


資料來源整理

每條標註本文用到它的位置。

Tekton

來源 用在 取用的內容
Using Workspaces in Pipelines 五、〈G〉 未指定 mountPath 時的預設掛載路徑;多 PVC 限制與 AZ 理由
Affinity Assistants 〈D〉 四種 coschedule 模式、完成即刪除
Authentication at Run Time 〈E〉 tekton.dev/git-* annotation 規則
affinity assistant 原始實作 commit 〈D〉 placeholder pod、podAffinity、singleton 的設計意圖
tektoncd/pipeline#3480 〈G〉 more than one PersistentVolumeClaim is bound 的使用者回報

Kubernetes 儲存

來源 用在 取用的內容
Storage Classes 〈A〉 volumeBindingModeWaitForFirstConsumer 的語意
Persistent Volumes 〈F〉 reclaimPolicy: Retain 的回收語意
kubevirt/hostpath-provisioner#33 〈H〉 PV capacity 大於 PVC request 的回報

工具

來源 用在 取用的內容
kubectl apply 參考 〈B〉 The resource name must be specified.
Red Hat KB 5969351 〈B〉 cannot use generate name with apply

上述 tekton.dev 連結描述的是上游現況,本文環境是 Red Hat 打包的 v1.12.2。文中所有非引用的數字與輸出,都來自「實測環境」那張表的版本組合,換版本請重驗。


上一篇
Day 12:跨 Namespace 引用 Task(Cluster Resolver)
下一篇
Day 14:自動觸發機制 —— Tekton Triggers 的授權規範與 CEL 的邊界
系列文
防範軟體供應鏈攻擊:從零打造具備硬性阻擋能力的雲原生 CI/CD 流水線14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言