在K8S集群内部搭建获取集群信息的服务

  1. 前期准备

    1. 创建service account     
      apiVersion: v1  
      kind: ServiceAccount  
      metadata:  
        name: operation-platform  
        namespace: default

    2. 创建ClusterRole
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: all-namespaces-pod-reader
      rules:
      - apiGroups: [""]
        resources: ["pods", "pods/log"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["apps"]
        resources: ["deployments"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: [""]
        resources: ["services"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: ["extensions", "networking.k8s.io"]
        resources: ["ingresses"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["nodes/stats"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["metrics.k8s.io"]
        resources: ["nodes"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["nodes/proxy"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
      - apiGroups: [""]
        resources: ["configmaps"]
        verbs: ["get", "list", "watch", "create", "update", "delete"]
    3. 创建ClusterRoleBinding
      apiVersion: rbac.authorization.k8s.io/v1  
      kind: ClusterRoleBinding  
      metadata:  
        name: all-namespaces-pod-reader  
      roleRef:  
        apiGroup: rbac.authorization.k8s.io  
        kind: ClusterRole  
        name: all-namespaces-pod-reader  
      subjects:  
      - kind: ServiceAccount  
        name: operation-platform  
        namespace: default

    4. 创建Secret
      apiVersion: v1  
      kind: Secret  
      metadata:  
        name: operation-platform-token  
        namespace: default
        annotations:  
          kubernetes.io/service-account.name: operation-platform  
      type: kubernetes.io/service-account-token  

    5. 使用deployment部署服务
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: operation-platform
        name: operation-platform
        namespace: default
      spec:
        replicas: 1   #pod数量
        selector:
          matchLabels:
            app: operation-platform
        strategy:  #升级策略(默认为滚动升级,不需要修改)
          type: RollingUpdate
          rollingUpdate:
            maxSurge: 1  #滚动升级时会先启动1个pod
            maxUnavailable: 0  #滚动更新时最大可以删除多少个pod
        template:  #定义pod
          metadata:
            labels:
              app: operation-platform
              logging: "true"
          spec:
            serviceAccountName: operation-platform
            containers:  #定义容器
              - name: operation-platform
                image: operation_platform_staging:latest
                imagePullPolicy: Always
                env:  
                - name: POD_NAME  
                  valueFrom:  
                    fieldRef:  
                      fieldPath: metadata.name  
                ports:
                  - containerPort: 58180
                    name: http
                resources:
                  limits:  #容器可以使用的最大限制
                    memory: 256Mi
                  requests:  #一个pod中容器运行需要的资源
                    cpu: 20m
                    memory: 96Mi
            
      ---
      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: operation-platform
        name: operation-platform
        namespace: default
      spec:
        ports:
          - port: 58180
            name: http
            protocol: TCP
            targetPort: 58180
        selector:
          app: operation-platform
      
      ---
      
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: operation-platform
        namespace: default
        labels:
          app: operation-platform
        annotations:
          nginx.ingress.kubernetes.io/configuration-snippet: |
            add_header Access-Control-Allow-Origin '*' always;
            add_header Access-Control-Allow-Credentials 'true' always;
            add_header Access-Control-Allow-Methods 'POST, GET, PUT, DELETE, PATCH, OPTIONS' always;
            add_header Access-Control-Allow-Headers '*' always;
            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass_request_headers      on;
          #Ingress Core Settings
          cert-manager.io/cluster-issuer: letsencrypt-cloudflare
          # 强制的从 HTTP 重定向刀 HTTPS
          ingress.kubernetes.io/ssl-redirect: "true"
          # 指定 Ingress Controller 的类型
          kubernetes.io/ingress.class: "nginx"
          nginx.ingress.kubernetes.io/use-regex: "true"
      spec:
        tls:
          - hosts:
            - "*.xxx.com"
            - xxx.com
            secretName: certificate-secret
        rules:
          - host: operation-platform-staging.xxx.com
            http:
              paths:
                - path: /
                  pathType: Prefix
                  backend:
                    service:
                      name: operation-platform
                      port:
                        number: 58180
      

    6. 在服务器上启动kubectl apply -f deployment.yml
    7. 后端服务
      import logging
      import os
      import time
      
      import uvicorn
      from fastapi import FastAPI,HTTPException
      from fastapi.responses import StreamingResponse
      from kubernetes import client, config, watch
      from kubernetes.client import V1Deployment, V1ObjectMeta
      
      app = FastAPI()
      
      # 创建 logger 实例并设置日志级别
      logger = logging.getLogger("myapp")
      logger.setLevel(logging.DEBUG)
      
      # 配置日志处理程序和格式
      handler = logging.StreamHandler()
      formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
      handler.setFormatter(formatter)
      logger.addHandler(handler)
      
      
      @app.get("/token")
      def get_service_account_token():
          with open("/var/run/secrets/kubernetes.io/serviceaccount/token", "r") as f:
              token = f.read()
          return {"message": token}
      
      
      @app.get("/health")
      async def root():
          return {"message": "Hello World"}
      
      
      @app.get("/service-account")
      def get_service_account_name():
          config.load_incluster_config()
          api_instance = client.CoreV1Api()
          # 从挂载的文件中读取命名空间
          with open("/var/run/secrets/kubernetes.io/serviceaccount/namespace", "r") as f:
              namespace = f.read()
      
              # 获取当前 Pod 名称(从环境变量中读取)
          pod_name = os.environ.get("POD_NAME")
      
          # 使用 Kubernetes API 获取 Pod 详细信息
          pod = api_instance.read_namespaced_pod(pod_name, namespace)
      
          # 从 Pod 详细信息中获取 ServiceAccount 名称
          service_account_name = pod.spec.service_account_name
          return {"message": service_account_name, "namespace": namespace, "pod_name": pod_name}
      
      
      @app.get("/pods-info/{namespace}/pod/{pod_name}")
      async def get_pod_detail(namespace: str, pod_name: str):
          # 加载配置并创建 API 实例
          config.load_incluster_config()
          api_instance = client.CoreV1Api()
      
          # 获取指定的 Pod
          pod_obj = api_instance.read_namespaced_pod(pod_name, namespace)
      
          # 提取 Pod 的名称、运行时间和镜像
          name = pod_obj.metadata.name
          run_time = pod_obj.status.start_time
          images = [container.image for container in pod_obj.spec.containers]
      
          return {"name": name, "run_time": run_time, "images": images}
      
      
      @app.get("/pods-info/{namespace}/deployment/{deployment}")
      async def get_pods_info(namespace: str, deployment: str):
          # 加载配置并创建 API 实例
          config.load_incluster_config()
          api_instance = client.CoreV1Api()
          apps_v1_api_instance = client.AppsV1Api()
      
          # 获取 Deployment
          deployment_obj = apps_v1_api_instance.read_namespaced_deployment(deployment, namespace)
      
          # 使用 Deployment 的 label 选择器过滤 Pod 列表
          label_selector = ','.join([f"{k}={v}" for k, v in deployment_obj.spec.selector.match_labels.items()])
          pods = api_instance.list_namespaced_pod(namespace, label_selector=label_selector)
      
          pod_info = []
          for pod in pods.items:
              pod_info.append({"name": pod.metadata.name, "status": pod.status.phase, "run_time": pod.status.start_time})
      
          return pod_info
      
      
      @app.get("/logs/{namespace}/pod/{pod_name}")
      async def get_pod_logs(namespace: str, pod_name: str):
          # Load config and create API instance
          config.load_incluster_config()
          api_instance = client.CoreV1Api()
      
          pod_logs = api_instance.read_namespaced_pod_log(pod_name, namespace)
          return {"logs": pod_logs}
      
      
      
      @app.post("/deploy/{namespace}")
      async def create_deployment(namespace: str, deployment_info: dict):
          # Load config and create API instance
          config.load_incluster_config()
          apps_v1_api_instance = client.AppsV1Api()
      
          # Extract deployment information from the request
          deployment_name = deployment_info["name"]
          image = deployment_info["image"]
          replicas = deployment_info["replicas"]
      
          # Validate input data
          if not (deployment_name and image and replicas):
              raise HTTPException(status_code=400, detail="Invalid deployment information provided")
      
              # Create the Deployment object
          deployment = V1Deployment(
              metadata=V1ObjectMeta(name=deployment_name),
              spec={
                  "replicas": replicas,
                  "selector": {"matchLabels": {"app": deployment_name}},
                  "template": {
                      "metadata": {"labels": {"app": deployment_name}},
                      "spec": {"containers": [{"name": deployment_name, "image": image}]},
                  },
              },
          )
      
          # Create the Deployment in the specified namespace
          try:
              created_deployment = apps_v1_api_instance.create_namespaced_deployment(namespace, deployment)
              return {"message": f"Deployment '{deployment_name}' created successfully",
                      "deployment": created_deployment.to_dict()}
          except client.exceptions.ApiException as e:
              raise HTTPException(status_code=400, detail=f"Error creating deployment: {e}")
      
      
      if __name__ == "__main__":
          uvicorn.run(app, host="0.0.0.0", port=58180)
      

 2.使用

curl 127.0.0.1:58180/health

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值