diff --git a/README.md b/README.md index 8d33ad3c3b..6f47e31159 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,6 @@ the release program.* To build your own release see [CONTRIBUTING.md](CONTRIBUT ## Releases -### 1.10 Kubernetes - -[Release](https://github.com/kubernetes-sigs/kubebuilder/releases): - -- [latest](https://github.com/kubernetes-sigs/kubebuilder/releases/latest) - -## Book - -See [The Kubebuilder Book](http://book.kubebuilder.io/) for documentation on building APIs with kubebuilder. - ## `kubebuilder` Kubebuilder is a framework for building Kubernetes APIs using [custom resource definitions (CRDs)](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions). @@ -23,328 +13,21 @@ Kubebuilder is a framework for building Kubernetes APIs using [custom resource d **Note:** kubebuilder does not exist as an example to *copy-paste*, but instead provides powerful libraries and tools to simplify building and publishing Kubernetes APIs from scratch. -## TL;DR - -**First:** Download the latest -`kubebuilder___amd64.tar.gz` release, where `version` -is the kubebuilder version. Extracting the archive will give -`kubebuilder___amd64` directory. Move the extracted directory to -/usr/local/kubebuilder and update your PATH to include -/usr/local/kubebuilder/bin. Given below are the steps: - -```shell - -# download the release -wget https://github.com/kubernetes-sigs/kubebuilder/releases/download//kubebuilder___amd64.tar.gz - -# extract the archive -tar -zxvf kubebuilder___amd64.tar.gz - -sudo mv kubebuilder___amd64 /usr/local/kubebuilder - -#update your PATH to include /usr/local/kubebuilder/bin -export PATH=$PATH:/usr/local/kubebuilder/bin - -``` - -Create an _empty_ project under a new GOPATH. - -```sh -# Initialize your project -kubebuilder init --domain example.com - -# Create a new API and controller -kubebuilder create resource --group bar --version v1alpha1 --kind Foo -kubectl apply -f hack/sample/foo.yaml - -# Install and run your API into the cluster for your current kubeconfig context -GOBIN=$(pwd)/bin go install /cmd/controller-manager -bin/controller-manager --kubeconfig ~/.kube/config -kubectl apply -f hack/sample/foo.yaml - -# Build your documentation -kubebuilder create example --group bar --version v1alpha1 --kind Foo -kubebuilder docs -``` - -See the [user guide](docs/tools_user_guide.md) for more details - -## Project structure - -Following describes the project structure setup by kubebuilder commands. - -### cmd/ - -*Most users do not need to edit this package.* - -The `cmd` package contains the main function for launching a new controller manager. It is responsible for parsing -a `rest.Config` and invoking the `inject` package to run the various controllers. It may optionally install CRDs -as part of starting up. - -This package is created automatically by running: - -```sh -kubebuilder init --domain k8s.io -``` - -### pkg/apis - -**Users must edit packages under this package** - -The `apis` package contains the schema definitions for the resource types you define. Resources are defined under -`pkg/apis///_types.go`. Resources may be annotated with comments to identify resources -to code generators. Comments are also used to generated field validation. - -Notably client generation, CRD generation, docs generation and config generation are all driven off of annotations -on resources package. - -See documentation and examples of annotations in godoc format here: -[gen/apis](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/apis#example-package) - -Subpackages of apis are created when running the following command to create a new resource and controller: - -```sh -kubebuilder create resource --group mygroup --version v1beta1 --kind MyKind -``` - -**Note:** While `create resource` automatically runs the code generators for the user, when -the user changes the resource file or adds `// +kubebuilder` annotations to the controller, -they will need to run `kubebuilder generate` to rerun the code generators. - -### pkg/controllers - -**Users must edit packages under this package** - -The `controllers` package contains the controllers to implement the resource APIs. Controllers are defined under -`pkg/controllers//controller.go`. Controllers may be annotated with comments to wire the controller into the -inject package, start informers they require and install RBAC rules they require. - -Subpackages of controllers are created when running the following command to create a new resource and controller: - -```sh -kubebuilder create resource --group mygroup --version v1beta1 --kind MyKind -``` - -See documentation and examples of annotations in godoc format here: -- [gen/controller](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/controller#example-package) - -**Note:** While `create resource` automatically runs the code generators for the user, when -the user changes the resource file or adds `// +kubebuilder` annotations to the controller, -they will need to run `kubebuilder generate` to rerun the code generators. - -### pkg/inject - -*Most users do not need to edit this package.* - -The `inject` package contains the `RunAll` function used to start all of the registered controllers and informers. -Wiring is autogenerated based on resource and controller annotations. - -Generated wiring: -- Installing CRDs -- Instantiating and starting controllers -- Starting sharedinformers -- Installing RBAC rules - -### pkg/inject/args - -*Only some users need to edit this package.* - -The `args` package contains the struct passed to the `ProvideController` function used to instantiating controllers. -The `InjectArgs` struct and `CreateInjectArgs` function in this package may be edited to pass additional information -to the controller provider functions. This is typically an advanced use case. - -The `args` package uses the `kubebuilder/pkg/inject/args` package documented here: -[inject/args](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/inject/args) - -### hack/ - -The `hack` directory contains generated samples and config. - -The hack/install.yaml config file for installing the API extension into a cluster will be created under this -directory by running. - -```sh -kubebuilder create config --controller-image mycontrollerimage --name myextensionname -``` - -### docs/ +### Download and Install -The `docs` package contains your examples and content for generating reference documentation for your APIs. +[Releases](https://github.com/kubernetes-sigs/kubebuilder/releases): -The docs package is created when running either +## Getting Started -```sh -kubebuilder docs -``` +See the [Getting Started](http://book.kubebuilder.io/quick_start.html) documentation. -or +## Documentation -```sh -kubebuilder create example --group mygroup --version v1beta1 --kind MyKind -``` +[book.kubebuilder.io](http://book.kubebuilder.io) -Example reference documentation lives under `docs/reference/examples`. Conceptual reference documentation -lives under `docs/reference/static_includes`. +#### Quick Start Demo -### / - -The project root directory contains several files - -- Dockerfile.controller - -Running `docker build` on this file will build a container image for running your controller. - -- Gopkg.toml / Gopkg.lock - -These files are used to update vendored go dependencies. - -## Available controller operations - -Controllers watch Kubernetes resources and call a "Reconcile" function in response to events. Reconcile functions -are typically "level-based", that is they are notified that something has changed for given resource namespace/name key, -but not specifically what changed (e.g. add, delete, update). This allows Reconcile functions to reconcile multiple -events at a time and more easily self-heal, as actions are taken by comparing the current desired state (resource Spec) -and the observed state of the system. - -### Creating a new controller - -A new GenericController is created for you by kubebuilder when creating a resource. If you are not using -kubebuilder to create resources and manage your project, you may create a controller directly by following -this example: - -[GenericController](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController) - - -To Watch additional resources from your controller do the following in your controller.go: - -1. Add a `gc.Watch*` call to the `ProvideController`. e.g. Call gc.[WatchTransformationKeyOf](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-WatchTransformationKeyOf) - - This will trigger Reconcile calls for events -2. Add an [// +informers:](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/controller#example-package) annotation - to the `type Controller struct` with the type of the resource you are watching - - This will make sure the informers that watch for events are started -3. Add an [// +rbac:](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/controller#example-package) - annotation to the `type Controller struct` with the type of the resource you are watching - - This will make sure the RBAC rules that allow the controller to watch events in a cluster are generated - -Example: - -```go -// +kubebuilder:rbac:groups="",resources=pods,verbs=get;watch;list -// +kubebuilder:informers:group=core,version=v1,kind=Pod -type FooController struct{} -``` - -### Watching resources - -Controllers watch resources to trigger reconcile functions. It is common for controllers to reconcile a single resource -type, but watch many other resource types to trigger a reconcile. An example of this is a Deployment controller that -watches Deployments, ReplicaSets (created by the controller) and Pods (created by the ReplicaSet controller). Pod -status events, such as becoming healthy, may trigger actions in the Deployment controller, such as continuing -a rolling update. - -#### Watching the resource managed by the controller - -Controllers typically watch for events on the resource they control and in response reconcile that resource instance. - -Note: Kubebuilder will automatically call the Watch function for controllers it creates when creating a resources. If -you are not using kubebuilder to create resources and manager your project, you may have your controller watch -a resource by following this example: - -[GenericController.Watch](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-Watch) - -#### Watching resources created by a controller and reconciling in the controller - -Controllers frequently watch for events on the resources created by the controller or transitively created by the -controller (e.g. controller creates a ReplicaSet and the ReplicaSet creates a Pod). - -Events for created resources need to be mapped back to the resource instance responsible for their creation - -e.g. if there is a Pod event -then reconcile the Deployment that owns the Pod. The owning resource is found by -looking at the instance (Pod) controller reference, looking up the object with the same namespace and name as the -owner reference and comparing the UID of the found object to the UID in the owner reference. This is check is done -to ensure the object is infact the owner and to disambiguate multiple resources with the same name and Kind that -are logically different (e.g. they are in different groups and are totally different things). - -e.g. In response to a Pod event, find the owner reference for the Pod that has `controller=true`. -Lookup the ReplicaSet with this name and compare its UID to the ownerref UID. If they are the same -find the owner reference for the ReplicaSet that has `controller=true`. Lookup the Deployment -with this name and compare the UID to the ownerref UID. If they are the same reconcile the Deployment with -this namespace/name. - -In order to watch objects created by a controller and reconcile the owning resource in response, the functions -to lookup the ancestors object must be provided (e.g. lookup a ReplicaSet for a namespace/name, -lookup a Deployment for a namespace/name). - -You may have you controller watch a resource created by the controller and then reconcile the owning object by -following this example: - -[GenericController.WatchControllerOf](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-WatchControllerOf) - -[Sample](https://github.com/kubernetes-sigs/kubebuilder/blob/master/samples/controller/controller.go#L91) - -#### Watching arbitrary resources and mapping them so the are reconciled in the controller - -In some cases it may be necessary to watch resources not owned or created by your controller, but respond to them. -An example would be taking some action in response to the deletion or creation of Nodes in the cluster. To do -this, your controller must watch that object (Node) and map events to the resource type of the controller. - -You may watch a resource and transform it into the key of the resource the controller manages by following this example: - -[GenericController.WatchTransformationOf](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-WatchTransformationOf) - -#### Watching arbitrary resources and handling the events that may caused a reconciliation in the controller - -In some cases it may be necessary to directly handle events and enqueue keys to be reconciled. You may do so -by following this example: - -[GenericController.WatchEvents](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-WatchEvents) - -### Watching a channel for resource names and reconciling them in the controller - -In some cases it may be necessary to respond to external events such as webhooks. You may enqueue reconcile events -from arbitrary sources by using a channel and following this example: - -[GenericController.WatchChannel](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller#example-GenericController-WatchChannel) - -## Running tests - -In order to run the integration tests, the following environment variables must be set to bring up the test environment: - -```sh -export TEST_ASSET_KUBECTL=/usr/local/kubebuilder/bin/kubectl -export TEST_ASSET_KUBE_APISERVER=/usr/local/kubebuilder/bin/kube-apiserver -export TEST_ASSET_ETCD=/usr/local/kubebuilder/bin/etcd -``` - -Tests can then be run with: - -```sh -go test ./pkg/... -``` - -## Godoc Links - -Many of the kubebuilder libraries can be used on their own without the kubebuilder code generation and scaffolding. - -See examples of using the libraries directly below: - -- [controller libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller) -- [config libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/config) -- [signals libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/signals) - -Kubebuilder generates codes for custom resource fields, and controller components such as watchers and informers. You have to add code generation tags in form of comment directives to initiate the code generation: - -- [resource code generation tags](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/apis) -- [controller code generation tags](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/controller) - -For example, you have to add controller code generation tags such as `+rbac` and `+informers` in `pkg/controller/foo/controller.go` file: -``` -// +controller:group=foo,version=v1beta1,kind=Bar,resource=bars -// +rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete -// +informers:group=apps,version=v1,kind=Deployment -// +rbac:groups="",resources=pods,verbs=get;watch;list -// +informers:group=core,version=v1,kind=Pod -type FooController struct{} -``` +![Quick Start](docs/gif/quickstart.gif) ## Motivation @@ -353,7 +36,6 @@ Building Kubernetes tools and APIs involves making a lot of decisions and writin In order to facilitate easily building Kubernetes APIs and tools using the canonical approach, this framework provides a collection of Kubernetes development tools to minimize toil. - Kubebuilder attempts to facilitate the following developer workflow for building APIs 1. Create a new project directory diff --git a/docs/book/README.md b/docs/book/README.md index b22d111838..83b5aefd80 100644 --- a/docs/book/README.md +++ b/docs/book/README.md @@ -2,7 +2,7 @@ This book is being actively developed. {% endpanel %} -# Introduction +**Note:** Impatient readers head straight to [Quick Start](quick_start.md). ## Who is this for @@ -58,12 +58,3 @@ The table of contents may be hidden using the hamburger icon at the left side of Some chapters have code snippets for multiple OS or Languages. These chapters will display OS or Language selections at the right side of the top nav, which may be used to change the OS or Language of the examples shown. - -## About the Author - -Phillip Wittrock is a Senior Engineer at Google working on GKE and Kubernetes. -Phillip is a member of the Kubernetes Steering Committee, and has lead the following -Kubernetes Special Interest Groups: SIG cli, SIG release and SIG docs. - -Phillip’s hobbies include debating how kubectl is pronounced, talking about Kubernetes APIs -at social events, and treating code like it is art. \ No newline at end of file diff --git a/docs/book/SUMMARY.md b/docs/book/SUMMARY.md index 0489dff80e..c28d34c99e 100644 --- a/docs/book/SUMMARY.md +++ b/docs/book/SUMMARY.md @@ -1,6 +1,7 @@ # Building Kubernetes APIs with Kubebuilder * [Introduction](README.md) +* [Quick Start](quick_start.md) ### Getting Started @@ -25,3 +26,6 @@ * Controller-Manager Fundamentals * [What is the Controller-Manager](basics/what_is_the_controller_manager.md) * [Simple Controller-Manager](basics/simple_controller_manager.md) + +### Reference Docs +* [GoDoc Links](go_docs.md) \ No newline at end of file diff --git a/docs/book/basics/simple_controller.md b/docs/book/basics/simple_controller.md index e16112d857..fb93e87e9b 100644 --- a/docs/book/basics/simple_controller.md +++ b/docs/book/basics/simple_controller.md @@ -12,9 +12,10 @@ This is a simple example of the Controller for the ContainerSet API shown in *Si > pkg/controller/containerset/controller.go -{% method %} ## Setup +{% method %} + Code generation requires the following to be defined in controller.go: - a `ProvideController` function returning an initialized `controller.GenericController`. This @@ -110,6 +111,18 @@ func ProvideController(arguments args.InjectArgs) ( ``` {% endmethod %} +{% panel style="warning", title="Adding Annotations For Watches And CRUD Operations" %} +It is critical to add the `// +kubebuilder:informers` and `// +kubebuilder:rbac` annotations when +adding watches or CRUD operations to your controller through either `GenericController.Watch*` +or CRUD (e.g. `.Update`) operations. + +After updating the annotations, `kubebuilder generate` must be rerun to regenerated code, and +`kubebuilder create config` must be run to regenerated installation yaml with the rbac rules. +{% endpanel %} + + +## Reconcile + {% panel style="success", title="Level vs Edge" %} The Reconcile function does not differentiate between create, update or deletion events. Instead it simply reads the desired state defined in ContainerSet.Spec and compares it @@ -117,7 +130,6 @@ to the observed state. {% endpanel %} {% method %} -## Reconcile The business logic of the controller is implemented in the `Reconcile` function. This function takes the *key* of a ContainerSet, allowing multiple Events to be batched together into a single Reconcile call. diff --git a/docs/book/go_docs.md b/docs/book/go_docs.md new file mode 100644 index 0000000000..50b8a389f6 --- /dev/null +++ b/docs/book/go_docs.md @@ -0,0 +1,13 @@ +## GoDoc Links + + +## Controller libraries + +- [controller libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/controller) +- [config libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/config) +- [signals libraries](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/signals) + +## Code generation tags + +- [resource code generation tags](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/apis) +- [controller code generation tags](https://godoc.org/github.com/kubernetes-sigs/kubebuilder/pkg/gen/controller) diff --git a/docs/book/quick_start.md b/docs/book/quick_start.md new file mode 100644 index 0000000000..45d837e7ee --- /dev/null +++ b/docs/book/quick_start.md @@ -0,0 +1,158 @@ +# Quick Start + +This Quick Start guide will cover. + +- Create a project +- Create an API +- Run the API + +## Installation +{% method %} + +- Install [dep](https://github.com/golang/dep) +- Download the latest release from the [releases page](https://github.com/kubernetes-sigs/kubebuilder/releases) +- Extract the tar and move+rename the extracted directory to `/usr/local/kubebuilder` +- Add `/usr/local/kubebuilder/bin` to your `PATH` + +{% sample lang="bash" %} +```bash +curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v0.1.X/kubebuilder_0.1.X__amd64.tar.gz + +tar -zxvf kubebuilder_0.1.X__amd64.tar.gz +sudo mv kubebuilder_0.1.X__amd64 /usr/local/kubebuilder + +export PATH=$PATH:/usr/local/kubebuilder/bin +``` +{% endmethod %} + +## Create a new API + +{% method %} + +#### Project Creation + +Initialize the project directory with the canonical project structure and go dependencies. + +{% sample lang="bash" %} +```bash +kubebuilder init --domain k8s.io +``` +{% endmethod %} + +{% method %} + +#### API Creation + +Create a new API called *Sloop*. The will create files for you to edit under `pkg/apis//` and under +`pkg/controller/`. + +**Optional:** Edit the schema or reconcile business logic in the `pkg/apis` and `pkg/controller` respectively, +**then run** `kubebuilder generate`. For more on this see [What is a Controller](basics/what_is_a_controller.md) +and [What is a Resource](basics/what_is_a_resource.md) + +{% sample lang="bash" %} +```bash +kubebuilder create resource --group ships --version v1beta1 --kind Sloop +``` +{% endmethod %} + +{% method %} + +#### Locally Running An API + +**Optional:** Create a new [minikube](https://github.com/kubernetes/minikube) cluster for development. + +Build and run your API by installing the CRD into the cluster and starting the controller as a local +process on your dev machine. + +Create a new instance of your API and look at the controller-manager output. + +{% sample lang="bash" %} +```bash +GOBIN=${PWD}/bin go install ${PWD#$GOPATH/src/}/cmd/controller-manager +bin/controller-manager --kubeconfig ~/.kube/config +``` + +> In a new terminal create an instance of your API + +```bash +kubectl apply -f hack/sample/sloop.yaml +``` +{% endmethod %} + +{% method %} + +#### Adding Schema and Business Logic + +Further your API schema and resource, then run `kubebuilder generate`. + +{% sample lang="bash" %} +```bash +nano -w pkg/apis/ship/v1beta1/sloop_types.go +... +nano -w pkg/controller/sloop/controller.go +... +kubebuilder generate +``` +{% endmethod %} + +## Publishing + +{% method %} + +#### Integration Testing + +Run the generated integration tests for your APIS. + +{% sample lang="bash" %} +```bash +go test ./pkg/... +``` +{% endmethod %} + +{% method %} + +#### Controller-Manager Container and Installation YAML + +- Build and push a container image. +- Create installation config for your API +- Install with kubectl apply + +{% sample lang="bash" %} + +```bash +docker build . -f Dockerfile.controller -t gcr.io/kubeships/controller-manager:v1 +kubebuilder create config --controller-image gcr.io/kubeships/controller-manager:v1 --name kubeships +``` + +```bash +gcloud auth configure-docker +docker push gcr.io/kubeships/controller-manager:v1 +``` + +```bash +kubectl apply -f hack/install.yaml +``` +{% endmethod %} + +{% method %} + +#### API Documentation + +Generate documentation: + +- Create an example of your API +- Generate the docs +- View the generated docs at `docs/reference/build/index.html` + +{% sample lang="bash" %} +```bash +kubebuilder create example --version v1beta1 --group ships.k8s.io --kind Sloop +nano -w docs/reference/examples/sloop/sloop.yaml +... +``` + +```bash +kubebuilder docs +``` +{% endmethod %} \ No newline at end of file diff --git a/docs/gif/implementapi.gif b/docs/gif/implementapi.gif new file mode 100644 index 0000000000..2643ce4a64 Binary files /dev/null and b/docs/gif/implementapi.gif differ diff --git a/docs/gif/quickstart.gif b/docs/gif/quickstart.gif new file mode 100644 index 0000000000..ac3499b204 Binary files /dev/null and b/docs/gif/quickstart.gif differ