vpcinfo

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2021 License: MIT Imports: 13 Imported by: 4

README

vpcinfo Circle CI Go Report Card GoDoc

Experimental model for distributing non-sensitive VPC information.

Motivation

Having access to network topology information is critical to large network infrastructures. However, the solutions for accessing this information are often limited in one way or another. At Segment, we explored multiple approaches to solving this problem, each came with its set of stengths and weaknesses. Overall, there are two ways in which network topology information can be collected and leveraged: within processes maintaining open connections, and out-of-band by some monitoring system.

In-process

Consul has been a popular choice to support advanced network routing models at Segment. Services register and add extra metadata (for example, to describe the availability zone they are part of), and clients use consul to discover targets and apply smart routing like zone-affinity on the traffic.

This model works well and has the advantage to be done on the application side, rich information about the netework routes can be injected in telemetry.

The downside of using a third-party system like Consul is that it is hard to cover resources that it is not deployed on. In today's Cloud infrastructures, we have heterogenous systems, sometimes deployed as managed services, functions, containers, etc... We found it very hard to use systems like Consul to cover all these use cases.

Accessing Cloud provider APIs could be seen as an alternative solution to collect insight into the environment that a program is running in. Unfortunately these APIs are often not designed for heavy read access, and apply low request-rate limits. These limits also apply across the board, so one abusive actor can end up impacting other use cases. In our experience, we have been more successful avoiding to access to Cloud APIs in production systems, reserving them for infrastructure configuration only.

Out-of-band

Many solutions exist that provide network topology information by monitoring network activity (using using techonologies like ebpf). We experimented with a couple of third-party solutions and built some prototypes of our own as well.

The strength of this approach is it applies across an entire infrastructure without having to make code changes to the services being monitored, we were able to quickly get deep insight into some of our networks.

The weakness of this approach is in how much insight can be gathered by the monitoring tool, usually limited to raw data. In our experience, most of the value is in connecting network topology to high-level information that only the applications have access to, because we can then tie product use cases to resource usage.

Design

The solution in this package relies on two components: a Terraform module and a Go package. The focus of this package is only on providing programs access with information about the network they are running in.

Terraform

The repository provides a terraform module that plugs into a cloud VPC and injects DNS TXT records that expose information about the network topology. Data is stored URL-encoded in the TXT records, each record representing one VPC resource.

Here is an example of how to deploy the resources to a VPC on AWS:

module "vpcinfo" {
  source = "git@github.com:segmentio/vpcinfo//aws"
  vpc_id = "${aws_vpc.main.id}"
}
Client

The second component is a Go package which supports querying the TXT records and extracing information from them, adding a smaller caching layer for efficiency since network topology does not change very often. We provide a Go client because this is what most of our infra is built in, but clients can be written in any languages and are pretty simple to construct: DNS client libraries and URL decoders are plenty out there.

Here is an example of looking up the list of subnets in the VPC:

package main

import (
    "fmt"

    "github.com/segmentio/vpcinfo"
)

func main() {
    subnets, _ := vpcinfo.LookupSubnets()

    for _, s := range subnets {
        fmt.Println(s)
    }
}
DNS

We chose to expose the VPC information over DNS because it is a protocol that operating systems have lots of infrastructure for, and DNS clients are usually available in every major programming language, making it simple to build programs that leverage this information.

By default, the Terraform module configures a new DNS zone called vpcinfo.local where DNS records are written. The Go client package is also configured to use this default domain name. Relying on a well-known domain, independent from corporation-specific names, helps deploy this solution in various environments without having to take on extra configuration options in every service that needs access to VPC information.

Documentation

Overview

Package vpcinfo provides APIs to extract VPC information from DNS resolvers.

The library abstract parsing and caching of VPC information resolved from TXT records, as configured by the terraform modules in this repository.

Index

Constants

View Source
const (
	// DefaultDomain is the default domain used when initializing the default
	// resolver.
	DefaultDomain = "vpcinfo.local"
)

Variables

View Source
var DefaultRegistry = &Registry{
	Resolver: ResolverWithDomain(DefaultDomain, net.DefaultResolver),
	Timeout:  2 * time.Second,
	TTL:      1 * time.Minute,
}

DefaultRegistry is the default registry used by top-level functions of this package.

Functions

This section is empty.

Types

type Platform added in v0.1.4

type Platform interface {
	// Returns the name of the platform.
	String() string
	// Returns the zone that the program is running in.
	LookupZone(context.Context) (Zone, error)
}

Platform is an interface representing the VPC platform that the program is running.

func LookupPlatform added in v0.1.3

func LookupPlatform() (Platform, error)

LookupPlatform returns the name of the VPC platform.

type Registry

type Registry struct {
	// The resolver used by this registry.
	//
	// If nil, net.DefaultResolver is used instead.
	Resolver Resolver

	// Time limit for blocking operations ran by this registry.
	//
	// Zero means to apply no limit.
	Timeout time.Duration

	// Limits how long cached entries are retained before attempting to refresh
	// them from the resolver.
	//
	// Defaults to 1 minute.
	TTL time.Duration
	// contains filtered or unexported fields
}

Registry exposes VPC information to the program.

Registry values are intended to be long-lived, they cache the results they observe from the resolver.

Registry values are safe to use concurrently from multiple goroutines.

func (*Registry) LookupPlatform added in v0.1.3

func (r *Registry) LookupPlatform(ctx context.Context) (Platform, error)

LookupPlatform returns the name of the VPC platform, which will be either "aws" or "unknown".

func (*Registry) LookupSubnets

func (r *Registry) LookupSubnets(ctx context.Context) (Subnets, error)

LookupSubnets returns the list of subnets in the VPC.

Multiple calls to this method may return the same Subnets value, programs should treat it as a read-only value and avoid modifying it to prevent race conditions.

func (*Registry) LookupZone added in v0.1.3

func (r *Registry) LookupZone(ctx context.Context) (Zone, error)

LookupZone returns the name of the VPC zone that the program is running in.

type Resolver

type Resolver interface {
	LookupTXT(ctx context.Context, name string) ([]string, error)
}

Resolver is the interface implemented by *net.Resolver, or other resolvers used to lookup VPC information.

func ResolverWithDomain

func ResolverWithDomain(domain string, resolver Resolver) Resolver

ResolverWithDomain wraps the resolver passed as argument to append the given domain to all name lookups.

type Subnet

type Subnet struct {
	ID   string     `name:"subnet"`
	Zone string     `name:"zone"`
	CIDR *net.IPNet `name:"cidr"`
}

Subnet values represent subnets.

func (Subnet) String

func (s Subnet) String() string

type Subnets

type Subnets []Subnet

Subnets is a slice type which represents a list of subnets.

func LookupSubnets

func LookupSubnets() (Subnets, error)

LookupSubnets returns the list of subnets in the VPC.

func (Subnets) Format added in v0.1.9

func (subnets Subnets) Format(w fmt.State, v rune)

Format writes subnets to w using the formatting verb v.

The following formats are supported:

s    formats a human-readable summary of the subnets
v    formats the subnet list as a slice of strings

func (Subnets) LookupAddr added in v0.1.2

func (subnets Subnets) LookupAddr(addr net.Addr) Subnet

LookupAddr returns the subnet that addr belongs to.

func (Subnets) LookupIP added in v0.1.2

func (subnets Subnets) LookupIP(ip net.IP) Subnet

LookupIP returns the subnet that ip belongs to

type Zone added in v0.1.4

type Zone string

Zone is a string type representing infrastructure zones.

func LookupZone added in v0.1.3

func LookupZone() (Zone, error)

LookupZone returns the name of the current VPC zone.

func (Zone) String added in v0.1.4

func (z Zone) String() string

String returns z as a string value, satisfies the fmt.Stringer interface.

Jump to

Keyboard shortcuts

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