Skip to content

Commit f9b177a

Browse files
authored
Merge pull request #488 from howardshaw/master
add support for create vpc-cni network cluster
2 parents 955da9a + 0e3b05d commit f9b177a

File tree

6 files changed

+341
-21
lines changed

6 files changed

+341
-21
lines changed

examples/tencentcloud-tke/main.tf

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,59 @@ resource "tencentcloud_kubernetes_cluster" "managed_cluster" {
4141
}
4242
}
4343

44+
#examples for MANAGED_CLUSTER VPC-CNI network type cluster with customized master params
45+
resource "tencentcloud_kubernetes_cluster" "managed_vpc_cni_cluster" {
46+
cluster_version = "1.14.3"
47+
vpc_id = var.vpc
48+
cluster_max_pod_num = 32
49+
cluster_name = "testvpccni"
50+
cluster_desc = "test vpc-cni cluster desc"
51+
cluster_max_service_num = 32
52+
service_cidr = "192.168.128.0/24"
53+
eni_subnet_ids = ["subnet-hmmlszs7", "subnet-4o0v4e7j"]
54+
claim_expired_seconds = 300
55+
network_type = "VPC-CNI"
56+
is_non_static_ip_mode = true
57+
cluster_extra_args {
58+
kube_apiserver = ["max-requests-inflight=450"]
59+
kube_controller_manager = ["kube-api-burst=500", "kube-api-qps=200"]
60+
kube_scheduler = ["kube-api-burst=500", "kube-api-qps=200"]
61+
}
62+
63+
worker_config {
64+
count = 2
65+
availability_zone = var.availability_zone
66+
instance_type = var.default_instance_type
67+
system_disk_type = "CLOUD_SSD"
68+
system_disk_size = 60
69+
internet_charge_type = "TRAFFIC_POSTPAID_BY_HOUR"
70+
internet_max_bandwidth_out = 100
71+
public_ip_assigned = true
72+
subnet_id = var.subnet
73+
74+
data_disk {
75+
disk_type = "CLOUD_PREMIUM"
76+
disk_size = 50
77+
}
78+
79+
enhanced_security_service = false
80+
enhanced_monitor_service = false
81+
user_data = "dGVzdA=="
82+
password = "ZZXXccvv1212"
83+
}
84+
85+
cluster_deploy_type = "MANAGED_CLUSTER"
86+
87+
tags = {
88+
"test" = "test"
89+
}
90+
91+
labels = {
92+
"test1" = "test1",
93+
"test2" = "test2",
94+
}
95+
}
96+
4497
#examples for INDEPENDENT_CLUSTER cluster
4598
resource "tencentcloud_kubernetes_cluster" "independing_cluster" {
4699
vpc_id = var.vpc

tencentcloud/data_source_tc_kubernetes_clusters.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,22 @@ LOOP:
225225
infoMap["cluster_deploy_type"] = info.DeployType
226226
infoMap["cluster_version"] = info.ClusterVersion
227227
infoMap["cluster_ipvs"] = info.Ipvs
228+
infoMap["cluster_as_enabled"] = info.AsEnabled
229+
infoMap["node_name_type"] = info.NodeNameType
230+
infoMap["cluster_extra_args"] = info.ExtraArgs
231+
infoMap["network_type"] = info.NetworkType
232+
infoMap["is_non_static_ip_mode"] = info.IsNonStaticIpMode
233+
infoMap["deletion_protection"] = info.DeletionProtection
234+
infoMap["kube_proxy_mode"] = info.KubeProxyMode
228235
infoMap["vpc_id"] = info.VpcId
229236
infoMap["project_id"] = info.ProjectId
230237
infoMap["cluster_cidr"] = info.ClusterCidr
231238
infoMap["ignore_cluster_cidr_conflict"] = info.IgnoreClusterCidrConflict
232-
infoMap["cluster_max_pod_num"] = info.MaxClusterServiceNum
239+
infoMap["cluster_max_pod_num"] = info.MaxNodePodNum
233240
infoMap["cluster_max_service_num"] = info.MaxClusterServiceNum
241+
infoMap["service_cidr"] = info.ServiceCIDR
242+
infoMap["eni_subnet_ids"] = info.EniSubnetIds
243+
infoMap["claim_expired_seconds"] = info.ClaimExpiredSeconds
234244
infoMap["cluster_node_num"] = info.ClusterNodeNum
235245
infoMap["tags"] = info.Tags
236246

tencentcloud/extension_tke.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,23 @@ const (
6161
TkeInternetStatusDeletedFailed = "DeletedFailed"
6262
TkeInternetStatusNotfound = "NotFound"
6363
)
64+
65+
const (
66+
TKE_CLUSTER_NETWORK_TYPE_GR = "GR"
67+
TKE_CLUSTER_NETWORK_TYPE_VPC_CNI = "VPC-CNI"
68+
)
69+
70+
var TKE_CLUSTER_NETWORK_TYPE = []string{TKE_CLUSTER_NETWORK_TYPE_GR, TKE_CLUSTER_NETWORK_TYPE_VPC_CNI}
71+
72+
const (
73+
TKE_CLUSTER_NODE_NAME_TYPE_LAN_IP = "lan-ip"
74+
TKE_CLUSTER_NODE_NAME_TYPE_HOSTNAME = "hostname"
75+
)
76+
77+
var TKE_CLUSTER_NODE_NAME_TYPE = []string{TKE_CLUSTER_NODE_NAME_TYPE_LAN_IP, TKE_CLUSTER_NODE_NAME_TYPE_HOSTNAME}
78+
79+
const (
80+
TKE_CLUSTER_KUBE_PROXY_MODE_BPF = "kube-proxy-bpf"
81+
)
82+
83+
var TKE_CLUSTER_KUBE_PROXY_MODE = []string{TKE_CLUSTER_KUBE_PROXY_MODE_BPF}

tencentcloud/resource_tc_kubernetes_cluster.go

Lines changed: 207 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,82 @@ func resourceTencentCloudTkeCluster() *schema.Resource {
414414
Default: true,
415415
Description: "Indicates whether ipvs is enabled. Default is true.",
416416
},
417+
"cluster_as_enabled": {
418+
Type: schema.TypeBool,
419+
ForceNew: true,
420+
Optional: true,
421+
Default: false,
422+
Description: "Indicates whether to enable cluster node auto scaler.",
423+
},
424+
"cluster_extra_args": {
425+
Type: schema.TypeList,
426+
ForceNew: true,
427+
Optional: true,
428+
MaxItems: 1,
429+
Elem: &schema.Resource{
430+
Schema: map[string]*schema.Schema{
431+
"kube_apiserver": {
432+
Type: schema.TypeList,
433+
ForceNew: true,
434+
Optional: true,
435+
Elem: &schema.Schema{Type: schema.TypeString},
436+
Description: "The customized parameters for kube-apiserver.",
437+
},
438+
"kube_controller_manager": {
439+
Type: schema.TypeList,
440+
ForceNew: true,
441+
Optional: true,
442+
Elem: &schema.Schema{Type: schema.TypeString},
443+
Description: "The customized parameters for kube-controller-manager.",
444+
},
445+
"kube_scheduler": {
446+
Type: schema.TypeList,
447+
ForceNew: true,
448+
Optional: true,
449+
Elem: &schema.Schema{Type: schema.TypeString},
450+
Description: "The customized parameters for kube-scheduler.",
451+
},
452+
},
453+
},
454+
Description: "Customized parameters for master component,such as kube-apiserver, kube-controller-manager, kube-scheduler.",
455+
},
456+
"node_name_type": {
457+
Type: schema.TypeString,
458+
ForceNew: true,
459+
Optional: true,
460+
Default: "lan-ip",
461+
Description: "Node name type of Cluster, the available values include: 'lan-ip' and 'hostname', Default is 'lan-ip'.",
462+
ValidateFunc: validateAllowedStringValue(TKE_CLUSTER_NODE_NAME_TYPE),
463+
},
464+
"network_type": {
465+
Type: schema.TypeString,
466+
ForceNew: true,
467+
Optional: true,
468+
Default: "GR",
469+
ValidateFunc: validateAllowedStringValue(TKE_CLUSTER_NETWORK_TYPE),
470+
Description: "Cluster network type, GR or VPC-CNI. Default is GR.",
471+
},
472+
"is_non_static_ip_mode": {
473+
Type: schema.TypeBool,
474+
ForceNew: true,
475+
Optional: true,
476+
Default: false,
477+
Description: "Indicates whether static ip mode is enabled. Default is false.",
478+
},
479+
"deletion_protection": {
480+
Type: schema.TypeBool,
481+
Optional: true,
482+
Default: false,
483+
Description: "Indicates whether cluster deletion protection is enabled. Default is false.",
484+
},
485+
"kube_proxy_mode": {
486+
Type: schema.TypeString,
487+
Optional: true,
488+
Default: "",
489+
ValidateFunc: validateAllowedStringValue(TKE_CLUSTER_KUBE_PROXY_MODE),
490+
Description: "Cluster kube-proxy mode, the available values include: 'kube-proxy-bpf'. Default is not set." +
491+
"When set to kube-proxy-bpf, cluster version greater than 1.14 and with TKE-optimized kernel is required.",
492+
},
417493
"vpc_id": {
418494
Type: schema.TypeString,
419495
ForceNew: true,
@@ -456,10 +532,13 @@ func resourceTencentCloudTkeCluster() *schema.Resource {
456532
"cluster_cidr": {
457533
Type: schema.TypeString,
458534
ForceNew: true,
459-
Required: true,
535+
Optional: true,
460536
Description: "A network address block of the cluster. Different from vpc cidr and cidr of other clusters within this vpc. Must be in 10./192.168/172.[16-31] segments.",
461537
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
462538
value := v.(string)
539+
if value == "" {
540+
return
541+
}
463542
_, ipnet, err := net.ParseCIDR(value)
464543
if err != nil {
465544
errors = append(errors, fmt.Errorf("%q must contain a valid CIDR, got error parsing: %s", k, err))
@@ -473,16 +552,16 @@ func resourceTencentCloudTkeCluster() *schema.Resource {
473552
errors = append(errors, fmt.Errorf("%q must be a network segment", k))
474553
return
475554
}
476-
if !strings.HasPrefix(value, "10.") && !strings.HasPrefix(value, "192.168.") && !strings.HasPrefix(value, "172.") {
477-
errors = append(errors, fmt.Errorf("%q must in 10. | 192.168. | 172.[16-31]", k))
555+
if !strings.HasPrefix(value, "9.") && !strings.HasPrefix(value, "10.") && !strings.HasPrefix(value, "192.168.") && !strings.HasPrefix(value, "172.") {
556+
errors = append(errors, fmt.Errorf("%q must in 9. | 10. | 192.168. | 172.[16-31]", k))
478557
return
479558
}
480559

481560
if strings.HasPrefix(value, "172.") {
482561
nextNo := strings.Split(value, ".")[1]
483562
no, _ := strconv.ParseInt(nextNo, 10, 64)
484563
if no < 16 || no > 31 {
485-
errors = append(errors, fmt.Errorf("%q must in 10. | 192.168. | 172.[16-31]", k))
564+
errors = append(errors, fmt.Errorf("%q must in 9.0 | 10. | 192.168. | 172.[16-31]", k))
486565
return
487566
}
488567
}
@@ -530,6 +609,69 @@ func resourceTencentCloudTkeCluster() *schema.Resource {
530609
},
531610
Description: "The maximum number of services in the cluster. Default is 256. Must be a multiple of 16.",
532611
},
612+
"service_cidr": {
613+
Type: schema.TypeString,
614+
ForceNew: true,
615+
Optional: true,
616+
Description: "A network address block of the service. Different from vpc cidr and cidr of other clusters within this vpc. Must be in 10./192.168/172.[16-31] segments.",
617+
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
618+
value := v.(string)
619+
if value == "" {
620+
return
621+
}
622+
_, ipnet, err := net.ParseCIDR(value)
623+
if err != nil {
624+
errors = append(errors, fmt.Errorf("%q must contain a valid CIDR, got error parsing: %s", k, err))
625+
return
626+
}
627+
if ipnet == nil || value != ipnet.String() {
628+
errors = append(errors, fmt.Errorf("%q must contain a valid network CIDR, expected %q, got %q", k, ipnet, value))
629+
return
630+
}
631+
if !strings.Contains(value, "/") {
632+
errors = append(errors, fmt.Errorf("%q must be a network segment", k))
633+
return
634+
}
635+
if !strings.HasPrefix(value, "9.") && !strings.HasPrefix(value, "10.") && !strings.HasPrefix(value, "192.168.") && !strings.HasPrefix(value, "172.") {
636+
errors = append(errors, fmt.Errorf("%q must in 9. | 10. | 192.168. | 172.[16-31]", k))
637+
return
638+
}
639+
640+
if strings.HasPrefix(value, "172.") {
641+
nextNo := strings.Split(value, ".")[1]
642+
no, _ := strconv.ParseInt(nextNo, 10, 64)
643+
if no < 16 || no > 31 {
644+
errors = append(errors, fmt.Errorf("%q must in 9. | 10. | 192.168. | 172.[16-31]", k))
645+
return
646+
}
647+
}
648+
return
649+
},
650+
},
651+
"eni_subnet_ids": {
652+
Type: schema.TypeList,
653+
Optional: true,
654+
Elem: &schema.Schema{Type: schema.TypeString},
655+
Description: "Subnet Ids for cluster with VPC-CNI network mode." +
656+
" This field can only set when field `network_type` is 'VPC-CNI'." +
657+
" `eni_subnet_ids` can not empty once be set.",
658+
},
659+
"claim_expired_seconds": {
660+
Type: schema.TypeInt,
661+
Optional: true,
662+
Default: 300,
663+
Description: "Claim expired seconds to recycle ENI." +
664+
" This field can only set when field `network_type` is 'VPC-CNI'." +
665+
" `claim_expired_seconds` must greater or equal than 300 and less than 15768000.",
666+
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
667+
value := v.(int)
668+
if value < 300 || value > 15768000 {
669+
errors = append(errors, fmt.Errorf("%q must greater or equal than 300 and less than 15768000", k))
670+
return
671+
}
672+
return
673+
},
674+
},
533675
"master_config": {
534676
Type: schema.TypeList,
535677
ForceNew: true,
@@ -864,27 +1006,75 @@ func resourceTencentCloudTkeClusterCreate(d *schema.ResourceData, meta interface
8641006
basic.ClusterDescription = v.(string)
8651007
}
8661008

867-
advanced.ContainerRuntime = d.Get("container_runtime").(string)
8681009
advanced.Ipvs = d.Get("cluster_ipvs").(bool)
869-
1010+
advanced.AsEnabled = d.Get("cluster_as_enabled").(bool)
1011+
advanced.ContainerRuntime = d.Get("container_runtime").(string)
1012+
advanced.NodeNameType = d.Get("node_name_type").(string)
1013+
advanced.NetworkType = d.Get("network_type").(string)
1014+
advanced.IsNonStaticIpMode = d.Get("is_non_static_ip_mode").(bool)
1015+
advanced.DeletionProtection = d.Get("deletion_protection").(bool)
1016+
advanced.KubeProxyMode = d.Get("kube_proxy_mode").(string)
1017+
1018+
if extraArgs, ok := d.GetOk("cluster_extra_args"); ok {
1019+
extraArgList := extraArgs.([]interface{})
1020+
for index := range extraArgList {
1021+
extraArg := extraArgList[index].(map[string]interface{})
1022+
if apiserverArgs, exist := extraArg["kube_apiserver"]; exist {
1023+
args := apiserverArgs.([]interface{})
1024+
for index := range args {
1025+
advanced.ExtraArgs.KubeAPIServer = append(advanced.ExtraArgs.KubeAPIServer, args[index].(string))
1026+
}
1027+
}
1028+
if cmArgs, exist := extraArg["kube_controller_manager"]; exist {
1029+
args := cmArgs.([]interface{})
1030+
for index := range args {
1031+
advanced.ExtraArgs.KubeControllerManager = append(advanced.ExtraArgs.KubeControllerManager, args[index].(string))
1032+
}
1033+
}
1034+
if schedulerArgs, exist := extraArg["kube_scheduler"]; exist {
1035+
args := schedulerArgs.([]interface{})
1036+
for index := range args {
1037+
advanced.ExtraArgs.KubeScheduler = append(advanced.ExtraArgs.KubeScheduler, args[index].(string))
1038+
}
1039+
}
1040+
}
1041+
}
8701042
cidrSet.ClusterCidr = d.Get("cluster_cidr").(string)
8711043
cidrSet.IgnoreClusterCidrConflict = d.Get("ignore_cluster_cidr_conflict").(bool)
8721044
cidrSet.MaxClusterServiceNum = int64(d.Get("cluster_max_service_num").(int))
8731045
cidrSet.MaxNodePodNum = int64(d.Get("cluster_max_pod_num").(int))
1046+
cidrSet.ServiceCIDR = d.Get("service_cidr").(string)
1047+
cidrSet.ClaimExpiredSeconds = int64(d.Get("claim_expired_seconds").(int))
1048+
1049+
if advanced.NetworkType == TKE_CLUSTER_NETWORK_TYPE_VPC_CNI {
1050+
// VPC-CNI cluster need to set eni subnet and service cidr.
1051+
eniSubnetIdList := d.Get("eni_subnet_ids").([]interface{})
1052+
for index := range eniSubnetIdList {
1053+
subnetId := eniSubnetIdList[index].(string)
1054+
cidrSet.EniSubnetIds = append(cidrSet.EniSubnetIds, subnetId)
1055+
}
1056+
if cidrSet.ServiceCIDR == "" || len(cidrSet.EniSubnetIds) == 0 {
1057+
return fmt.Errorf("`service_cidr` must be set and `eni_subnet_ids` must be set when cluster `network_type` is VPC-CNI.")
1058+
}
1059+
} else {
1060+
// GR cluster
1061+
if cidrSet.ClusterCidr == "" {
1062+
return fmt.Errorf("`service_cidr` must be set when cluster `network_type` is GR")
1063+
}
1064+
items := strings.Split(cidrSet.ClusterCidr, "/")
1065+
if len(items) != 2 {
1066+
return fmt.Errorf("`cluster_cidr` must be network segment ")
1067+
}
8741068

875-
items := strings.Split(cidrSet.ClusterCidr, "/")
876-
if len(items) != 2 {
877-
return fmt.Errorf("`cluster_cidr` must be network segment ")
878-
}
879-
880-
bitNumber, err := strconv.ParseInt(items[1], 10, 64)
1069+
bitNumber, err := strconv.ParseInt(items[1], 10, 64)
8811070

882-
if err != nil {
883-
return fmt.Errorf("`cluster_cidr` must be network segment ")
884-
}
1071+
if err != nil {
1072+
return fmt.Errorf("`cluster_cidr` must be network segment ")
1073+
}
8851074

886-
if math.Pow(2, float64(32-bitNumber)) <= float64(cidrSet.MaxNodePodNum) {
887-
return fmt.Errorf("`cluster_cidr` Network segment range is too small, can not cover cluster_max_service_num")
1075+
if math.Pow(2, float64(32-bitNumber)) <= float64(cidrSet.MaxNodePodNum) {
1076+
return fmt.Errorf("`cluster_cidr` Network segment range is too small, can not cover cluster_max_service_num")
1077+
}
8881078
}
8891079

8901080
if masters, ok := d.GetOk("master_config"); ok {

0 commit comments

Comments
 (0)