Skip to content

Commit

Permalink
Merge pull request #100 from p-strusiewiczsurmacki-mobica/extended-ro…
Browse files Browse the repository at this point in the history
…uting-visability

Added monitoring endpoint
  • Loading branch information
chdxD1 authored May 24, 2024
2 parents daeaedc + 1827b80 commit 9de1c88
Show file tree
Hide file tree
Showing 11 changed files with 1,012 additions and 17 deletions.
22 changes: 21 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

# Image URL to use all building/pushing image targets
IMG ?= ghcr.io/telekom/das-schiff-network-operator:latest
# Sidecar image URL to use all building/pushing image targets
SIDECAR_IMG ?= ghcr.io/telekom/frr-exporter:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.25

Expand Down Expand Up @@ -69,7 +71,7 @@ test: manifests generate fmt vet envtest ## Run tests.
build: generate fmt vet ## Build manager binary.
go build -o bin/manager cmd/manager/main.go

.PHONY: build
.PHONY: sidecar-build
sidecar-build: build
go build -o bin/frr-exporter cmd/frr-exporter/main.go

Expand All @@ -81,10 +83,19 @@ run: manifests generate fmt vet ## Run a controller from your host.
docker-build: test ## Build docker image with the manager.
docker build -t ${IMG} .

.PHONY: docker-build-sidecar
docker-build-sidecar: test ## Build docker image with the manager.
docker build -t ${SIDECAR_IMG} -f frr-exporter.Dockerfile .

.PHONY: docker-push
docker-push: ## Push docker image with the manager.
docker push ${IMG}

.PHONY: docker-push-sidecar
docker-push-sidecar: ## Push docker image with the manager.
docker push ${SIDECAR_IMG}


##@ Release

RELEASE_DIR ?= out
Expand All @@ -108,13 +119,22 @@ endif
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | kubectl apply -f -

.PHONY: install-certs
install-certs: manifests kustomize ## Install certs
$(KUSTOMIZE) build config/certmanager | kubectl apply -f -

.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: uninstall-certs
uninstall-certs: manifests kustomize ## Uninstall certs
$(KUSTOMIZE) build config/certmanager | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
cd config/manager && $(KUSTOMIZE) edit set image frr-exporter=${SIDECAR_IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

.PHONY: undeploy
Expand Down
75 changes: 65 additions & 10 deletions cmd/frr-exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/telekom/das-schiff-network-operator/pkg/frr"
"github.com/telekom/das-schiff-network-operator/pkg/monitoring"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

const (
twenty = 20
)

var (
setupLog = ctrl.Log.WithName("setup")
)

func main() {
var addr string
flag.StringVar(&addr, "listen-address", ":7082", "The address to listen on for HTTP requests.")
Expand All @@ -29,6 +35,42 @@ func main() {
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// Setup a new registry.
reg, err := setupPrometheusRegistry()
if err != nil {
log.Fatal(fmt.Errorf("prometheus registry setup error: %w", err))
}

setupLog.Info("configured Prometheus registry")

endpoint, err := setupMonitoringEndpoint()
if err != nil {
log.Fatal(fmt.Errorf("error configuring monitoring endpoint: %w", err))
}

setupLog.Info("configured monitoring endpoint")

// Expose the registered metrics and monitoring endpoint via HTTP.
mux := setupMux(reg, endpoint)

server := http.Server{
Addr: addr,
ReadHeaderTimeout: twenty * time.Second,
ReadTimeout: time.Minute,
Handler: mux,
}

setupLog.Info("created server, starting...", "Addr", server.Addr,
"ReadHeaderTimeout", server.ReadHeaderTimeout, "ReadTimeout", server.ReadTimeout)

// Run server
err = server.ListenAndServe()
if err != nil {
log.Fatal(fmt.Errorf("failed to start server: %w", err))
}
}

func setupPrometheusRegistry() (*prometheus.Registry, error) {
// Create a new registry.
reg := prometheus.NewRegistry()

Expand All @@ -42,27 +84,40 @@ func main() {
"bpf": false,
})
if err != nil {
log.Fatal(fmt.Errorf("failed to create collector %w", err))
return nil, fmt.Errorf("failed to create collector %w", err)
}
reg.MustRegister(collector)

// Expose the registered metrics via HTTP.
http.Handle("/metrics", promhttp.HandlerFor(
return reg, nil
}

func setupMux(reg *prometheus.Registry, e *monitoring.Endpoint) *http.ServeMux {
mux := e.CreateMux()
mux.Handle("/metrics", promhttp.HandlerFor(
reg,
promhttp.HandlerOpts{
// Opt into OpenMetrics to support exemplars.
EnableOpenMetrics: true,
Timeout: time.Minute,
},
))
server := http.Server{
Addr: addr,
ReadHeaderTimeout: twenty * time.Second,
ReadTimeout: time.Minute,
return mux
}

func setupMonitoringEndpoint() (*monitoring.Endpoint, error) {
clientConfig := ctrl.GetConfigOrDie()
c, err := client.New(clientConfig, client.Options{})
if err != nil {
return nil, fmt.Errorf("error creating controller-runtime client: %w", err)
}
err = server.ListenAndServe()
// Run server

setupLog.Info("loaded kubernetes config")

svcName, svcNamespace, err := monitoring.GetStatusServiceConfig()
if err != nil {
log.Fatal(fmt.Errorf("failed to start server: %w", err))
return nil, fmt.Errorf("error getting status service info: %w", err)
}
setupLog.Info("loaded status service config")

return monitoring.NewEndpoint(c, frr.NewCli(), svcName, svcNamespace), nil
}
1 change: 1 addition & 0 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
resources:
- manager.yaml
- manager_master.yaml
- service.yaml
# - namespace.yaml

generatorOptions:
Expand Down
6 changes: 6 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: STATUS_SVC_NAME
value: network-operator-status
- name: STATUS_SVC_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: frr-exporter:latest
name: frr-exporter
securityContext:
Expand Down
6 changes: 6 additions & 0 deletions config/manager/manager_master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: STATUS_SVC_NAME
value: network-operator-status
- name: STATUS_SVC_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: frr-exporter:latest
name: frr-exporter
securityContext:
Expand Down
15 changes: 15 additions & 0 deletions config/manager/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: status
namespace: system
spec:
type: ClusterIP
clusterIP: None
selector:
app.kubernetes.io/component: worker
app.kubernetes.io/name: network-operator
ports:
- protocol: TCP
port: 7083
targetPort: 7083
12 changes: 12 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ rules:
- list
- update
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- apiGroups:
- ""
resources:
- services
verbs:
- get
- apiGroups:
- network.schiff.telekom.de
resources:
Expand Down
12 changes: 6 additions & 6 deletions pkg/frr/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func getVRFInfo(vrf string) (name string, isMulti bool) {
return vrf, false
}

func (frr *Cli) executeWithJSON(args []string) []byte {
func (frr *Cli) ExecuteWithJSON(args []string) []byte {
// Ensure JSON is always appended
args = append(args, "json")
return frr.execute(args)
Expand All @@ -51,7 +51,7 @@ func (frr *Cli) execute(args []string) []byte {

func (frr *Cli) ShowEVPNVNIDetail() (EVPNVniDetail, error) {
evpnInfo := EVPNVniDetail{}
data := frr.executeWithJSON([]string{
data := frr.ExecuteWithJSON([]string{
"show",
"evpn",
"vni",
Expand All @@ -66,7 +66,7 @@ func (frr *Cli) ShowEVPNVNIDetail() (EVPNVniDetail, error) {

func (frr *Cli) ShowBGPSummary(vrf string) (BGPVrfSummary, error) {
vrfName, multiVRF := getVRFInfo(vrf)
data := frr.executeWithJSON([]string{
data := frr.ExecuteWithJSON([]string{
"show",
"bgp",
"vrf",
Expand All @@ -93,7 +93,7 @@ func (frr *Cli) ShowBGPSummary(vrf string) (BGPVrfSummary, error) {

func (frr *Cli) showVRFVnis() (VrfVni, error) {
vrfInfo := VrfVni{}
vrfVniData := frr.executeWithJSON([]string{
vrfVniData := frr.ExecuteWithJSON([]string{
"show",
"vrf",
"vni",
Expand Down Expand Up @@ -204,15 +204,15 @@ func (frr *Cli) ShowVRFs(vrfName string) (VrfVni, error) {
}

func (frr *Cli) getDualStackRouteSummaries(vrf string) (routeSummariesV4, routeSummariesV6 RouteSummaries, err error) {
dataV4 := frr.executeWithJSON([]string{
dataV4 := frr.ExecuteWithJSON([]string{
"show",
"ip",
"route",
"vrf",
vrf,
"summary",
})
dataV6 := frr.executeWithJSON([]string{
dataV6 := frr.ExecuteWithJSON([]string{
"show",
"ipv6",
"route",
Expand Down
Loading

0 comments on commit 9de1c88

Please sign in to comment.