k8s自定义controller

1.创建CRD

2.自动生成代码

3.编写controller代码

1.创建CRD

目标如下:
创建自定义API对象(Custom Resource Definition),名为Student;
用代码生成工具生成informer和client相关代码;
创建并运行自定义控制器,k8s环境中所有Student相关的"增、删、改"操作都会被此控制器监听到,可以根据实际需求在控制器中编写业务代码;

创建CRD的第一步是通过官方文档做初步了解,地址:https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#create-a-customresourcedefinition
登录可以执行kubectl命令的机器,创建student.yaml文件,内容如下:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  # name must match the spec fields below, and be in the form: <plural>.<group>
  name: students.stable.example.com
spec:
  # group name to use for REST API: /apis/<group>/<version>
  group: stable.example.com
  # list of versions supported by this CustomResourceDefinition
  versions:
    - name: v1
      # Each version can be enabled/disabled by Served flag.
      served: true
      # One and only one version must be marked as the storage version.
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                name:
                  type: string
                school:
                  type: string
                replicas:
                  type: integer
  # either Namespaced or Cluster
  scope: Namespaced
  names:
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
    plural: students
    # singular name to be used as an alias on the CLI and for display
    singular: students
    # kind is normally the CamelCased singular type. Your resource manifests use this.
    kind: Students
    # shortNames allow shorter string to match your resource on the CLI
    shortNames:
    - stu

在student.yaml所在目录执行命令kubectl apply -f student.yaml,即可在k8s环境创建Student的定义,今后如果发起对类型为Student的对象的处理,k8s的api server就能识别到该对象类型了

访问k8s的etcd上存储的数据,那么执行以下命令,就可以看到新的CRD已经保存在etcd中

ETCDCTL_API=3 etcdctl --endpoints="192.168.204.129:2379,192.168.204.130:2379,192.168.204.131:2379" --cacert=/etc/kubernetes/pki/etcd/etcd-ca.pem --cert=/etc/kubernetes/pki/etcd/etcd.pem --key=/etc/kubernetes/pki/etcd/etcd-key.pem  get /registry/apiextensions.k8s.io/customresourcedefinitions/ --prefix

创建Student对象
前面的步骤使得k8s能识别Student类型了,接下来创建个Student对象

apiVersion: "stable.example.com/v1"
kind: Student
metadata:
  name: object-student
spec:
  name: "李四"
  school: "北京中学"

在object-student.yaml文件所在目录执行命令kubectl apply -f object-student.yaml

执行命令kubectl get stu可见已创建成功的Student对象

创建成功的Stutend对象存储在etcd中是什么样的呢,如果您的etcdctl已经配置好,执行以下命令

ETCDCTL_API=3 etcdctl --endpoints="192.168.204.129:2379,192.168.204.130:2379,192.168.204.131:2379" --cacert=/etc/kubernetes/pki/etcd/etcd-ca.pem --cert=/etc/kubernetes/pki/etcd/etcd.pem --key=/etc/kubernetes/pki/etcd/etcd-key.pem  get /registry/stable.example.com/students/default/object-student --print-value-only

至此,自定义API对象(也就是CRD)就创建成功了,此刻我们只是让k8s能识别到Student这个对象的身份,但是当我们创建Student对象的时候,还没有触发任何业务(相对于创建Pod对象的时候,会触发kubelet在node节点创建docker容器)

2.自动生成代码

为什么要做controller
但如果仅仅是在etcd保存Student对象是没有什么意义的,试想通过deployment创建pod时,如果只在etcd创建pod对象,而不去node节点创建容器,那这个pod对象只是一条数据而已,没有什么实质性作用,其他对象如service、pv也是如此;
controller的作用就是监听指定对象的新增、删除、修改等变化,针对这些变化做出相应的响应(例如新增pod的响应为创建docker容器),关于controller的详细设计,最好的参考就是Harry (Lei) Zhang老师在twitter上的分享,地址是:https://twitter.com/resouer/status/1009996649832185856
API对象的变化会通过Informer存入队列(WorkQueue),在Controller中消费队列的数据做出响应,响应相关的具体代码就是我们要做的真正业务逻辑;
自动生成代码是什么
接下来要做的事情就是编写API对象Student相关的声明的定义代码,然后用代码生成工具结合这些代码,自动生成Client、Informet、WorkQueue相关的代码;

在$GOPATH/src/目录下创建一个文件夹k8s_customize_controller:
进入文件夹k8s_customize_controller,执行如下命令创建三层目录:

mkdir -p pkg/apis/stable

在新建的stable目录下创建文件register.go,内容如下:

package stable

const (
	GroupName = "stable.example.com"
	Version   = "v1"
)

在新建的stable目录下创建名为v1的文件夹;
在新建的v1文件夹下创建文件doc.go,内容如下:

// +k8s:deepcopy-gen=package

// +groupName=stable.example.com
package v1

上述代码中的两行注释,都是代码生成工具会用到的,一个是声明为整个v1包下的类型定义生成DeepCopy方法,另一个声明了这个包对应的API的组名,和CRD中的组名一致;
在v1文件夹下创建文件types.go,里面定义了Student对象的具体内容:

package v1

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

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

type Student struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
	Spec              StudentSpec `json:"spec"`
}

type StudentSpec struct {
	name   string `json:"name"`
	school string `json:"school"`
}

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

// StudentList is a list of Student resources
type StudentList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []Student `json:"items"`
}

从上述源码可见,Student对象的内容已经被设定好,主要有name和school这两个字段,表示学生的名字和所在学校,因此创建Student对象的时候内容就要和这里匹配了;
在v1目录下创建register.go文件,此文件的作用是通过addKnownTypes方法使得client可以知道Student类型的API对象:

package v1

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

	"k8s_customize_controller/pkg/apis/stable"
)

var SchemeGroupVersion = schema.GroupVersion{
	Group:   stable.GroupName,
	Version: stable.Version,
}

var (
	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
	AddToScheme   = SchemeBuilder.AddToScheme
)

func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}

func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}

func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(
		SchemeGroupVersion,
		&Student{},
		&StudentList{},
	)

	// register the type in the scheme
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}

至此,为自动生成代码做的准备工作已经完成了,目前为止,$GOPATH/src/k8s_customize_controller目录下的文件和目录结构是这样的:

    .
    └── pkg
        └── apis
            └── bolingcavalry
                ├── register.go
                └── v1
                    ├── doc.go
                    ├── register.go
                    └── types.go
4 directories, 4 files

执行下面的命令,要在$GOPATH/src下执行:

go get -u k8s.io/apimachinery@v0.24.2
go get -u k8s.io/code-generator@v0.24.2
./k8s.io/code-generator/generate-groups.sh all k8s_customize_controller/pkg/client k8s_customize_controller/pkg/apis stable:v1

会看到以下输出:

Generating deepcopy funcs
Generating clientset for stable:v1 at k8s_customize_controller/pkg/client/clientset
Generating listers for stable:v1 at k8s_customize_controller/pkg/client/listers
Generating informers for stable:v1 at k8s_customize_controller/pkg/client/informers

在$GOPATH/src/k8s_customize_controller目录下执行tree命令,可见已生成了很多内容:

.
├── go.mod
├── go.sum
└── pkg
    ├── apis
    │   └── stable
    │       ├── register.go
    │       └── v1
    │           ├── doc.go
    │           ├── register.go
    │           ├── types.go
    │           └── zz_generated.deepcopy.go
    └── client
        ├── clientset
        │   └── versioned
        │       ├── clientset.go
        │       ├── doc.go
        │       ├── fake
        │       │   ├── clientset_generated.go
        │       │   ├── doc.go
        │       │   └── register.go
        │       ├── scheme
        │       │   ├── doc.go
        │       │   └── register.go
        │       └── typed
        │           └── stable
        │               └── v1
        │                   ├── doc.go
        │                   ├── fake
        │                   │   ├── doc.go
        │                   │   ├── fake_stable_client.go
        │                   │   └── fake_student.go
        │                   ├── generated_expansion.go
        │                   ├── stable_client.go
        │                   └── student.go
        ├── informers
        │   └── externalversions
        │       ├── factory.go
        │       ├── generic.go
        │       ├── internalinterfaces
        │       │   └── factory_interfaces.go
        │       └── stable
        │           ├── interface.go
        │           └── v1
        │               ├── interface.go
        │               └── student.go
        └── listers
            └── stable
                └── v1
                    ├── expansion_generated.go
                    └── student.go

21 directories, 29 files

如上所示,zz_generated.deepcopy.go就是DeepCopy代码文件,client目录下的内容都是客户端相关代码,在开发controller时会用到;
client目录下的clientset、informers、listers的身份和作用可以和前面的自动生成代码-controller的详细设计结合来理解;

3.编写controller代码

我们创建了CRD,再通过自动生成代码的工具将controller所需的informer、client等依赖全部准备好,到了本章,就该编写controller的代码了,也就是说,现在已经能监听到Student对象的增删改等事件,接下来就是根据这些事件来做不同的事情,满足个性化的业务需求;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值