k8s自定义CRD生成controller

主要参考这两篇文章:代码部分基本参考k8s自定义生成controller三部曲 & 中间细节部分参考code-generator使用
然后踩了非常多的坑,最后在师兄亲自指导下才成功x
完整操作流程个人总结一下

初始化项目

这里有一个大坑
一开始在 $ GOPATH/src/目录下创建文件夹k8s_customize_controller:
走到后面发现,自动生成代码那里由于路径设计等原因生成的代码要么没有informer和lister要么就自己在项目root下重新新建一个k8s_customize_controller 然后在下面生成代码,就非常奇怪。最后发现,$GOPATH/src下必须要要两个目录层级,比如 $GOPATH/src/work/k8s_customize_contrller
才能正常生成代码

进入k8s_customize_contrller目录,执行

#创建目录
mkdir -p  pkg/apis/bolingcavalry
#初始化项目 把环境拉到vendor中
go mod init vendor
# 获取依赖:此处可能会出现拉不到code-generator的情况,需要手动进入vendor目录 git clone k8s.io/code-generator
go get k8s.io/apimachinery@v0.0.0-20190425132440-17f84483f500
go get k8s.io/client-go@v0.0.0-20190425172711-65184652c889
go get k8s.io/code-generator@v0.0.0-20190419212335-ff26e7842f9d

创建CRD(Custom Resource Definition)

官方CRD创建说明

  1. 在能够执行kubectl的机器上创建student.yaml文件,内容如下:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # metadata.name的内容是由"复数名.分组名"构成,如下,students是复数名,bolingcavalry.k8s.io是分组名
  name: students.bolingcavalry.k8s.io
spec:
  # 分组名,在REST API中也会用到的,格式是: /apis/分组名/CRD版本
  group: bolingcavalry.k8s.io
  # list of versions supported by this CustomResourceDefinition
  versions:
    - name: v1
      # 是否有效的开关.
      served: true
      # 只有一个版本能被标注为storage
      storage: true
  # 范围是属于namespace的
  scope: Namespaced
  names:
    # 复数名
    plural: students
    # 单数名
    singular: student
    # 类型名
    kind: Student
    # 简称,就像service的简称是svc
    shortNames:
    - stu

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

kubectl get crd
NAME                            CREATED AT
students.bolingcavalry.k8s.io   2021-04-29T08:16:08Z

kubectl describe crd stu 命令查看更多细节,stu是在student.yaml中定义的简称

kubectl get crd
NAME                            CREATED AT
students.bolingcavalry.k8s.io   2021-04-29T08:16:08Z
ydzhang@ydzhangdeMacBook-Pro ~ % kubectl describe crd stu
Name:         students.bolingcavalry.k8s.io
Namespace:    
Labels:       <none>
Annotations:  <none>
API Version:  apiextensions.k8s.io/v1
Kind:         CustomResourceDefinition
Metadata:
  Creation Timestamp:  2021-04-29T08:16:08Z
  Generation:          1
  Managed Fields:
    API Version:  apiextensions.k8s.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:status:
        f:acceptedNames:
          f:kind:
          f:listKind:
          f:plural:
          f:shortNames:
          f:singular:
        f:conditions:
    Manager:      kube-apiserver
    Operation:    Update
    Time:         2021-04-29T08:16:08Z
    API Version:  apiextensions.k8s.io/v1beta1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        f:conversion:
          .:
          f:strategy:
        f:group:
        f:names:
          f:kind:
          f:listKind:
          f:plural:
          f:shortNames:
          f:singular:
        f:preserveUnknownFields:
        f:scope:
        f:version:
        f:versions:
      f:status:
        f:storedVersions:
    Manager:         kubectl-client-side-apply
    Operation:       Update
    Time:            2021-04-29T08:16:08Z
  Resource Version:  76925
  Self Link:         /apis/apiextensions.k8s.io/v1/customresourcedefinitions/students.bolingcavalry.k8s.io
  UID:               78f13ee1-7c2b-400e-9073-77e311653e23
Spec:
  Conversion:
    Strategy:  None
  Group:       bolingcavalry.k8s.io
  Names:
    Kind:       Student
    List Kind:  StudentList
    Plural:     students
    Short Names:
      stu
    Singular:               student
  Preserve Unknown Fields:  true
  Scope:                    Namespaced
  Versions:
    Name:     v1
    Served:   true
    Storage:  true
Status:
  Accepted Names:
    Kind:       Student
    List Kind:  StudentList
    Plural:     students
    Short Names:
      stu
    Singular:  student
  Conditions:
    Last Transition Time:  2021-04-29T08:16:08Z
    Message:               protected groups must have approval annotation "api-approved.kubernetes.io", see https://github.com/kubernetes/enhancements/pull/1111
    Reason:                MissingAnnotation
    Status:                False
    Type:                  KubernetesAPIApprovalPolicyConformant
    Last Transition Time:  2021-04-29T08:16:08Z
    Message:               no conflicts found
    Reason:                NoConflicts
    Status:                True
    Type:                  NamesAccepted
    Last Transition Time:  2021-04-29T08:16:08Z
    Message:               the initial names have been accepted
    Reason:                InitialNamesAccepted
    Status:                True
    Type:                  Established
  Stored Versions:
    v1
Events:  <none>

3.使用etcd查看保存的crd,(这一步没有做,本地没有装etcd)
4.前面的步骤使得k8s能识别Student类型,接下来创建个Student对象:创建object-student.yaml

apiVersion: bolingcavalry.k8s.io/v1
kind: Student
metadata:
  name: object-student
spec:
  name: "张三"
  school: "深圳中学"

执行kubectl apply -f object-student.yaml会看到

kubectl apply -f object-student.yaml 
student.bolingcavalry.k8s.io/object-student created

至此,自定义API对象(也就是CRD)就创建成功了,此刻我们只是让k8s能识别到Student这个对象的身份,但是当我们创建Student对象的时候,还没有触发任何业务(相当于创建Pod对象的时候,会触发kubelet在node节点创建docker容器),接下来要通过go代码实现创建Student对象时的触发各种业务操作(监听等等)

自动代码生成

  1. 进入项目目录 k8s_customize_controller/pkg/apis/bolingcavalry 下创建register.go
package bolingcavalry

const (
        GroupName = "bolingcavalry.k8s.io"
        Version   = "v1"
)
  1. 在bolingcavalry下创建目录v1,在v1下创建doc.go,代码中的两行注释,都是代码生成工具会用到的,一个是声明为整个v1包下的类型定义生成DeepCopy方法,另一个声明了这个包对应的API的组名,和CRD中的组名一致;
// +k8s:deepcopy-gen=package

// +groupName=bolingcavalry.k8s.io
package v1
  1. 在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对象的时候内容就要和这里匹配了;
4. 在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/bolingcavalry"
)

var SchemeGroupVersion = schema.GroupVersion{
   
	Group:   bolingcavalry.GroupName,
	Version: bolingcavalry.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
}

目前为止的代码结构如下:

tree
.
└── k8s_customize_controller
    └── pkg
        └── apis
            └── bolingcavalry
                ├── register.go
                └── v1
                    ├── doc.go
                    ├── register.go
                    └── types.go

5 directories, 4 files

5.本来使用如下方法即可生成代码,但是由于我的code-generator拉不下来,加上go环境有些问题,以及原文章省略了一些东西,所以使用创建脚本,自动生成代码的方法最后成功生成。

cd $GOPATH/src \
&& go get -
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值