- k8s-api: supports watching and listing default resources (such as Service, Pod, Configmap) and another custom resources definition
 - redis-operator: including a simple master-slave mode which was main based on the resources of k8s.StatefulSet and k8s.Service
 - mysql-operator: the same with the redis-operator
 
- core/v1/interfaces would add the storage plugins(e.g. nfs) later for dynamically creating pv and pvc
 
- ingress controller
 
$ git clone https://github.com/neverCase/k8s-controller-custom-resource.git $ cd k8s-controller-custom-resource # build image $ make mysql $ make redis # compile controller $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o multiplexcrd cmd/multiplex/main.go
$ cat > redis-resource.yaml <<EOF apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: redisoperators.nevercase.io spec: group: nevercase.io version: v1 names: kind: RedisOperator plural: redisoperators scope: Namespaced EOF $ kubectl apply -f redis-resource.yaml customresourcedefinition.apiextensions.k8s.io/redisoperators.nevercase.io created
$ cat > example-redis.yaml <<EOF apiVersion: nevercase.io/v1 kind: RedisOperator metadata: name: example-redis spec: masterSpec: spec: name: "redis-cn1" replicas: 1 image: harbor.domain.com/helix-saga/redis-slave:1.1 imagePullSecrets: - name: private-harbor volumePath: /mnt/nas1 containerPorts: - containerPort: 6379 protocol: TCP servicePorts: - port: 6379 protocol: TCP targetPort: 6379 resources: limits: memory: "1Gi" cpu: "100m" requests: memory: "0.5Gi" cpu: "100m" slaveSpec: spec: name: "redis-cn1" replicas: 4 image: harbor.domain.com/helix-saga/redis-slave:1.1 imagePullSecrets: - name: private-harbor volumePath: /mnt/nas1 containerPorts: - containerPort: 6379 protocol: TCP servicePorts: - port: 6379 protocol: TCP targetPort: 6379 resources: limits: memory: "1Gi" cpu: "100m" requests: memory: "0.5Gi" cpu: "100m" EOF $ kubectl apply -f example-redis.yaml redisoperator.nevercase.io/example-redis created
$ ./multiplexcrd -kubeconfig=$HOME/.kube/config -alsologtostderr=true I0603 14:48:38.844075 20412 controller.go:72] Setting up event handlers I0603 14:48:38.844243 20412 controller.go:195] Starting Foo controller I0603 14:48:38.844249 20412 controller.go:198] Waiting for informer caches to sync I0603 14:48:38.944352 20412 controller.go:209] Starting workers I0603 14:48:38.944366 20412 controller.go:215] Started workers ... I0603 14:48:47.721574 20412 event.go:255] Event(v1.ObjectReference{Kind:"RedisOperator", ... type: 'Normal' reason: 'Synced' Foo synced successfully
$ kubectl get statefulset NAME READY AGE statefulset-redis-demo-master 1/1 46s statefulset-redis-demo-slave 4/4 46s $ kubectl get pod NAME READY STATUS RESTARTS AGE statefulset-redis-demo-master-0 1/1 Running 0 101s statefulset-redis-demo-slave-0 1/1 Running 0 101s statefulset-redis-demo-slave-1 1/1 Running 0 99s statefulset-redis-demo-slave-2 1/1 Running 0 98s statefulset-redis-demo-slave-3 1/1 Running 0 97s $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service-redis-demo-master ClusterIP 10.96.110.148 <none> 6379/TCP 4m38s service-redis-demo-slave ClusterIP 10.96.0.120 <none> 6379/TCP 4m38s
The usage was the same with the RedisOperator.
opt := k8sCoreV1.NewOption(&mysqlOperatorV1.MysqlOperator{}, controllerName, OperatorKindName, mysqlOperatorScheme.AddToScheme(scheme.Scheme), clientSet, fooInformer, fooInformer.Informer(), CompareResourceVersion, Get, Sync, SyncStatus) opts := k8sCoreV1.NewOptions() if err := opts.Add(opt); err != nil { klog.Fatal(err) } op := k8sCoreV1.NewKubernetesOperator(k8sClientSet, stopCh, controllerName, opts) kc := k8sCoreV1.NewKubernetesController(op) ...