tailscalesd

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 24, 2023 License: MIT Imports: 14 Imported by: 0

README

TailscaleSD - Prometheus Service Discovery for Tailscale

Serves Prometheus HTTP Service Discovery for devices on a Tailscale Tailnet.

For details on HTTP Service Discovery, read the Prometheus docs: https://prometheus.io/docs/prometheus/latest/http_sd/

Usage

The tailscalesd server is very simple. It serves the SD payload at / on its HTTP server. It respects the following configuration parameters, each of which may be specified as a flag or an environment variable.

As of v0.2.1 the the local and public APIs are no longer mutually exclusive. Setting the -localapi flag and providing -tailnet + -token will result in a union of targets from both APIs.

  • -address / ADDRESS is the host:port on which to serve TailscaleSD. Defaults to 0.0.0.0:9242.
  • -ipv6 / EXPOSE_IPV6 instructs TailscaleSD to include IPv6 addresses in the target list. Be careful with this, the colons in IPv6 addresses wreak havoc with Prometheus configurations!
  • -localapi / TAILSCALE_USE_LOCAL_API instructs TailscaleSD to use the tailscaled-exported local API for discovery.
  • -localapi_socket / TAILSCALE_LOCAL_API_SOCKET is the path to the Unix domain socket over which tailscaled serves the local API.
  • -poll / TAILSCALE_API_POLL_LIMIT is the limit of how frequently the Tailscale API may be polled. Cached results are served between intervals. Defaults to 5 minutes. Also applies to local API.
  • -tailnet / TAILNET is the name of the tailnet to enumerate. Required when using the public API.
  • -token / TAILSCALE_API_TOKEN is a Tailscale API token with appropriate permissions to access the Tailscale API and enumerate devices. Required when using the public API.
$ TAILSCALE_API_TOKEN=SUPERSECRET tailscalesd --tailnet alice@gmail.com
2021-08-04T15:38:14Z Serving Tailscale service discovery on "0.0.0.0:9242"
Public vs Local API

TailscaleSD is capable of discovering devices both from Tailscale's public API, and from the local API served by tailscaled on the node on which TailscaleSD is run. By using the public API, TailscaleSD will dicover all devices in the tailnet, regardless of whether the local node is able to reach them or not. Devices found using the local API will be reachable from the local node, according to your Tailscale ACLs.

See the label comments in tailscalesd.go for details about which labels are supported for each API type. Do not assume they will be the same labels, or that values will match across the APIs!

Metrics

As of v0.2.1, TailscaleSD exports Prometheus metrics on the standard /metrics endpoint. In addition to the standard Go metrics, you will find TailscaleSD-specific metrics defined in metrics.go. The metrics are targetted at understanding the behavior of TailscaleSD itself. Contributions of additional interesting metrics are welcome, but please remember that details about your devices should be handled by your monitoring. This is a target discovery tool, not a Prometheus exporter for Tailscale!

Prometheus Configuration

Configure Prometheus by placing the tailscalesd URL in a http_sd_configs block in a scrape_config. The following labels are potentially made available for all Tailscale nodes discovered, however any label for which the Tailscale API did not return a value will be omitted. For more details on each field and the API in general, see: https://github.com/tailscale/tailscale/blob/main/api.md#tailnet-devices-get

Possible target labels follow. See the label comments in tailscalesd.go for details. There will be one target entry for each unique combination of all labels.

  • __meta_tailscale_api
  • __meta_tailscale_device_authorized
  • __meta_tailscale_device_client_version
  • __meta_tailscale_device_hostname
  • __meta_tailscale_device_id
  • __meta_tailscale_device_name
  • __meta_tailscale_device_os
  • __meta_tailscale_device_tag
  • __meta_tailscale_tailnet
Example: Pinging Tailscale Hosts

In the example below, Prometheus will discover Tailscale nodes and attempt to ping them using a blackbox exporter.

---
global:
  scrape_interval: 1m
scrape_configs:
- job_name: tailscale-prober
    metrics_path: /probe
    params:
      module: [icmp]
    http_sd_configs:
      - url: http://localhost:9242/
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - source_labels: [__meta_tailscale_device_hostname]
        target_label: tailscale_hostname
      - source_labels: [__meta_tailscale_device_name]
        target_label: tailscale_name
      - target_label: __address__
        replacement: your.blackbox.exporter:9115
Example: Scraping Node Exporter from Tailscale Hosts

This example appends the node exporter port 9100 to the addresses returned from the Tailscale API, and instructs Prometheus to collect those metrics. This is likely to result in many "down" targets if your tailnet contains hosts without the node exporter. It also doesn't play well with IPv6 addresses.

---
global:
  scrape_interval: 1m
scrape_configs:
- job_name: tailscale-node-exporter
    http_sd_configs:
      - url: http://localhost:9242/
    relabel_configs:
      - source_labels: [__meta_tailscale_device_hostname]
        target_label: tailscale_hostname
      - source_labels: [__meta_tailscale_device_name]
        target_label: tailscale_name
      - source_labels: [__address__]
        regex: '(.*)'
        replacement: $1:9100
        target_label: __address__

Documentation

Overview

Package tailscalesd provides Prometheus Service Discovery for Tailscale using a naive, bespoke Tailscale API client supporting both the public v2 and local APIs. It has only the functionality needed for tailscalesd. You should not be tempted to use it for anything else.

Index

Constants

View Source
const (
	// LabelMetaAPI is the host which provided the details about this device.
	// Will be "localhost" for the local API.
	LabelMetaAPI = "__meta_tailscale_api"

	// LabelMetaDeviceAuthorized is whether the target is currently authorized
	// on the Tailnet. Will always be true when using the local API.
	LabelMetaDeviceAuthorized = "__meta_tailscale_device_authorized"

	// LabelMetaDeviceClientVersion is the Tailscale client version in use on
	// target. Not reported when using the local API.
	LabelMetaDeviceClientVersion = "__meta_tailscale_device_client_version"

	// LabelMetaDeviceHostname is the short hostname of the device.
	LabelMetaDeviceHostname = "__meta_tailscale_device_hostname"

	// LabelMetaDeviceID is the target's unique ID within Tailscale, as reported
	// by the API. The public API reports this as a large integer. The local API
	// reports a base64 string.
	// string.
	LabelMetaDeviceID = "__meta_tailscale_device_id"

	// LabelMetaDeviceName is the name of the device as reported by the API. Not
	// reported when using the local API.
	LabelMetaDeviceName = "__meta_tailscale_device_name"

	// LabelMetaDeviceOS is the OS of the target.
	LabelMetaDeviceOS = "__meta_tailscale_device_os"

	// LabelMetaDeviceTag is a Tailscale ACL tag applied to the target.
	LabelMetaDeviceTag = "__meta_tailscale_device_tag"

	// LabelMetaTailnet is the name of the Tailnet from which this target
	// information was retrieved. Not reported when using the local API.
	LabelMetaTailnet = "__meta_tailscale_tailnet"
)
View Source
const LocalAPISocket = "/run/tailscale/tailscaled.sock"

LocalAPISocket is the path to the Unix domain socket on which tailscaled listens locally.

View Source
const PublicAPIHost = "api.tailscale.com"

PublicAPIHost host for Tailscale.

Variables

This section is empty.

Functions

func Export

func Export(d Discoverer, with ...TargetFilter) http.Handler

Export the Tailscale Discoverer for Service Discovery via HTTP, optionally applying filters to the discovery results.

Types

type Device added in v0.2.0

type Device struct {
	Addresses     []string `json:"addresses"`
	API           string   `json:"api"`
	Authorized    bool     `json:"authorized"`
	ClientVersion string   `json:"clientVersion,omitempty"`
	Hostname      string   `json:"hostname"`
	ID            string   `json:"id"`
	Name          string   `json:"name"`
	OS            string   `json:"os"`
	Tailnet       string   `json:"tailnet"`
	Tags          []string `json:"tags"`
}

Device in a Tailnet, as reported by one of the various Tailscale APIs.

type Discoverer

type Discoverer interface {
	// Devices reported by the Tailscale public API as belonging to the
	// configured tailnet.
	Devices(context.Context) ([]Device, error)
}

Discoverer of things exposed by the various Tailscale APIs.

func LocalAPI added in v0.2.0

func LocalAPI(socket string) Discoverer

LocalAPI Discoverer interrogates the Tailscale localapi for peer devices.

func PublicAPI added in v0.2.0

func PublicAPI(tailnet, token string, opts ...PublicAPIOption) Discoverer

PublicAPI Discoverer polls the public Tailscale API for hosts in the tailnet.

type MultiDiscoverer added in v0.2.1

type MultiDiscoverer []Discoverer

MultiDiscoverer aggregates responses from multiple Discoverers.

func (MultiDiscoverer) Devices added in v0.2.1

func (md MultiDiscoverer) Devices(ctx context.Context) ([]Device, error)

Devices aggregates the results of calling Devices on each contained Discoverer. Returns the first encountered error.

type PublicAPIOption added in v0.2.0

type PublicAPIOption func(*publicAPIDiscoverer)

func WithAPIHost added in v0.2.0

func WithAPIHost(host string) PublicAPIOption

WithAPIHost sets the API base against which the PublicAPI Discoverers will attempt discovery. If not used, defaults to PublicAPIHost.

func WithHTTPClient added in v0.2.0

func WithHTTPClient(client *http.Client) PublicAPIOption

WithHTTPClient is a PublicAPIOption which allows callers to provide a HTTP client to PublicAPI instances. If not used, the defaultHTTPClient is used.

type RateLimitedDiscoverer added in v0.2.0

type RateLimitedDiscoverer struct {
	Wrap      Discoverer
	Frequency time.Duration
	// contains filtered or unexported fields
}

RateLimitedDiscoverer wraps a Discoverer and limits calls to it to be no more frequent than once per Frequency, returning cached values if more frequent calls are made.

func (*RateLimitedDiscoverer) Devices added in v0.2.0

func (c *RateLimitedDiscoverer) Devices(ctx context.Context) ([]Device, error)

type TargetDescriptor

type TargetDescriptor struct {
	Targets []string          `json:"targets"`
	Labels  map[string]string `json:"labels,omitempty"`
}

TargetDescriptor as Prometheus expects it. For more details, see https://prometheus.io/docs/prometheus/latest/http_sd/.

func FilterIPv6Addresses added in v0.2.2

func FilterIPv6Addresses(td TargetDescriptor) TargetDescriptor

FilterIPv6Addresses from TargetDescriptors. Results in only IPv4 targets.

type TargetFilter added in v0.2.2

type TargetFilter func(TargetDescriptor) TargetDescriptor

TargetFilter maniupulates TargetDescriptors before being served.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL