文档首页/ 云容器实例 CCI/ SDK参考/ 使用client-go访问CCI的CRD资源Network
更新时间:2024-04-26 GMT+08:00
分享

使用client-go访问CCI的CRD资源Network

您可以前往开发体验馆Codelabs / Namespace生命周期代码示例(Go)下载相关代码,并在线调试。

初始化项目

创建项目examples.com/cci-examples。

项目依赖k8s.io/client-go、k8s.io/code-generator,以下版本可供参考

  • k8s.io/client-go@kubernetes-1.15.0、k8s.io/code-generator@kubernetes-1.15.0
  • k8s.io/client-go@kubernetes-1.16.0、k8s.io/code-generator@kubernetes-1.16.0
  • k8s.io/client-go@kubernetes-1.17.0、k8s.io/code-generator@kubernetes-1.17.0
  • k8s.io/client-go@kubernetes-1.18.0、k8s.io/code-generator@kubernetes-1.18.0
  • k8s.io/client-go@kubernetes-1.19.0、k8s.io/code-generator@kubernetes-1.19.0
  • k8s.io/client-go@kubernetes-1.20.0、k8s.io/code-generator@kubernetes-1.20.0
mkdir -p examples.com/cci-examples
cd examples.com/cci-examples/
go mod init examples.com/cci-examples
go get k8s.io/client-go@kubernetes-1.15.0
go get k8s.io/code-generator@kubernetes-1.15.0

定义CRD资源Network

创建文件夹pkg/apis/networking.cci.io/v1beta1,其中networking.cci.io为CRD资源的group,v1beta1为CRD资源版本

mkdir -p pkg/apis/networking.cci.io/v1beta1

在新建文件夹中新建以下文件:

doc.go

// +k8s:deepcopy-gen=package
// +groupName=networking.cci.io
// +groupGoName=NetworkingCCI
package v1beta1

types.go

package v1beta1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// NetworkList is a list of network resource in container.
type NetworkList struct {
	metav1.TypeMeta `json:",inline"`
	// Standard list metadata.
	// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
	// +optional
	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
	Items           []Network `json:"items" protobuf:"bytes,2,rep,name=items"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Network is a network resource in container.
type Network struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
	// Spec defines the attributes on a network
	// +optional
	Spec NetworkSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
	// Status describes the network status
	// +optional
	Status NetworkStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

// NetworkSpec describes the attributes on a network resource.
type NetworkSpec struct {
	// network type
	NetworkType string `json:"networkType,omitempty" protobuf:"bytes,5,opt,name=networkType"`
	// ID of the VPC to attach
	AttachedVPC string `json:"attachedVPC,omitempty" protobuf:"bytes,4,opt,name=attachedVPC"`
	// network ID
	NetworkID string `json:"networkID,omitempty" protobuf:"bytes,7,opt,name=networkID"`
	// Subnet ID
	SubnetID string `json:"subnetID,omitempty" protobuf:"bytes,8,opt,name=subnetID"`
	// available zone
	AvailableZone string `json:"availableZone,omitempty" protobuf:"bytes,9,opt,name=availableZone"`
	// The CIDR of the network
	CIDR string `json:"cidr,omitempty" protobuf:"bytes,3,opt,name=cidr"`
}

// NetworkStatus describes the status of a network
type NetworkStatus struct {
	// State describes the network state
	// +optional
	State string `json:"state" protobuf:"bytes,1,opt,name=state"`
	// Message describes why network is in current state
	// +optional
	Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`
}

const (
	// NetworkInitializing means the network is initializing
	NetworkInitializing = "Initializing"
	// NetworkPending means the network is processing
	NetworkPending = "Pending"
	// NetworkActive means the network is available
	NetworkActive = "Active"
	// NetworkFailed means the network is not available
	NetworkFailed = "Failed"
	// NetworkTerminating means the network is undergoing graceful termination
	NetworkTerminating = "Terminating"
)

register.go

package v1beta1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// GroupName is the group name use in this package
const GroupName = "networking.cci.io"

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
	localSchemeBuilder = &SchemeBuilder
	AddToScheme        = localSchemeBuilder.AddToScheme
)

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&Network{},
		&NetworkList{},
	)
	// Add the watch version that applies
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}

创建构建脚本

新建hack文件夹用以存放构建脚本及依赖文件

mkdir hack

在hack文件夹中创建以下文件:

tools.go,建立该文件来依赖code-generator

// +build tools
 
/*
Copyright 2019 The Kubernetes Authors.
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
    http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
 
// This package imports things required by build scripts, to force `go mod` to see them as dependencies
package tools
 
import _ "k8s.io/code-generator"

update-codegen.sh

#!/usr/bin/env bash
 
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
 
set -o errexit
set -o nounset
set -o pipefail
 
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
 
# generate the code with:
# --output-base    because this script should also be able to run inside the vendor dir of
#                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
#                  instead of the $GOPATH directly. For normal projects this can be dropped.
# generators deepcopy,client,informer,lister
export CLIENTSET_PKG_NAME=networking.cci.io
export CLIENTSET_NAME_VERSIONED=v1beta1
"${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client" \
  examples.com/cci-examples/pkg/client examples.com/cci-examples/pkg/apis \
  networking.cci.io:v1beta1 \
  --output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \
  --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt
 
# To use your own boilerplate text append:
#   --go-header-file "${SCRIPT_ROOT}"/hack/custom-boilerplate.go.txt

boilerplate.go.txt构建出来的文件头,可定制

/*
Copyright The Kubernetes Authors.
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
    http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

至此,完成所有准备过程,此时目录的文件结构如下:

├── go.mod
├── go.sum
├── hack
│   ├── boilerplate.go.txt
│   ├── tools.go
│   └── update-codegen.sh
└── pkg
    └── apis
        └── networking.cci.io
            └── v1beta1
                ├── doc.go
                ├── register.go
                └── types.go
 
5 directories, 8 files

执行命名生成代码

以下命令在linux环境下执行

# 生成vendor文件夹
go mod vendor
# 执行构建脚本
chmod 755 hack/update-codegen.sh
# hack/update-codegen.sh会执行vendor/k8s.io/code-generator/generate-groups.sh
chmod 755 vendor/k8s.io/code-generator/generate-groups.sh
./hack/update-codegen.sh

执行成功后,将会生成代码,目录结构将为

├── go.mod
├── go.sum
├── hack
│   ├── boilerplate.go.txt
│   ├── tools.go
│   └── update-codegen.sh
└── pkg
    ├── apis
    │   └── networking.cci.io
    │       └── v1beta1
    │           ├── doc.go
    │           ├── register.go
    │           ├── types.go
    │           └── zz_generated.deepcopy.go
    └── client
        └── networking.cci.io
            └── v1beta1
                ├── clientset.go
                ├── doc.go
                ├── fake
                │   ├── clientset_generated.go
                │   ├── doc.go
                │   └── register.go
                ├── scheme
                │   ├── doc.go
                │   └── register.go
                └── typed
                    └── networking.cci.io
                        └── v1beta1
                            ├── doc.go
                            ├── fake
                            │   ├── doc.go
                            │   ├── fake_network.go
                            │   └── fake_networking.cci.io_client.go
                            ├── generated_expansion.go
                            ├── network.go
                            └── networking.cci.io_client.go

示例代码:创建Network

该示例测试版本:

k8s.io/client-go@kubernetes-1.15.0

k8s.io/code-generator@kubernetes-1.15.0

import (
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/tools/clientcmd"

	"examples.com/cci-examples/pkg/apis/networking.cci.io/v1beta1"
	clientset "examples.com/cci-examples/pkg/client/networking.cci.io/v1beta1"
)

const (
	name      = "test-k8s-client-namespace-cn-north-1-default-network"
	namespace = "test-k8s-client-namespace"
)

// CreateNetwork 创建Network,并等待其状态变更为Active
// 参考《Namespace和Network》 https://support.huaweicloud.com/devg-cci/cci_05_0023.html
// API参考:https://support.huaweicloud.com/api-cci/createNetworkingCciIoV1beta1NamespacedNetwork.html
func CreateNetwork() (*v1beta1.Network, error) {
	config, _ := clientcmd.BuildConfigFromFlags("", "{path to kubeconfig}")
	cs, err := clientset.NewForConfig(config)
	if err != nil {
		return nil, err
	}

	projectId := "<账号ID,可以在我的凭证获取>"
	domainId := "<项目ID,可以在我的凭证获取>"
	securityGroupID := "<安全组ID,可以在安全组控制台获取>"
	availableZone := "<az名称,例如cn-north-1a、cn-north-4a或cn-east-3a>"
	vpcID := "虚拟私有云的ID,可在VPC控制台获取"
	cidr := "<子网网段,例如192.168.128.0/18>"
	networkID := "<子网的网络ID,可在VPC控制台 > 子网中获取>"
	subnetID := "<子网ID,可在VPC控制台 > 子网获取>"

	network := &v1beta1.Network{
		ObjectMeta: metav1.ObjectMeta{
			Annotations: map[string]string{
				"network.alpha.kubernetes.io/default-security-group": securityGroupID,
				"network.alpha.kubernetes.io/domain-id":              domainId,
				"network.alpha.kubernetes.io/project-id":             projectId,
			},
			Name: name,
		},
		Spec: v1beta1.NetworkSpec{
			AvailableZone: availableZone,
			CIDR:          cidr,
			AttachedVPC:   vpcID,
			NetworkID:     networkID,
			NetworkType:   "underlay_neutron",
			SubnetID:      subnetID,
		},
	}
	network, err = cs.NetworkingCCIV1beta1().Networks(namespace).Create(network)
	if err != nil {
		return nil, err
	}

	// 查询Network状态,等待其状态变为"Active"
	err = wait.Poll(time.Second*5, time.Second*30, func() (done bool, err error) {
		network, err = cs.NetworkingCCIV1beta1().Networks(namespace).Get(name, metav1.GetOptions{})
		if err != nil {
			return false, err
		}
		if network.Status.State == v1beta1.NetworkActive {
			return true, nil
		}
		return false, nil
	})
	return network, err
}

相关文档