kubebuilder學習參考文章:
kubebuilder github
使用 kubebuilder 創(chuàng)建 operator 示例
kubebuilder云原生開發(fā)
一怜校、項目創(chuàng)建
- 創(chuàng)建項目文件目錄
mkdir kubebuilder-example
cd kubebuilder-example
- 初始化module
通過mod管理钢拧,不需要將go項目放在GOPATH目錄下澈驼,但是在通過kubebuilder創(chuàng)建架子之前有送,需要初始化一下go.mod
~/kubebuilder-example go mod init example.io
go: creating new go.mod: module example.io
內容如下
~//kubebuilder-example cat go.mod
module example.io
go 1.14
- kubebuilder腳手架搭建項目
~/kubebuilder-example kubebuilder init --domain example.io
Writing scaffold for you to edit...
Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.5.0
go: downloading sigs.k8s.io/controller-runtime v0.5.0
go: downloading k8s.io/apimachinery v0.17.2
go: downloading k8s.io/client-go v0.17.2
......
Next: define a resource with:
$ kubebuilder create api
創(chuàng)建完成后媳叨,內容如下
~/kubebuilder-example tree
├── Dockerfile
├── Makefile
├── PROJECT
├── bin
│ └── manager
├── config
│ ├── certmanager
│ ├── crd
│ ├── default
│ ├── manager
│ ├── prometheus
│ ├── rbac
│ ├── samples
│ └── webhook
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
└── main.go
創(chuàng)建示例api如下
~/GolandProjects/kubebuilder-example kubebuilder create api --group webapp --version v1 --kind Guestbook
Create Resource [y/n]
y
Create Controller [y/n]
y
Writing scaffold for you to edit...
api/v1/guestbook_types.go
controllers/guestbook_controller.go
......
go build -o bin/manager main.go
創(chuàng)建完成后
~/kubebuilder-example tree
├── Dockerfile
├── Makefile
├── PROJECT
├── api
│ └── v1
│ ├── groupversion_info.go
│ ├── guestbook_types.go
│ └── zz_generated.deepcopy.go
├── bin
│ └── manager
├── config
│ ├── certmanager
│ ├── crd
│ ├── default
│ ├── manager
│ ├── prometheus
│ ├── rbac
│ ├── samples
│ └── webhook
├── controllers
│ ├── guestbook_controller.go
│ └── suite_test.go
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
└── main.go
- 安裝crd
$ make install
本地部署 controller行拢,便于調試
$ make run
將在本地看到調試和輸出
將 controller 部署到 Kubernetes
執(zhí)行下面的命令部署 controller 到 Kubernetes 上旭愧,這一步將會在本地構建 controller 的鏡像辽狈,并推送到 DockerHub 上,然后在 Kubernetes 上部署 Deployment 資源秀鞭。
make docker-build docker-push IMG=woshiwoniu/kubebuilder-example:latest
make deploy IMG=woshiwoniu/kubebuilder-example:latest
在初始化項目時趋观,kubebuilder 會自動根據項目名稱創(chuàng)建一個 Namespace扛禽,如本文中的 kubebuilder-example-system锋边,查看 Deployment 對象和 Pod 資源皱坛。
$ kubectl get deployment -n kubebuilder-example-system
NAME READY UP-TO-DATE AVAILABLE AGE
kubebuilder-example-controller-manager 1/1 1 1 3h26m
$ kubectl get pod -n kubebuilder-example-system
NAME READY STATUS RESTARTS AGE
kubebuilder-example-controller-manager-77b4c685f9-2npz8 2/2 Running 0 3h16m
創(chuàng)建 CR
Kubebuilder 在初始化項目的時候已生成了示例 CR,執(zhí)行下面的命令部署 CR豆巨。
kubectl apply -f config/samples/webapp_v1_guestbook.yaml
執(zhí)行下面的命令查看新創(chuàng)建的 CR剩辟。
$ kubectl get guestbooks.webapp.example.io guestbook-sample -o yaml
至此一個基本的 Operator 框架已經創(chuàng)建完成,但這個 Operator 只是修改了 etcd 中的數據而已往扔,實際上什么事情也沒做贩猎,因為我們沒有在 Operator 中的增加業(yè)務邏輯。
增加業(yè)務邏輯
下面我們將修改 CRD 的數據結構并在 controller 中增加一些日志輸出萍膛。
修改 CRD
我們將修改上文中使用 kubebuilder 命令生成的默認 CRD 配置吭服,在 CRD 中增加 FirstName、LastName 和 Status 字段蝗罗。
下面是修改后的 api/v1/guestbook_types.go 文件的內容艇棕,對應修改的地方已在代碼中注釋說明。
/*
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.
*/
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// GuestbookSpec defines the desired state of Guestbook
type GuestbookSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of Guestbook. Edit Guestbook_types.go to remove/update
// 添加兩個新的字段
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
}
// GuestbookStatus defines the observed state of Guestbook
type GuestbookStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Status string `json:"Status"`
}
// +kubebuilder:object:root=true
// 在這里增加 status 的說明
// +kubebuilder:subresource:status
// Guestbook is the Schema for the guestbooks API
type Guestbook struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec GuestbookSpec `json:"spec,omitempty"`
Status GuestbookStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// GuestbookList contains a list of Guestbook
type GuestbookList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Guestbook `json:"items"`
}
func init() {
SchemeBuilder.Register(&Guestbook{}, &GuestbookList{})
}
上面的代碼比原先使用 kubebuilder 生成的默認代碼增加了以下內容:
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
Status string `json:"Status"`
// +kubebuilder:subresource:status
修改 Reconcile 函數
Reconcile 函數是 Operator 的核心邏輯串塑,Operator 的業(yè)務邏輯都位于 controllers/guestbook_controller.go 文件的 func (r *GuestbookReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) 函數中沼琉。
// +kubebuilder:rbac:groups=webapp.example.io,resources=guestbooks,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=webapp.example.io,resources=guestbooks/status,verbs=get;update;patch
func (r *GuestbookReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
_ = context.Background()
_ = r.Log.WithValues("guestbook", req.NamespacedName)
// your logic here
ctx := context.Background()
_ = r.Log.WithValues("apiexamplea", req.NamespacedName)
// 獲取當前的 CR,并打印
obj := &webappv1.Guestbook{}
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
log.Println(err, "Unable to fetch object")
} else {
log.Println("Geeting from Kubebuilder to", obj.Spec.FirstName, obj.Spec.LastName)
}
// 初始化 CR 的 Status 為 Running
obj.Status.Status = "Running"
if err := r.Status().Update(ctx, obj); err != nil {
log.Println(err, "unable to update status")
}
return ctrl.Result{}, nil
}
這段代碼的業(yè)務邏輯是當發(fā)現(xiàn)有 guestbooks.webapp.example.io 的 CR 變更時桩匪,在控制臺中輸出日志打瘪。
運行測試
修改好 Operator 的業(yè)務邏輯后,再測試一下新的邏輯是否可以正常運行傻昙。
部署 CRD
跟上文的做法一樣闺骚,執(zhí)行下面的命令部署 CRD。
make install
運行 controller
跟上文的做法一樣妆档,執(zhí)行下面的命令運行 controller僻爽。為了方便起見,我們將在本地運行 controller过吻,當然您也可以將其部署到 Kubernetes 上運行进泼。
make run
保持該窗口在前臺運行。
部署 CR
修改 config/samples/webapp_v1_guestbook.yaml 文件中的配置纤虽,將之前默認的foo字段刪除乳绕,添加firstname和lastname。
apiVersion: webapp.example.io/v1
kind: Guestbook
metadata:
name: guestbook-sample
spec:
# Add fields here
firstname: Jimmy
lastname: Song
將其應用到 Kubernetes逼纸。
kubectl apply -f config/samples/webapp_v1_guestbook.yaml
此時轉到上文中運行 controller 的窗口洋措,將在命令行前臺中看到如下輸出。
go fmt ./...
go vet ./...
/Users/test/Workspace/go/bin/controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
go run ./main.go
2020-06-07T16:48:29.966+0800 INFO controller-runtime.metrics metrics server is starting to listen {"addr": ":8080"}
2020-06-07T16:48:29.967+0800 INFO setup starting manager
2020-06-07T16:48:29.967+0800 INFO controller-runtime.manager starting metrics server {"path": "/metrics"}
2020-06-07T16:48:29.967+0800 INFO controller-runtime.controller Starting EventSource {"controller": "guestbook", "source": "kind source: /, Kind="}
2020-06-07T16:48:30.068+0800 INFO controller-runtime.controller Starting Controller {"controller": "guestbook"}
2020-06-07T16:48:30.068+0800 INFO controller-runtime.controller Starting workers {"controller": "guestbook", "worker count": 1}
2020/06/07 16:48:30 Geeting from Kubebuilder to Jimmy Song
2020-06-07T16:48:30.080+0800 DEBUG controller-runtime.controller Successfully Reconciled {"controller": "guestbook", "request": "kubebuilder-example-system/guestbook-sample"}
從上面的日志中杰刽,可以看到這條輸出菠发。
2020/06/07 16:48:30 Geeting from Kubebuilder to Jimmy Song
這正是在 Reconcile 函數中的輸出王滤。
刪除 CR
使用下面的命令刪除 CR,這里的資源類型以Kind的小寫加上apiVersion拼接滓鸠。
kubectl delete guestbooks.webapp.example.io guestbook-sample