* docker.io/library/golang from 1.22 to 1.23
* gotestsum from 0.4.2 to 1.12.0
* protoc-gen-go from 1.28.1 to 1.35.2
* protoc-gen-go-grpc from 1.2 to 1.5.1
* docker.io/library/rust from 1.76.0 to 1.83.0
* cargo-deny from 0.14.11 to 0.16.3
* cargo-nextest from 0.9.67 to 0.9.85
* cargo-tarpaulin from 0.27.3 to 0.31.3
* just from 1.24.0 to 1.37.0
* yq from 4.33.3 to 4.44.5
* markdownlint-cli2 from 0.10.0 to 0.15.0
* shellcheck from 0.9.0 to 0.10.0
* actionlint from 1.6.26 to 1.7.4
* protoc from 3.20.3 to 29.0
* step from 0.25.2 to 0.28.2
* kubectl from 1.29.2 to 1.31.3
* k3d from 5.6.0 to 5.7.5
* k3s image shas
* helm from 3.14.1 to 3.16.3
* helm-docs from 1.12.0 to 1.14.2
Tokio has an unstable feature supporting runtime metrics.
This allows service operators to export metrics to systems like
Prometheus, so that they can observe how their workloads are performing
on the tokio runtime. This exposes information like the number of worker
threads, queue depth, the number of tasks polled, and so on.
`linkerd2-proxy` should expose these metrics.
This uses the `kubert-prometheus-tokio` crate to register a `Runtime`
metrics worker, and spawn a task to probe these metrics at a fixed,
regular interval.
see: <https://github.com/olix0r/kubert/tree/main/kubert-prometheus-tokio>
if the `tokio_unstable` feature is not enabled, this will emit a debug
event and do nothing.
Signed-off-by: katelyn martin <kate@buoyant.io>
This change introduces a new, optional /debug/pprof/profile.pb.gz
endpoint to the proxy's admin server. This endpoint is feature-gated
and, initially, it will not be included in release builds. It replicates
Go's /debug/pprof/profile, but it always returns gzipped protobuf (i.e.
as can be read by pprof pprofutils).
When the feature is enabled, profiling requests are only permitted over
the loopback interface.
The development Dockerfile is updated to prevent stripping debug
symbols when pprof is enabled so that the pprof data has useful names.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
The proxy's release debug symbols are currently >6GB. It doesn't appear
to even be possible to build the proxy with debuginfo=2, as we overflow
u32::MAX and violate the restrictions of DWARF32.
To fix this, we more aggressively use dynamic dispatch via the new
`Stack::arc_new_box` helpers. This helps reduce our largest type
signatures from >700KB to ~50KB. We'll want to follow up with changes
that monitor the size of these signatures to prevent regressions.
This allows us to minimize many type assertions, etc.
There are no functional changes in this PR.
* Update dev to v42
* Update Rust to 1.73.0
* Address new clippy & check warnings
* Update debian from bullseye to bookworm
* Update K3d to v5.6.0
* Update CI from k3s 1.26 to 1.28
* Fix `just linkerd-install` to specify k8s context
* Update markdownlint-cli2 to 0.10.0
* Update Dockerfile to use a debian base image for easier debugging
* Update proc-macro2 to fix rust-nightly build failures
The proxy currently emits very little useful version information.
This change updates the proxy to support new build-time environment
variables that are used to report version information:
* LINKERD2_PROXY_BUILD_TIME
* LINKERD2_PROXY_VENDOR
* LINKERD2_PROXY_VERSION
Additionally, several pre-existing Git-oriented metadata have been
removed, as they were generally redundant or uninformative. The Rustc
version has also been removed (since it has no real user-facing value
and can be easily determined by the version/tag).
Since upstream has yet to release a version with PR
bluejekyll/trust-dns#1881, this commit changes the proxy's default log
level to silence warnings from `trust_dns_proto` that are generally
spurious.
See linkerd/linkerd2#10123 for details.
We don't currently test that proxy changes are at least usable in a
basic Linkerd installation. This adds a CI workflow to test all Linkerd
code changes against a real k8s cluster with the control plane from the
most recent edge release.
This change adds release targets for static binaries (using musl).
Expected checksec outputs are split per platform, to account
for cross-compiled MUSL binaries.
With this change, we retain debug symbols in an separate file. So
they can be loaded in a debugger.
This change bumps the devcontainer to v38 to include just-cargo fixes.
Use the new `dev:v32-rust-cross` image variant to support releases.
This change removes the checksec.sh helper script, moving that logic
into the justfile.
Signed-off-by: Oliver Gould <ver@buoyant.io>
The proxy repo maintains a nearly identical devcontainer configuration
to that used in the main linkerd2 repo (minus some Go tooling). This
means that we have to pull the same sets of tools redundantly, and that
it's easy for the tool versions to diverge needlessly.
This change updates the proxy to use the published linkerd dev, adding
a rust nightly toolchain for cargo-fuzz (which is only used in this repo
currently) on creation.
Signed-off-by: Oliver Gould <ver@buoyant.io>
* Update Rust to v1.62, with new lints
* Update k3d to v5.4.4
* Update just to 1.2.0
* Update kubectl to v1.24.2
* Update cargo-nextest to v0.9.24
Signed-off-by: Oliver Gould <ver@buoyant.io>
- Updates the debian base from `buster` to `bullseye`;
- Bumps the devcontainer version;
- Removes the `update-rust-version.sh` script, since it's too brittle
and isn't necessary any longer (since we check rust versions in CI);
- Updates checksec to v2.5.;
- Acknowledges that releases no longer produces binaries with
`FORTIFY_SOURCE`
Signed-off-by: Oliver Gould <ver@buoyant.io>
PR #1479 changed the docker base image to not include a shell, which
broke the dockerfile's logic for skipping the identity wrapper. It's no
longer possible to run the proxy without identity, so this functionality
isn't needed in any case.
This change fixes the Dockerfile and adds a CI workflow to test docker
builds on Dockerfile changes.
Signed-off-by: Oliver Gould <ver@buoyant.io>
Some development tooling (like recent versions of cargo-deny) depends on
Rust v1.56.1. This change updates proxy build/CI to use this version for
consistency.
This change adds a `meshtls-boring` proxy feature that can be used to
compile the proxy with an alternate TLS implementation. The
`meshtls-rustls` feature should be disabled to take advantage of this
alternate backend.
In its current mode, the boring backend is compatible with the existing
identity credentials and algorithms (specifically TLSv1.3 and
ECDSA-P256-SHA256 with CHACHA20-POLY1305-SHA256).
In future changes--once `boring` has been updated--we can:
- Improve error handling, especially for SSL errors
- Relax deny.toml changes needed by bindgen features
- Add a FIPS mode
Co-authored-by: Arnar Páll <arnar@netapp.com>
This branch updates the Rust toolchain to 1.52.1. This includes a [major
bugfix][1] for an issue effecting incremental compilation. Additionally,
Rust 1.51 enabled the `resolver = "2"` feature in Cargo.toml, which can
be used to fix the feature flagging issues with tracing in a more
principled way than the current solution.
A *very* large amount of new lints were added since Rust 1.49.0; in
particular:
* clippy now warns when an `Into` impl could be a `From` impl, because
`From` impls provide `Into` impls for free, but the reverse is not
the case
* panic messages must now *always* be `format_args!`
* exact comparisons of floating-point numbers (rather than within an
error margin) now produce a warning
This branch also fixes all the new warnings.
[1]: https://blog.rust-lang.org/2021/05/10/Rust-1.52.1.html
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This branch introduces a new `transport::listen::Bind` trait that
abstracts over binding and listening on a socket. Now, rather than
owning an instance of the `BindTcp` type, `ServerConfig`s are passed as
a parameter to a type implementing the `Bind` trait. This will
eventually allow end-to-end testing without creating actual TCP sockets,
as `Bind` produces a `Stream` of an IO type and an `Addrs` type.
PR #955 changed the proxy stacks to be a target type which implements
the `Param` trait for various types of address, rather than a fixed
type. This PR also changes the inbound and outbound proxies to take
targets which implement `Param<OrigDstAddr>`, rather than requiring
`Param<Option<OrigDstAddr>>` and punting fallibility to every point
where original dst addresses are used.
The `BindTcp` type is now generic over a more general `GetAddrs` trait,
rather than a `SO_ORIGINAL_DST`-specific `OrigDstAddr` trait. Rather
than always producing a `listen::Addrs` with an `Option<OrigDstAddr>`,
we now produce a variable addresses type, which may or may not incldue
the original destination address (the admin and tap servers don't
require SO_ORIGINAL_DST). This allows whether or not original
destination addresses are included to be determined at compile time
rather than at runtime.
Finally, the incorrect feature flagging of mock original destination
addresses has been fixed, The "mock-orig-dst" feature has been removed,
and the integration tests now simply construct their own mock `GetAddrs`
function that's used to configure the test proxy. In the future, we
should be able to refactor the tests to avoid this by simply passing in
their own mock `Bind` types which produce streams of in-memory mock
connections, rather than actual TCP connections.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
## Motivation
The proxy identity-initializing wrapper is responsible for generating a CSR and
key for the proxy upon startup. These files (located in `end-entity/`) are used
by the proxy for establishing identity.
When mocking identity, we'd like to be able to provide a pre-generated CSR and
key so that we can expect certain certificates in the Signed certificate
request.
Therefore, when building a proxy to be used with mock identity there should be a
way to remove this wrapper so that the identity files are not overwritten.
## Solution
Introduce a new `SKIP_IDENTITY_WRAPPER` build-arg that when set, removes the
proxy identity-initializing script that is run at starup.
The use of it below will build a proxy with the `mock-orig-dst` feature and skip
identity generation.
```
:; docker buildx build . --build-arg PROXY_FEATURES=mock-orig-dst --build-arg SKIP_IDENTITY_WRAPPER=1 --load --tag=kevinlbuoyant/l2-proxy:proxy-identity-v1
```
I have confirmed this works with the changes in olix0r/l2-proxy-harness#2.
Signed-off-by: Kevin Leimkuhler <kevin@kleimkuhler.com>
## Motivation
When debugging proxy issues, it can be useful to inspect the list of
currently spawned Tokio tasks and their states. This can be used
similarly to the thread or coroutine dumps provided by other languages'
runtimes.
## Solution
This branch adds a new endpoint to the proxy's admin server, `/tasks`,
that returns a dump of all tasks currently spawned on the Tokio runtime,
using the new Tracing instrumentation added in tokio-rs/tokio#2655, and
a work-in-progress [`tokio-trace`] crate that provides Tokio-specific
Tracing layers.
Currently, the `/tasks` admin endpoint records the following information
about each task:
* Whether it is a normal, local, or blocking task (not relevant to us
currently, since Linkerd does not use local or blocking tasks...but
we might eventually!)
* Whether the task is active (currently being polled) or idle (waiting
to be polled)
* The type of the future that was spawned
* The Tracing span context from which the task was spawned
* The total number of times the task has been polled
* Timing statistics about the task, including:
- The time in nanoseconds between when the task was spawned and when
it was first polled (essentially, measuring the Tokio scheduler's
latency)
- The total time in nanoseconds the task has existed
- The task's _busy time_ in nanoseconds (time it was actively being
polled)
- The tasks _idle time_ in nanoseconds (time it was _not_ being
polled)
In the future, Tokio will likely expose additional Tracing information,
which we'll be able to collect as well.
The task dump can be accessed either as an HTML table or as JSON. JSON
is returned if the request has an `Accept: application/json` header, or
whenever the path `/tasks.json` is requested; otherwise, the data is
rendered as an HTML table. Like the `/proxy-log-level` endpoint, access
is denied to requests coming from sources other than localhost, to help
restrict access to authorized users (since a high volume of requests for
task dumps could be used to starve the proxy).
Example JSON output (in Firefox Dev Edition's extremely nice GUI
JSON viewer):

Zoomed in on the timing data for a single task:

And HTML:

Because the task data is generated from Tracing spans emitted by Tokio,
the task spans must be enabled for it to be used. This can be done by
setting a trace filter that enables the `trace` level for the target
`tokio::task`, e.g.:
```
tokio::task=trace
```
or
```
tokio=trace
```
## Notes
* This branch depends on unreleased code from upstream, including a
Tokio change that has merged to master but not been published, and my
unreleased work-in-progress [`tokio-trace`] crate. Therefore, I've
pinned these upstreams to fixed Git SHAs, to guard against
dependencies changing under us unexpectedly.
* I considered requiring a build-time feature flag to enable this
feature, the way we do for the mock SO_ORIG_DST implementation for
testing. However, this would make it harder to use task tracking to
debug issues in proxies not built with the flag. I'm happy to change
this code to be feature flagged if we think that's the right approach.
[`tokio-trace`]: https://github.com/hawkw/tokio-traceCloseslinkerd/linkerd2#3803
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This branch enables feature-flagged support for using Tokio's
multithreaded runtime when the proxy is given more than two CPU cores to
run on. The proxy's understanding of the system's number of CPUs
reflects cgroups limits, so docker CPU limits are taken into
consideration.
If only a single core is available to run a worker on, we will construct
Tokio's basic_scheduler, rather than a threaded_scheduler with a
single worker thread. This is because there is some overhead introduced
by the threaded scheduler, which results in worse performance when only
1 core is available.
Finally, a bug in the handle time metrics layer results in a deadlock
when used with the multithreaded runtime. Therefore, I've disabled this
metric for now --- my understanding is that nothing consumes it at the
moment. If it's needed, we can fix the bug and put it back.
Microsoft's `mimalloc` is a general purpose allocator with excellent
performance characteristics and, furthermore, it implements defensive
security features to protect against heap vulnerabilities. See
https://github.com/microsoft/mimalloc.
In initial tests, it appears that it may improve latency at the cost of
~20% memory overhead.
This change primarily enables further testing, since it doesn't seem
worth taking the memory overhead at this point.
This change modifies the development dockerfile to wrap build commands
with `/usr/bin/time -v` so that we get diagnostic information (like the
RSS of the build process).
Our docker builds do not permit caching of dependencies or intermediate
build artifacts. However, Docker's new (experimental) buildkit features
add this functionality. I've been using this configuration locally for
some time, and it seems generaly useful enough to promote (especially
since this Dockerfile is only intended for development).
This change also untroduces the `PROXY_FEATURES` build-arg so that the
Dockerfile can be used to support profiling builds.
Furthermore, the `update-rust-versions.sh` script has been updated to
check versions and be more permissive about how it replaces versions in
the Dockerfile.
The docker CI build has been disabled until GitHub Actions has support
for this Dockerfile format.
Replicate our integration test configuration to also run docker builds
on our remote host.
Furthermore, run these builds in unoptimized mode (since we don't
consume the results).
* internal: internal: Spilt app from linkerd2-proxy
The `linkerd2-proxy crate currently comprises the entirety of the
application logic for the proxy. This unfortunately leads to exceedingly
high compile times (35+ minutes to compile the application with tests).
Specifically:
* Any change to the inbound or outbound proxy configuration necessitated
recompiling the other; and this compilation could not be parallelized.
* Integration tests depended on the `linkerd2-proxy` executable, adding
about 10 minutes to every build.
* The tests/support module (which is also extremely costly to build) was
compiled _for each integration test_.
This change restructures the crates in this repository to allow `cargo`
to cache intermediate code that was otherwise being compiled
redundantly or serially:
* The `linkerd2-proxy` crate now contains _only_ the executable and need
not be built during tests.
* The `linkerd2-app` crate exposes the app's `Main`, but uses
`linkerd2-app-inbound` and `linkerd2-app-outbound` subcrates to
improve parellization/cacheability.
* The rest of the top-level application code
* The `linkerd2-app-integration` crate now contains all of the
integration test support code (as well as the tests themselves), so
that the tests only need to compile the support library once.
All in all, this reduces compile time to under 20 minutes.