Skip to content

Commit

Permalink
WIP : Expose active/inactive connection to service backend as prometh…
Browse files Browse the repository at this point in the history
…eus metrics

putting basic skelton framework to use prometheus

Fixes #5
  • Loading branch information
Murali Reddy committed Jul 15, 2017
1 parent 152ce38 commit 60482bc
Show file tree
Hide file tree
Showing 292 changed files with 49,656 additions and 74 deletions.
60 changes: 60 additions & 0 deletions app/controllers/network_services_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net"
"net/http"
"reflect"
"strconv"
"strings"
Expand All @@ -18,6 +19,8 @@ import (
"github.com/coreos/go-iptables/iptables"
"github.com/golang/glog"
"github.com/mqliang/libipvs"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/vishvananda/netlink"
"k8s.io/client-go/kubernetes"
)
Expand All @@ -27,10 +30,21 @@ const (
IFACE_NOT_FOUND = "Link not found"
IFACE_HAS_ADDR = "file exists"
IPVS_SERVER_EXISTS = "file exists"
namespace = "kube_router"
)

var (
h libipvs.IPVSHandle
serviceBackendActiveConn = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Name: "service_backend_active_connections",
Help: "Active conntection to backend of service",
}, []string{"namespace", "service_name", "backend"})
serviceBackendInactiveConn = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Name: "service_backend_inactive_connections",
Help: "Active conntection to backend of service",
}, []string{"namespace", "service_name", "backend"})
)

// Network services controller enables local node as network service proxy through IPVS/LVS.
Expand All @@ -55,6 +69,8 @@ type NetworkServicesController struct {

// internal representation of kubernetes service
type serviceInfo struct {
name string
namespace string
clusterIP net.IP
port int
protocol string
Expand Down Expand Up @@ -90,6 +106,12 @@ func (nsc *NetworkServicesController) Run(stopCh <-chan struct{}, wg *sync.WaitG
return errors.New("Failed to do add masqurade rule in POSTROUTING chain of nat table due to: %s" + err.Error())
}

// register metrics
prometheus.MustRegister(serviceBackendActiveConn)
prometheus.MustRegister(serviceBackendInactiveConn)
http.Handle("/metrics", promhttp.Handler())
go http.ListenAndServe(":8080", nil)

// enable ipvs connection tracking
err = ensureIpvsConntrack()
if err != nil {
Expand Down Expand Up @@ -132,6 +154,7 @@ func (nsc *NetworkServicesController) sync() {
glog.Errorf("Error syncing hairpin iptable rules: %s", err.Error())
}
nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
nsc.publishMetrics(nsc.serviceMap)
}

// handle change in endpoints update from the API server
Expand Down Expand Up @@ -308,6 +331,41 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
return nil
}

func (nsc *NetworkServicesController) publishMetrics(serviceInfoMap serviceInfoMap) error {
ipvsSvcs, err := h.ListServices()
if err != nil {
return errors.New("Failed to list IPVS services: " + err.Error())
}

for _, svc := range serviceInfoMap {
for _, ipvsSvc := range ipvsSvcs {
if strings.Compare(svc.clusterIP.String(), ipvsSvc.Address.String()) == 0 &&
svc.protocol == ipvsSvc.Protocol.String() && uint16(svc.port) == ipvsSvc.Port {
dsts, err := h.ListDestinations(ipvsSvc)
if err != nil {
glog.Errorf("Failed to get list of servers from ipvs service")
}
for _, dst := range dsts {
serviceBackendActiveConn.WithLabelValues(svc.namespace, svc.name, dst.Address.String()).Set(float64(dst.ActiveConns))
serviceBackendInactiveConn.WithLabelValues(svc.namespace, svc.name, dst.Address.String()).Set(float64(dst.InactConns))
}
}
if strings.Compare(nsc.nodeIP.String(), ipvsSvc.Address.String()) == 0 &&
svc.protocol == ipvsSvc.Protocol.String() && uint16(svc.port) == ipvsSvc.Port {
dsts, err := h.ListDestinations(ipvsSvc)
if err != nil {
glog.Errorf("Failed to get list of servers from ipvs service")
}
for _, dst := range dsts {
serviceBackendActiveConn.WithLabelValues(svc.namespace, svc.name, dst.Address.String()).Set(float64(dst.ActiveConns))
serviceBackendInactiveConn.WithLabelValues(svc.namespace, svc.name, dst.Address.String()).Set(float64(dst.InactConns))
}
}
}
}
return nil
}

func buildServicesInfo() serviceInfoMap {
serviceMap := make(serviceInfoMap)
for _, svc := range watchers.ServiceWatcher.List() {
Expand All @@ -328,6 +386,8 @@ func buildServicesInfo() serviceInfoMap {
port: int(port.Port),
protocol: strings.ToLower(string(port.Protocol)),
nodePort: int(port.NodePort),
name: svc.ObjectMeta.Name,
namespace: svc.ObjectMeta.Namespace,
}

svcInfo.sessionAffinity = (svc.Spec.SessionAffinity == "ClientIP")
Expand Down
33 changes: 30 additions & 3 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ import:
version: master
- package: github.com/aws/aws-sdk-go/
version: ^v1.8.36
- package: github.com/prometheus/client_golang
version: ~0.8.0
11 changes: 11 additions & 0 deletions vendor/github.com/aws/aws-sdk-go/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/github.com/aws/aws-sdk-go/aws/version.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 60482bc

Please sign in to comment.