add controllers

change kiali mux to go-restful

add knative

add health api
This commit is contained in:
Jeff
2019-03-20 11:12:40 +08:00
committed by zryfish
parent 4b73883096
commit 867129cdce
14 changed files with 172 additions and 132 deletions

View File

@@ -68,8 +68,8 @@ func addWebService(c *restful.Container) error {
To(metrics.GetWorkloadMetrics).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get workload metrics from a specific namespace").
Param(webservice.PathParameter("namespace", "name of the namespace")).
Param(webservice.PathParameter("workload", "name of the workload")).
Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)).
Param(webservice.PathParameter("workload", "name of the workload").Required(true)).
Param(webservice.QueryParameter("filters[]", "type of metrics type, e.g. request_count, request_duration, request_error_count")).
Param(webservice.QueryParameter("queryTime", "from which UNIX time to extract metrics")).
Param(webservice.QueryParameter("duration", "metrics duration, in seconds")).
@@ -87,7 +87,7 @@ func addWebService(c *restful.Container) error {
To(metrics.GetNamespaceMetrics).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get workload metrics from a specific namespace").
Param(webservice.PathParameter("namespace", "name of the namespace")).
Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)).
Param(webservice.QueryParameter("filters[]", "type of metrics type, e.g. request_count, request_duration, request_error_count")).
Param(webservice.QueryParameter("queryTime", "from which UNIX time to extract metrics")).
Param(webservice.QueryParameter("duration", "metrics duration, in seconds")).
@@ -105,7 +105,7 @@ func addWebService(c *restful.Container) error {
To(metrics.GetNamespaceGraph).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get service graph for a specific namespace").
Param(webservice.PathParameter("namespace", "name of a namespace")).
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
Param(webservice.QueryParameter("graphType", "type of the generated service graph, eg. ")).
Param(webservice.QueryParameter("groupBy", "group nodes by kind")).
Param(webservice.QueryParameter("queryTime", "from which time point, default now")).
@@ -118,7 +118,7 @@ func addWebService(c *restful.Container) error {
To(metrics.GetNamespacesGraph).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get service graph for a specific namespace").
Param(webservice.PathParameter("namespace", "name of a namespace")).
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
Param(webservice.QueryParameter("graphType", "type of the generated service graph, eg. ")).
Param(webservice.QueryParameter("groupBy", "group nodes by kind")).
Param(webservice.QueryParameter("queryTime", "from which time point, default now")).
@@ -126,6 +126,39 @@ func addWebService(c *restful.Container) error {
Param(webservice.QueryParameter("namespaces", "names of namespaces")).
Writes(errors.Error{})).Produces(restful.MIME_JSON)
// Get workloads health
webservice.Route(webservice.GET("/namespaces/{namespace}/workloads/{workload}/health").
To(metrics.GetWorkloadHealth).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get workload health").
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
Param(webservice.PathParameter("workload", "workload name").Required(true)).
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
Writes(errors.Error{})).Produces(restful.MIME_JSON)
// Get app health
webservice.Route(webservice.GET("/namespaces/{namespace}/apps/{app}/health").
To(metrics.GetAppHealth).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get workload health").
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
Param(webservice.PathParameter("app", "app name").Required(true)).
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
Writes(errors.Error{})).Produces(restful.MIME_JSON)
// Get service health
webservice.Route(webservice.GET("/namespaces/{namespace}/services/{service}/health").
To(metrics.GetServiceHealth).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get workload health").
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
Param(webservice.PathParameter("service", "service name").Required(true)).
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
Writes(errors.Error{})).Produces(restful.MIME_JSON)
c.Add(webservice)
return nil

View File

@@ -23,7 +23,7 @@ import (
)
const (
ApiRootPath = "/apis"
ApiRootPath = "/kapis"
)
// container holds all webservice of apiserver

View File

@@ -48,3 +48,18 @@ func GetNamespaceGraph(request *restful.Request, response *restful.Response) {
func GetNamespacesGraph(request *restful.Request, response *restful.Response) {
handlers.GraphNamespaces(request, response)
}
// Get workload health
func GetWorkloadHealth(request *restful.Request, response *restful.Response) {
handlers.WorkloadHealth(request, response)
}
// Get app health
func GetAppHealth(request *restful.Request, response *restful.Response) {
handlers.AppHealth(request, response)
}
// Get service health
func GetServiceHealth(request *restful.Request, response *restful.Response) {
handlers.ServiceHealth(request, response)
}

View File

@@ -139,10 +139,6 @@ func (v *DestinationRuleController) Run(workers int, stopCh <-chan struct{}) {
go wait.Until(v.worker, v.workerLoopPeriod, stopCh)
}
go func() {
defer utilruntime.HandleCrash()
}()
<-stopCh
}
@@ -222,9 +218,9 @@ func (v *DestinationRuleController) syncService(key string) error {
}
subset := v1alpha3.Subset{
Name: util.NormalizeVersionName(name),
Name: util.NormalizeVersionName(version),
Labels: map[string]string{
util.VersionLabel: name,
util.VersionLabel: version,
},
}
@@ -239,10 +235,15 @@ func (v *DestinationRuleController) syncService(key string) error {
Name: service.Name,
Labels: service.Labels,
},
Spec: v1alpha3.DestinationRuleSpec{
Host: name,
},
}
} else {
log.Error(err, "Couldn't get destinationrule for service", "key", key)
return err
}
log.Error(err, "Couldn't get destinationrule for service", "key", key)
return err
}
createDestinationRule := len(currentDestinationRule.Spec.Subsets) == 0

View File

@@ -18,6 +18,7 @@ func getAppNameByStrategy(strategy *v1alpha2.Strategy) string {
return ""
}
// if virtualservice not specified with port number, then fill with service first port
func fillDestinationPort(vs *v1alpha3.VirtualService, service *v1.Service) error {
if len(service.Spec.Ports) == 0 {
@@ -27,14 +28,22 @@ func fillDestinationPort(vs *v1alpha3.VirtualService, service *v1.Service) error
// fill http port
for i := range vs.Spec.Http {
for j := range vs.Spec.Http[i].Route {
vs.Spec.Http[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
if vs.Spec.Http[i].Route[j].Destination.Port.Number == 0 {
vs.Spec.Http[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
}
}
if vs.Spec.Http[i].Mirror != nil && vs.Spec.Http[i].Mirror.Port.Number == 0 {
vs.Spec.Http[i].Mirror.Port.Number = uint32(service.Spec.Ports[0].Port)
}
}
// fill tcp port
for i := range vs.Spec.Tcp {
for j := range vs.Spec.Tcp[i].Route {
vs.Spec.Tcp[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
if vs.Spec.Tcp[i].Route[j].Destination.Port.Number == 0 {
vs.Spec.Tcp[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
}
}
}

View File

@@ -16,7 +16,6 @@ const (
// resource with these following labels considered as part of servicemesh
var ApplicationLabels = [...]string{
ApplicationNameLabel,
ApplicationVersionLabel,
ServiceMeshEnabledLabel,
AppLabel,
}

View File

@@ -128,7 +128,7 @@ func NewVirtualServiceController(serviceInformer coreinformers.ServiceInformer,
}
func (v *VirtualServiceController) Start(stopCh <-chan struct{}) error {
v.Run(5, stopCh)
v.Run(1, stopCh)
return nil
}
@@ -147,10 +147,6 @@ func (v *VirtualServiceController) Run(workers int, stopCh <-chan struct{}) {
go wait.Until(v.worker, v.workerLoopPeriod, stopCh)
}
go func() {
defer utilruntime.HandleCrash()
}()
<-stopCh
}
@@ -202,7 +198,6 @@ func (v *VirtualServiceController) syncService(key string) error {
if err != nil && !errors.IsNotFound(err) {
return err
}
return nil
}
@@ -278,9 +273,7 @@ func (v *VirtualServiceController) syncService(key string) error {
if len(vs.Spec.Http) > 0 || len(vs.Spec.Tcp) > 0 {
_, err := v.virtualServiceClient.NetworkingV1alpha3().VirtualServices(namespace).Create(vs)
if err != nil {
v.eventRecorder.Eventf(vs, v1.EventTypeWarning, "FailedToCreateVirtualService", "Failed to create virtualservice for service %v/%v: %v", service.Namespace, service.Name, err)
log.Error(err, "create virtualservice for service failed.", "service", service)
return err
}
@@ -288,7 +281,6 @@ func (v *VirtualServiceController) syncService(key string) error {
log.Info("service doesn't have a tcp port.")
return nil
}
}
return nil
@@ -328,7 +320,6 @@ func (v *VirtualServiceController) addDestinationRule(obj interface{}) {
func (v *VirtualServiceController) deleteStrategy(obj interface{}) {
// nothing to do right now
}
func (v *VirtualServiceController) handleErr(err error, key interface{}) {
@@ -343,7 +334,7 @@ func (v *VirtualServiceController) handleErr(err error, key interface{}) {
return
}
log.V(0).Info("Dropping service %q out of the queue: %v", "key", key, "error", err)
log.V(4).Info("Dropping service out of the queue.", "key", key, "error", err)
v.queue.Forget(key)
utilruntime.HandleError(err)
}

View File

@@ -20,13 +20,10 @@ package k8s
import (
"flag"
"fmt"
"log"
"os"
"sync"
"github.com/mitchellh/go-homedir"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
@@ -37,10 +34,12 @@ var (
k8sClient *kubernetes.Clientset
k8sClientOnce sync.Once
KubeConfig *rest.Config
masterURL string
)
func init() {
flag.StringVar(&kubeConfigFile, "kubeconfig", fmt.Sprintf("%s/.kube/config", os.Getenv("HOME")), "path to kubeconfig file")
flag.StringVar(&kubeConfigFile, "kubeconfig", "", "path to kubeconfig file")
flag.StringVar(&masterURL, "master-url","", "kube-apiserver url, only needed when out of cluster")
}
func Client() *kubernetes.Clientset {
@@ -63,18 +62,8 @@ func Client() *kubernetes.Clientset {
func Config() (kubeConfig *rest.Config, err error) {
if kubeConfigFile == "" {
if env := os.Getenv("KUBECONFIG"); env != "" {
kubeConfigFile = env
} else {
if home, err := homedir.Dir(); err == nil {
kubeConfigFile = fmt.Sprintf("%s/.kube/config", home)
}
}
}
if _, err = os.Stat(kubeConfigFile); err == nil {
kubeConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfigFile)
kubeConfig, err = clientcmd.BuildConfigFromFlags(masterURL, kubeConfigFile)
} else {
kubeConfig, err = rest.InClusterConfig()
}

View File

@@ -19,9 +19,10 @@ package namespace
import (
"fmt"
"github.com/golang/glog"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"time"
"github.com/golang/glog"
corev1 "k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
@@ -36,6 +37,8 @@ import (
"k8s.io/client-go/util/workqueue"
)
var log = logf.Log.WithName("namespace-controller")
const threadiness = 2
var (
@@ -54,18 +57,18 @@ type NamespaceController struct {
}
func NewNamespaceController(
kubeclientset kubernetes.Interface,
clientset kubernetes.Interface,
namespaceInformer coreinformers.NamespaceInformer,
roleInformer rbacinformers.RoleInformer) *NamespaceController {
controller := &NamespaceController{
clientset: kubeclientset,
clientset: clientset,
namespaceInformer: namespaceInformer,
roleInformer: roleInformer,
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespaces"),
}
glog.Info("setting up event handlers")
log.V(3).Info("setting up event handlers")
namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.handleObject,
@@ -86,29 +89,24 @@ func NewNamespaceController(
}
func (c *NamespaceController) Start(stopCh <-chan struct{}) error {
go func() {
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
// Start the informer factories to begin populating the informer caches
glog.Info("starting namespace controller")
log.V(3).Info("starting namespace controller")
defer glog.Info("shutting down namespace controller")
// Wait for the caches to be synced before starting workers
glog.Info("waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
}
// Wait for the caches to be synced before starting workers
log.Info("waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
}
glog.Info("starting workers")
log.V(3).Info("starting workers")
for i := 0; i < threadiness; i++ {
go wait.Until(c.runWorker, time.Second, stopCh)
}
for i := 0; i < threadiness; i++ {
go wait.Until(c.runWorker, time.Second, stopCh)
}
glog.Info("started workers")
<-stopCh
glog.Info("shutting down workers")
}()
<-stopCh
return nil
}
@@ -142,7 +140,7 @@ func (c *NamespaceController) processNextWorkItem() bool {
}
c.workqueue.Forget(obj)
glog.Infof("successfully namespace synced '%s'", namespace)
log.V(4).Info("successfully namespace synced ", "namespace", namespace)
return nil
}(obj)