404 Not Found
  • Introduction
  • Monitoring related
    • K8s cluster monitoring
    • Monitor Jenkins with G.A.P on K8s cluster
    • Monitoring tools | projects
      • Grafana
      • AlertManager
      • Prometheus
      • Wavefront
  • Logging related
    • BOSH logs
    • How to gather systemd log
    • K8s cluster logging
    • Logging tools | projects
      • vRealize Log Insight
      • Fluentd
      • syslog vs fluentd
  • Having fun with docker
    • Using docker-compose for redmine
    • Customize Fluentd docker image
  • K8S or Apache Mesos
  • K8S Related
    • Main Architecture
      • Master components
        • API Server
        • etcd
        • Controller Manager
        • Kube Scheduler
      • Worker components
        • kubelet
        • kube-proxy
    • K8S Storage
      • Volume Provisioning
      • Understand CSI
      • How to write CSI
      • VMware CNS
      • K8S storage e2e experiment under VMware vSphere
      • Experiment on Persistent Volume Access Mode
      • Design: Storage in Cluster-API architecture
    • K8S Networking
      • Ingress
      • Endpoints
    • K8S Policies
      • Resource Quotas
    • K8S Management Platform
    • K8S Tests Tool
    • K8S Extension
      • CRDs
        • Custom Resources
        • Custom Controllers
        • How to user code-generator
        • K8S Operators
        • Operators Development Tools
          • Kubebuilder
          • Metacontroller
          • Operator SDK
      • Custom API Server
    • K8S Resource CRUD Workflow
    • K8S Garbage Collection
  • K8S CONTROLLER RELATED
    • IsController: true
    • Controller clients
  • PKS RELATED
    • How to Access VMs and Databases related to PKS
    • PKS Basics
    • BOSH Director
    • Backup and Restore on Ent. PKS with Velero
  • CICD RELATED
    • Configure Jenkins to run on K8S
    • Customize Jenkins JNLP slave image
    • Jenkins global shared libs
  • Google Anthos
    • Google Anthos Day from KubeCon 2019 San Diego
    • Migrate for Anthos
    • Config Connector
  • SYSTEM DESIGN RELATED
    • Design Data Intensive Application - Notes
      • RSM
        • Reliability
        • Scalability
      • Data models and Query Languages
      • Storage and Retrieval
    • How Alibaba Ensure K8S Performance At Large Scale
  • Miscellaneous
    • Knative
    • Serverless
    • Service Mesh
    • gRPC
    • Local persistent volumes
    • ownerReferences in K8S
    • File(NAS) vs Block(SAN) vs Object storage
    • KubeVirt
    • Why K8S HA chooses 3 instead of 5..6..7 as the size of masters?
    • goroutine & go channel
    • How to make docker images smaller
Powered by GitBook
On this page
  • Write type definition code
  • doc.go
  • types.go
  • register.go
  • Run code-generator to create client codes

Was this helpful?

  1. K8S Related
  2. K8S Extension
  3. CRDs

How to user code-generator

PreviousCustom ControllersNextK8S Operators

Last updated 5 years ago

Was this helpful?

In this article, we will focus on how to use the K8s from scratch.

Let's assume we want to create CRD in group "foo.com", and there is a type called "HelloType" with a "message" field in the spec:

# Definition
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:  
  name: hellotypes.foo.com
spec:  
  group: foo.com  
  version: v1
  scope: Namespaced  
  names:    
    kind: HelloType   
    shortNames: ht
    plural: hellotypes
    singular: hellotype
# HelloType
---
apiVersion: foo.com/v1
kind: HelloType 
metadata: 
  name: superman-hello
spec:
  message: hello world

There are two steps to generate the CRD resource code:

  1. Write the type definition code with code generator tags

  2. Run run the generator to create the client codes which include: clientset, informers, listers for your customer resource

Write type definition code

  • cd $GOPATH/src

  • mkdir -p github.com/superman/demo

  • cd $GOPATH/src/github.com/superman/demo

  • Create the skeleton files as below under $GOPATH/src/github.com/superman/demo

pkg/
├── apis
    └── foo
        └── v1
            ├── doc.go
            ├── register.go
            └── types.go

doc.go

doc.go
// +k8s:deepcopy-gen=package
// +k8s:defaulter-gen=TypeMeta
// +groupName=foo.com

package v1

This file provide controls of the global tags that will apply to every type in the same version with default setting.

The tags compose of two parts, the function name and the value to pass in normally. For example in+k8s:deepcopy-gen=package, deepcopy-gen is the function to call for generating the deep copies codes for types. packagedenotes applying the function to the whole v1 package in this case.

types.go

types.go
package v1

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

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

// HelloType is a top-level type
type HelloType struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ObjectMeta `json:"metadata,omitempty"`
	
	// +optional
	Status HelloTypeStatus `json:"status,omitempty"`
	// This is where you can define
	// your own custom spec
	Spec HelloSpec `json:"spec,omitempty"`
}

// custom spec 
type HelloSpec struct {
	Message string `json:"message,omitempty"`
}

// custom status
type HelloTypeStatus struct {
	Name string
}

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

// no client needed for list as it's been created in above
type HelloTypeList struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ListMeta `son:"metadata,omitempty"`

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

+genclient means generating API client for the type.

+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Objectmeans when generating deepcopy for the type, use runtime.Object interface.

+optional indicates the field is optional. The data can be empty for the field.

register.go

register.go
package v1

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

// Define your schema name and the version
var SchemeGroupVersion = schema.GroupVersion{
	Group:   "foo.com",
	Version: "v1",
}

var (
	SchemeBuilder      runtime.SchemeBuilder
	localSchemeBuilder = &SchemeBuilder
	AddToScheme        = localSchemeBuilder.AddToScheme
)

func init() {
	// We only register manually written functions here. The registration of the
	// generated functions takes place in the generated files. The separation
	// makes the code compile even when the generated files are missing.
	localSchemeBuilder.Register(addKnownTypes)
}

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

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(
		SchemeGroupVersion,
		&HelloType{},
		&HelloTypeList{},
	)

	scheme.AddKnownTypes(
		SchemeGroupVersion,
		&metav1.Status{},
	)

	metav1.AddToGroupVersion(
		scheme,
		SchemeGroupVersion,
	)

	return nil
}

The register.go file contains the functions registering the new types we just created to the schema so the API server can recognize them.

Run code-generator to create client codes

go get -u k8s.io/code-generator/... 
go get k8s.io/apimachinery
cd $GOPATH/src/k8s.io/code-generator 
./generate-groups.sh all "github.com/superman/demo/pkg/client" "github.com/superman/demo/pkg/apis" "foo:v1"
Usage: $(basename "$0") <generators> <output-package> <apis-package> <groups-versions> ...
  <generators>        the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all".
  <output-package>    the output package name (e.g. github.com/example/project/pkg/generated).
  <apis-package>      the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis).
  <groups-versions>   the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative
                      to <api-package>.
  ...                 arbitrary flags passed to all generator binaries.

After above steps, you will see the following file structure:

kubo@jumper:~/GoProjects/src/github.com/superman/demo/pkg$ tree client/
client/
├── clientset
│   └── versioned
│       ├── clientset.go
│       ├── doc.go
│       ├── fake
│       │   ├── clientset_generated.go
│       │   ├── doc.go
│       │   └── register.go
│       ├── scheme
│       │   ├── doc.go
│       │   └── register.go
│       └── typed
│           └── foo
│               └── v1
│                   ├── doc.go
│                   ├── fake
│                   │   ├── doc.go
│                   │   ├── fake_foo_client.go
│                   │   └── fake_hellotype.go
│                   ├── foo_client.go
│                   ├── generated_expansion.go
│                   └── hellotype.go
├── informers
│   └── externalversions
│       ├── factory.go
│       ├── foo
│       │   ├── interface.go
│       │   └── v1
│       │       ├── hellotype.go
│       │       └── interface.go
│       ├── generic.go
│       └── internalinterfaces
│           └── factory_interfaces.go
└── listers
    └── foo
        └── v1
            ├── expansion_generated.go
            └── hellotype.go

16 directories, 22 files

References:

The usage of generate-groups.sh. More details could be found .

code-generator
here
How to generate client codes for Kubernetes Custom Resource Definitions (CRD)ITNEXT
Logo
Extending Kubernetes: Create Controllers for Core and Custom ResourcesMedium
Logo
GitHub - kubernetes/sample-controller: Repository for sample controller. Complements sample-apiserverGitHub
Logo