本文介绍如何安装Alibaba Cloud ACK SDK for Go和如何快速使用Alibaba Cloud ACK SDK for Go完成常见操作,如创建集群、集群扩容以及添加已有ECS实例至Kubernetes集群。

前提条件

在安装和使用Alibaba Cloud ACK SDK for Go前,确保您已经完成以下操作:
  • 安装Golang的环境。

    阿里云Go SDK支持Go 1.7及以上版本。

  • 注册阿里云账号并生成访问密钥(AccessKey)。

    详情参见获取AccessKey

源码地址

请参见以下信息获取源码。

Go alibaba-cloud-sdk-go README.md

安装Alibaba Cloud ACK SDK for Go

您可以通过以下方式安装阿里云Go SDK:
  • 使用Glide(推荐)

    执行以下命令,安装阿里云Go SDK:

    glide get github.com/aliyun/alibaba-cloud-sdk-go
  • 使用govendor

    执行以下命令,安装阿里云Go SDK:
    go get -u github.com/aliyun/alibaba-cloud-sdk-go/sdk

示例

  • 创建集群

    以下示例指定master节点数为3、worker节点数为3,用于创建一个的新的Kubernetes集群实例。有关更多参数详情,请参见创建Kubernetes专有版集群

    package main
    
    import (
        "fmt"
        "github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    )
    
    func main() {
        // 创建并初始化client实例。
        // 更多方法请见 https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-CN.md。
        client,err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
        if err != nil {
            // Handle exceptions
            fmt.Println("err")
            panic(err)
        }
        // 创建请求。
        request := cs.CreateCreateClusterRequest()
        // 设置创建集群参数。
        // 更多参数细节请见 https://help.aliyun.com/document_detail/87525.html。
        request.FormParams = map[string]string{
            "cluster_type":"Kubernetes",
            "name":"my-test-Kubernetes-cluster",
            "region_id":"cn-beijing",
            "disable_rollback":"true",
            "timeout_mins":"60",
            "kubernetes_version":"1.12.6-aliyun.1",
            "snat_entry":"true",
            "endpoint_public_access":"false",
            "cloud_monitor_flags":"false",
            "node_cidr_mask":"25",
            "proxy_mode":"iptables",
            "tags":`[]`,
            "addons": `[{"name": "flannel"},{"name": "aliyun-log-controller","config": "{\"sls_project_name\":\"k8s-log-c64f6eab6a1764d3dbee3dc2b9e41****\"}"},{"name": "nginx-ingress-controller", "config": "{\"IngressSlbNetworkType\":\"internet\"}"}]`,
            "node_port_range":"30000-32767",
            "login_password":"test****",
            "cpu_policy":"none",
            "master_count":"3",
            "master_vswitch_ids":`["vsw-2ze48rkq464rsdts****","vsw-2ze48rkq464rsdts1****","vsw-2ze48rkq464rsdts1****"]`,
            "master_instance_types":`["ecs.sn1.medium","ecs.sn1.medium","ecs.sn1.medium"]`,
            "master_system_disk_category":"cloud_efficiency",
            "master_system_disk_size":"40",
            "worker_instance_types":`["ecs.sn2.3xlarge"]`,
            "num_of_nodes":"3",
            "worker_system_disk_category":"cloud_efficiency",
            "worker_system_disk_size":"120",
            "vpcid":"vpc-2zegvl5etah5requ0****",
            "worker_vswitch_ids":`["vsw-2ze48rkq464rsdts****"]`,
            "container_cidr":"172.20.XX.XX/16",
            "service_cidr":"172.21.XX.XX/20",
            "worker_data_disks": `[{"category": "cloud_ssd", "size": 500}]`,
            "master_data_disks": `[{"category": "cloud_ssd", "size": 500}]`,
            "taints":`[{"key": "special", "value": "true", "effect": "NoSchedule"}]`,
        }
    
        // 创建请求。
        response,err := client.CreateCluster(request)
        if err != nil {
            panic(err)
        }
        // 判断是否成功。
        if response.IsSuccess() {
            fmt.Printf("%s | Failed reate cluster, response is %s",response.RequestId, response.GetHttpContentString())
        } else {
            fmt.Printf("%s | Create cluster successfully",response.RequestId)
        }
    }
    	  

  • 集群扩容

    以下示例将在集群ID为cf68eabc的集群中扩容一台类型为ecs.c5.xlarge的节点。有关更多参数详情,请参见扩容集群

    package main
    
    import (
        "fmt"
        "github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    )
    
    func main() {
        // 创建并初始化client实例。
        client,err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
        if err != nil {
            // Handle exceptions
            fmt.Println("err")
            panic(err)
        }
        // 创建集群扩容请求,并设置参数。
        request := cs.CreateScaleClusterRequest()
        // 更多参数细节请见 https://help.aliyun.com/document_detail/123927.html。
        request.PathParams = map[string]string{
            "ClusterId": "cf68eabc",
        }
        request.FormParams = map[string]string{
            "key_pair":"common", // KeyPair
            "vswitch_ids":`["vsw-uf684tfrpwup8gcsw****"]`,
            "worker_instance_types":`["ecs.c5.xlarge"]`,
            "worker_system_disk_category":"cloud_efficiency",
            "worker_system_disk_size":"120",
            "worker_data_disk":"false",
            "worker_data_disks": `[{"category": "cloud_ssd", "size": 500}]`,
            "count":"1",
        }
    
        // 创建请求。
        response,err := client.ScaleCluster(request)
        if err != nil {
            panic(err)
        }
        // 判断是否成功。
        if response.IsSuccess() {
            fmt.Printf("%s | Failed to scale cluster, response is %s",response.RequestId, response.GetHttpContentString())
        } else {
            fmt.Printf("%s | Successfully scale cluster",response.RequestId)
        }
    }
    	  
  • 添加已有ECS实例至Kubernetes集群

    以下示例将实例ID为i-xxxx和i-yyyy的ECS添加到集群cf68eabc中。有关更多参数详情,请参见添加已有实例到集群

    package main
    
    import (
        "fmt"
        "github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    )
    
    func main() {
        // 创建并初始化client实例。
        client,err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
        if err != nil {
            // Handle exceptions
            fmt.Println("err")
            panic(err)
        }
        // 创建请求,并设置参数。
        request := cs.CreateAttachInstancesRequest()
        // 更多参数细节请见 https://help.aliyun.com/document_detail/86807.html。
        request.PathParams = map[string]string{
            "ClusterId": "cf68eabc",
        }
        request.FormParams = map[string]string{
            "password": "Hello1234",
            "instances": `["i-xxxx","i-yyyy"]`,
        }
    
        // 创建请求。
        response,err := client.AttachInstances(request)
        if err != nil {
            panic(err)
        }
        // 判断是否成功。
        if response.IsSuccess() {
            fmt.Printf("Failed to attach intstance to cluster, response is %s", response.GetHttpContentString())
        } else {
            fmt.Printf("Successfully attach intstance to cluster",)
        }
    }
    	  
  • 查询节点池列表
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    	"time"
    )
    
    
    type SpotPrice struct {
    	InstanceType string `json:"instance_type"`
    	PriceLimit   string `json:"price_limit"`
    }
    
    type NodePoolInfo struct {
    	NodePoolId      string    `json:"nodepool_id"`
    	RegionId        string    `json:"region_id"`
    	Name            string    `json:"name"`
    	Created         time.Time `json:"created"`
    	Updated         time.Time `json:"updated"`
    	IsDefault       bool      `json:"is_default"`
    	NodePoolType    string    `json:"type"`
    	ResourceGroupId string    `json:"resource_group_id"`
    }
    
    type NodePoolDataDisk struct {
    	Category             string `json:"category"`
    	KMSKeyId             string `json:"kms_key_id"`
    	Encrypted            string `json:"encrypted"` // true|false
    	Device               string `json:"device"`    //  could be /dev/xvd[a-z]. If not specification, will use default value.
    	Size                 int    `json:"size"`
    	DiskName             string `json:"name"`
    	AutoSnapshotPolicyId string `json:"auto_snapshot_policy_id"`
    	PerformanceLevel     string `json:"performance_Level"`
    }
    
    type Effect string
    
    var (
    	TaintNoExecute        = "NoExecute"
    	TaintNoSchedule       = "NoSchedule"
    	TaintPreferNoSchedule = "PreferNoSchedule"
    )
    
    type Tag struct {
    	Key   string `json:"key"`
    	Value string `json:"value"`
    }
    
    //taint
    type Taint struct {
    	Key    string `json:"key"`
    	Value  string `json:"value"`
    	Effect Effect `json:"effect"`
    }
    
    type Label struct {
    	Key   string `json:"key"`
    	Value string `json:"value"`
    }
    
    type ScalingGroup struct {
    	VpcId                      string             `json:"vpc_id"`
    	VswitchIds                 []string           `json:"vswitch_ids"`
    	InstanceTypes              []string           `json:"instance_types"`
    	LoginPassword              string             `json:"login_password"`
    	KeyPair                    string             `json:"key_pair"`
    	SecurityGroupId            string             `json:"security_group_id"`
    	SystemDiskCategory         string             `json:"system_disk_category"`
    	SystemDiskSize             int64              `json:"system_disk_size"`
    	SystemDiskPerformanceLevel string             `json:"system_disk_performance_level"`
    	DataDisks                  []NodePoolDataDisk `json:"data_disks"` //支持多个数据盘
    	Tags                       []Tag              `json:"tags"`
    	ImageId                    string             `json:"image_id"`
    	Platform                   string             `json:"platform"`
    	// 支持包年包月
    	InstanceChargeType string `json:"instance_charge_type"`
    	Period             int    `json:"period"`
    	PeriodUnit         string `json:"period_unit"`
    	AutoRenew          bool   `json:"auto_renew"`
    	AutoRenewPeriod    int    `json:"auto_renew_period"`
    	// Spot实例
    	SpotStrategy   string      `json:"spot_strategy"`
    	SpotPriceLimit []SpotPrice `json:"spot_price_limit"`
    
    	RdsInstances   []string `json:"rds_instances"`
    	ScalingPolicy  string   `json:"scaling_policy"`
    	ScalingGroupId string   `json:"scaling_group_id"`
    }
    
    type AutoScaling struct {
    	Enable       bool   `json:"enable"`
    	MaxInstances int64  `json:"max_instances"`
    	MinInstances int64  `json:"min_instances"`
    	Type         string `json:"type"`
    	// eip
    	IsBindEip *bool `json:"is_bond_eip"`
    	// value: PayByBandwidth / PayByTraffic
    	EipInternetChargeType string `json:"eip_internet_charge_type"`
    	// default 5
    	EipBandWidth int64 `json:"eip_bandwidth"`
    }
    
    type KubernetesConfig struct {
    	NodeNameMode string  `json:"node_name_mode"`
    	Taints       []Taint `json:"taints"`
    	Labels       []Label `json:"labels"`
    	CpuPolicy    string  `json:"cpu_policy"`
    	UserData     string  `json:"user_data"`
    
    	Runtime           string `json:"runtime,omitempty"`
    	RuntimeVersion    string `json:"runtime_version"`
    	CmsEnabled        bool   `json:"cms_enabled"`
    	OverwriteHostname bool   `json:"overwrite_hostname"`
    }
    
    // 加密计算节点池
    type TEEConfig struct {
    	TEEType   string `json:"tee_type"`
    	TEEEnable bool   `json:"tee_enable"`
    }
    
    // 托管节点池配置
    type Management struct {
    	Enable      bool        `json:"enable"`
    	AutoRepair  bool        `json:"auto_repair"`
    	UpgradeConf UpgradeConf `json:"upgrade_config"`
    }
    
    type UpgradeConf struct {
    	AutoUpgrade       bool  `json:"auto_upgrade"`
    	Surge             int64 `json:"surge"`
    	SurgePercentage   int64 `json:"surge_percentage,omitempty"`
    	MaxUnavailable    int64 `json:"max_unavailable"`
    	KeepSurgeOnFailed bool  `json:"keep_surge_on_failed"`
    }
    
    type CreateNodePoolRequest struct {
    	RegionId         string `json:"region_id"`
    	Count            int64  `json:"count"`
    	NodePoolInfo     `json:"nodepool_info"`
    	ScalingGroup     `json:"scaling_group"`
    	KubernetesConfig `json:"kubernetes_config"`
    	AutoScaling      `json:"auto_scaling"`
    	TEEConfig        `json:"tee_config"`
    	Management       `json:"management"`
    }
    
    type BasicNodePool struct {
    	NodePoolInfo   `json:"nodepool_info"`
    	NodePoolStatus `json:"status"`
    }
    
    type NodePoolStatus struct {
    	TotalNodes   int `json:"total_nodes"`
    	OfflineNodes int `json:"offline_nodes"`
    	ServingNodes int `json:"serving_nodes"`
    	//DesiredNodes int  `json:"desired_nodes"`
    	RemovingNodes int    `json:"removing_nodes"`
    	FailedNodes   int    `json:"failed_nodes"`
    	InitialNodes  int    `json:"initial_nodes"`
    	HealthyNodes  int    `json:"healthy_nodes"`
    	State         string `json:"state"`
    }
    
    type NodePoolDetail struct {
    	BasicNodePool
    	KubernetesConfig `json:"kubernetes_config"`
    	ScalingGroup     `json:"scaling_group"`
    	AutoScaling      `json:"auto_scaling"`
    	TEEConfig        `json:"tee_config"`
    	Management       `json:"management"`
    }
    
    type NodePools struct {
    	NodePools []NodePoolDetail `json:"nodepools"`
    }
    
    func main() {
    	// 创建并初始化Client实例。
    	client, err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
    	if err != nil {
    		// Handle exceptions
    		fmt.Printf("err")
    		panic(err)
    	}
    	// 创建请求,并设置参数。
    	request := cs.CreateDescribeClusterNodePoolsRequest()
    	request.ClusterId = "your_cluster_id"
    
    	// 创建请求。
    	response, err := client.DescribeClusterNodePools(request)
    	if err != nil {
    		panic(err)
    	}
    	// 判断是否成功。
    	if response.IsSuccess() {
    
    		nodePools := &NodePools{}
    		err := json.Unmarshal(response.GetHttpContentBytes(), nodePools)
    		if err != nil {
    			panic(err)
    		}
    
    		fmt.Printf("the node pool list: %++v", nodePools)
    	} else {
    		fmt.Printf("Failed to get node pool list")
    	}
    
    }
    	  
  • 查询节点池详情
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    	"time"
    )
    
    type SpotPrice struct {
    	InstanceType string `json:"instance_type"`
    	PriceLimit   string `json:"price_limit"`
    }
    
    type NodePoolInfo struct {
    	NodePoolId      string    `json:"nodepool_id"`
    	RegionId        string    `json:"region_id"`
    	Name            string    `json:"name"`
    	Created         time.Time `json:"created"`
    	Updated         time.Time `json:"updated"`
    	IsDefault       bool      `json:"is_default"`
    	NodePoolType    string    `json:"type"`
    	ResourceGroupId string    `json:"resource_group_id"`
    }
    
    type NodePoolDataDisk struct {
    	Category             string `json:"category"`
    	KMSKeyId             string `json:"kms_key_id"`
    	Encrypted            string `json:"encrypted"` // true|false
    	Device               string `json:"device"`    //  could be /dev/xvd[a-z]. If not specification, will use default value.
    	Size                 int    `json:"size"`
    	DiskName             string `json:"name"`
    	AutoSnapshotPolicyId string `json:"auto_snapshot_policy_id"`
    	PerformanceLevel     string `json:"performance_Level"`
    }
    
    type Effect string
    
    var (
    	TaintNoExecute        = "NoExecute"
    	TaintNoSchedule       = "NoSchedule"
    	TaintPreferNoSchedule = "PreferNoSchedule"
    )
    
    type Tag struct {
    	Key   string `json:"key"`
    	Value string `json:"value"`
    }
    
    //taint
    type Taint struct {
    	Key    string `json:"key"`
    	Value  string `json:"value"`
    	Effect Effect `json:"effect"`
    }
    
    type Label struct {
    	Key   string `json:"key"`
    	Value string `json:"value"`
    }
    
    type ScalingGroup struct {
    	VpcId                      string             `json:"vpc_id"`
    	VswitchIds                 []string           `json:"vswitch_ids"`
    	InstanceTypes              []string           `json:"instance_types"`
    	LoginPassword              string             `json:"login_password"`
    	KeyPair                    string             `json:"key_pair"`
    	SecurityGroupId            string             `json:"security_group_id"`
    	SystemDiskCategory         string             `json:"system_disk_category"`
    	SystemDiskSize             int64              `json:"system_disk_size"`
    	SystemDiskPerformanceLevel string             `json:"system_disk_performance_level"`
    	DataDisks                  []NodePoolDataDisk `json:"data_disks"` //支持多个数据盘
    	Tags                       []Tag              `json:"tags"`
    	ImageId                    string             `json:"image_id"`
    	Platform                   string             `json:"platform"`
    	// 支持包年包月
    	InstanceChargeType string `json:"instance_charge_type"`
    	Period             int    `json:"period"`
    	PeriodUnit         string `json:"period_unit"`
    	AutoRenew          bool   `json:"auto_renew"`
    	AutoRenewPeriod    int    `json:"auto_renew_period"`
    	// spot实例
    	SpotStrategy   string      `json:"spot_strategy"`
    	SpotPriceLimit []SpotPrice `json:"spot_price_limit"`
    
    	RdsInstances   []string `json:"rds_instances"`
    	ScalingPolicy  string   `json:"scaling_policy"`
    	ScalingGroupId string   `json:"scaling_group_id"`
    }
    
    type AutoScaling struct {
    	Enable       bool   `json:"enable"`
    	MaxInstances int64  `json:"max_instances"`
    	MinInstances int64  `json:"min_instances"`
    	Type         string `json:"type"`
    	// eip
    	IsBindEip *bool `json:"is_bond_eip"`
    	// value: PayByBandwidth / PayByTraffic
    	EipInternetChargeType string `json:"eip_internet_charge_type"`
    	// default 5
    	EipBandWidth int64 `json:"eip_bandwidth"`
    }
    
    type KubernetesConfig struct {
    	NodeNameMode string  `json:"node_name_mode"`
    	Taints       []Taint `json:"taints"`
    	Labels       []Label `json:"labels"`
    	CpuPolicy    string  `json:"cpu_policy"`
    	UserData     string  `json:"user_data"`
    
    	Runtime           string `json:"runtime,omitempty"`
    	RuntimeVersion    string `json:"runtime_version"`
    	CmsEnabled        bool   `json:"cms_enabled"`
    	OverwriteHostname bool   `json:"overwrite_hostname"`
    }
    
    // 加密计算节点池
    type TEEConfig struct {
    	TEEType   string `json:"tee_type"`
    	TEEEnable bool   `json:"tee_enable"`
    }
    
    // 托管节点池配置
    type Management struct {
    	Enable      bool        `json:"enable"`
    	AutoRepair  bool        `json:"auto_repair"`
    	UpgradeConf UpgradeConf `json:"upgrade_config"`
    }
    
    type UpgradeConf struct {
    	AutoUpgrade       bool  `json:"auto_upgrade"`
    	Surge             int64 `json:"surge"`
    	SurgePercentage   int64 `json:"surge_percentage,omitempty"`
    	MaxUnavailable    int64 `json:"max_unavailable"`
    	KeepSurgeOnFailed bool  `json:"keep_surge_on_failed"`
    }
    
    type CreateNodePoolRequest struct {
    	RegionId         string `json:"region_id"`
    	Count            int64  `json:"count"`
    	NodePoolInfo     `json:"nodepool_info"`
    	ScalingGroup     `json:"scaling_group"`
    	KubernetesConfig `json:"kubernetes_config"`
    	AutoScaling      `json:"auto_scaling"`
    	TEEConfig        `json:"tee_config"`
    	Management       `json:"management"`
    }
    
    type BasicNodePool struct {
    	NodePoolInfo   `json:"nodepool_info"`
    	NodePoolStatus `json:"status"`
    }
    
    type NodePoolStatus struct {
    	TotalNodes   int `json:"total_nodes"`
    	OfflineNodes int `json:"offline_nodes"`
    	ServingNodes int `json:"serving_nodes"`
    	//DesiredNodes int  `json:"desired_nodes"`
    	RemovingNodes int    `json:"removing_nodes"`
    	FailedNodes   int    `json:"failed_nodes"`
    	InitialNodes  int    `json:"initial_nodes"`
    	HealthyNodes  int    `json:"healthy_nodes"`
    	State         string `json:"state"`
    }
    
    type NodePoolDetail struct {
    	BasicNodePool
    	KubernetesConfig `json:"kubernetes_config"`
    	ScalingGroup     `json:"scaling_group"`
    	AutoScaling      `json:"auto_scaling"`
    	TEEConfig        `json:"tee_config"`
    	Management       `json:"management"`
    }
    
    func main() {
    	// 创建并初始化Client实例。
    	client, err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
    	if err != nil {
    		// Handle exceptions
    		fmt.Printf("err")
    		panic(err)
    	}
    	// 创建请求,并设置参数。
    	request := cs.CreateDescribeClusterNodePoolDetailRequest()
    	request.ClusterId = "your_cluster_id"
    	request.NodepoolId = "your_nodepool_id"
    
    	// 创建请求。
    	response, err := client.DescribeClusterNodePoolDetail(request)
    	if err != nil {
    		panic(err)
    	}
    	// 判断是否成功。
    	if response.IsSuccess() {
    
    		nodePool := &NodePoolDetail{}
    		err := json.Unmarshal(response.GetHttpContentBytes(), nodePool)
    		if err != nil {
    			panic(err)
    		}
    
    		fmt.Printf("the node pool detail: %++v", nodePool)
    	} else {
    		fmt.Printf("Failed to get node pool detail")
    	}
    
    }
    	  
  • 查询节点池下所有节点列表
    package main
    
    import (
    	"fmt"
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    	"strconv"
    )
    
    func main() {
    	// 创建并初始化client实例。
    	client, err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
    	if err != nil {
    		// Handle exceptions
    		fmt.Printf("err")
    		panic(err)
    	}
    	results := make([]cs.Node, 0)
    	// 创建请求,并设置参数。
    	request := cs.CreateDescribeClusterNodesRequest()
    	request.ClusterId = "your_cluster_id"
    	request.NodepoolId = "your_nodepool_id"
    	request.PageSize = "50"
    
    	for {
    		fmt.Println("Describe nodepool node list")
    		r, err := client.DescribeClusterNodes(request)
    		if err != nil {
    			panic(err)
    		}
    
    		if r.IsSuccess() {
    			results = append(results, r.Nodes...)
    			if r.Page.PageNumber*r.Page.PageSize >= r.Page.TotalCount {
    				break
    			}
    
    			request.PageSize = strconv.Itoa(r.Page.PageSize)
    			request.PageNumber = strconv.Itoa(r.Page.PageNumber + 1)
    		} else {
    			fmt.Printf("Failed to describe nodepool node")
    			break
    		}
    	}
    
    	fmt.Printf("Total nodes: %++v of nodepool %s", results, request.NodepoolId)
    
    }
    	  
  • 移除节点
    package main
    
    import (
    	"context"
    	"encoding/json"
    	"fmt"
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/cs"
    	"time"
    )
    
    type RemoveNodeResponse struct {
    	TaskId string `json:"task_id"`
    }
    
    func main() {
    	// 创建并初始化client实例。
    	client, err := cs.NewClientWithAccessKey("your_region", "your_access_key_id", "your_access_key_secret")
    	if err != nil {
    		// Handle exceptions
    		fmt.Printf("err")
    		panic(err)
    	}
    	// 创建请求,并设置参数。
    	request := cs.CreateDeleteClusterNodesRequest()
    	request.ClusterId = "your_cluster_id"
    
    	// refer to: https://help.aliyun.com/document_detail/167591.html
    	params := map[string]interface{}{
    		"drain_node":   false,
    		"release_node": false,
    		"nodes":        []string{"cn-shenzhen.172.16.1.157"}, // node_name
    	}
    
    	body, _ := json.Marshal(params)
    	request.Headers["Content-Type"] = "application/json"
    	request.Content = body
    
    	// 创建请求。
    	response, err := client.DeleteClusterNodes(request)
    	if err != nil {
    		panic(err)
    	}
    	// 判断是否成功。
    	if response.IsSuccess() {
    		resp := &RemoveNodeResponse{}
    		err := json.Unmarshal(response.GetHttpContentBytes(), resp)
    		if err != nil {
    			panic(err)
    		}
    
    		fmt.Printf("start to remove nodes by task: %++v", resp)
    		taskReq := cs.CreateDescribeTaskInfoRequest()
    		taskReq.TaskId = resp.TaskId
    
    		// wait for task finish
    		ctx, cancel := context.WithTimeout(context.Background(), 15.*time.Minute)
    		defer cancel()
    		ticker := time.NewTicker(15 * time.Second)
    		defer ticker.Stop()
    		timeout := false
    		for !timeout {
    
    			r, err := client.DescribeTaskInfo(taskReq)
    			if err != nil {
    				panic(err)
    			}
    
    			fmt.Printf("Current state of task is %s", r.State)
    
    			switch r.State {
    			case "success":
    				fmt.Printf("Remove nodes success")
    				cancel()
    			case "fail":
    				fmt.Printf("Failed to remove nodes %++v", r.TaskResult)
    				cancel()
    			}
    			select {
    			case <-ctx.Done():
    				timeout = true
    			case <-ticker.C:
    			}
    		}
    
    	} else {
    		fmt.Printf("Failed to remove nodes")
    	}
    
    }