在现代化 .net9
应用部署阶段,零代码入侵模式,自动获取 kubernetes
命名空间 kube-system
的 UID
,并其作为变量配置到应用。
以下是几种实现方式:
方法一:使用 InitContainer + Downward API
您可以通过 Kubernetes
的 Downward API
和 initContainers
在部署时将 kube-system
命名空间的 UID
自动注入到 .NET 9
应用的环境变量中,无需编写代码。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dotnet-app
spec:
replicas: 1
selector:
matchLabels:
app: dotnet-app
template:
metadata:
labels:
app: dotnet-app
spec:
serviceAccountName: dotnet-app-sa
initContainers:
- name: get-cluster-uid
image: bitnami/kubectl:latest
command:
- sh
- -c
- |
# 获取 kube-system 命名空间的 UID
KUBE_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-uid
volumeMounts:
- name: shared-data
mountPath: /shared
containers:
- name: dotnet-app
image: your-dotnet-app:latest
env:
# 通过 Downward API 从卷中读取 UID
- name: KUBE_SYSTEM_UID
valueFrom:
configMapKeyRef:
name: cluster-info
key: kube-system-uid
optional: true
volumeMounts:
- name: shared-data
mountPath: /shared
volumes:
- name: shared-data
emptyDir: {}
---
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: ServiceAccount
name: dotnet-app-sa
namespace: default
roleRef:
kind: ClusterRole
name: dotnet-app-cluster-role
apiGroup: rbac.authorization.k8s.io
方法二:使用 ConfigMap + Helm 或 Kustomize 预处理
1. 创建预处理脚本 (pre-deploy.sh)
bash
#!/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)"
EOF
echo "ConfigMap 'cluster-info' created with kube-system UID: $KUBE_SYSTEM_UID"
2. Deployment 配置
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dotnet-app
spec:
replicas: 1
selector:
matchLabels:
app: dotnet-app
template:
metadata:
labels:
app: dotnet-app
spec:
containers:
- name: dotnet-app
image: your-dotnet-app:latest
env:
# 直接从 ConfigMap 注入环境变量
- name: KUBE_SYSTEM_UID
valueFrom:
configMapKeyRef:
name: cluster-info
key: kube-system-uid
- name: CLUSTER_CREATED
valueFrom:
configMapKeyRef:
name: cluster-info
key: cluster-created
方法三:使用 Kubernetes Job 预先创建 ConfigMap
1. 创建 Job 来生成 ConfigMap
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: create-cluster-info
spec:
ttlSecondsAfterFinished: 300 # Job 完成后 5 分钟自动清理
template:
spec:
serviceAccountName: cluster-info-sa
restartPolicy: Never
containers:
- name: kubectl
image: bitnami/kubectl:latest
command:
- sh
- -c
- |
# 等待 API Server 准备就绪
sleep 5
# 获取 kube-system UID
KUBE_SYSTEM_UID=$(kubectl get namespace kube-system -o jsonpath='{.metadata.uid}')
# 创建 ConfigMap
kubectl 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: ServiceAccount
name: cluster-info-sa
roleRef:
kind: Role
name: cluster-info-role
apiGroup: rbac.authorization.k8s.io
2. 主应用 Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dotnet-app
spec:
replicas: 1
selector:
matchLabels:
app: dotnet-app
template:
metadata:
labels:
app: dotnet-app
spec:
containers:
- name: dotnet-app
image: your-dotnet-app:latest
env:
# 从预先创建的 ConfigMap 注入环境变量
- name: KUBE_SYSTEM_UID
valueFrom:
configMapKeyRef:
name: cluster-info
key: kube-system-uid
- name: CLUSTER_CREATED
valueFrom:
configMapKeyRef:
name: cluster-info
key: cluster-created
方法四:使用 Admission Controller 或 Mutating Webhook
如果您有更高级的需求,可以创建一个 Mutating Webhook
,在 Pod
创建时自动注入环境变量:
yaml
# 简化的示例,实际实现需要编写 Webhook 服务
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: cluster-info-injector
webhooks:
- name: cluster-info.example.com
clientConfig:
service:
name: webhook-service
namespace: webhook-namespace
path: "/mutate"
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
# 其他配置...
在 .NET 9 应用中读取环境变量
无论使用哪种方案,您的 .NET 9
应用都可以通过标准方式读取环境变量:
bash
// 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
启动时执行额外操作 - 灵活性高:可以同时注入多个集群相关信息
部署流程:
bash
# 1. 运行预处理脚本创建 ConfigMap
./pre-deploy.sh
# 2. 部署应用
kubectl apply -f deployment.yaml
这样您的 .NET 9
应用就可以通过标准的环境变量方式获取 KUBE_SYSTEM_UID
,而无需编写任何代码来获取该信息。