Add metrics for iptables operations

This commit is contained in:
Alex Stockinger 2022-07-25 14:27:11 +00:00
parent cb238c85a1
commit 5f29355cb7
5 changed files with 121 additions and 8 deletions

View File

@ -245,7 +245,7 @@ func runRoot(_ *cobra.Command, _ []string) error {
if port < 1 || port > 1<<16-1 {
return fmt.Errorf("invalid port: port mus be in range [%d:%d], but got %d", 1, 1<<16-1, port)
}
m, err := mesh.New(b, enc, gr, hostname, port, s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, iptablesForwardRule, log.With(logger, "component", "kilo"))
m, err := mesh.New(b, enc, gr, hostname, port, s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, iptablesForwardRule, log.With(logger, "component", "kilo"), registry)
if err != nil {
return fmt.Errorf("failed to create Kilo mesh: %v", err)
}

View File

@ -16,6 +16,7 @@ package iptables
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"io"
"net"
"os"
@ -254,7 +255,7 @@ func WithClients(v4, v6 Client) ControllerOption {
// New generates a new iptables rules controller.
// If no options are given, IPv4 and IPv6 clients
// will be instantiated using the regular iptables backend.
func New(opts ...ControllerOption) (*Controller, error) {
func New(registerer prometheus.Registerer, opts ...ControllerOption) (*Controller, error) {
c := &Controller{
errors: make(chan error),
logger: log.NewNopLogger(),
@ -267,7 +268,7 @@ func New(opts ...ControllerOption) (*Controller, error) {
if err != nil {
return nil, fmt.Errorf("failed to create iptables IPv4 client: %v", err)
}
c.v4 = v4
c.v4 = wrapWithMetrics(v4, "IPv4", registerer)
}
if c.v6 == nil {
disabled, err := ipv6Disabled()
@ -282,7 +283,7 @@ func New(opts ...ControllerOption) (*Controller, error) {
if err != nil {
return nil, fmt.Errorf("failed to create iptables IPv6 client: %v", err)
}
c.v6 = v6
c.v6 = wrapWithMetrics(v6, "IPv6", registerer)
}
}
return c, nil

View File

@ -15,6 +15,7 @@
package iptables
import (
"github.com/prometheus/client_golang/prometheus"
"testing"
)
@ -84,7 +85,7 @@ func TestSet(t *testing.T) {
},
} {
client := &fakeClient{}
controller, err := New(WithClients(client, client))
controller, err := New(prometheus.NewRegistry(), WithClients(client, client))
if err != nil {
t.Fatalf("test case %q: got unexpected error instantiating controller: %v", tc.name, err)
}
@ -141,7 +142,7 @@ func TestCleanUp(t *testing.T) {
},
} {
client := &fakeClient{}
controller, err := New(WithClients(client, client))
controller, err := New(prometheus.NewRegistry(), WithClients(client, client))
if err != nil {
t.Fatalf("test case %q: got unexpected error instantiating controller: %v", tc.name, err)
}

111
pkg/iptables/metrics.go Normal file
View File

@ -0,0 +1,111 @@
// Copyright 2019 the Kilo authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iptables
import (
"github.com/prometheus/client_golang/prometheus"
)
type metricsClientWrapper struct {
client Client
operationCounter *prometheus.CounterVec
}
func wrapWithMetrics(client Client, protocol string, registerer prometheus.Registerer) Client {
labelNames := []string{
"operation",
"table",
"chain",
}
counter := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "kilo_iptables_operations_total",
Help: "Number of iptables operations.",
ConstLabels: prometheus.Labels{"protocol": protocol},
}, labelNames)
registerer.MustRegister(counter)
return &metricsClientWrapper{client, counter}
}
func (m *metricsClientWrapper) AppendUnique(table string, chain string, rule ...string) error {
m.operationCounter.With(prometheus.Labels{
"operation": "AppendUnique",
"table": table,
"chain": chain,
}).Inc()
return m.client.AppendUnique(table, chain, rule...)
}
func (m *metricsClientWrapper) Delete(table string, chain string, rule ...string) error {
m.operationCounter.With(prometheus.Labels{
"operation": "Delete",
"table": table,
"chain": chain,
}).Inc()
return m.client.Delete(table, chain, rule...)
}
func (m *metricsClientWrapper) Exists(table string, chain string, rule ...string) (bool, error) {
m.operationCounter.With(prometheus.Labels{
"operation": "Exists",
"table": table,
"chain": chain,
}).Inc()
return m.client.Exists(table, chain, rule...)
}
func (m *metricsClientWrapper) List(table string, chain string) ([]string, error) {
m.operationCounter.With(prometheus.Labels{
"operation": "List",
"table": table,
"chain": chain,
}).Inc()
return m.client.List(table, chain)
}
func (m *metricsClientWrapper) ClearChain(table string, chain string) error {
m.operationCounter.With(prometheus.Labels{
"operation": "ClearChain",
"table": table,
"chain": chain,
}).Inc()
return m.client.ClearChain(table, chain)
}
func (m *metricsClientWrapper) DeleteChain(table string, chain string) error {
m.operationCounter.With(prometheus.Labels{
"operation": "DeleteChain",
"table": table,
"chain": chain,
}).Inc()
return m.client.DeleteChain(table, chain)
}
func (m *metricsClientWrapper) NewChain(table string, chain string) error {
m.operationCounter.With(prometheus.Labels{
"operation": "NewChain",
"table": table,
"chain": chain,
}).Inc()
return m.client.NewChain(table, chain)
}
func (m *metricsClientWrapper) ListChains(table string) ([]string, error) {
m.operationCounter.With(prometheus.Labels{
"operation": "ListChains",
"table": table,
"chain": "",
}).Inc()
return m.client.ListChains(table)
}

View File

@ -88,7 +88,7 @@ type Mesh struct {
}
// New returns a new Mesh instance.
func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port int, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr, iptablesForwardRule bool, logger log.Logger) (*Mesh, error) {
func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port int, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr, iptablesForwardRule bool, logger log.Logger, registerer prometheus.Registerer) (*Mesh, error) {
if err := os.MkdirAll(kiloPath, 0700); err != nil {
return nil, fmt.Errorf("failed to create directory to store configuration: %v", err)
}
@ -156,7 +156,7 @@ func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularit
externalIP = publicIP
}
level.Debug(logger).Log("msg", fmt.Sprintf("using %s as the public IP address", publicIP.String()))
ipTables, err := iptables.New(iptables.WithLogger(log.With(logger, "component", "iptables")), iptables.WithResyncPeriod(resyncPeriod))
ipTables, err := iptables.New(registerer, iptables.WithLogger(log.With(logger, "component", "iptables")), iptables.WithResyncPeriod(resyncPeriod))
if err != nil {
return nil, fmt.Errorf("failed to IP tables controller: %v", err)
}