巡检当前K8S集群namespace中是否存在image-secret,不存在则创建

387 阅读2分钟

背景

做容器化自动化发布的时候,经常需要到对应的namespace创建imagePullSecret,deploy指定secret过后,才能正常拉取镜像。当namespace非常多或者我们新增namespace时,都需要手动创建imagePullSecret。此解决方案意在利用python代码,自动巡检imagePullSecret,没有则创建。

说明:

  • 该脚本使用python SDK直接操作K8S api-server;
  • config.load_incluster_config()直接加载Kubernetes集群内部的配置, 获取sa的权限。需要提前创建专用serviceaccout,如sreadmin;
kubectl create ns sre
kubectl create clusterrolebinding sreadmin --clusterrole=cluster-admin --serviceaccount=sre:sreadmin
  • 使用K8S CronJob轮巡检查当前K8S集群namespace中是否存在image-secret,不存在则创建;

核心代码逻辑

# -*- coding: utf-8 -*-

#pip install -i https://mirrors.aliyun.com/pypi/simple/ kubernetes pyyaml

from kubernetes import client, config
import yaml,base64


def get_namespaces():    
    api_v1 = client.CoreV1Api()
    
    try:
        namespaces = api_v1.list_namespace().items  # 获取所有命名空间列表
        filtered_namespaces = [
            ns.metadata.name for ns in namespaces
        ]
        return  filtered_namespaces
    except client.ApiException as e:
        print("Exception when calling CoreV1Api->list_namespace: %s\n" % e)
        return []
    


def create_secret(namespace):
    """
    已弃用该函数
    """
    # 创建Secret对象
    secret = client.V1Secret()
    secret_name = "image-secret"
    secret.metadata = client.V1ObjectMeta(name=secret_name)
    # 创建Kubernetes客户端
    api_v1 = client.CoreV1Api()

    # 添加数据项到Secret中(以Base64编码的形式)
    secret.data = {
        # sre
        "username": "c3Jl",
        # Sre123456!    
        "password": "U3JlMTIzNDU2IQ=="
    }

    # 先判断是否存在secret,不存在则创建
    try:
        # 调用 API 获取指定命名空间中的 Secret
        api_v1.read_namespaced_secret(secret_name, namespace)
    except client.exceptions.ApiException as e:
        if e.status == 404:
            # 创建Secret
            api_v1.create_namespaced_secret(namespace=namespace, body=secret)
            print(f"namespace {namespace} secret 创建成功")
        else:
            print("secret查询异常")
            print(e)



def create_image_pull_secret(namespace, registry, username, password):
    # 创建Secret对象
    secret = client.V1Secret()
    secret_name = "aws-harbor-image-secret"
    secret.metadata = client.V1ObjectMeta(name=secret_name)
    # 创建Kubernetes客户端
    api_v1 = client.CoreV1Api()

    # 添加数据项到Secret中(以Base64编码的形式)
    secret.data = {
        ".dockerconfigjson": base64.b64encode(
            f'{{"auths": {{"{registry}": {{"username": "{username}", "password": "{password}", "email": "none"}}}}}}'.encode('utf-8')
        ).decode('utf-8')
    }
    secret.type='kubernetes.io/dockerconfigjson'
    # 先判断是否存在Secret,不存在则创建
    try:
        # 调用 API 获取指定命名空间中的 Secret
        api_v1.read_namespaced_secret(secret_name, namespace)
    except client.exceptions.ApiException as e:
        if e.status == 404:
            # 创建Secret
            api_v1.create_namespaced_secret(namespace=namespace, body=secret)
            print(f"Namespace '{namespace}' 中的 Secret '{secret_name}' 创建成功")
        else:
            print("Secret查询异常")
            print(e)



if __name__ == "__main__":
    registry = "harbor.example.com"
    username = "xxx"
    password = "xxx"

    # 方式一,直接加载Kubernetes集群内部的配置 
    config.load_incluster_config()
    # 方式二,加载kube config
    # config.load_kube_config(config_file='./eks-qa-config')

    # 查找满足条件的namespace
    namespaces = get_namespaces()
    for ns in namespaces:
        create_image_pull_secret(ns, registry, username, password)