|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | + |
| 3 | +import time |
| 4 | +from enum import Enum |
| 5 | +from pprint import pprint |
| 6 | + |
| 7 | +from volcenginesdkvke import (AutoScalingForUpdateNodePoolConfigInput, |
| 8 | + ClusterConfigForCreateClusterInput, |
| 9 | + CreateAddonRequest, CreateClusterRequest, |
| 10 | + CreateNodePoolRequest, |
| 11 | + FilterForListClustersInput, |
| 12 | + FilterForListNodePoolsInput, |
| 13 | + FilterForListNodesInput, |
| 14 | + FlannelConfigForCreateClusterInput, |
| 15 | + ListClustersRequest, ListNodePoolsRequest, |
| 16 | + ListNodesRequest, LoginForCreateNodePoolInput, |
| 17 | + NodeConfigForCreateNodePoolInput, |
| 18 | + PodsConfigForCreateClusterInput, |
| 19 | + SecurityForCreateNodePoolInput, |
| 20 | + ServicesConfigForCreateClusterInput, |
| 21 | + SystemVolumeForCreateNodePoolInput, |
| 22 | + UpdateNodePoolConfigRequest, |
| 23 | + VpcCniConfigForCreateClusterInput) |
| 24 | + |
| 25 | + |
| 26 | +class NetworkMode(Enum): |
| 27 | + |
| 28 | + Flannel = "Flannel" |
| 29 | + VpcCniShared = "VpcCniShared" |
| 30 | + |
| 31 | + |
| 32 | +class VKEOption: |
| 33 | + """包含搭建最基本的VKE服务的选项""" |
| 34 | + |
| 35 | + def __init__( |
| 36 | + self, |
| 37 | + cluster_name, |
| 38 | + network_mode, |
| 39 | + node_pool_name, |
| 40 | + instance_type, |
| 41 | + password, |
| 42 | + subnet_ids, |
| 43 | + service_cidrs, |
| 44 | + pod_cidrs=None, |
| 45 | + api_server_public_access_enabled=False, |
| 46 | + auto_scaling=False, |
| 47 | + ): |
| 48 | + |
| 49 | + self.cluster_name = cluster_name |
| 50 | + self.network_mode = network_mode |
| 51 | + self.node_pool_name = node_pool_name |
| 52 | + self.instance_type = instance_type |
| 53 | + self.password = password |
| 54 | + self.subnet_ids = subnet_ids |
| 55 | + self.service_cidrs = service_cidrs |
| 56 | + self.pod_cidrs = pod_cidrs |
| 57 | + self.api_server_public_access_enabled = api_server_public_access_enabled |
| 58 | + self.auto_scaling = auto_scaling |
| 59 | + |
| 60 | + |
| 61 | +def create_pods_config(opt): |
| 62 | + """根据用户提供的集群NetworkMode类型,创建PodConfig""" |
| 63 | + network_mode = opt.network_mode |
| 64 | + if network_mode == NetworkMode.Flannel.value: |
| 65 | + pod_config = PodsConfigForCreateClusterInput( |
| 66 | + pod_network_mode=NetworkMode.Flannel.value, |
| 67 | + flannel_config=FlannelConfigForCreateClusterInput( |
| 68 | + pod_cidrs=opt.pod_cidrs, |
| 69 | + ), |
| 70 | + ) |
| 71 | + elif network_mode == NetworkMode.VpcCniShared.value: |
| 72 | + pod_config = PodsConfigForCreateClusterInput( |
| 73 | + pod_network_mode=NetworkMode.VpcCniShared.value, |
| 74 | + vpc_cni_config=VpcCniConfigForCreateClusterInput( |
| 75 | + subnet_ids=opt.subnet_ids, |
| 76 | + ), |
| 77 | + ) |
| 78 | + else: |
| 79 | + raise ValueError( |
| 80 | + "Network mode: {network_mode} is not accepted. Please choose from: 'Flannel' and 'VpcCniShared'.".format( |
| 81 | + network_mode=network_mode |
| 82 | + ) |
| 83 | + ) |
| 84 | + return pod_config |
| 85 | + |
| 86 | + |
| 87 | +def create_cluster(vke_api, name, cluster_config, pods_config, services_config): |
| 88 | + """创建VKE集群""" |
| 89 | + req = CreateClusterRequest( |
| 90 | + cluster_config=cluster_config, |
| 91 | + name=name, |
| 92 | + pods_config=pods_config, |
| 93 | + services_config=services_config, |
| 94 | + ) |
| 95 | + return vke_api.create_cluster(req) |
| 96 | + |
| 97 | + |
| 98 | +def get_cluster(vke_api, cluster_id): |
| 99 | + """获取指定ID的集群信息""" |
| 100 | + req = ListClustersRequest(filter=FilterForListClustersInput(ids=[cluster_id])) |
| 101 | + return vke_api.list_clusters(req) |
| 102 | + |
| 103 | + |
| 104 | +def create_node_pool( |
| 105 | + vke_api, cluster_id, node_pool_name, instance_type, password, subnet_ids |
| 106 | +): |
| 107 | + """创建节点池""" |
| 108 | + node_config = NodeConfigForCreateNodePoolInput( |
| 109 | + instance_type_ids=[instance_type], |
| 110 | + security=SecurityForCreateNodePoolInput( |
| 111 | + login=LoginForCreateNodePoolInput(password=password), |
| 112 | + ), |
| 113 | + subnet_ids=subnet_ids, |
| 114 | + system_volume=SystemVolumeForCreateNodePoolInput(size=40, type="ESSD_PL0"), |
| 115 | + ) |
| 116 | + req = CreateNodePoolRequest( |
| 117 | + cluster_id=cluster_id, |
| 118 | + name=node_pool_name, |
| 119 | + node_config=node_config, |
| 120 | + ) |
| 121 | + return vke_api.create_node_pool(req) |
| 122 | + |
| 123 | + |
| 124 | +def get_node_pool(vke_api, node_pool_id): |
| 125 | + """获取指定ID的节点池信息""" |
| 126 | + req = ListNodePoolsRequest(filter=FilterForListNodePoolsInput(ids=[node_pool_id])) |
| 127 | + return vke_api.list_node_pools(req) |
| 128 | + |
| 129 | + |
| 130 | +def update_node_pool(vke_api, cluster_id, node_pool_id, auto_scaling): |
| 131 | + """更新节点池节点数量""" |
| 132 | + replicas = 1 |
| 133 | + if auto_scaling: |
| 134 | + replicas = 0 |
| 135 | + req = UpdateNodePoolConfigRequest( |
| 136 | + cluster_id=cluster_id, |
| 137 | + id=node_pool_id, |
| 138 | + auto_scaling=AutoScalingForUpdateNodePoolConfigInput( |
| 139 | + enabled=auto_scaling, |
| 140 | + desired_replicas=replicas, |
| 141 | + ), |
| 142 | + ) |
| 143 | + return vke_api.update_node_pool_config(req) |
| 144 | + |
| 145 | + |
| 146 | +def list_nodes(vke_api, node_pool_id): |
| 147 | + """获取指定ID的节点池的节点信息""" |
| 148 | + req = ListNodesRequest(filter=FilterForListNodesInput(node_pool_ids=[node_pool_id])) |
| 149 | + return vke_api.list_nodes(req) |
| 150 | + |
| 151 | + |
| 152 | +def install_addon(vke_api, cluster_id): |
| 153 | + """安装插件""" |
| 154 | + # 在每个addon安装之后,sleep 5秒 |
| 155 | + _interval = 5 |
| 156 | + metrics_server_req = CreateAddonRequest( |
| 157 | + cluster_id=cluster_id, name="metrics-server" |
| 158 | + ) |
| 159 | + metrics_server_resp = vke_api.create_addon(metrics_server_req) |
| 160 | + pprint(metrics_server_resp) |
| 161 | + |
| 162 | + time.sleep(_interval) |
| 163 | + |
| 164 | + coredns_req = CreateAddonRequest(cluster_id=cluster_id, name="core-dns") |
| 165 | + coredns_resp = vke_api.create_addon(coredns_req) |
| 166 | + pprint(coredns_resp) |
| 167 | + |
| 168 | + time.sleep(_interval) |
| 169 | + |
| 170 | + cluster_autoscaler_req = CreateAddonRequest( |
| 171 | + cluster_id=cluster_id, |
| 172 | + name="cluster-autoscaler", |
| 173 | + config='{"Expander":"random"}', |
| 174 | + ) |
| 175 | + cluster_autoscaler_resp = vke_api.create_addon(cluster_autoscaler_req) |
| 176 | + pprint(cluster_autoscaler_resp) |
| 177 | + |
| 178 | + |
| 179 | +def create_vke(vke_api, opt): |
| 180 | + """创建VKE服务""" |
| 181 | + pods_config = create_pods_config(opt) |
| 182 | + cluster_config = ClusterConfigForCreateClusterInput( |
| 183 | + api_server_public_access_enabled=opt.api_server_public_access_enabled, |
| 184 | + subnet_ids=opt.subnet_ids, |
| 185 | + ) |
| 186 | + services_config = ServicesConfigForCreateClusterInput( |
| 187 | + service_cidrsv4=opt.service_cidrs |
| 188 | + ) |
| 189 | + |
| 190 | + # 1. 创建集群 |
| 191 | + create_cluster_resp = create_cluster( |
| 192 | + vke_api, opt.cluster_name, cluster_config, pods_config, services_config |
| 193 | + ) |
| 194 | + cluster_id = create_cluster_resp.to_dict().get("id") |
| 195 | + pprint("cluster id: {}".format(cluster_id)) |
| 196 | + |
| 197 | + # 2. 查询集群状态 |
| 198 | + while True: |
| 199 | + get_cluser_resp = get_cluster(vke_api, cluster_id) |
| 200 | + results = get_cluser_resp.to_dict().get("items") |
| 201 | + if len(results) > 0 and results[0].get("status", {}).get("phase") == "Running": |
| 202 | + break |
| 203 | + time.sleep(10) |
| 204 | + |
| 205 | + # 3. 创建节点池 |
| 206 | + create_node_pool_resp = create_node_pool( |
| 207 | + vke_api, |
| 208 | + cluster_id, |
| 209 | + opt.node_pool_name, |
| 210 | + opt.instance_type, |
| 211 | + opt.password, |
| 212 | + opt.subnet_ids, |
| 213 | + ) |
| 214 | + node_pool_id = create_node_pool_resp.to_dict().get("id") |
| 215 | + pprint("node pool id: {}".format(node_pool_id)) |
| 216 | + |
| 217 | + # 4. 查看节点池 |
| 218 | + while True: |
| 219 | + get_node_pool_resp = get_node_pool(vke_api, node_pool_id) |
| 220 | + results = get_node_pool_resp.to_dict().get("items") |
| 221 | + if len(results) > 0 and results[0].get("status", {}).get("phase") == "Running": |
| 222 | + break |
| 223 | + time.sleep(10) |
| 224 | + pprint("node pool:") |
| 225 | + pprint(results) |
| 226 | + |
| 227 | + # 5. 查看节点列表 |
| 228 | + list_nodes_resp = list_nodes(vke_api, node_pool_id) |
| 229 | + results = list_nodes_resp.to_dict().get("items") |
| 230 | + pprint("node list:") |
| 231 | + pprint(results) |
| 232 | + |
| 233 | + # 6. 安装组件 & 设置节点池弹性策略 |
| 234 | + pprint("install addon (including cluster-autoscaler)") |
| 235 | + install_addon(vke_api, cluster_id) |
| 236 | + |
| 237 | + # 7. 修改节点数量 |
| 238 | + pprint("update node pool") |
| 239 | + update_node_pool_resp = update_node_pool( |
| 240 | + vke_api, |
| 241 | + cluster_id, |
| 242 | + node_pool_id, |
| 243 | + auto_scaling=opt.auto_scaling, |
| 244 | + ) |
| 245 | + pprint(update_node_pool_resp) |
| 246 | + |
| 247 | + # 8. 查看节点列表 |
| 248 | + pprint("check nodes count") |
| 249 | + while len(results) == 0: |
| 250 | + list_nodes_resp = list_nodes(vke_api, node_pool_id) |
| 251 | + results = list_nodes_resp.to_dict().get("items") |
| 252 | + time.sleep(10) |
| 253 | + pprint("node list:") |
| 254 | + pprint(results) |
0 commit comments