零代码入侵:Kubernetes 部署时自动注入 kube-system UID 到 .NET 9 环境变量

在现代化 .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 + 预处理脚本),因为:

  1. 简单可靠:不需要复杂的初始化逻辑
  2. 易于维护 :ConfigMap 可以独立管理和更新
  3. 性能好 :不需要在每次 Pod 启动时执行额外操作
  4. 灵活性高:可以同时注入多个集群相关信息

部署流程:

bash 复制代码
# 1. 运行预处理脚本创建 ConfigMap
./pre-deploy.sh

# 2. 部署应用
kubectl apply -f deployment.yaml

这样您的 .NET 9 应用就可以通过标准的环境变量方式获取 KUBE_SYSTEM_UID,而无需编写任何代码来获取该信息。

相关推荐
IT规划师10 小时前
MQTT实战 - 用了8年MQTT,我为什么还要重新系统啃一遍(一)
物联网·.net
陈陈CHENCHEN11 小时前
【Kubernetes】纯 IPv6 K8s 用 socat 打通 IPv4 服务
云原生·容器·kubernetes
邹肖桥16 小时前
使用S7.net动态库对西门子Plc S7-1200进行通讯操作
.net
chingho20 小时前
GitHub上这10个C#项目,不仅实用,还怪好玩的
c#·github·.net·开源项目
wzq11_66621 小时前
Kubernetes集群——网络管理
云原生·容器·kubernetes
学以智用21 小时前
Visual Studio 模板详解
.net
Nontee2 天前
K3s vs K8s:差的不是功能,是交付方式
云原生·容器·kubernetes
朱包林2 天前
iTerm2终端配置指南
linux·javascript·python·云原生·容器·kubernetes·云计算
小陈运维2 天前
使用kubeadm初始化IPV4/IPV6集群
linux·docker·云原生·容器·kubernetes
笑洋仟2 天前
k8s的Ingress配置问题
云原生·容器·kubernetes