562 lines
30 KiB
Python
562 lines
30 KiB
Python
import time
|
|
import yaml
|
|
import base64
|
|
from kubernetes import client, config
|
|
from kubernetes.client.exceptions import ApiException
|
|
from appPublic.log import debug
|
|
from .k8s_utils_public import format_source_labels
|
|
|
|
def create_or_update_namespace(v1, namespace_name):
|
|
"""创建或更新命名空间"""
|
|
try:
|
|
v1.read_namespace(namespace_name)
|
|
debug(f"namespace_name={namespace_name} 命名空间已存在,跳过创建。")
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "Namespace",
|
|
"metadata": {"name": namespace_name}
|
|
}
|
|
v1.create_namespace(body=body)
|
|
debug(f"namespace_name={namespace_name} 命名空间创建成功。")
|
|
else:
|
|
raise e
|
|
|
|
def create_or_update_secret(v1, namespace_name, secret_name, password):
|
|
"""创建或更新 Secret"""
|
|
try:
|
|
v1.read_namespaced_secret(secret_name, namespace_name)
|
|
debug(f"secret_name={secret_name} 在命名空间 {namespace_name} 中已存在,跳过创建。")
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
# 对密码进行 base64 编码
|
|
encoded_password = base64.b64encode(password.encode('utf-8')).decode('utf-8')
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "Secret",
|
|
"metadata": {"name": secret_name, "namespace": namespace_name},
|
|
"type": "Opaque",
|
|
"data": {"password": encoded_password}
|
|
}
|
|
v1.create_namespaced_secret(namespace=namespace_name, body=body)
|
|
debug(f"secret_name={secret_name} 在命名空间 {namespace_name} 中创建成功。")
|
|
else:
|
|
raise e
|
|
|
|
def create_or_update_service_account(v1, namespace_name, service_account_name):
|
|
"""创建或更新服务账户"""
|
|
try:
|
|
v1.read_namespaced_service_account(name=service_account_name, namespace=namespace_name)
|
|
debug(f"namespace_name={namespace_name} service_account_name={service_account_name} 服务账户已存在,跳过创建。")
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "ServiceAccount",
|
|
"metadata": {
|
|
"name": service_account_name,
|
|
"namespace": namespace_name
|
|
}
|
|
}
|
|
v1.create_namespaced_service_account(namespace=namespace_name, body=body)
|
|
debug(f"namespace_name={namespace_name} service_account_name={service_account_name} 服务账户创建成功。")
|
|
else:
|
|
raise e
|
|
|
|
def create_or_update_service(v1, namespace_name, service_name, port_mode, internal_port, selector,
|
|
inside_port, outside_port):
|
|
"""创建或更新服务"""
|
|
try:
|
|
existing_service = v1.read_namespaced_service(name=service_name, namespace=namespace_name)
|
|
update_info = []
|
|
need_update = False
|
|
|
|
ports_config = [
|
|
{
|
|
"name": f"mysql-port",
|
|
"protocol": "TCP",
|
|
"port": internal_port,
|
|
"targetPort": inside_port,
|
|
"nodePort": outside_port if port_mode == "NodePort" else None
|
|
}
|
|
]
|
|
|
|
if existing_service.spec.type != port_mode:
|
|
need_update = True
|
|
update_info.append(f"服务类型从 {existing_service.spec.type} 更新为 {port_mode}")
|
|
existing_service.spec.type = port_mode
|
|
|
|
if existing_service.spec.selector != selector:
|
|
need_update = True
|
|
update_info.append(f"服务选择器从 {existing_service.spec.selector} 更新为 {selector}")
|
|
existing_service.spec.selector = selector
|
|
|
|
if existing_service.spec.ports != ports_config:
|
|
need_update = True
|
|
update_info.append(f"服务端口配置更新")
|
|
existing_service.spec.ports = ports_config
|
|
|
|
if need_update:
|
|
v1.patch_namespaced_service(name=service_name, namespace=namespace_name, body=existing_service)
|
|
debug(f"service_name={service_name} update_info={update_info} 服务已更新,更新内容: {update_info}")
|
|
else:
|
|
debug(f"service_name={service_name} 服务配置无变化,无需更新。")
|
|
return existing_service
|
|
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
ports_config = [
|
|
{
|
|
"name": f"mysql-port",
|
|
"protocol": "TCP",
|
|
"port": internal_port,
|
|
"targetPort": inside_port,
|
|
"nodePort": outside_port if port_mode == "NodePort" else None
|
|
}
|
|
]
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "Service",
|
|
"metadata": {"name": service_name, "namespace": namespace_name},
|
|
"spec": {"type": port_mode, "selector": selector, "ports": ports_config}
|
|
}
|
|
v1.create_namespaced_service(namespace=namespace_name, body=body)
|
|
debug(f"service_name={service_name} 服务创建成功。")
|
|
return v1.read_namespaced_service(name=service_name, namespace=namespace_name)
|
|
else:
|
|
raise e
|
|
|
|
def create_persistent_volume(v1, pv_name, capacity, access_modes, storage_class_name, nfs_server, nfs_path):
|
|
"""创建PV"""
|
|
try:
|
|
v1.read_persistent_volume(name=pv_name)
|
|
debug(f"PersistentVolume {pv_name} 已存在,跳过创建。")
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "PersistentVolume",
|
|
"metadata": {"name": pv_name},
|
|
"spec": {
|
|
"capacity": {
|
|
"storage": capacity
|
|
},
|
|
"accessModes": access_modes,
|
|
"persistentVolumeReclaimPolicy": "Retain",
|
|
"storageClassName": storage_class_name,
|
|
"nfs": {
|
|
"server": nfs_server,
|
|
"path": nfs_path
|
|
}
|
|
}
|
|
}
|
|
try:
|
|
v1.create_persistent_volume(body=body)
|
|
debug(f"PersistentVolume {pv_name} 创建成功。")
|
|
except ApiException as create_e:
|
|
raise Exception(f"创建 PersistentVolume {pv_name} 失败: {create_e.reason}")
|
|
else:
|
|
raise Exception(f"检查 PersistentVolume {pv_name} 是否存在时出错: {e.reason}")
|
|
|
|
def create_persistent_volume_claim(v1, namespace_name, pvc_name, access_modes, storage_class_name, pvc_capacity, source_selflabel):
|
|
"""创建pvc"""
|
|
try:
|
|
v1.read_namespaced_persistent_volume_claim(name=pvc_name, namespace=namespace_name)
|
|
debug(f"PersistentVolumeClaim {pvc_name} 已存在,跳过创建。")
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
body = {
|
|
"apiVersion": "v1",
|
|
"kind": "PersistentVolumeClaim",
|
|
"metadata": {
|
|
"name": pvc_name,
|
|
"namespace": namespace_name,
|
|
"labels": source_selflabel
|
|
},
|
|
"spec": {
|
|
"accessModes": access_modes,
|
|
"resources": {"requests": {"storage": pvc_capacity}},
|
|
"storageClassName": storage_class_name
|
|
}
|
|
}
|
|
try:
|
|
v1.create_namespaced_persistent_volume_claim(namespace=namespace_name, body=body)
|
|
debug(f"PersistentVolumeClaim {pvc_name} 创建成功。")
|
|
except ApiException as create_e:
|
|
raise Exception(f"创建 PersistentVolumeClaim {pvc_name} 失败: {create_e.reason}")
|
|
else:
|
|
raise Exception(f"检查 PersistentVolumeClaim {pvc_name} 是否存在时出错: {e.reason}")
|
|
|
|
def create_or_update_statefulset(apps_v1, v1, namespace_name, statefulset_name, service_account_name,
|
|
image, replicas, cpu_limit, memory_limit, node_selector,
|
|
container_name, initial_password, restart_policy,
|
|
inside_port, volume_mount_path, pvc_name,
|
|
env_vars, readiness_probe, liveness_probe, source_selflabel):
|
|
"""创建或更新StatefulSet"""
|
|
try:
|
|
existing_statefulset = apps_v1.read_namespaced_stateful_set(name=statefulset_name, namespace=namespace_name)
|
|
update_info = []
|
|
need_update = False
|
|
template = existing_statefulset.spec.template
|
|
container = template.spec.containers[0]
|
|
|
|
# 更新副本数
|
|
if existing_statefulset.spec.replicas != replicas:
|
|
need_update = True
|
|
update_info.append(f"副本数从 {existing_statefulset.spec.replicas} 更新为 {replicas}")
|
|
existing_statefulset.spec.replicas = replicas
|
|
|
|
# 更新服务账户和重启策略
|
|
if template.spec.service_account_name != service_account_name:
|
|
need_update = True
|
|
update_info.append(f"服务账户从 {template.spec.service_account_name} 更新为 {service_account_name}")
|
|
template.spec.service_account_name = service_account_name
|
|
|
|
if template.spec.restart_policy != restart_policy:
|
|
need_update = True
|
|
update_info.append(f"重启策略从 {template.spec.restart_policy} 更新为 {restart_policy}")
|
|
template.spec.restart_policy = restart_policy
|
|
|
|
# 更新容器配置
|
|
if container.name != container_name:
|
|
need_update = True
|
|
update_info.append(f"容器名称从 {container.name} 更新为 {container_name}")
|
|
container.name = container_name
|
|
|
|
if container.image != image:
|
|
need_update = True
|
|
update_info.append(f"镜像从 {container.image} 更新为 {image}")
|
|
container.image = image
|
|
|
|
if container.env != env_vars:
|
|
need_update = True
|
|
update_info.append(f"环境变量更新")
|
|
container.env = env_vars
|
|
|
|
if container.resources.limits != {"cpu": cpu_limit, "memory": memory_limit}:
|
|
need_update = True
|
|
update_info.append(f"资源限制更新为 CPU:{cpu_limit}, 内存:{memory_limit}")
|
|
container.resources.limits = {"cpu": cpu_limit, "memory": memory_limit}
|
|
|
|
if container.ports != [{"containerPort": inside_port}]:
|
|
need_update = True
|
|
update_info.append(f"容器端口从 {container.ports} 更新为 {inside_port}")
|
|
container.ports = [{"containerPort": inside_port}]
|
|
|
|
# 更新探针
|
|
if container.readiness_probe != readiness_probe:
|
|
need_update = True
|
|
update_info.append(f"就绪探针更新")
|
|
container.readiness_probe = readiness_probe
|
|
|
|
if container.liveness_probe != liveness_probe:
|
|
need_update = True
|
|
update_info.append(f"存活探针更新")
|
|
container.liveness_probe = liveness_probe
|
|
|
|
# 更新卷挂载
|
|
if container.volume_mounts != [{"name": pvc_name, "mountPath": volume_mount_path}]:
|
|
need_update = True
|
|
update_info.append(f"卷挂载从 {container.volume_mounts} 更新为 {volume_mount_path}")
|
|
container.volume_mounts = [{"name": pvc_name, "mountPath": volume_mount_path}]
|
|
|
|
if need_update:
|
|
apps_v1.patch_namespaced_stateful_set(name=statefulset_name, namespace=namespace_name, body=existing_statefulset)
|
|
debug(f"StatefulSet {statefulset_name} 更新成功: {update_info}")
|
|
else:
|
|
debug(f"StatefulSet {statefulset_name} 配置无变化")
|
|
return existing_statefulset
|
|
|
|
except ApiException as e:
|
|
if e.status == 404:
|
|
container_config = {
|
|
"name": container_name,
|
|
"image": image,
|
|
"env": env_vars,
|
|
"resources": {"limits": {"cpu": cpu_limit, "memory": memory_limit}},
|
|
"ports": [{"containerPort": inside_port}],
|
|
"readinessProbe": readiness_probe,
|
|
"livenessProbe": liveness_probe,
|
|
"volumeMounts": [{"name": pvc_name, "mountPath": volume_mount_path}],
|
|
}
|
|
body = {
|
|
"apiVersion": "apps/v1",
|
|
"kind": "StatefulSet",
|
|
"metadata": {"name": statefulset_name, "namespace": namespace_name},
|
|
"spec": {
|
|
"replicas": replicas,
|
|
"selector": {"matchLabels": source_selflabel},
|
|
"serviceName": statefulset_name,
|
|
"template": {
|
|
"metadata": {"labels": source_selflabel},
|
|
"spec": {
|
|
"serviceAccountName": service_account_name,
|
|
"restartPolicy": restart_policy,
|
|
"containers": [container_config],
|
|
"nodeSelector": node_selector,
|
|
"volumes": [{
|
|
"name": pvc_name,
|
|
"persistentVolumeClaim": {
|
|
"claimName": pvc_name
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
apps_v1.create_namespaced_stateful_set(namespace=namespace_name, body=body)
|
|
debug(f"StatefulSet {statefulset_name} 创建成功,副本数: {replicas}")
|
|
return apps_v1.read_namespaced_stateful_set(name=statefulset_name, namespace=namespace_name)
|
|
else:
|
|
raise e
|
|
|
|
def delete_secret(v1, namespace_name, secret_name):
|
|
"""删除 Secret"""
|
|
try:
|
|
v1.delete_namespaced_secret(secret_name, namespace_name)
|
|
debug(f"secret_name={secret_name} 在命名空间 {namespace_name} 中删除成功。")
|
|
except ApiException as e:
|
|
if e.status != 404: # 忽略 Secret 不存在的情况
|
|
raise Exception(f"删除 Secret {secret_name} 失败: {e.reason}")
|
|
|
|
def delete_persistent_volume(v1, pv_name):
|
|
"""删除PV"""
|
|
try:
|
|
v1.delete_persistent_volume(name=pv_name)
|
|
debug(f"PersistentVolume {pv_name} 删除成功")
|
|
except ApiException as e:
|
|
raise Exception(f"删除 PersistentVolume {pv_name} 失败: {e.reason}")
|
|
|
|
def delete_persistent_volume_claim(v1, namespace_name, pvc_name):
|
|
"""删除pvc"""
|
|
try:
|
|
v1.delete_namespaced_persistent_volume_claim(name=pvc_name, namespace=namespace_name)
|
|
debug(f"PersistentVolumeClaim {pvc_name} 删除成功")
|
|
except ApiException as e:
|
|
raise Exception(f"删除 PersistentVolumeClaim {pvc_name} 失败: {e.reason}")
|
|
|
|
def delete_namespace(v1, namespace_name, root_namespace="your_root_namespace"):
|
|
"""删除命名空间"""
|
|
if namespace_name != root_namespace:
|
|
try:
|
|
v1.delete_namespace(namespace_name, propagation_policy="Foreground")
|
|
debug(f"命名空间 {namespace_name} 删除请求已提交")
|
|
except ApiException as e:
|
|
raise Exception(f"删除命名空间 {namespace_name} 失败: {e.reason}")
|
|
else:
|
|
debug(f"跳过删除根命名空间 {namespace_name}")
|
|
|
|
def delete_service_account(v1, namespace_name, service_account_name, root_namespace="your_root_namespace"):
|
|
"""删除服务账户"""
|
|
if namespace_name != root_namespace:
|
|
try:
|
|
v1.delete_namespaced_service_account(service_account_name, namespace_name)
|
|
debug(f"服务账户 {service_account_name} 删除成功")
|
|
except ApiException as e:
|
|
raise Exception(f"删除服务账户 {service_account_name} 失败: {e.reason}")
|
|
else:
|
|
debug(f"跳过删除根命名空间中的服务账户 {service_account_name}")
|
|
|
|
def delete_service(v1, namespace_name, service_name):
|
|
"""删除服务"""
|
|
try:
|
|
v1.delete_namespaced_service(service_name, namespace_name)
|
|
debug(f"服务 {service_name} 删除成功")
|
|
except ApiException as e:
|
|
raise Exception(f"删除服务 {service_name} 失败: {e.reason}")
|
|
|
|
def delete_statefulset(apps_v1, namespace_name, statefulset_name):
|
|
"""删除StatefulSet"""
|
|
try:
|
|
apps_v1.delete_namespaced_stateful_set(
|
|
name=statefulset_name,
|
|
namespace=namespace_name,
|
|
propagation_policy="Foreground"
|
|
)
|
|
debug(f"StatefulSet {statefulset_name} 删除请求已提交")
|
|
except ApiException as e:
|
|
raise Exception(f"删除 StatefulSet {statefulset_name} 失败: {e.reason}")
|
|
|
|
def handle_k8s_operations(frontend_params):
|
|
"""处理Kubernetes资源操作"""
|
|
kubeconfig = yaml.safe_load(frontend_params.pop("kubeconfig"))
|
|
config.load_kube_config_from_dict(kubeconfig)
|
|
v1 = client.CoreV1Api()
|
|
apps_v1 = client.AppsV1Api()
|
|
action = frontend_params["action"]
|
|
namespace_name = frontend_params["namespace_name"]
|
|
service_account_name = frontend_params["serviceaccount_name"]
|
|
service_name = frontend_params["service_name"]
|
|
statefulset_name = frontend_params["podcd_name"]
|
|
image = frontend_params["pod_imagepath"]
|
|
replicas = int(frontend_params.get("source_replicasetnum", 1))
|
|
cpu_limit = frontend_params["source_cpurate"]
|
|
memory_limit = frontend_params["source_memrate"]
|
|
port_mode = frontend_params["source_portmode"]
|
|
internal_port = int(frontend_params["source_apiport"])
|
|
inside_port = int(frontend_params["source_insideport"])
|
|
outside_port = int(frontend_params["source_outsideport"])
|
|
container_name = frontend_params["source_name"]
|
|
initial_password = frontend_params["source_authpasswd"]
|
|
restart_policy = frontend_params["source_restartpolicy"]
|
|
volume_mount_path = frontend_params["source_mountpath"]
|
|
pvc_name = container_name.replace(" ", "").lower() + "-pvc"
|
|
secret_name = f"{container_name.replace(' ', '').lower()}-secret"
|
|
env_varsa = [
|
|
{"name": "MYSQL_ROOT_PASSWORD", "valueFrom": {"secretKeyRef": {"name": secret_name, "key": "password"}}},
|
|
{"name": "MYSQL_DATABASE", "value": frontend_params.get("mysql_database", "kyycloud")},
|
|
{"name": "MYSQL_USER", "value": frontend_params.get("mysql_user", "user")},
|
|
{"name": "MYSQL_PASSWORD", "valueFrom": {"secretKeyRef": {"name": secret_name, "key": "password"}}},
|
|
]
|
|
env_vars = frontend_params.get("env_vars", env_varsa)
|
|
readiness_probea = {
|
|
"exec": {
|
|
"command": ["/bin/sh", "-c", "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"]
|
|
},
|
|
"initialDelaySeconds": 10,
|
|
"periodSeconds": 5,
|
|
"timeoutSeconds": 2,
|
|
"successThreshold": 1,
|
|
"failureThreshold": 3
|
|
}
|
|
readiness_probe = frontend_params.get("readiness_probe", readiness_probea)
|
|
liveness_probea = {
|
|
"exec": {
|
|
"command": ["/bin/sh", "-c", "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"]
|
|
},
|
|
"initialDelaySeconds": 20,
|
|
"periodSeconds": 10,
|
|
"timeoutSeconds": 5,
|
|
"successThreshold": 1,
|
|
"failureThreshold": 3
|
|
}
|
|
liveness_probe = frontend_params.get("liveness_probe", liveness_probea)
|
|
access_modesa = ["ReadWriteOnce"]
|
|
access_modes = frontend_params.get("access_modes", access_modesa)
|
|
storage_class_name = frontend_params.get("storage_class_name", "nfs-storage-class")
|
|
nfs_server = frontend_params.get("host")
|
|
nfs_path = frontend_params.get("nfs_path","/d/k8s_nss")
|
|
pv_name = f"{pvc_name}-pv"
|
|
source_storagelimits = frontend_params.get("source_storagelimits", "5Gi")
|
|
pv_capacity = frontend_params.get("pv_capacity", source_storagelimits)
|
|
pvc_capacity = frontend_params.get("pvc_capacity",source_storagelimits)
|
|
source_selflabel = format_source_labels(frontend_params.get("source_selflabel",":"),type="pod")
|
|
node_selector = format_source_labels(frontend_params.get("source_nodeSelector","="),type="node")
|
|
# 删除选项控制
|
|
delete_options = {
|
|
"secret": frontend_params.get("delete_secret", True),
|
|
"pvc": frontend_params.get("delete_pvc", True),
|
|
"pv": frontend_params.get("delete_pv", True),
|
|
"service": frontend_params.get("delete_service", True),
|
|
"service_account": frontend_params.get("delete_service_account", False),
|
|
"namespace": frontend_params.get("delete_namespace", False)
|
|
}
|
|
# 参数验证
|
|
required_params = [
|
|
"action",
|
|
"namespace_name",
|
|
"serviceaccount_name",
|
|
"service_name",
|
|
"podcd_name",
|
|
"pod_imagepath",
|
|
"source_replicasetnum",
|
|
"source_cpurate",
|
|
"source_memrate",
|
|
"source_portmode",
|
|
"source_apiport",
|
|
"source_insideport",
|
|
"source_outsideport",
|
|
"source_name",
|
|
"source_authpasswd",
|
|
"source_restartpolicy",
|
|
"source_mountpath",
|
|
"host", # nfs_server
|
|
"source_selflabel",
|
|
# "source_nodeSelector"
|
|
]
|
|
for param in required_params:
|
|
if not frontend_params.get(param):
|
|
debug(f"param={param} 错误:缺少必要参数 {param}")
|
|
raise ValueError(f"缺少必要参数:{param}")
|
|
if action == "apply":
|
|
# 创建资源(按依赖顺序)
|
|
create_or_update_namespace(v1, namespace_name)
|
|
create_or_update_secret(v1, namespace_name, secret_name, initial_password)
|
|
create_or_update_service_account(v1, namespace_name, service_account_name)
|
|
create_or_update_service(v1, namespace_name, service_name, port_mode, internal_port, source_selflabel, inside_port, outside_port)
|
|
create_persistent_volume(v1, pv_name, pv_capacity, access_modes, storage_class_name, nfs_server, nfs_path)
|
|
create_persistent_volume_claim(v1, namespace_name, pvc_name, access_modes, storage_class_name, pvc_capacity, source_selflabel)
|
|
create_or_update_statefulset(
|
|
apps_v1, v1, namespace_name, statefulset_name, service_account_name,
|
|
image, replicas, cpu_limit, memory_limit, node_selector,
|
|
container_name, initial_password, restart_policy,
|
|
inside_port, volume_mount_path, pvc_name,
|
|
env_vars, readiness_probe, liveness_probe, source_selflabel
|
|
)
|
|
debug(f"成功申请 {replicas} 个副本的 {statefulset_name},共享pvc: {pvc_name}")
|
|
|
|
elif action == "delete":
|
|
# 删除资源(按逆序)
|
|
delete_statefulset(apps_v1, namespace_name, statefulset_name)
|
|
|
|
# 等待一段时间,确保Pod完全终止
|
|
debug(f'正在销毁资源实例,请稍等...')
|
|
time.sleep(5) # 可根据实际情况调整
|
|
|
|
if delete_options["pvc"]:
|
|
delete_persistent_volume_claim(v1, namespace_name, pvc_name)
|
|
|
|
if delete_options["pv"]:
|
|
delete_persistent_volume(v1, pv_name)
|
|
|
|
if delete_options["service"]:
|
|
delete_service(v1, namespace_name, service_name)
|
|
|
|
if delete_options["secret"]:
|
|
delete_secret(v1, namespace_name, secret_name)
|
|
|
|
if delete_options["service_account"]:
|
|
delete_service_account(v1, namespace_name, service_account_name)
|
|
|
|
if delete_options["namespace"]:
|
|
delete_namespace(v1, namespace_name)
|
|
|
|
debug(f"成功销毁 {statefulset_name} 及其相关资源")
|
|
else:
|
|
raise ValueError("action参数必须为'apply'或'delete'")
|
|
|
|
if __name__ == "__main__":
|
|
kbc = "apiVersion: v1\nclusters:\n- cluster:\n certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJTGd4THlGMjM3QmN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBME1ETXdOelE1TXpWYUZ3MHpOVEEwTURFd056VTBNelZhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURQUm5hdkZmNXBTWWUvVmJLc0s2SnhEazhyc2hsc2h5WnNNRk8xZDVhZG45Z055T0wwR2NtbEsrQ1EKVklKSnF3RklJeSsxUVlEd3VRMytzczEwYmV2Y2lqM1BRanluaXJRRkNhRlA0NHh2ZkEyK2thV1FYeTVncGwrMwpjSkI1K1MxVmx2Vi9aSHQ5SXgwNjFCdHB4dE5oMUkxNS9IYk4rWmVNNnEvd3lxUW93Y01ub2pyNDltYkxxOWNwCnFSem5LL2FwWXlBYnljUk9uWWlIZ0FjQWdsclFOTjBKUEJZd2dRd0pIUmlIcGhtVFBkdmY2ckxkNFR0dFl2OXgKdmZIRDNjVUdwZkVBUElaNUJBVi9ZM3p5V0pSbDQzSFV2Ri9jemNDQ01jOVlUd3VXaEpxb2doUUZUdnNuSVZzTwovNEtKQzRwQXFSenJlZFRWdExmMXgzQlRpVCt0QWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUZjRZbzBpOVpIZC9ObzdkYWZrZVRTbzVzdzN6QVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRRERLalJWVVp1YwppckJ4QWdZWnBBeW5NSHdWQTF6YStVT09FM1U0MEMyVTN0VGgrK1BsN2o2ZGJZTWNWdEFvTXhxaDRiVjNQRW5SCmtWcWNaN2NjS3FGSXduZlhHK0ZGTVVwazVoTk0xLzc2UXBobi9OWk8zSStSVjFtV0VOU1BzM1FZdEVoWktXUlgKYWRXZ0krK0x1cUZyZVpTVzVjRXNnMWZDODFtd3dhTXdkRHZWcFJZMFEwWlBsMGFqTURsSlNDaDNOSXpQOS82bwpndXBrY1JSdWtvRGlscWVraXlrRWJ5OVJCWHZIbXo3Q0sxQ1ZnZXZJTDZrVnRPRFF2Rm10Qm1WemlRNWFDcXJOCmtZNmd6OUNGMkdKc2M4UkZrcWQxbzdMelhPakJsTkdzN2k2WmdEOE1Ca2tiank2RmZDZWVndmxOOGFCU2VmblEKZ2ZNOVptbnRpMVNDCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K\n server: https://192.168.0.3:6443\n name: kubernetes\ncontexts:\n- context:\n cluster: kubernetes\n user: kubernetes-admin\n name: kubernetes-admin@kubernetes\ncurrent-context: kubernetes-admin@kubernetes\nkind: Config\npreferences: {}\nusers:\n- name: kubernetes-admin\n user:\n client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJRENDQWdpZ0F3SUJBZ0lIVGZPdmU4TzBJVEFOQmdrcWhraUc5dzBCQVFzRkFEQVZNUk13RVFZRFZRUUQKRXdwcmRXSmxjbTVsZEdWek1CNFhEVEkxTURRd016QTNORGt6TlZvWERUSTJNRFF3TXpBM05UUXpOMW93TkRFWApNQlVHQTFVRUNoTU9jM2x6ZEdWdE9tMWhjM1JsY25NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5Ym1WMFpYTXRZV1J0CmFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEWVJJT3h0TWFkOWs2T1JsL1UKZ2ZnZVJDQkpjZmMrc2ZFbzkxeW4vc05KZFVIbWRuamtMaC9wRjcwZkdoVWZ3R2t5dzR0WkdpTFFNR0xwclpyeAphVTdJT0R3a3I2ejl1SkQzaHlFZExhZGpZT0NOMHJhUFNpV05GV1QwSVN2UVBjZzNGQkQ2YmFHb2RtSmN5YnBPCk5qY1VZZmh5WEVqRXMwOU92QzhhZUJCbm9Na1RkRk53dlFaYXE2LzR3eTUyN0k3aUdIUVdvL21JS1VUVHhzRFgKMzJnVXErZmRVMEh5STJJeWhNMGdwT29uNURCVmRUbWsyMkZsVHk0ZWJ3Q3R4QmMvRCtpelhuZFpVd2tHMExMVwpqTEc4L3JkWTZ4WFJDVkhHM1BWNURRK0JvNEpnMTUwWWFSUnBKeDJYSGxad3N5OFBZcWVLcTM0b1pxczRTRndmCjJCY3JBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0QKQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRk4vaGlqU0wxa2QzODJqdDFwK1I1TktqbXpEZgpNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFTR0phc1EyQXpLdVNZWFdtMGlYOUhnWTNZQUJGMHpYRzRKZU5lCjREekxkOHF2TXlqRGMwUWFWSUtNbWswemhrV1ZIQzNKSEZWalRXcDBUNFE0TlVBMk8rOXFob1p0a25NL3dsQlUKS0Zab3ZHNFd6SU1sdVJwL21ZRUIzL3dHbkFPV01MdEtBSWJ3d3FRVWl4VW5KYkxCeG4xQ1k5ZERzb1o4VmZZMQp4N2R0WDBJWjJkbU1ETTVLV1lrbW5tQWJBR0tXazZBR3pVWEpWNmlTU3laYjlWLzNuN3hmZlpZRkVDQXBQNk91CjhmRGdIVjBCdEMxS3VmU0tsTitLMnF2aXAzMlRjRHdoTEVHQWQ2aU9qYzhBRXlHelJmOWY4M0xUSGJ2dGtibjYKR0VQQlBQSExSTFlQWEh0OE9LbHdNOThwQWxkSkIyWEJ6UEttc0JFeGFOSWRXd2FTCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K\n client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMkVTRHNiVEduZlpPamtaZjFJSDRIa1FnU1hIM1BySHhLUGRjcC83RFNYVkI1blo0CjVDNGY2UmU5SHhvVkg4QnBNc09MV1JvaTBEQmk2YTJhOFdsT3lEZzhKSytzL2JpUTk0Y2hIUzJuWTJEZ2pkSzIKajBvbGpSVms5Q0VyMEQzSU54UVErbTJocUhaaVhNbTZUalkzRkdINGNseEl4TE5QVHJ3dkduZ1FaNkRKRTNSVApjTDBHV3F1ditNTXVkdXlPNGhoMEZxUDVpQ2xFMDhiQTE5OW9GS3ZuM1ZOQjhpTmlNb1ROSUtUcUorUXdWWFU1CnBOdGhaVTh1SG04QXJjUVhQdy9vczE1M1dWTUpCdEN5MW95eHZQNjNXT3NWMFFsUnh0ejFlUTBQZ2FPQ1lOZWQKR0drVWFTY2RseDVXY0xNdkQyS25pcXQrS0dhck9FaGNIOWdYS3dJREFRQUJBb0lCQVFDQ1djRjZ3YmdaQzVWTApvZFV1MCt1RjZvLy9WS2F1YmpncDlmWXQ5NXNqVW42Vzl2OWtvUHh3MVBNVHBQZm9mR09yeWpyYVNLdUZDalVFCkhiUlBINmJ4ZlJ1YkRSdmFqWDByQkpLTDhMRjhiNjdKTEtFR2VxMXBmT1N0VkxVQXZjeElqbHF4WnBUU1loQmwKVnQxcE9MbzRHZGpTclJiYklDeUVDMTdrdUV0QytZV3lFb3E5MmlLNVdMTHdHM2hwVzhyVlVLVzZ2T0cyd0l4bAp0RWhMSGpOOWtnb1VVa2pORG9tK2FlcVVxeXhDeUZEdll4UmdhVTd0Y3pJSk52SUk3aDYxaExQbEZtMmxGQ0xlCjhjeTdKUDMyV1ZDSUpUMHhRNkJJRTdvVld4WWIvMzFVSHYrTHg0UHlBcFpiZ3piMjlvQm54VjhneUxnVjZDWW0Kd1psQlQ4S2hBb0dCQU9tMFZqTkVHVm5EaXNsTDFVVkNKYzFCVU1KcjNwalQvV0g4d2s0UzJYWmhwRWdVQmpQYgpDM3Y5czkxNHh6SjhXYWFtUFZPVGZMRmxzRWFLNnJpMFhjQkhXQi9ob1R1aDVKaDByS1RNWWFMTm9SdU00VCt6Ci9zUG1aY1ZMVXcxdHFmd3U5YlVpSTJCQURQNFM2MUFubk5hSnF1UmFWRk8vT1pqZUkvbHJzMVBSQW9HQkFPem0KVTNvcjNuSDh4WHI2WDNJUjRDM3l3TkZLaHNVVE44VmdWNWRVL0U5RmRHTldUVzRkWHdCK01jeUlQMlFLbjlycwpmcU9Cb0c3NlRKVHF0YzVobjY5Q014c1lVNVdPcDhOZW9oaXplY1luSTFjTk94TmZwdzZDdUZVb1pmTFFxU1dICmJ4dEVEaFkrcXJjR2FLZ3VzMk1uMkJ2cEg1bUhCTk5DL05pSVZ1WTdBb0dBZFlnVEhkOHVuSjBockJCdUpsR1kKN3p2YzRKb2RMV0RYZWpNQ2lQOGp6RXhZc1VNWXgzVnV0aUdtRmtpS2JWSnFSOHdzNVY0MEJJY3VlcHVjWmQyWApsSDZNekNQTjBVNmV4eWxPTmVidlowL2dxUmxWb3BMa0dpTkJwVkkzWjNaeVdYaElhNXJLamJwSWpuSjNVeTFJCnpBQWFLSk5nKzJrZEQwc1FibnlDaURFQ2dZQVFDZVA2OEg5bDdqd2NnRmozNnhmblpIa0RjbTAvYUhhdEtVR2sKNEQ4WXl0WC9aN2RrVGg3QmRNbkFWRFVlZTgyb3o3d2ZLOGFGM1BKVVhyT2lYbCttU1BBVzFJWE1LVlZZVjg3WApwMGNHVUY0SEpjRXJKWjIwME1yVUVTRWQyRnlyU3NrTjZvU2RvdTZCNTdBc09zVXdZR0UwT290R0pLc0I5cFlSCnZ1RkxRd0tCZ1FEZVFuRElPaUQ2SEpmc2loTC8xZ3dnS0hVeVc2WGYrNFhQODd3ZlVXT1N0SEpza29oTkZHdk8KSnpNdUFvc2V2UGFWdElCSXBZbFgycUlaaHlhdyt2VW9BUTZYRnR3WjM1QWo1T1VPbVFQQUJWbkVXZUJZRzdSaQpaZmhEU2NTek5xb3ozWFpjMnA4a2VMWE1XOWJsTDNNOTdOMFRLbExuZ0NrSTdoaXJMVGE2T0E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo="
|
|
action = 'apply' # 'apply' or 'delete' 删除的关键在于pod引擎名字
|
|
frontend_params = {
|
|
"host": "192.168.0.3",
|
|
"port": 22,
|
|
"user": "root",
|
|
"password": "Yuanshenhong.1",
|
|
"kubeconfig": kbc,
|
|
"action": action,
|
|
"namespace_name": "4hbm8atruisou2bs24t-n-0",
|
|
"serviceaccount_name": "4hbm8atruisou2bs24t-n-0-serviceaccount",
|
|
"podcd_name": "wti3n36klyruaye-vzh8e-statefulset",
|
|
"service_name": "wti3n36klyruaye-vzh8e-service",
|
|
"cpcid": "AROU9udKtPNyh0AZtO_WY",
|
|
"source_name": "kyymysql",
|
|
"source_authuser": "root",
|
|
"source_authpasswd": "123456",
|
|
"source_podengine": "StatefulSet",
|
|
"source_replicasetnum": 2,
|
|
"pod_imagepath": "docker.io/library/mysql:8.0",
|
|
"source_memrate": "512Mi",
|
|
"source_cpurate": "300m",
|
|
"source_selflabel": "app: mysql",
|
|
"source_portmode": "NodePort",
|
|
"source_restartpolicy": "Always",
|
|
"source_apiport": 3306,
|
|
"source_insideport": 3306,
|
|
"source_outsideport": 30061,
|
|
"source_mountpath": "/data/mysql"
|
|
}
|
|
# 处理Kubernetes操作
|
|
handle_k8s_operations(frontend_params)
|