首先安装kubebuilder (我是mac电脑)
#下载
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
#+x
chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/(这个目录随便 就是个可执行文件 放哪里都行)
# 方便使用
echo "export PATH=$PATH:/Users/haoxuanli/go/bin/kubebuilder(你kubebuilder位置)" >> 你的本地profile 比如~/.zshrc
初始化kubebuilder 脚手架
初始化项目
kubebuilder init --domain ksl.com --repo operatorsky
开启多接口组支持
kubuilder edit --multigroup=true
创建api crd 我命名叫 “大car” dacar 也就是大卡车的意思 嗯
kubebuilder create api --group kslgroup01 --version v144 --kind Dacar
目录生成结果如下
在这个文件中定义 dacar 这个crd的spec
api/v144/dacar_types.go
目前只初始化这两个属性就够了
type DacarSpec 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 Dacar. Edit dacar_types.go to remove/update
Replicas int32 `json:"replicas,omitempty"`
Template v1.PodTemplateSpec `json:"template,omitempty"`
}
这是整个文件
api/v144/dacar_types.go
/*
Copyright 2024.
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 v144
import (
v1 "k8s.io/api/core/v1"
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.
// DacarSpec defines the desired state of Dacar
type DacarSpec 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 Dacar. Edit dacar_types.go to remove/update
Replicas int32 `json:"replicas,omitempty"`
Template v1.PodTemplateSpec `json:"template,omitempty"`
}
// DacarStatus defines the observed state of Dacar
type DacarStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// Dacar is the Schema for the dacars API
type Dacar struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DacarSpec `json:"spec,omitempty"`
Status DacarStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// DacarList contains a list of Dacar
type DacarList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Dacar `json:"items"`
}
func init() {
SchemeBuilder.Register(&Dacar{}, &DacarList{})
}
写好这个文件后 直接通过自带的make命令 install 到k8s中
install 如果报错 我这还有个秘方
使用kubebuilder 遇到的 262144 bytes 超长问题
# 学习的话最好先用这2个
make manifest
make install
# 其实一条命令就可以搞定 install 自带make manifest
make install
以上命令需要本地 kubectl 可以操作目标k8s
kubeconf 配置到 ~/.kube/kubeconfig 即可
有了这个dacar类型之后 我们徒手制作一个这个类型的部署文件
apiVersion: kslgroup01.ksl.com/v144
kind: Dacar
metadata:
labels:
app: dacar-demo01
name: dacar-demo01
namespace: default
spec:
replicas: 5
template:
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
apply 这个文件后
我们发现可以查看到这个crd了
haoxuanli@HaoxuandeMacBook-Pro operatorsky % kubectl get dacars
NAME AGE
dacar-demo01 12s
但是 还是看不到 pod
是因为我们没有写这个crd对应的operator
那就写个呗
注意这个operator的位置 dacar_controller.go 这里
主要实现这个reconcile方法就可以了
通过拿到的运行期状态 来跟部署文件的期望状态对比 然后进行不同业务响应就ok了
internal/controller/dacar_controller.go
func (r *DacarReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
// 通过 reconciler 拉取 dacar 状态
// 1. 获取demo的api实例对象
dacar := &kslgroup01v144.Dacar{}
err := r.Get(ctx, req.NamespacedName, dacar)
if err != nil {
logger.Error(err, "unable to fetch Demo")
}
podList := &v1.PodList{}
// 2. 获取当前api对象关联的运行pod
err = r.List(ctx, podList, client.InNamespace(req.Namespace), client.MatchingLabels{"app": dacar.Name})
if err != nil {
logger.Error(err, "")
return ctrl.Result{}, err
}
currentPodCount := len(podList.Items)
// 比较dacar
if int(dacar.Spec.Replicas) > currentPodCount {
for i := 0; i < int(dacar.Spec.Replicas)-currentPodCount; i++ {
pod := &v1.Pod{
ObjectMeta: ctrl.ObjectMeta{
Name: dacar.Name + "-" + uuid.New().String()[0:5] + "666",
Namespace: dacar.Namespace,
Labels: dacar.Labels,
},
Spec: dacar.Spec.Template.Spec,
}
err = ctrl.SetControllerReference(dacar, pod, r.Scheme)
if err != nil {
logger.Error(err, "unable to set ownerReference for Pod")
return ctrl.Result{}, err
}
err = r.Create(ctx, pod)
}
} else {
deleteCount := currentPodCount - int(dacar.Spec.Replicas)
deletePods := podList.Items[:deleteCount]
for _, pod := range deletePods {
err = r.Delete(ctx, &pod)
if err != nil {
logger.Error(err, "unable to delete Pod for Demo")
return ctrl.Result{}, err
}
}
}
return ctrl.Result{}, nil
}
运行operator
由于这个是demo 我们就不把operator部署到集群侧了
直接 make run 启动就可以了 日志不报错 就没啥问题
haoxuanli@HaoxuandeMacBook-Pro operatorsky % make run
/Users/haoxuanli/Documents/GitHub/operatorsky/bin/controller-gen rbac:roleName=manager-role crd=maxDescLen=0 webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/Users/haoxuanli/Documents/GitHub/operatorsky/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./cmd/main.go
2024-08-03T15:25:26+08:00 INFO setup starting manager
2024-08-03T15:25:26+08:00 INFO starting server {"name": "health probe", "addr": "[::]:8081"}
2024-08-03T15:25:26+08:00 INFO Starting EventSource {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar", "source": "kind source: *v144.Dacar"}
2024-08-03T15:25:26+08:00 INFO Starting Controller {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar"}
2024-08-03T15:25:26+08:00 INFO Starting workers {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar", "worker count": 1}
然后这边 kubectl get pod 可以看到如我们所愿 有5个启动的pod 对应了上方的部署文件
haoxuanli@HaoxuandeMacBook-Pro operatorsky % kubectl get po
NAME READY STATUS RESTARTS AGE
dacar-demo01-2c116666 0/1 ContainerCreating 0 59s
dacar-demo01-2e1ca666 0/1 ContainerCreating 0 59s
dacar-demo01-a10ef666 0/1 ContainerCreating 0 59s
dacar-demo01-a41b5666 0/1 ContainerCreating 0 59s
dacar-demo01-def5b666 0/1 ContainerCreating 0 59s
haoxuanli@HaoxuandeMacBook-Pro operatorsky %
好demo结束
## 停止operator 进程
停止那个刚才 make run的进程
## 删除crd
make uninstall
具体需要完整代码的话 可以下方评论找我要