在現代化 .net9
應用部署階段,零代碼入侵模式,自動獲取 kubernetes
命名空間 kube-system
的 UID
,并其作為變量配置到應用。
以下是幾種實現方式:
方法一:使用 InitContainer + Downward API
您可以通過 Kubernetes
的 Downward API
和 initContainers
在部署時將 kube-system
命名空間的 UID
自動注入到 .NET 9
應用的環境變量中,無需編寫代碼。
apiVersion: apps/v1
kind: Deployment
metadata:name: dotnet-app
spec:replicas: 1selector:matchLabels:app: dotnet-apptemplate:metadata:labels:app: dotnet-appspec:serviceAccountName: dotnet-app-sainitContainers:- name: get-cluster-uidimage: bitnami/kubectl:latestcommand:- sh- -c- |# 獲取 kube-system 命名空間的 UIDKUBE_SYSTEM_UID=$(kubectl get namespace kube-system -o jsonpath='{.metadata.uid}')echo "kube-system UID: $KUBE_SYSTEM_UID"# 將 UID 寫入共享卷echo "$KUBE_SYSTEM_UID" > /shared/cluster-uidvolumeMounts:- name: shared-datamountPath: /sharedcontainers:- name: dotnet-appimage: your-dotnet-app:latestenv:# 通過 Downward API 從卷中讀取 UID- name: KUBE_SYSTEM_UIDvalueFrom:configMapKeyRef:name: cluster-infokey: kube-system-uidoptional: truevolumeMounts:- name: shared-datamountPath: /sharedvolumes:- name: shared-dataemptyDir: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:name: dotnet-app-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: dotnet-app-cluster-role
rules:
- apiGroups: [""]resources: ["namespaces"]verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: dotnet-app-cluster-rolebinding
subjects:
- kind: ServiceAccountname: dotnet-app-sanamespace: default
roleRef:kind: ClusterRolename: dotnet-app-cluster-roleapiGroup: rbac.authorization.k8s.io
方法二:使用 ConfigMap + Helm 或 Kustomize 預處理
1. 創建預處理腳本 (pre-deploy.sh)
#!/bin/bash# 獲取 kube-system UID
KUBE_SYSTEM_UID=$(kubectl get namespace kube-system -o jsonpath='{.metadata.uid}')# 創建包含 UID 的 ConfigMap
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:name: cluster-info
data:kube-system-uid: "$KUBE_SYSTEM_UID"cluster-created: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
EOFecho "ConfigMap 'cluster-info' created with kube-system UID: $KUBE_SYSTEM_UID"
2. Deployment 配置
apiVersion: apps/v1
kind: Deployment
metadata:name: dotnet-app
spec:replicas: 1selector:matchLabels:app: dotnet-apptemplate:metadata:labels:app: dotnet-appspec:containers:- name: dotnet-appimage: your-dotnet-app:latestenv:# 直接從 ConfigMap 注入環境變量- name: KUBE_SYSTEM_UIDvalueFrom:configMapKeyRef:name: cluster-infokey: kube-system-uid- name: CLUSTER_CREATEDvalueFrom:configMapKeyRef:name: cluster-infokey: cluster-created
方法三:使用 Kubernetes Job 預先創建 ConfigMap
1. 創建 Job 來生成 ConfigMap
apiVersion: batch/v1
kind: Job
metadata:name: create-cluster-info
spec:ttlSecondsAfterFinished: 300 # Job 完成后 5 分鐘自動清理template:spec:serviceAccountName: cluster-info-sarestartPolicy: Nevercontainers:- name: kubectlimage: bitnami/kubectl:latestcommand:- sh- -c- |# 等待 API Server 準備就緒sleep 5# 獲取 kube-system UIDKUBE_SYSTEM_UID=$(kubectl get namespace kube-system -o jsonpath='{.metadata.uid}')# 創建 ConfigMapkubectl create configmap cluster-info \--from-literal=kube-system-uid="$KUBE_SYSTEM_UID" \--from-literal=cluster-created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \--dry-run=client -o yaml | kubectl apply -f -echo "Successfully created ConfigMap with kube-system UID: $KUBE_SYSTEM_UID"
---
apiVersion: v1
kind: ServiceAccount
metadata:name: cluster-info-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: cluster-info-role
rules:
- apiGroups: [""]resources: ["namespaces"]verbs: ["get", "list"]
- apiGroups: [""]resources: ["configmaps"]verbs: ["create", "get", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: cluster-info-rolebinding
subjects:
- kind: ServiceAccountname: cluster-info-sa
roleRef:kind: Rolename: cluster-info-roleapiGroup: rbac.authorization.k8s.io
2. 主應用 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:name: dotnet-app
spec:replicas: 1selector:matchLabels:app: dotnet-apptemplate:metadata:labels:app: dotnet-appspec:containers:- name: dotnet-appimage: your-dotnet-app:latestenv:# 從預先創建的 ConfigMap 注入環境變量- name: KUBE_SYSTEM_UIDvalueFrom:configMapKeyRef:name: cluster-infokey: kube-system-uid- name: CLUSTER_CREATEDvalueFrom:configMapKeyRef:name: cluster-infokey: cluster-created
方法四:使用 Admission Controller 或 Mutating Webhook
如果您有更高級的需求,可以創建一個 Mutating Webhook
,在 Pod
創建時自動注入環境變量:
# 簡化的示例,實際實現需要編寫 Webhook 服務
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:name: cluster-info-injector
webhooks:
- name: cluster-info.example.comclientConfig:service:name: webhook-servicenamespace: webhook-namespacepath: "/mutate"rules:- operations: ["CREATE"]apiGroups: [""]apiVersions: ["v1"]resources: ["pods"]# 其他配置...
在 .NET 9 應用中讀取環境變量
無論使用哪種方案,您的 .NET 9
應用都可以通過標準方式讀取環境變量:
// Program.cs
var kubeSystemUID = Environment.GetEnvironmentVariable("KUBE_SYSTEM_UID");
Console.WriteLine($"Kube System UID: {kubeSystemUID}");// 或者使用 IConfiguration
var kubeSystemUID = builder.Configuration["KUBE_SYSTEM_UID"];
推薦方案
對于大多數場景,我推薦使用 方法二(ConfigMap + 預處理腳本),因為:
- 簡單可靠:不需要復雜的初始化邏輯
- 易于維護:
ConfigMap
可以獨立管理和更新 - 性能好:不需要在每次
Pod
啟動時執行額外操作 - 靈活性高:可以同時注入多個集群相關信息
部署流程:
# 1. 運行預處理腳本創建 ConfigMap
./pre-deploy.sh# 2. 部署應用
kubectl apply -f deployment.yaml
這樣您的 .NET 9
應用就可以通過標準的環境變量方式獲取 KUBE_SYSTEM_UID
,而無需編寫任何代碼來獲取該信息。