2
Makefile
2
Makefile
@@ -1,6 +1,8 @@
|
||||
|
||||
# Image URL to use all building/pushing image targets
|
||||
IMG ?= localhost:5000/monitor
|
||||
|
||||
# Makefile
|
||||
CONTROLLER_GEN = bin/controller-gen
|
||||
|
||||
CI_COMMIT ?= $(shell git rev-parse --short HEAD)
|
||||
|
||||
1
apis/v1/crd_types.go
Normal file
1
apis/v1/crd_types.go
Normal file
@@ -0,0 +1 @@
|
||||
package v1
|
||||
18
apis/v1/groupversion_info.go
Normal file
18
apis/v1/groupversion_info.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=demo.io
|
||||
package v1
|
||||
|
||||
import (
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = ctrl.GroupVersion{Group: "demo.io", Version: "v1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &ctrl.SchemeBuilder{GroupVersion: GroupVersion}
|
||||
|
||||
// AddToScheme adds the types in this group-version to the given scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
@@ -3,18 +3,15 @@ namespace: kube-system
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
|
||||
namePrefix: monitor-
|
||||
namePrefix: demo-
|
||||
|
||||
commonLabels:
|
||||
app: monitor
|
||||
app: demo
|
||||
|
||||
resources:
|
||||
- rbac/service_account.yaml
|
||||
- rbac/role.yaml
|
||||
- rbac/leader_election_role.yaml
|
||||
- rbac/role_binding.yaml
|
||||
- webhook/manifests.yaml
|
||||
- webhook/service.yaml
|
||||
- deployment.yaml
|
||||
|
||||
patchesStrategicMerge:
|
||||
@@ -27,5 +24,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: controller
|
||||
newName: localhost:5000/monitor
|
||||
newName: localhost:5000/demo
|
||||
|
||||
|
||||
22
docs/manager.drawio
Normal file
22
docs/manager.drawio
Normal file
@@ -0,0 +1,22 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="MNM1TiEP8gX_f5g81jJT" name="Manager">
|
||||
<mxGraphModel dx="1454" dy="668" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="6" value="<font style="font-size: 20px;">ControllerManager</font>" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=12;align=center;fillColor=#d5e8d4;strokeColor=#82b366;comic=1;labelPosition=center;verticalLabelPosition=top;verticalAlign=bottom;" vertex="1" parent="1">
|
||||
<mxGeometry x="115" y="180" width="190" height="250" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="2" value="<font style="font-size: 20px;" face="Comic Sans MS">Manager</font>" style="rounded=0;whiteSpace=wrap;html=1;comic=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="80" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="<font style="font-size: 20px;" face="Comic Sans MS">Runnables</font>" style="rounded=0;whiteSpace=wrap;html=1;comic=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="240" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="5" value="<font style="font-size: 20px;" face="Comic Sans MS">Clusters</font>" style="rounded=0;whiteSpace=wrap;html=1;comic=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="330" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
1
go.mod
1
go.mod
@@ -6,5 +6,6 @@ require (
|
||||
go.uber.org/zap v1.19.1
|
||||
k8s.io/api v0.23.5
|
||||
k8s.io/apimachinery v0.23.5
|
||||
k8s.io/client-go v0.23.5
|
||||
sigs.k8s.io/controller-runtime v0.11.2
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=demo.io
|
||||
package v1
|
||||
// +groupName=monitor.io
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = ctrl.GroupVersion{Group: "demo.io", Version: "v1"}
|
||||
GroupVersion = ctrl.GroupVersion{Group: "monitor.io", Version: "v1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &ctrl.SchemeBuilder{GroupVersion: GroupVersion}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
|
||||
v1 "monitor/pkg/apis/v1"
|
||||
v1 "monitor/apis/v1"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
11
tests/README.md
Normal file
11
tests/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
```bash
|
||||
|
||||
docker build --network host -t devkitpro/devkita64 - << EOF
|
||||
FROM devkitpro/devkita64:20231108
|
||||
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
|
||||
&& apt-get update && apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/* /usr/share/man/*
|
||||
EOF
|
||||
|
||||
```
|
||||
62
tests/ctrl/main.go
Normal file
62
tests/ctrl/main.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
)
|
||||
|
||||
type podReconcile struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (r *podReconcile) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
rs := &appsv1.ReplicaSet{}
|
||||
err := r.Get(ctx, req.NamespacedName, rs)
|
||||
if err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
// DoSometing
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *podReconcile) InjectClient(c client.Client) error {
|
||||
r.Client = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
log := ctrl.Log.WithName("entrypoint")
|
||||
|
||||
// 初始化 manager,同时生成一个默认配置的 Cache
|
||||
mgr, err := ctrl.NewManager(config.GetConfigOrDie(), ctrl.Options{})
|
||||
if err != nil {
|
||||
log.Error(err, "unable to set up overall controller manager")
|
||||
}
|
||||
// 注册 scheme
|
||||
if err = corev1.AddToScheme(mgr.GetScheme()); err != nil {
|
||||
log.Error(err, "unable to add scheme")
|
||||
}
|
||||
|
||||
// 创建新的 controller
|
||||
err = ctrl.NewControllerManagedBy(mgr).For(&appsv1.ReplicaSet{}).
|
||||
// 当 Pod 变更时,也触发 ReplicaSet
|
||||
Watches(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForObject{}).
|
||||
Complete(&podReconcile{})
|
||||
if err != nil {
|
||||
log.Error(err, "unable to add controller")
|
||||
}
|
||||
|
||||
// 启动 manager
|
||||
if err = mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||
log.Error(err, "unable to run manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
52
tests/informer/informer.go
Normal file
52
tests/informer/informer.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var kubeconfig string
|
||||
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", filepath.Join(homedir.HomeDir(), ".kube", "config"), "(optional) absolute path to the kubeconfig file")
|
||||
flag.Parse()
|
||||
// use the current context in kubeconfig
|
||||
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
AddPod := func(obj interface{}) {
|
||||
|
||||
}
|
||||
DeletePod := func(obj interface{}) {
|
||||
|
||||
}
|
||||
UpdatePod := func(oldObj, newObj interface{}) {
|
||||
|
||||
}
|
||||
|
||||
clientset := kubernetes.NewForConfigOrDie(config)
|
||||
// 基于GVK 操作资源,假设需要操作数十种不同资源时,我们需要为每一种资源实现各自的函数
|
||||
podInformer := informers.NewSharedInformerFactory(clientset, 0).
|
||||
Core().V1().Pods().Informer()
|
||||
podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: AddPod,
|
||||
DeleteFunc: DeletePod,
|
||||
UpdateFunc: UpdatePod,
|
||||
})
|
||||
// 启动informer
|
||||
podInformer.Run(ctx.Done())
|
||||
cache.WaitForCacheSync(ctx.Done(), podInformer.HasSynced)
|
||||
// 此处没有使用workqueue,但一般都是会用workqueue 增强处理逻辑的
|
||||
}
|
||||
55
tests/watch/watch.go
Normal file
55
tests/watch/watch.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var kubeconfig string
|
||||
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", filepath.Join(homedir.HomeDir(), ".kube", "config"), "(optional) absolute path to the kubeconfig file")
|
||||
flag.Parse()
|
||||
// use the current context in kubeconfig
|
||||
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
// 创建 clientset
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// 使用 clientsent 监听 kube-system 下 Pod 对象
|
||||
list, err := clientset.CoreV1().Pods("kube-system").
|
||||
Watch(ctx, metav1.ListOptions{Watch: true})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for event := range list.ResultChan() {
|
||||
pod := event.Object.(*corev1.Pod)
|
||||
switch event.Type {
|
||||
case watch.Added:
|
||||
fmt.Printf("Pod %s added\n", pod.Name)
|
||||
// todo: reconcile logic goes here
|
||||
case watch.Modified:
|
||||
fmt.Printf("Pod %s modified\n", pod.Name)
|
||||
// todo: reconcile logic goes here
|
||||
case watch.Deleted:
|
||||
fmt.Printf("Pod %s deleted\n", pod.Name)
|
||||
// todo: reconcile logic goes here
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user