watch机制是一种非常重要的功能,它允许客户端实时获取Kubernetes集群中资源对象的状态变更通知。
在Kubernetes(K8S)中,watch CRD(CustomResourceDefinition,自定义资源定义)是指客户端实时监听Kubernetes API Server上自定义资源(CRD)的变化情况。这种机制使得开发者可以构建出对自定义资源变化敏感的应用程序,从而自动化地响应这些变化。
创建一个Custom Resource Definition(CRD)的demo涉及几个步骤,包括定义CRD本身、创建CRD资源,以及(可选地)编写一个控制器来监听这些资源的变化并作出响应。
# myapps.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myapps.my.domain
spec:
group: my.domain
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
appName:
type: string
version:
type: string
names:
plural: myapps
singular: myapp
kind: MyApp
shortNames:
- ma
scope: Namespaced
kubectl apply -f myapps.yaml
# myapp-instance.yaml
apiVersion: my.domain/v1
kind: MyApp
metadata:
name: example-myapp
namespace: default
spec:
appName: MyAwesomeApp
version: 1.0.0
使用kubectl来创建这个实例。
kubectl apply -f myapp-instance.yaml
kubectl get myapps -n default
kubectl describe myapp example-myapp -n default
或者,如果定义了短名称,也可以使用短名称来列出实例。
kubectl get ma -n default
// main.go
package main
import (
"flag"
"os"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
// +kubebuilder:scaffold:imports
mycrdsv1 "path/to/your/api/v1" // 替换为你的API包路径
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
// 将你的CRD添加到scheme中
utilruntime.Must(mycrdsv1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}
func main() {
var metricsAddr string
var enableLeaderElection bool
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: 9443,
LeaderElection: enableLeaderElection,
LeaderElectionID: "your-controller-leader-election", // 替换为你的控制器ID
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
// +kubebuilder:scaffold:builder
if err = (&MyCrdReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("MyCrd"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "MyCrd")
os.Exit(1)
}
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
// MyCrdReconciler 是控制器逻辑的实现
// 这里需要自己实现Reconcile方法
type MyCrdReconc