經過前一天建立了完整的 OTel → Loki 日誌數據流,今天我們要學習 OpenTelemetry Collector 項目本身是如何使用 KinD 進行端到端測試的!就像醫生需要在實驗室裡驗證新藥一樣,我們的可觀測性系統也需要在真實的 Kubernetes 環境中進行全面測試。今天讓我們深入 OpenTelemetry Contrib Collector 的測試架構,學習如何用 KinD 建立測試環境!
今日主要了解 OpenTelemetry Contrib Collector 在 GitHub CICD pipeline 中利用 KinD 建立測試環境來進行 e2e testing。
✅ 理解 OpenTelemetry Collector 如何使用 KinD 進行測試
✅ 掌握 KinD 在 CI/CD Pipeline 中的最佳實踐
🤔 為什麼需要在 Kubernetes 中測試?
# 🔴 傳統測試的局限性
docker run otel/opentelemetry-collector-contrib # ✅ 單容器測試
go test ./... # ✅ 單元測試
# 😵 但是無法測試:
# - Kubernetes 特定的 receiver(k8sattributes, k8sobjects)
# - 服務發現和自動配置
# - 多節點網路通訊交互
# - 真實的微服務間追蹤
# - Kubernetes 權限和 RBAC
🟢 KinD 解決的問題
# 現代測試方法:真實 K8s 環境
kind create cluster --config e2e-kind-config.yaml # 🏗️ 建立測試集群
kubectl apply -f test-manifests/ # 🚀 部署測試應用
go test --tags=e2e ./... # 🧪 端到端測試
kind delete cluster # 🧹 清理環境
# e2e-kind-config.yaml - OpenTelemetry 測試用 cluster配置
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
# 🔧 全局 kubeadm 配置
kubeadmConfigPatches:
- |
kind: KubeletConfiguration
# 🔐 啟用 TLS bootstrap - 用於測試 kubeletstatsreceiver
serverTLSBootstrap: true
# 🎯 節點配置
nodes:
- role: control-plane
labels:
# 🏷️ 用於 k8sattributesprocessor e2e 測試的自定義標籤
foo: too
🎨 配置特色分析
kubeadmConfigPatches:
- |
kind: KubeletConfiguration
serverTLSBootstrap: true
nodes:
- role: control-plane
labels:
foo: too
k8sattributesprocessor
提供測試標籤從 e2e-tests.yml
可以看到 OpenTelemetry 使用了非常完整的測試策略:
# 🎯 多維度測試矩陣
strategy:
fail-fast: false
matrix:
k8s-version:
- "v1.30.0" # 🚀 最新版本
- "v1.23.17" # 🛡️ 舊版本兼容性
component:
- receiver/k8sclusterreceiver # 🏗️ 集群級別監控
- processor/k8sattributesprocessor # 🏷️ 屬性豐富化
- receiver/kubeletstatsreceiver # 📊 節點統計
- receiver/k8sobjectsreceiver # 🎭 物件監控
- extension/observer/k8sobserver # 👁️ 服務發現
collector-build:
runs-on: ubuntu-24.04
steps:
- name: Build Collector
run: make otelcontribcol
- name: Upload Collector Binary
uses: actions/upload-artifact@v4
docker-build:
steps:
- name: Build Docker Image
run: make docker-otelcontribcol
- name: export image to tar
run: docker save otelcontribcol:latest > /tmp/otelcontribcol.tar
kubernetes-test-matrix:
steps:
- name: Create kind cluster
uses: helm/kind-action@v1.12.0
with:
node_image: kindest/node:${{ matrix.k8s-version }}
config: ./.github/workflows/configs/e2e-kind-config.yaml
- name: Fix kubelet TLS server certificates
run: |
kubectl get csr -o=jsonpath='{range.items[?(@.spec.signerName=="kubernetes.io/kubelet-serving")]}{.metadata.name}{" "}{end}' | xargs kubectl certificate approve
其中一個 e2e 測試程式在這,是以 Go 撰寫設計的。
透過宣告註解//go:build e2e
然後執行 go test -v --tags=e2e
就只會對有宣告該註解的測試腳本執行測試。
相關的GitHub Action的執行結果如下。
//go:build e2e
// +build e2e
package k8sobserver
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/extension/extensiontest"
)
🎯 標籤機制的優勢:
func TestK8sObserver_EndToEnd(t *testing.T) {
// 🎯 測試設置
ctx := context.Background()
// 🔧 建立測試配置
cfg := &Config{
AuthType: "serviceAccount",
Node: "${K8S_NODE_NAME}",
}
// 🏗️ 建立擴展實例
factory := NewFactory()
extension, err := factory.CreateExtension(ctx, extensiontest.NewNopCreateSettings(), cfg)
require.NoError(t, err)
// 🚀 啟動擴展
err = extension.Start(ctx, componenttest.NewNopHost())
require.NoError(t, err)
defer extension.Shutdown(ctx)
// 🧪 執行測試邏輯
observer := extension.(*k8sObserver)
// ⏳ 等待服務發現
time.Sleep(10 * time.Second)
// 🔍 驗證發現的端點
endpoints := observer.ListEndpoints()
require.NotEmpty(t, endpoints, "Should discover at least one endpoint")
// 🎯 驗證端點屬性
for _, endpoint := range endpoints {
require.NotEmpty(t, endpoint.ID, "Endpoint should have ID")
require.NotEmpty(t, endpoint.Target, "Endpoint should have target")
// 🏷️ 驗證 Kubernetes 屬性
attrs := endpoint.Details.GetAttributes()
require.Contains(t, attrs, "k8s.namespace.name")
require.Contains(t, attrs, "k8s.pod.name")
}
}
小弟將自己的程式碼跟 GitHub Actions 做整合。
從 GitHub Actions 執行結果可以看到,我成功實現了一個完整的 KinD E2E 測試流程!🎉
✅ build-app: 47s # 應用程式建置
✅ build-test: 1m 59s # 測試映像建置
✅ e2e-test (v1.30.0) # Kubernetes 1.30 測試
✅ e2e-test (v1.29.0) # Kubernetes 1.29 測試
✅ e2e-summary: 3s # 測試總結
// cmd/server/main.go - 簡潔的測試應用
type HealthResponse struct {
Status string `json:"status"`
Timestamp time.Time `json:"timestamp"`
Version string `json:"version"`
Env map[string]string `json:"env"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
response := HealthResponse{
Status: "healthy",
Timestamp: time.Now(),
Version: os.Getenv("APP_VERSION"),
Env: map[string]string{
"KUBERNETES_SERVICE_HOST": os.Getenv("KUBERNETES_SERVICE_HOST"),
"HOSTNAME": os.Getenv("HOSTNAME"),
},
}
// ... JSON response
}
// test/e2e/e2e_test.go
//go:build e2e
// +build e2e
func TestApplicationHealthEndpoint(t *testing.T) {
// 🔍 健康檢查端點測試
resp, err := http.Get("http://go-e2e-app-service:8080/health")
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
var health HealthResponse
err = json.NewDecoder(resp.Body).Decode(&health)
require.NoError(t, err)
require.Equal(t, "healthy", health.Status)
}
# k8s/deployment.yaml - 完整的部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-e2e-app
spec:
replicas: 2
selector:
matchLabels:
app: go-e2e-app
template:
spec:
containers:
- name: app
image: go-e2e-app:latest
imagePullPolicy: Never
ports:
- containerPort: 8080
env:
- name: APP_VERSION
value: "1.0.0"
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
# k8s/rbac.yaml - 測試用服務帳戶
apiVersion: v1
kind: ServiceAccount
metadata:
name: e2e-test-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: e2e-test-role
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
# test/k8s/e2e-job.yaml - Kubernetes Job 執行測試
apiVersion: batch/v1
kind: Job
metadata:
name: e2e-test
spec:
backoffLimit: 2
template:
spec:
serviceAccountName: e2e-test-sa
containers:
- name: e2e-test
image: go-e2e-test:latest
imagePullPolicy: Never
command: ["go", "test", "-v", "--tags=e2e", "./test/e2e/"]
restartPolicy: Never
我們從 OpenTelemetry 學到的經驗
# 將測試環境配置版本化
kind-config.yaml # 集群配置
test-manifests/ # 測試用 K8s 資源
e2e-tests/ # 測試腳本
Makefile # 自動化命令
# 使用不同的集群名稱避免衝突
cluster_name: e2e-test-${{ github.run_id }}
# 完整的測試流程
kind create cluster → 部署應用 → 執行測試 → 收集結果 → 清理環境
# 階段 1: 基本功能測試
make test
# 階段 2: 容器化測試
make docker-build && make test
# 階段 3: Kubernetes 整合測試
make e2e-local
# 階段 4: 多環境兼容性測試
GitHub Actions 自動執行
KinD 讓我們能在 CI/CD 中運行接近運營環境的測試
🔺 E2E Tests (少量,高價值)
🔺🔺 Integration Tests (適量)
🔺🔺🔺🔺 Unit Tests (大量,快速)