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)