Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
115
plugins/inputs/ipvs/README.md
Normal file
115
plugins/inputs/ipvs/README.md
Normal file
|
@ -0,0 +1,115 @@
|
|||
# IPVS Input Plugin
|
||||
|
||||
This plugin gathers metrics about the [IPVS virtual and real servers][ipvs]
|
||||
using the netlink socket interface of the Linux kernel.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The plugin requires `CAP_NET_ADMIN` and `CAP_NET_RAW` capabilities.
|
||||
> Check the [permissions section](#permissions) for ways to grant them.
|
||||
|
||||
⭐ Telegraf v1.9.0
|
||||
🏷️ network, system
|
||||
💻 linux
|
||||
|
||||
[ipvs]: http://www.linuxvirtualserver.org/software/ipvs.html
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Collect virtual and real server stats from Linux IPVS
|
||||
# This plugin ONLY supports Linux
|
||||
[[inputs.ipvs]]
|
||||
# no configuration
|
||||
```
|
||||
|
||||
### Permissions
|
||||
|
||||
Assuming you installed the Telegraf package via one of the published packages,
|
||||
the process will be running as the `telegraf` user. However, in order for this
|
||||
plugin to communicate over netlink sockets it needs the telegraf process to have
|
||||
`CAP_NET_ADMIN` and `CAP_NET_RAW` capabilities.
|
||||
|
||||
This is the case when running Telegraf as `root` or some user with
|
||||
`CAP_NET_ADMIN` and `CAP_NET_RAW`. Alternatively, you can add the capabilities
|
||||
when starting Telegraf via systemd by running `systemctl edit telegraf.service`
|
||||
and add the following:
|
||||
|
||||
```shell
|
||||
[Service]
|
||||
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
|
||||
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
Server will contain tags identifying how it was configured, using one of
|
||||
`address` + `port` + `protocol` *OR* `fwmark`. This is how one would normally
|
||||
configure a virtual server using `ipvsadm`.
|
||||
|
||||
- ipvs_virtual_server
|
||||
- tags:
|
||||
- sched (the scheduler in use)
|
||||
- netmask (the mask used for determining affinity)
|
||||
- address_family (inet/inet6)
|
||||
- address
|
||||
- port
|
||||
- protocol
|
||||
- fwmark
|
||||
- fields:
|
||||
- connections
|
||||
- pkts_in
|
||||
- pkts_out
|
||||
- bytes_in
|
||||
- bytes_out
|
||||
- pps_in
|
||||
- pps_out
|
||||
- cps
|
||||
|
||||
- ipvs_real_server
|
||||
- tags:
|
||||
- address
|
||||
- port
|
||||
- address_family (inet/inet6)
|
||||
- virtual_address
|
||||
- virtual_port
|
||||
- virtual_protocol
|
||||
- virtual_fwmark
|
||||
- fields:
|
||||
- active_connections
|
||||
- inactive_connections
|
||||
- connections
|
||||
- pkts_in
|
||||
- pkts_out
|
||||
- bytes_in
|
||||
- bytes_out
|
||||
- pps_in
|
||||
- pps_out
|
||||
- cps
|
||||
|
||||
## Example Output
|
||||
|
||||
Virtual server is configured using `fwmark` and backed by 2 real servers:
|
||||
|
||||
```text
|
||||
ipvs_virtual_server,address=172.18.64.234,address_family=inet,netmask=32,port=9000,protocol=tcp,sched=rr bytes_in=0i,bytes_out=0i,pps_in=0i,pps_out=0i,cps=0i,connections=0i,pkts_in=0i,pkts_out=0i 1541019340000000000
|
||||
ipvs_real_server,address=172.18.64.220,address_family=inet,port=9000,virtual_address=172.18.64.234,virtual_port=9000,virtual_protocol=tcp active_connections=0i,inactive_connections=0i,pkts_in=0i,bytes_out=0i,pps_out=0i,connections=0i,pkts_out=0i,bytes_in=0i,pps_in=0i,cps=0i 1541019340000000000
|
||||
ipvs_real_server,address=172.18.64.219,address_family=inet,port=9000,virtual_address=172.18.64.234,virtual_port=9000,virtual_protocol=tcp active_connections=0i,inactive_connections=0i,pps_in=0i,pps_out=0i,connections=0i,pkts_in=0i,pkts_out=0i,bytes_in=0i,bytes_out=0i,cps=0i 1541019340000000000
|
||||
```
|
||||
|
||||
Virtual server is configured using `proto+addr+port` and backed by 2 real
|
||||
servers:
|
||||
|
||||
```text
|
||||
ipvs_virtual_server,address_family=inet,fwmark=47,netmask=32,sched=rr cps=0i,connections=0i,pkts_in=0i,pkts_out=0i,bytes_in=0i,bytes_out=0i,pps_in=0i,pps_out=0i 1541019340000000000
|
||||
ipvs_real_server,address=172.18.64.220,address_family=inet,port=9000,virtual_fwmark=47 inactive_connections=0i,pkts_out=0i,bytes_out=0i,pps_in=0i,cps=0i,active_connections=0i,pkts_in=0i,bytes_in=0i,pps_out=0i,connections=0i 1541019340000000000
|
||||
ipvs_real_server,address=172.18.64.219,address_family=inet,port=9000,virtual_fwmark=47 cps=0i,active_connections=0i,inactive_connections=0i,connections=0i,pkts_in=0i,bytes_out=0i,pkts_out=0i,bytes_in=0i,pps_in=0i,pps_out=0i 1541019340000000000
|
||||
```
|
153
plugins/inputs/ipvs/ipvs.go
Normal file
153
plugins/inputs/ipvs/ipvs.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
//go:build linux
|
||||
|
||||
package ipvs
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/moby/ipvs"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/common/logrus"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type IPVS struct {
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
handle *ipvs.Handle
|
||||
}
|
||||
|
||||
func (*IPVS) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (i *IPVS) Gather(acc telegraf.Accumulator) error {
|
||||
if i.handle == nil {
|
||||
h, err := ipvs.New("") // TODO: make the namespace configurable
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open IPVS handle: %w", err)
|
||||
}
|
||||
i.handle = h
|
||||
}
|
||||
|
||||
services, err := i.handle.GetServices()
|
||||
if err != nil {
|
||||
i.handle.Close()
|
||||
i.handle = nil // trigger a reopen on next call to gather
|
||||
return fmt.Errorf("failed to list IPVS services: %w", err)
|
||||
}
|
||||
for _, s := range services {
|
||||
fields := map[string]interface{}{
|
||||
"connections": s.Stats.Connections,
|
||||
"pkts_in": s.Stats.PacketsIn,
|
||||
"pkts_out": s.Stats.PacketsOut,
|
||||
"bytes_in": s.Stats.BytesIn,
|
||||
"bytes_out": s.Stats.BytesOut,
|
||||
"pps_in": s.Stats.PPSIn,
|
||||
"pps_out": s.Stats.PPSOut,
|
||||
"cps": s.Stats.CPS,
|
||||
}
|
||||
acc.AddGauge("ipvs_virtual_server", fields, serviceTags(s))
|
||||
|
||||
destinations, err := i.handle.GetDestinations(s)
|
||||
if err != nil {
|
||||
i.Log.Errorf("Failed to list destinations for a virtual server: %v", err)
|
||||
continue // move on to the next virtual server
|
||||
}
|
||||
|
||||
for _, d := range destinations {
|
||||
fields := map[string]interface{}{
|
||||
"active_connections": d.ActiveConnections,
|
||||
"inactive_connections": d.InactiveConnections,
|
||||
"connections": d.Stats.Connections,
|
||||
"pkts_in": d.Stats.PacketsIn,
|
||||
"pkts_out": d.Stats.PacketsOut,
|
||||
"bytes_in": d.Stats.BytesIn,
|
||||
"bytes_out": d.Stats.BytesOut,
|
||||
"pps_in": d.Stats.PPSIn,
|
||||
"pps_out": d.Stats.PPSOut,
|
||||
"cps": d.Stats.CPS,
|
||||
}
|
||||
destTags := destinationTags(d)
|
||||
if s.FWMark > 0 {
|
||||
destTags["virtual_fwmark"] = strconv.Itoa(int(s.FWMark))
|
||||
} else {
|
||||
destTags["virtual_protocol"] = protocolToString(s.Protocol)
|
||||
destTags["virtual_address"] = s.Address.String()
|
||||
destTags["virtual_port"] = strconv.Itoa(int(s.Port))
|
||||
}
|
||||
acc.AddGauge("ipvs_real_server", fields, destTags)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// helper: given a Service, return tags that identify it
|
||||
func serviceTags(s *ipvs.Service) map[string]string {
|
||||
ret := map[string]string{
|
||||
"sched": s.SchedName,
|
||||
"netmask": strconv.Itoa(bits.OnesCount32(s.Netmask)),
|
||||
"address_family": addressFamilyToString(s.AddressFamily),
|
||||
}
|
||||
// Per the ipvsadm man page, a virtual service is defined "based on
|
||||
// protocol/addr/port or firewall mark"
|
||||
if s.FWMark > 0 {
|
||||
ret["fwmark"] = strconv.Itoa(int(s.FWMark))
|
||||
} else {
|
||||
ret["protocol"] = protocolToString(s.Protocol)
|
||||
ret["address"] = s.Address.String()
|
||||
ret["port"] = strconv.Itoa(int(s.Port))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// helper: given a Destination, return tags that identify it
|
||||
func destinationTags(d *ipvs.Destination) map[string]string {
|
||||
return map[string]string{
|
||||
"address": d.Address.String(),
|
||||
"port": strconv.Itoa(int(d.Port)),
|
||||
"address_family": addressFamilyToString(d.AddressFamily),
|
||||
}
|
||||
}
|
||||
|
||||
// helper: convert protocol uint16 to human-readable string (if possible)
|
||||
func protocolToString(p uint16) string {
|
||||
switch p {
|
||||
case syscall.IPPROTO_TCP:
|
||||
return "tcp"
|
||||
case syscall.IPPROTO_UDP:
|
||||
return "udp"
|
||||
case syscall.IPPROTO_SCTP:
|
||||
return "sctp"
|
||||
default:
|
||||
return strconv.FormatUint(uint64(p), 10)
|
||||
}
|
||||
}
|
||||
|
||||
// helper: convert addressFamily to a human-readable string
|
||||
func addressFamilyToString(af uint16) string {
|
||||
switch af {
|
||||
case syscall.AF_INET:
|
||||
return "inet"
|
||||
case syscall.AF_INET6:
|
||||
return "inet6"
|
||||
default:
|
||||
return strconv.FormatUint(uint64(af), 10)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("ipvs", func() telegraf.Input {
|
||||
logrus.InstallHook()
|
||||
return &IPVS{}
|
||||
})
|
||||
}
|
33
plugins/inputs/ipvs/ipvs_notlinux.go
Normal file
33
plugins/inputs/ipvs/ipvs_notlinux.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
//go:build !linux
|
||||
|
||||
package ipvs
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type Ipvs struct {
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
}
|
||||
|
||||
func (*Ipvs) SampleConfig() string { return sampleConfig }
|
||||
|
||||
func (i *Ipvs) Init() error {
|
||||
i.Log.Warn("Current platform is not supported")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*Ipvs) Gather(_ telegraf.Accumulator) error { return nil }
|
||||
|
||||
func init() {
|
||||
inputs.Add("ipvs", func() telegraf.Input {
|
||||
return &Ipvs{}
|
||||
})
|
||||
}
|
4
plugins/inputs/ipvs/sample.conf
Normal file
4
plugins/inputs/ipvs/sample.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Collect virtual and real server stats from Linux IPVS
|
||||
# This plugin ONLY supports Linux
|
||||
[[inputs.ipvs]]
|
||||
# no configuration
|
Loading…
Add table
Add a link
Reference in a new issue