Commit Graph

412 Commits

Author SHA1 Message Date
Oliver Gould f1210b4947
Decouple reconnect & connect layers from proxy::http::client (#101)
Previously, the `client` module was responsible for instrument
reconnects. Now, the reconnect module becomes its own stack layer that
composes over NewService stacks.

Additionally, the `proxy::http::client` module can now layer over an
underlying Connect stack.
2018-10-11 16:08:25 -07:00
Oliver Gould 978fed1cf6
refactor: Structure the proxy in terms of `Stack` (#100)
As the proxy's functionality has grown, the HTTP routing functionality
has become complex. Module boundaries have become ill-defined, which
leads to tight coupling--especially around the `ctx` metadata types and
`Service` type signatures.

This change introduces a `Stack` type (and subcrate) that is used as the
base building block for proxy functionality. The `proxy` module now
exposes generic components--stack layers--that are configured and
instantiated in the `app::main` module.

This change reorganizes the repo as follows:
- Several auxiliary crates have been split out from the `src/` directory
  into `lib/fs-watch`, `lib/stack` and `lib/task`.
- All logic specific to configuring and running the linkerd2 sidecar
  proxy has been moved into `src/app`. The `Main` type has been moved
  from `src/lib.rs` to `src/app/main.rs`.
- The `src/proxy` has reusable, generic components useful for building
  proxies in terms of `Stack`s.

The logic contained in `lib/bind.rs`, pertaining to per-endpoint service
behavior, has almost entirely been moved into `app::main`.

`control::destination` has changed so that it is not responsible for
building services. (It used to take a clone of `Bind` and use it to
create per-endpoint services). Instead, the destination service
implements the new `proxy::Resolve` trait, which produces an infinite
`Resolution` stream for each lookup. This allows the `proxy::balance`
module to be generic over the servie discovery source.

Furthermore, the `router::Recognize` API has changed to only expose a
`recgonize()` method and not a `bind_service()` method. The
`bind_service` logic is now modeled as a `Stack`.

The `telemetry::http` module has been replaced by a
`proxy::http::metrics` module that is generic over its metadata types
and does not rely on the old telemetry event system. These events are
now a local implementation detail of the `tap` module.

There are no user-facing changes in the proxy's behavior.
2018-10-11 11:25:03 -07:00
Eliza Weisman 51db6f8be8
Change trust-dns-resolver to a version rather than git dependency (#103)
This branch changes the proxy's `trust-dns-resolver` dependency to a
version dependency rather than a Git dependency, since the
`0.10.0-alpha.3` version has the features that we previously required
the git dependency for.

The only changes to the proxy codebase itself were fixes for deprecation
warnings introduced by the dependency upgrade, since it was necessary to
update the minimum `tokio_timer` version as `trust-dns-proto` uses APIs
added in `tokio-timer` v0.2.6. In particular, `tokio_timer::Deadline`
was deprecated and replaced by `Timeout`.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-10-10 13:10:36 -07:00
Oliver Gould 977ff25cb9
Make config variable naming uniform (#99)
There are a few crufty remaining references to the `private` and
`public` proxy interfaces. `private` referred to the pod-local side of
the proxy; and `public` the external side.

These terms have been replaced by `inbound` and `outbound` proxies.

The "private forward address" is now the "inbound forward address".
The "private listener" is now the "outbound listener".
The "public listener" is now the "inbound listener".

This change adds alternate environment variables to support configuration:
- `LINKERD2_PROXY_INBOUND_CONNECT_TIMEOUT`
- `LINKERD2_PROXY_INBOUND_FORWARD`
- `LINKERD2_PROXY_INBOUND_LISTENER`
- `LINKERD2_PROXY_OUTBOUND_CONNECT_TIMEOUT`
- `LINKERD2_PROXY_OUTBOUND_LISTENER`

The old configuration variables have not been removed. Instead, a
warning is logged when such a variable is used to configure the proxy.
2018-10-03 07:51:54 -07:00
Oliver Gould b4ced35838
Fix linkerd2-metrics test compilation (#98)
* Fix linkerd2-metrics test compilation

The `quickcheck` dependency was lost when the subcrate was split out.
This change restores the dependency.

Fixes linkerd/linkerd2#1685

* Run tests for all packages in `make test`
2018-09-18 16:16:56 -07:00
Oliver Gould a4d4110776
Create a `lib` dir for subcrates (#97)
As we extract subcrates from the `src/` directory, the repository root
becomes a bit cluttered. This change moves these subcrates into a `lib`
directory.
2018-09-18 16:02:31 -07:00
Oliver Gould 53a85f442a
Split the `timeout` module into its own subcrate (#96)
The `timeout` module has very little to do with the proxy, specifically.

This change moves it into a dedicated subcrate. This helps to clarify
dependencies and to minimize generic logic in the main proxy crate.

In doing this, an unused implementation of AsyncRead/AsyncWrite for
Timeout was deleted.

Furthermore, the `HumanDuration` type has been copied into
tests/support/mod.rs so that this type need not be part of the timeout
module's public API.
2018-09-18 15:09:31 -07:00
Sean McArthur 0861f968d7 update hyper to v0.12.9
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-09-14 13:36:02 -07:00
Sean McArthur 66d59dafde update http to v0.1.13
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-09-14 13:36:02 -07:00
Oliver Gould 567b1b7ff2
Move bind::NormalizeUri to its own module in proxy::http (#94)
Split proxy infrastructure from `bind`

In order to simplify `bind.rs`, this change moves `NormalizeUri` into
its own module, `proxy::http::normalize_uri`.

This will later become part of the "client stack" built from
`proxy::http`.
2018-09-13 16:43:50 -07:00
Oliver Gould bbf296668b
Move HTTP-specific `proxy` modules into proxy::http (#93)
To prepare to move http-specific proxying logic from bind.rs into
proxy, let's carve out a proxy::http module for HTTP-specific behavior.
2018-09-13 13:45:56 -07:00
Oliver Gould ccd5d21978
Introduce a "server stack" (#90)
Previously, `proxy::Server` was generic over a `NewService` (constructed
in `lib.rs`) that instruments error handling around the router and metrics. In
preparation of adding a metrics module into the server stack (that is configured
by the source connection), `Server` should be changed to instantaneously build
clients with a `MakeClient<Arc<ctx::transport::Server>>`.

In order to do this, the following changes were made:

1. The `svc::NewClient` type was changed to `svc::MakeClient<Target>`. The
    naming change ("New" to "Make") is intended to differentiate the type from
    `NewService`, which is asynchronous and does not accept a `Target` argument.
2. The `proxy::h2_router` module was split from `lib.rs` and `map_err.rs`.  `MapErr`
    tried to be generic, though we only used it in once place. Now, the `h2_router::Make`
    type supports cloning routers and handling their errors.
3. The `TimestampRequestOpen` middleware was split into its own file and given a
    `MakeClient` implementation.
4. The `svc::Layer` trait has been introduced to support layering middlewares like
    `TimestampRequestOpen`. This is analogous to Finagle's `Stack.Module` type.

There are no functional changes.
2018-09-11 16:47:25 -07:00
Oliver Gould 9f9518a98f
Rename `transparency` to `proxy` (#89)
This change clarifies the naming and role of the `proxy` (née transparency)
module. There are no functional changes.

`proxy::tcp::Proxy` has been renamed to `proxy::tcp::Forward` to help
disambiguate terminology: TCP connections may be _forwarded_
by the proxy server.
2018-09-10 16:21:05 -07:00
Oliver Gould 216fe16523
Reorder endpoint-specific HTTP middlewares (#88)
Currently, the layered service implementations that comprise the HTTP
stack are a mix of `Service` and `NewService` types. In the
endpoint-specific stack. `transparency::Client` is the only layer that
actually needs to be a `NewService` if it is wrapped immediately with a
`Reconnect`.

This allows us to remove several `NewService` implementations.

This extracts a new `svc::Reconnect` middleware from `bind`, handling
connection error logging and hiding `tower_reconnect::Error` from outer
layers.

Furthermore, two HTTP/1-specific middlewares have been moved outside of
the TLS rebinding layer, since they are not dependent on TLS
configuration.

Finally, `bind`'s type aliases have been simplified, removing the
`HttpRequest` and `HttpResponse` aliases. By removing these, and
removing `transparency::Client`'s dependency on the telemetry body
types, it should be easier to change type signatures going forward.
2018-09-10 14:27:36 -07:00
Oliver Gould b86694546a
Remove redundant reconnect logic (#87)
`bind::BoundService` wraps a `Reconnect` service and handles its Connect
errors. However, `BoundService` exposes `Reconnect`'s Error type to
callers even though these errors can never be returned.

Furthermore, `Reconnect` is allowed be polled after returning an error,
triggering the inner service to be rebuilt. We needlessly duplicate this
logic in `BoundService`.

Before splitting this file up into smaller chunks, let's update
`BoundService` to more narrowly adhere to `Reconnect`s API:

- Only the inner error type is returned. `unreachable!` assertions
  have been made where error variants cannot be returned.
- Do not "rebind" the stack explicitly. Instead, let `Reconnect` do
  this.
- Now BoundService::call may panic if invoked before poll_ready. It's a
  programming error, since `Reconnect` requires that `poll_ready` be
  called first.
2018-08-31 15:58:28 -07:00
Oliver Gould d98c83404b
Move `control::Bind` to `svc::NewClient` (#86)
The `control::destination` exposes an important trait, `Bind`, that
abstracts the logic of instantiating a new service for an individual
endpoint (i.e., in a load balancer).

This interface is not specific to our service discovery implementation,
and can easily be used to model other types of client factory.

In the spirit of consolidating our HTTP-specific logic, and making the
core APIs of the proxy more visible, this change renames the `Bind`
trait to `NewClient`, simplifies the trait to have fewer type
parameters, and documents this new generalized API.
2018-08-28 15:48:28 -07:00
Oliver Gould 8ea9a3644d
Move telemetry::transport to transport::metrics (#85)
Following #84, the `telemetry::transport` module can be moved into the
`transport` module.

This should allow us to simplify type signatures by combining redundant
types. It's also hoped that we can reduce the API boilerplate around
metrics so it's much easier to instrument and track new metrics in
transport code.
2018-08-24 15:09:36 -07:00
Oliver Gould 8a9a9bf26b
Move telemetry::metrics into dedicated crate (#84)
The `metrics!` macro is currently local to the telemetry module.
Furthermore, the `telemetry::metrics` module no longer has
proxy-specific logic.

This change moves the `telemetry::metrics` module into a new crate,
`linkerd2_metrics`.

This will enable unifying `telemetry::http` and `telemetry::transport`
into `http` and `transport`, respectively.
2018-08-24 14:53:53 -07:00
Oliver Gould d38f686c5e
Move metrics server into control module (#83)
The metrics Service implementation that renders prometheus metrics can
be used independently of any specific listener.

This change moves the binding and listening details into the `control`
module, as this seems like the best umbrella for the specifics of
serving things to the control plane.
2018-08-22 18:49:41 -07:00
Oliver Gould 60683aeca3
Make telemetry::metrics application-agnostic (#82)
Now that transport details have been separated into modules, the
`metrics::Root` type makes more sense as a `telemetry::Report` type.
With this change, the `telemetry::metrics` module holds only the
abstract structural details of metrics reporting.

To this end:
- `metrics::Root` is now `telemetry::Report`
- `metrics::Serve` is now generic over `FmtMetrics`. It's only an
  implementation detail that the `telemetry::Report` type is used.
- all _Report_ types now implement `Clone` so that the main report
  can be cloned for each connection (i.e. from prometheus).
2018-08-22 17:43:17 -07:00
Oliver Gould d6d05905f1
Move metrics eviction into telemetry::http (#81)
The metrics server is responsible for evicting unused metrics, which
seems like an unnecessary coupling with the storage implementation.

This change moves this logic into `telemetry::http` so that the
eviction strategy is specific to the implementation.

Now that the metrics structure is shared internally to `http`,
`Report`'s implementation of `FmtMetrics` can evict expired metrics.

There are no functional changes.
2018-08-22 16:20:51 -07:00
Oliver Gould dfcc0086b8
Hide HTTP telemetry implementation details (#80)
Previously, much of `telemetry::http`'s types and internal
implementation details are exposed to the rest of the telemetry system.
In preparation for further changes to support more granular locking,
this change makes metric storage and recording implementation details.

Following this, `telemetry::http` exposes a `Report` type for printing
metrics to the server and a `Sensors` type used to instrument stacks
with HTTP telemetry. These types share an internally-mutable metrics
registry that is private to the http module.

The `event` types continue to be exposed to support Tap, but the
convenience exports have been removed.

The `metrics::Root` type no longer needs to be shareable. This type will
be replaced in a followup change.
2018-08-22 15:17:11 -07:00
Oliver Gould b0526e4af7
Consolidate HTTP telemetry in telemetry::http (#79)
In preparation for further simplifications to HTTP telemetry, this
change consolidates all HTTP-specific logic under the `telemetry::http`
module.

Specifically, the following modules have been moved:
- `telemetry::event`;
- `telemetry::metrics::labels`;
- `telemetry::metrics::record`;
- `telemetry::sensors`; and
- `telemetry::sensors::http`.

This change takes pains to avoid changing any implementation details, so
some types and methods have been made public temporarily while the
interface boundaries are not well defined. This will be fixed in a
subsequent change.
2018-08-21 15:17:38 -07:00
Oliver Gould 40e9ffcaf8
Require Sensors for Bind (#78)
`Bind` was initially written so that a `Sensors` implementation is
optional. Over time, this hasn't proven to be very useful.

In preparation for further changes to HTTP telemetry, this change
simplifies the Bind and Sensors types so that an HTTP sensor is always
required to construct `Bind`.

Test-only constructors have been added to satisfy the case where Sensors
were omitted.
2018-08-21 10:43:47 -07:00
Oliver Gould 447f3320a7
Record transport telemetry without Events (#76)
Previousy, transport telemetry was recorded by emitting Events from an
IO instance to an aggegator. This requires that each update take a
global telemetry lock, and is an impediment to richer telemetry.

This change removes the transport event types so that the Event and
Record types are left only to represent HTTP telemetry. Now, the
transport's IO type holds a reference to a shared `Metrics` structure.
As the transport is used, metric values are updated immediately.

A lock on the transport _registry_ is taken whenever a new transport is
opened/accepted and when metrics are reported. Each transport class's
metrics are now shared & locked independently, so it's possible for a
transport to update its metrics while the registry is being manipulated.

This has one functional change: the `tcp_read_bytes_total` and
`tcp_write_bytes_total` counters are now updated instantaneously.
Previously these values were only incremented on transport close, which
is misleading, especially for long-lived connections.

With this change, all transport-related telemetry logic lives in
`telemetry::transport`.
2018-08-20 15:54:16 -07:00
Oliver Gould 912b9d3b7c
Split transport metrics into read and write halves (#74)
In anticipation of removing Transport-related Event types, we want to
separate the concerns of recording transport metrics updates from
reporting them to the metrics endpoint.

The transport module has been split into `Registry` and `Report` types:
`Registry` is responsible for recording updates, and `Report` is
responsible for rendering metrics.
2018-08-20 15:02:50 -07:00
Sean McArthur 6b4b35b083
update rustls for async IO bug (#75)
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-08-20 13:40:58 -07:00
Oliver Gould 652dfb7fc3
Revert "travis: Avoid caching proxy binaries (#69)" (#77)
This reverts commit c64d7aa0e5.

The CI change introduced in #69 appears to break the master build.
2018-08-20 09:27:56 -07:00
Oliver Gould 58ed628308
Remove the labels::TlsStatus type (#73)
Following #67 and #68, the `labels::TlsStatus` type can be removed in
favor of extending underlying `ctx::transport::TlsStatus` type to
implement `FmtLabels`.
2018-08-17 15:09:43 -07:00
Oliver Gould 35b47fb3a0
Remove the labels::Direction type (#72)
Following #67 and #68, the `labels::Direction` type can be replaced with
an `impl FmtLabels for ctx::Proxy`.
2018-08-17 14:50:52 -07:00
Sean McArthur e3df08678d update hyper 0.12.7 to 0.12.8
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-08-17 13:19:15 -07:00
Sean McArthur 823f981ec8 update futures 0.1.21 to 0.1.23
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-08-17 13:19:15 -07:00
Sean McArthur a43bd34ad2 update h2 0.1.11 to 0.1.12
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-08-17 13:19:15 -07:00
Sean McArthur 747edb54e3 update bytes 0.4.7 to 0.4.9
Signed-off-by: Sean McArthur <sean@buoyant.io>
2018-08-17 13:19:15 -07:00
Oliver Gould c64d7aa0e5
travis: Avoid caching proxy binaries (#69)
There's no reason that we should ever need to cache proxy binaries
between CI runs.

For instance, for each pull request build we appear to cache a ~125M
binary.

Cache interactions seem to account for much of our CI times, so any
reduction here is helpful.
2018-08-17 13:13:49 -07:00
Oliver Gould 279611d409
Make telemetry::metrics::labels::DstLabels private (#71)
The `DstLabels` type has a large an undefined scope. Over time, it's
become critical in a variety of contexts, even outside of the scope of
prometheus endpoint labels.

This change makes `DstLabels` private to the
`telemetry::metrics::labels` module. This more clearly separates the
concerns of prometheus labeling from discovery, etc.

Now, destination metadata includes an index map of arbitrary metadata
labels.

Previously, dst label strings would be formatted eagerly at
service-discovery-time. This change moves this string formatting into
the data path(!). I think this is an acceptable tradeoff temporarily,
while we work to stop constructing RequestLabels in the data path
altogether.
2018-08-16 17:44:31 -07:00
Oliver Gould 1d1d76aa5b
Introduce the FmtMetrics and FmtLabels traits (#67)
There are many different types of things that implement `fmt::Display`
in the metrics library: lists of key-value labels, individial label keys
or values, groups of metrics output, etc. While modifying metrics code,
it can be very easy to use something that's not a label in the context
of a label.
2018-08-16 10:51:03 -07:00
Oliver Gould 6dde18cf34
Delete ctx::Process (#68)
In order to start dismantling the monolithic ctx structures, this change
removes the root `ctx::Process` type. This simplifies `ctx::Proxy` such
that is copyable and need not be `Arc`ed.

`telemetry::metrics::labels::Direction` has been updated to decorate
`ctx::Proxy` instead of modeling the same variants directly as an enum.
2018-08-15 16:27:57 -07:00
Oliver Gould 48b7383ff0
Store transport metrics hierarchically (#66)
Previously, transport metrics have been stored in two "scopes": an
"open" scope, storing metrics by transport class, and a "close" scope
storing metrics by transport and end-of-stream classes.

Instead of storing these as parallel maps, this changes transport
metrics to be stored hierarchically so that the end-of-stream metrics
are stored _within_ the transport metrics type.

This will make it possible to share the transport metrics structure
directly with the transport wrapper so that a global lock need only be
taken at connect-time. Subsequent updates will then be scoped to the
shared transport structure.

This helps to setup linkerd/linkerd2#1430, among other improvements.

Furthermore, the `Scopes` type is no longer used for transport metrics,
since it's much easier to use the full affordances of `indexmap`,
especially now that it isn't part of an API.
2018-08-14 16:29:07 -07:00
Oliver Gould b9051f0f45
Narrow transport metric's API (#65)
The `telemetry::metrics::transport` module exposes much of its
implementation details to callers, which makes it difficult to make
changes to how the module is structured. In preparation for further
refactors, this change narrows the module's public API:

All labels and scopes types have been made private. A single, public
`Transports` type has been introduce to describe the entire public
interface of the module. This has been crafted to be free of `event`
types and to have minimal external dependencies.

A new `transport::Eos` type has been introduced to replace the
overloaded `labels::Classification` type -- this type was initially
introduced to model _HTTP response_ classification, but it was
reused for transports. This is an undesirable coupling that will have to
be broken when we start to adddress HTTP response classification
properly.
2018-08-14 15:11:17 -07:00
Oliver Gould d0e1e71bff
Relax Metric::fmt_scopes' type bounds (#64)
005d4f1 made `Metric::fmt_scopes` generic over an Iterator, but
maintained some of the unnecessary type bounds inherited from its
initial implementation.

This change relaxes the constraints on the label value so that it need
not be passed as a reference or be hashable--our only requirement is
that it can be rendered.
2018-08-14 12:43:18 -07:00
Oliver Gould 0d890dab6b
Mark tcp_connect_err tests as macos-specific (#63)
The `tcp_connect_err` tests do not pass on Linux.

I initially observed that the errno produced is ECONNREFUSED on Linux,
not EXFULL, but even changing this does not help the test to pass
reliably, as the socket teardown semantics appear to be slightly
different.

In order to prevent spurious test failures during development, this
change marks these two tests as macos-specific.
2018-08-14 12:32:41 -07:00
Oliver Gould 7131d3ccae
Consolidate labels into metrics::transport (#57)
Various transport-specific labels are defined in the common
`metrics::labels` module.

In preparation to refactor transport metrics into Sensor and Report
halves, this change moves all transport-specific labels into the
transport metrics module.
2018-08-10 14:29:28 -07:00
Oliver Gould 37d6e56f3a
Make `metrics` private to `telemetry` (#59)
Only the `DstLabels` and `Serve` types in `metrics` are used outside of
`telemetry`.

This change narrows visibility so that `metrics` is not referenced
outside of `telemetry`.
2018-08-10 11:41:36 -07:00
Oliver Gould 005d4f19c6
Make `Metric::fmt_scopes` generic over an Iterator (#60)
The `Scopes` type shouldn't be critical to metrics formatting.

This change makes the `Metric` type unaware of `Scopes` so that other
labeling mechanisms can be used if appropriate.
2018-08-10 11:16:06 -07:00
Oliver Gould f7a35442be
Remove `record` benches (#58)
As we begin to remove event-based metrics telemetry, the `record` bench
test becomes an obstacle that needs to be updated at every step.

Given that we have already removed the event channel and plan to remove
the `Record` type entirely, it's suitable to remove the bench test
entirely.

While this is done, the `test-benches` Make target and rust-nightly
travis stage are obsoleted.
2018-08-10 10:59:36 -07:00
Oliver Gould da591802af
Extract metrics::Scopes into its own module (#55)
The metrics::Scopes type exposes its internal implementation to many of
its uses.

By extracting the type into its own module, we are forced to provide an
explicit public interface, hiding its IndexMap implementation details.
2018-08-10 10:20:47 -07:00
Oliver Gould 5a70495496
Move metrics::tls_config_reload into telemetry (#53)
Following on #52, this change moves the
`telemetry::metrics::tls_config_reload` module to
`telemetry::tls_config_reload`.

The `Fmt` type has been renamed to `Report`.

Furthermore, two helper methods have been added to `metrics::Scopes` so
that its internal representation need not be made public.
2018-08-09 17:47:05 -07:00
Oliver Gould 6ddf38f2a7
Move Errno into telemetry (#52)
Following on #50, this change moves the `Errno` types into `telemetry`
so that metrics implementation can be moved out of the `metrics` module.
2018-08-09 14:33:13 -07:00
Oliver Gould 7cdb5bd790
Move telemetry::metrics::process into telemetry (#51)
As a follow-on to #50, which begins to tease apart metrics
infrastructure from application logic, this change moves the
`telemetry::metrics::process` module into `telemetry::process`.

The `Process` type has been renamed to `Report` and some other minor
cosmetic changes have been made.
2018-08-09 12:33:40 -07:00