Tekton on a Homelab: What GitHub Actions Won't Tell You
1. Why Homelab CI ≠ Cloud CI
The allure of CI/CD is universal, but the journey from cloud to homelab can be fraught with challenges. For those running Kubernetes in a personal or small-scale environment, the traditional cloud-based CI solutions like GitHub Actions can seem like a distant dream. The primary reasons for this are the cost of cloud runners, the complexity of hairpin NAT, the need for internal registry DNS, and the operational burden on a single administrator.
Cost of Cloud Runners
Cloud runners, while convenient, come at a cost. For small projects, the recurring charges can add up quickly. In a homelab setting, where resources are limited and budget is often non-existent, cloud runners are often out of the question. Moreover, the cost of cloud runners can vary significantly depending on the provider and the region, making it difficult to predict or budget for.
Hairpin NAT and Internal Registry DNS
Hairpin NAT is a common issue in homelab environments. When a pod needs to access an internal registry, it often requires a workaround due to the way Kubernetes handles network traffic. This can be particularly challenging when trying to set up a webhook to push images to an internal registry. The lack of a proper DNS resolution for internal services can lead to connectivity issues, making it difficult to establish reliable CI pipelines.
Single-Admin Ops Burden
In a homelab, the burden of managing CI/CD pipelines falls on a single administrator. This means that the solution needs to be robust, yet straightforward enough to manage without the need for extensive technical expertise. The complexity of setting up and maintaining CI/CD pipelines in a cloud environment can be overwhelming, and the need for a single point of contact can make troubleshooting and maintenance a significant challenge.
Example Scenario
Consider a scenario where you have a small Kubernetes cluster running in your home lab. You want to set up a CI pipeline for a series of applications, but you don't want to spend money on cloud runners. You also need to ensure that your internal registry is accessible from the CI pipeline. The lack of proper DNS resolution and the complexity of hairpin NAT can make this a daunting task.
# Example of a problematic setup
kubectl apply -f https://example.com/tekton-crd.yaml
kubectl apply -f https://example.com/tekton-pipelines.yaml
2. Tekton vs ARC: When Actions Runner Controller is Enough vs When Tekton Pipelines + Triggers Fit a Multi-Repo Homelab
GitHub Actions Runner Controller (ARC) is a popular choice for CI in homelab environments because it is simple to set up and manage. However, for more complex scenarios, such as multi-repo environments, Tekton pipelines with Triggers can provide a more robust solution. Let's explore the differences between these two approaches.
GitHub Actions Runner Controller (ARC)
ARC is a lightweight solution that allows you to run GitHub Actions on your Kubernetes cluster. It is easy to set up and manage, making it a popular choice for small-scale projects. However, it has limitations when it comes to more complex CI/CD workflows.
# Example of ARC setup
kubectl apply -f https://github.com/actions/runner-controller/releases/download/v1.0.12/runner-controller.yaml
Tekton Pipelines + Triggers
Tekton pipelines offer more flexibility and power for complex CI/CD workflows. They allow you to define custom pipelines and triggers, making it easier to manage multi-repo environments. However, setting up Tekton can be more complex and requires a deeper understanding of Kubernetes and CI/CD concepts.
# Example of Tekton setup
kubectl apply -f https://github.com/tektoncd/pipeline/releases/download/v0.27.0/tekton-pipelines.yaml
When to Use ARC
ARC is a good choice when you have a simple CI/CD workflow and don't need the advanced features of Tekton. It is easy to set up and manage, making it a good fit for small-scale projects.
When to Use Tekton
Tekton is a better choice when you have a multi-repo environment and need more advanced CI/CD workflows. It allows you to define custom pipelines and triggers, making it easier to manage complex workflows.
Example Scenario
Consider a scenario where you have a multi-repo environment with multiple developers contributing to different projects. You want to set up a CI pipeline that triggers builds and tests for each repository. In this case, Tekton pipelines with Triggers would be a better choice than ARC.
# Example Tekton pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: multi-repo-ci
spec:
workspaces:
- name: source
tasks:
- name: build-and-test
taskRef:
name: build-and-test-task
workspaces:
- name: source
workspace: source
3. Layout: Namespaces (ci-triggers, ci-tenant-*), EventListener, GPU Node Avoidance for CI Pods
To set up a reliable CI pipeline in a homelab environment, it is essential to organize your resources and avoid common pitfalls. This section will cover the layout of your Kubernetes cluster, including namespaces, EventListener, and GPU node avoidance.
Namespaces
Namespaces are a powerful feature in Kubernetes that allow you to organize your resources. In a CI/CD environment, it is a good practice to use separate namespaces for different components. This makes it easier to manage and troubleshoot your pipelines.
# Create namespaces
kubectl create namespace ci-triggers
kubectl create namespace ci-tenant-infra-bootstrap
EventListener
EventListener is a Kubernetes resource that watches for events and triggers actions based on those events. In a CI/CD environment, you can use EventListener to trigger builds and tests when changes are pushed to your repositories.
# Example EventListener
apiVersion: eventing.knative.dev/v1
kind: EventListener
metadata:
name: ci-trigger
namespace: ci-triggers
spec:
subscriber:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: ci-trigger-subscriber
GPU Node Avoidance
In a homelab environment, it is common to have a mix of CPU and GPU nodes. However, CI/CD pods should be run on CPU nodes to avoid any potential issues with GPU drivers or conflicts. To avoid running CI/CD pods on GPU nodes, you can use node selectors or affinity rules.
# Example node selector
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: NotIn
values:
- nvidia
containers:
- name: ci-pod
image: <image:tag>
Example Scenario
Consider a scenario where you have a mix of CPU and GPU nodes in your Kubernetes cluster. You want to ensure that your CI/CD pods are run on CPU nodes to avoid any potential issues. In this case, you can use node selectors or affinity rules to avoid running CI/CD pods on GPU nodes.
# Example node selector
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: NotIn
values:
- nvidia
containers:
- name: ci-pod
image: <image:tag>
4. Kaniko / Build → registry-internal.*: Push Pattern, Tag Discipline, Tie-In to ImagePullBackOff Prevention
Kaniko is a powerful tool for building container images directly on your Kubernetes cluster. In a homelab environment, it is essential to use Kaniko to build images and push them to an internal registry. This section will cover the push pattern, tag discipline, and how to tie it in with ImagePullBackOff prevention.
Push Pattern
The push pattern involves building images using Kaniko and pushing them to an internal registry. This pattern is essential in a homelab environment because it allows you to avoid the overhead of cloud runners and ensures that your images are stored locally.
# Example Kaniko build
kubectl run -it --rm --image=gcr.io/kaniko-project/executor:latest --restart=Never \
--env=REGISTRY=<registry-host> \
--env=IMAGE=<image:tag> \
-- /bin/sh -c "export REGISTRY_PASSWORD=$(kubectl get secret -n ci-tenant-infra-bootstrap registry-credentials -o jsonpath='{.data.password}' | base64 --decode); \
export REGISTRY_USERNAME=$(kubectl get secret -n ci-tenant-infra-bootstrap registry-credentials -o jsonpath='{.data.username}' | base64 --decode); \
/kaniko/executor --dockerfile=Dockerfile --destination=<registry-host>/<image:tag>"
Tag Discipline
Tag discipline is essential in a CI/CD environment because it ensures that your images are always up-to-date and can be easily rolled back. In a homelab environment, it is a good practice to use semantic versioning for your tags.
# Example tag discipline
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
containers:
- name: ci-pod
image: <registry-host>/<image:tag>:<version>
Tie-In to ImagePullBackOff Prevention
ImagePullBackOff is a common issue in Kubernetes when a pod cannot pull an image from a registry. To prevent this issue, you can use a combination of tag discipline and a custom webhook to ensure that the correct image is always available.
# Example webhook
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
Example Scenario
Consider a scenario where you have a CI/CD pipeline that builds and pushes images to an internal registry. You want to ensure that the correct image is always available and prevent ImagePullBackOff issues. In this case, you can use a combination of tag discipline and a custom webhook to ensure that the correct image is always available.
# Example webhook
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
5. L0 Before Webhooks: run-pilot-l0.sh Smoke on Current HEAD — Why Manual PipelineRun Beats Debugging GitHub Delivery First
Before setting up webhooks, it is essential to perform a manual smoke test to ensure that your CI/CD pipeline is working correctly. This section will cover the run-pilot-l0.sh script and why a manual PipelineRun beats debugging GitHub delivery first.
run-pilot-l0.sh Script
The run-pilot-l0.sh script is a simple script that runs a manual PipelineRun to ensure that your CI/CD pipeline is working correctly. This script is particularly useful in a homelab environment because it allows you to test your pipeline without relying on external triggers.
# Example run-pilot-l0.sh
#!/bin/bash
# Set environment variables
export REGISTRY=<registry-host>
export IMAGE=<image:tag>
# Run PipelineRun
kubectl apply -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pilot-l0
spec:
pipelineRef:
name: ci-pipeline
workspaces:
- name: source
workspace: source
params:
- name: registry
value: $REGISTRY
- name: image
value: $IMAGE
EOF
Why Manual PipelineRun Beats Debugging GitHub Delivery First
Debugging GitHub delivery can be a complex and time-consuming process. In a homelab environment, it is often easier to perform a manual PipelineRun to ensure that your pipeline is working correctly. This approach allows you to test your pipeline without relying on external triggers, making it easier to identify and fix any issues.
Example Scenario
Consider a scenario where you have a CI/CD pipeline that builds and pushes images to an internal registry. You want to ensure that the pipeline is working correctly before setting up webhooks. In this case, you can use the run-pilot-l0.sh script to perform a manual PipelineRun and ensure that the pipeline is working correctly.
# Example run-pilot-l0.sh
#!/bin/bash
# Set environment variables
export REGISTRY=<registry-host>
export IMAGE=<image:tag>
# Run PipelineRun
kubectl apply -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pilot-l0
spec:
pipelineRef:
name: ci-pipeline
workspaces:
- name: source
workspace: source
params:
- name: registry
value: $REGISTRY
- name: image
value: $IMAGE
EOF
6. Failure Modes: Webhook Signature, Ingress Port 8080 Mismatch, Task Pod Stuck Init on Bad runc Nodes, Status Token RBAC
In a CI/CD environment, failure modes can arise from various sources. This section will cover common failure modes such as webhook signature issues, ingress port mismatches, task pod stuck in Init state, and RBAC issues.
Webhook Signature
Webhook signatures are used to ensure that webhooks are coming from a trusted source. In a homelab environment, it is essential to ensure that webhook signatures are correctly configured to prevent unauthorized access.
# Example webhook signature
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
webhookClientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
Ingress Port 8080 Mismatch
Ingress port mismatches can cause issues with webhooks. In a homelab environment, it is essential to ensure that the ingress port is correctly configured to prevent any issues with webhooks.
# Example ingress port mismatch
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ci-ingress
spec:
rules:
- host: <hostname>
http:
paths:
- path: /webhook
pathType: Prefix
backend:
service:
name: ci-webhook
port:
number: 8080
Task Pod Stuck Init on Bad runc Nodes
Task pods can get stuck in the Init state on bad runc nodes. In a homelab environment, it is essential to ensure that your runc nodes are healthy and up-to-date to prevent any issues with task pods.
# Example runc node health
apiVersion: node.k8s.io/v1
kind: Node
metadata:
name: <node-name>
spec:
taints:
- key: "runc-node"
effect: "NoSchedule"
value: "true"
Status Token RBAC
RBAC (Role-Based Access Control) is essential in a CI/CD environment to ensure that only authorized users can access resources. In a homelab environment, it is essential to ensure that RBAC is correctly configured to prevent any unauthorized access.
# Example RBAC
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ci-webhook
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "update"]
Example Scenario
Consider a scenario where you have a CI/CD pipeline that uses webhooks to trigger builds and tests. You want to ensure that the pipeline is working correctly and prevent any issues with webhook signatures, ingress port mismatches, task pod stuck in Init state, and RBAC issues. In this case, you can use the above examples to configure your webhook, ingress, runc nodes, and RBAC to prevent any issues.
# Example webhook signature
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
webhookClientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
7. Runbook Pointer
If you encounter any issues with your CI/CD pipeline, you can refer to the runbook for detailed instructions on how to troubleshoot and resolve common issues. The runbook is available at the following URL:
Runbook URL: https://example.com/runbook/tekton-homelab-ci
By following the runbook, you can ensure that your CI/CD pipeline is working correctly and prevent any issues from arising.
Example Runbook
# Runbook: Tekton on a Homelab
## Troubleshooting
- **Webhook Signature Issues:** Ensure that webhook signatures are correctly configured.
- **Ingress Port Mismatch:** Check the ingress port configuration.
- **Task Pod Stuck Init:** Ensure that runc nodes are healthy and up-to-date.
- **RBAC Issues:** Ensure that RBAC is correctly configured.
## Next Steps
- Perform a manual PipelineRun using `run-pilot-l0.sh` to ensure that your pipeline is working correctly.
- Set up webhooks to trigger builds and tests.
- Monitor your pipeline for any issues and refer to the runbook for troubleshooting.
By following the above steps and referring to the runbook, you can ensure that your CI/CD pipeline is working correctly and prevent any issues from arising.
Tekton在家庭實驗室中:GitHub Actions沒有告訴你的事情
1. 何謂家庭實驗室 CI ≠ 云端 CI
CI/CD 的魅力無處不在,但從雲端轉移到家庭實驗室可能會充滿挑戰。對於在個人或小型環境中運行 Kubernetes 的人士來說,傳統的雲端基於 CI 的解決方案如 GitHub Actions 往往像遙不可及的夢想。主要原因包括雲端執行器的成本、回頭 NAT 的複雜性、需要內部註冊表的 DNS 設置,以及單一管理員的運維負擔。
雲端執行器的成本
雲端執行器雖然方便,但成本也不低。對於小項目來說,反覆的費用很快會累積。在家庭實驗室環境中,資源有限,預算往往不存在,因此雲端執行器往往是不可行的。此外,雲端執行器的成本會因提供者和地區而異,這使得預測或預算變得困難。
回頭 NAT 和內部註冊表 DNS
回頭 NAT 是家庭實驗室環境中常見的問題。當一個 pod 需要訪問內部註冊表時,由於 Kubernetes 處理網絡流量的方式,往往需要工作-around。當嘗試設置推送圖像到內部註冊表的 webhook 時,這可能會特別具有挑戰性。內部服務缺乏適當的 DNS 解決方案可能會導致連接問題,使建立可靠的 CI 管道變得困難。
単一管理員的運維負擔
在家庭實驗室中,管理 CI/CD 管道的負擔落在單一管理員身上。這意味著解決方案需要強大,但又簡潔易於管理,不需要大量的技術專業知識。在雲端環境中設置和維護 CI/CD 管道的複雜性可能會令人生畏,而單一聯繫點的需求會使故障排除和維護成為一個重大挑戰。
示例場景
考慮這樣一個場景:您在家中實驗室運行一個小型的 Kubernetes 集群。您希望為一系列應用程式設置 CI 管道,但又不想花錢在雲端執行器上。您還需要確保內部註冊表可以從 CI 管道訪問。缺乏適當的 DNS 解決方案和回頭 NAT 的複雜性可能會使這個任務變得困難。
# 無效的設定示例
kubectl apply -f https://example.com/tekton-crd.yaml
kubectl apply -f https://example.com/tekton-pipelines.yaml
2. Tekton vs ARC:當 Actions Runner Controller 足夠時 vs 需要 Tekton Pipelines + Triggers 的多 Repository 家用 Lab
GitHub Actions Runner Controller (ARC) 是在家用 Lab 環境中進行 CI 的流行選擇,因為它設定和管理起來非常簡單。然而,在更複雜的場景,例如多 Repository 環境中,Tekton Pipelines 與 Triggers 可以提供更為穩固的解決方案。讓我們來探討這兩種方法之間的差異。
GitHub Actions Runner Controller (ARC)
ARC 是一個輕量級的解決方案,允許你在 Kubernetes 集群上執行 GitHub Actions。它設定和管理起來非常簡單,因此成為小型專案的流行選擇。然而,當涉及到更複雜的 CI/CD 工作流時,ARC 有其限制。
# ARC 設置範例
kubectl apply -f https://github.com/actions/runner-controller/releases/download/v1.0.12/runner-controller.yaml
Tekton Pipelines + Triggers
Tekton Pipelines 提供更多靈活性和力量,適用於複雜的 CI/CD 工作流。它允許您定義自訂的 Pipelines 和 Triggers,讓您更容易管理多 Repository 環境。然而,設定 Tekton 可能會更複雜,需要對 Kubernetes 和 CI/CD 概念有更深的理解。
# Tekton 設置範例
kubectl apply -f https://github.com/tektoncd/pipeline/releases/download/v0.27.0/tekton-pipelines.yaml
當使用 ARC 時
ARC 是一個適合簡單 CI/CD 工作流且不需要 Tekton 的進階功能的選擇。它設定和管理起來非常簡單,因此適合小型專案。
當使用 Tekton 時
Tekton 是一個適合多 Repository 環境且需要更進階的 CI/CD 工作流的選擇。它允許您定義自訂的 Pipelines 和 Triggers,讓您更容易管理複雜的工作流。
範例場景
考慮一個場景,您有一個多 Repository 環境,有多位開發者為不同的專案貢獻。您想要設置一個 CI 管道,當每個 Repository 都觸發建立和測試。在這種情況下,Tekton Pipelines 與 Triggers 是比 ARC 更好的選擇。
# Tekton 管道範例
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: multi-repo-ci
spec:
workspaces:
- name: source
tasks:
- name: build-and-test
taskRef:
name: build-and-test-task
workspaces:
- name: source
workspace: source
3. 布局: 命名空間(ci-triggers,ci-tenant-*),事件監聽器,CI 基礦節點避免使用GPU
在家庭實驗室環境中建立可靠的CI流水線,組織資源和避免常見的問題是至關重要的。本節將覆蓋Kubernetes集群的佈局,包括命名空間、事件監聽器和CI基礦節點避免使用GPU。
命名空間
命名空間是Kubernetes中一個強大的功能,允許您組織資源。在CI/CD環境中,為不同的組件使用不同的命名空間是一個良好的實踐,這樣可以更容易地管理和排除問題。
# 創建命名空間
kubectl create namespace ci-triggers
kubectl create namespace ci-tenant-infra-bootstrap
事件監聽器
事件監聽器是Kubernetes的一種資源,它會監控事件並根據這些事件觸發操作。在CI/CD環境中,您可以使用事件監聽器在推送代碼庫更改時觸發構建和測試。
# 事件監聽器範例
apiVersion: eventing.knative.dev/v1
kind: EventListener
metadata:
name: ci-trigger
namespace: ci-triggers
spec:
subscriber:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: ci-trigger-subscriber
避免使用GPU節點
在家庭實驗室環境中,通常會有CPU和GPU節點的混搭。然而,CI/CD Pod應在CPU節點上運行,以避免任何潛在的GPU驅動程序問題或衝突。要避免在GPU節點上運行CI/CD Pod,可以使用節點選擇器或親和性規則。
# 节點選擇器範例
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: NotIn
values:
- nvidia
containers:
- name: ci-pod
image: <image:tag>
範例場景
考慮一個場景,您的Kubernetes集群中混有CPU和GPU節點。您希望確保CI/CD Pod在CPU節點上運行,以避免任何潛在的問題。在這種情況下,您可以使用節點選擇器或親和性規則來避免在GPU節點上運行CI/CD Pod。
# 节點選擇器範例
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: NotIn
values:
- nvidia
containers:
- name: ci-pod
image: <image:tag>
4. Kaniko / 建構 → registry-internal.*: 推送模式、標記紀律、與 ImagePullBackOff 防範的連接
Kaniko 是一個強大的工具,可以直接在您的 Kubernetes 集群上建立容器影像。在家庭實驗室環境中,使用 Kaniko 建構影像並推送至內部註冊表是必要的。本節將介紹推送模式、標記紀律,以及如何與 ImagePullBackOff 防範連接。
推送模式
推送模式涉及使用 Kaniko 建構影像並將其推送至內部註冊表。在家庭實驗室環境中,這種模式是必要的,因為它允許您避免雲端執行器的開銷,並確保您的影像存儲在本地端。
# Kaniko 建構範例
kubectl run -it --rm --image=gcr.io/kaniko-project/executor:latest --restart=Never \
--env=REGISTRY=<registry-host> \
--env=IMAGE=<image:tag> \
-- /bin/sh -c "export REGISTRY_PASSWORD=$(kubectl get secret -n ci-tenant-infra-bootstrap registry-credentials -o jsonpath='{.data.password}' | base64 --decode); \
export REGISTRY_USERNAME=$(kubectl get secret -n ci-tenant-infra-bootstrap registry-credentials -o jsonpath='{.data.username}' | base64 --decode); \
/kaniko/executor --dockerfile=Dockerfile --destination=<registry-host>/<image:tag>"
標記紀律
在 CI/CD 環境中,標記紀律是必要的,因為它確保您的影像始終是最新的,並且可以輕鬆地回滾。在家庭實驗室環境中,使用語義版本控制來標記您的影像是一個好習慣。
# 標記紀律範例
apiVersion: batch/v1
kind: Job
metadata:
name: ci-pod
spec:
template:
spec:
containers:
- name: ci-pod
image: <registry-host>/<image:tag>:<version>
與 ImagePullBackOff 防範的連接
ImagePullBackOff 是 Kubernetes 中一個常見的問題,當一個 pod 不能從註冊表拉取影像時會發生。要防止這個問題,您可以使用標記紀律和自訂 webhook 的組合,確保始終可用正確的影像。
# 自訂 webhook 範例
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
範例場景
考慮一個情況,您有一個 CI/CD 管道會建構並推送影像至內部註冊表。您希望確保始終可用正確的影像,並防止 ImagePullBackOff 問題。在這種情況下,您可以使用標記紀律和自訂 webhook 的組合來確保始終可用正確的影像。
# 自訂 webhook 範例
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-encoded-certificate>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
5. L0 未設置 webhook 前:run-pilot-l0.sh 簡易測試 — 何以手動 PipelineRun 比先行Debug GitHub 交付更優
在設置 webhook 之前,進行手動簡易測試以確保 CI/CD 管道正常運行是至關重要的。本節將介紹 run-pilot-l0.sh 腳本,並解釋為何手動 PipelineRun 比先行Debug GitHub 交付更優。
run-pilot-l0.sh 腳本
run-pilot-l0.sh 腳本是一個簡單的腳本,用於手動執行 PipelineRun,以確保 CI/CD 管道正常運行。在家庭實驗室環境中,該腳本特別有用,因為它允許你測試管道而不依賴外部觸發器。
# 例:run-pilot-l0.sh
#!/bin/bash
# 設置環境變數
export REGISTRY=<registry-host>
export IMAGE=<image:tag>
# 執行 PipelineRun
kubectl apply -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pilot-l0
spec:
pipelineRef:
name: ci-pipeline
workspaces:
- name: source
workspace: source
params:
- name: registry
value: $REGISTRY
- name: image
value: $IMAGE
EOF
何以手動 PipelineRun 比先行Debug GitHub 交付更優
Debug GitHub 交付可能是一個複雜且耗時的過程。在家庭實驗室環境中,手動執行 PipelineRun 以確保管道正常運行往往更為容易。此方法允許你在不依賴外部觸發器的情況下測試管道,從而更容易地識別和修復問題。
範例場景
考慮一個場景,你的 CI/CD 管道負責構建和推送圖像到內部寄存器。你希望在設置 webhook 之前確保管道正常運行。在這種情況下,你可以使用 run-pilot-l0.sh 腳本來手動執行 PipelineRun,並確保管道正常運行。
# 例:run-pilot-l0.sh
#!/bin/bash
# 設置環境變數
export REGISTRY=<registry-host>
export IMAGE=<image:tag>
# 執行 PipelineRun
kubectl apply -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pilot-l0
spec:
pipelineRef:
name: ci-pipeline
workspaces:
- name: source
workspace: source
params:
- name: registry
value: $REGISTRY
- name: image
value: $IMAGE
EOF
6. 失敗模式:Webhook 簽章、Ingress 端口 8080 不匹配、Task Pod 在壞的 runc 节點上卡在 Init 狀態、Status Token RBAC
在 CI/CD 環境中,失敗模式可以來自於各種來源。本節將介紹一些常見的失敗模式,例如 Webhook 簽章問題、Ingress 端口不匹配、Task Pod 在 Init 狀態卡住,以及 RBAC 問題。
Webhook 簽章
Webhook 簽章用於確保 Webhook 是來自可信的來源。在家庭實驗室環境中,確保 Webhook 簽章正確配置以防止未授權訪問是至關重要的。
# Webhook 簽章範例
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-編碼的憑證>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
webhookClientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-編碼的憑證>
Ingress 端口 8080 不匹配
Ingress 端口不匹配可能會導致 Webhook 出現問題。在家庭實驗室環境中,確保 Ingress 端口正確配置以防止任何 Webhook 問題是至關重要的。
# Ingress 端口不匹配範例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ci-ingress
spec:
rules:
- host: <hostname>
http:
paths:
- path: /webhook
pathType: Prefix
backend:
service:
name: ci-webhook
port:
number: 8080
Task Pod 在壞的 runc 节點上卡在 Init 狀態
Task Pod 可能在壞的 runc 节點上卡在 Init 狀態。在家庭實驗室環境中,確保您的 runc 节點健康且最新版本,以防止任何 Task Pod 問題。
# 壞的 runc 节點健康範例
apiVersion: node.k8s.io/v1
kind: Node
metadata:
name: <node-name>
spec:
taints:
- key: "runc-node"
effect: "NoSchedule"
value: "true"
Status Token RBAC
RBAC(基於角色的訪問控制)在 CI/CD 環境中至關重要,用於確保只有授權用戶才能訪問資源。在家庭實驗室環境中,確保 RBAC 正確配置以防止任何未授權訪問是至關重要的。
# RBAC 範例
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ci-webhook
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "update"]
範例場景
考慮一個場景,您有一個 CI/CD 管道,使用 Webhook 觸發構建和測試。您希望確保管道運行正確,並防止任何 Webhook 簽章問題、Ingress 端口不匹配、Task Pod 在 Init 狀態卡住,以及 RBAC 問題。在此情況下,您可以使用上述範例配置您的 Webhook、Ingress、runc 节點和 RBAC,以防止任何問題。
# Webhook 簽章範例
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: ci-webhook
webhooks:
- name: ci-webhook.example.com
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["batch"]
apiVersions: ["v1"]
resources: ["jobs"]
clientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-編碼的憑證>
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
failurePolicy: Ignore
sideEffects: None
timeoutSeconds: 30
matchPolicy: Exact
webhookClientConfig:
service:
namespace: ci-triggers
name: ci-webhook-service
caBundle: <base64-編碼的憑證>
7. Runbook 指南
如果您遇到 CI/CD 管道相關問題,可以參考runbook以獲得詳細的排錯和解決常見問題的指示。runbook 可在以下網址取得:
Runbook 網址: https://example.com/runbook/tekton-homelab-ci
透過遵循runbook,您可以確保 CI/CD 管道運作正確,並預防任何問題發生。
範例 Runbook
# Runbook: Tekton on a Homelab
排除錯誤
- Webhook 簽章問題: 確保 webhook 簽章正確配置。
- Ingress 埠號不符: 檢查 ingress 埠號配置。
- 任務 Pod 初始化卡住: 確保 runc 节點健康且為最新版本。
- RBAC 問題: 確保 RBAC 正確配置。
接下來的步驟
- 使用
run-pilot-l0.sh執行手動 PipelineRun,以確保您的管道運作正常。 - 設置 webhook 以觸發構建和測試。
- 監控您的管道,以檢測任何問題,並參考手冊進行排錯。
按照上述步驟並參考手冊,您可以確保您的 CI/CD 管道運作正常,並預防任何問題的出現。```
Related internal runbook: tekton-homelab-ci (VPN) 相關內部 runbook:tekton-homelab-ci(VPN)