背景
做容器化自动化发布的时候,经常需要到对应的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)