Skip to content

Commit

Permalink
New content dir for 2.11 docs (#1178)
Browse files Browse the repository at this point in the history
* New content dir for 2.11 docs

`/content/2.11` is basically a copy of `/content/2.10`, where all new
content pertaining to 2.11 should reside. I tried to remove all direct
references to `2.10` and made them relative dir references instead, so
this process gets easier as new major versions are released.
  • Loading branch information
alpeb authored Sep 30, 2021
1 parent 24701b0 commit e9ae777
Show file tree
Hide file tree
Showing 121 changed files with 15,142 additions and 99 deletions.
2 changes: 1 addition & 1 deletion linkerd.io/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ identifier = "start"
name = "GET STARTED"
post = "</span>"
pre = "<span class='button-spacer'>"
url = "/2.10/getting-started/"
url = "/getting-started/"
weight = 6
[outputFormats.REDIRECTS]
baseName = "_redirects"
Expand Down
2 changes: 1 addition & 1 deletion linkerd.io/content/1/getting-started/k8s.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ weight = 34
+++
{{< note >}}
This document is specific to Linkerd 1.x. If you're on Kubernetes, you may wish
to consider [Linkerd 2.x](/2.10/getting-started/) instead.
to consider [Linkerd 2.x](/getting-started/) instead.
{{< /note >}}

If you have a Kubernetes cluster or even just run
Expand Down
104 changes: 55 additions & 49 deletions linkerd.io/content/2.10/features/protocol-detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,71 @@ aliases = [
Linkerd is capable of proxying all TCP traffic, including TLS connections,
WebSockets, and HTTP tunneling.

In most cases, Linkerd can do this without configuration. To do this, Linkerd
performs *protocol detection* to determine whether traffic is HTTP or HTTP/2
(including gRPC). If Linkerd detects that a connection is HTTP or HTTP/2,
Linkerd will automatically provide HTTP-level metrics and routing.
In most cases, Linkerd can do this without configuration. To accomplish this,
Linkerd performs *protocol detection* to determine whether traffic is HTTP or
HTTP/2 (including gRPC). If Linkerd detects that a connection is HTTP or
HTTP/2, Linkerd automatically provides HTTP-level metrics and routing.

If Linkerd *cannot* determine that a connection is using HTTP or HTTP/2,
Linkerd will proxy the connection as a plain TCP connection, applying
[mTLS](../automatic-mtls/) and providing byte-level metrics as usual.

{{< note >}}
Client-initiated HTTPS will be treated as TCP, not as HTTP, as Linkerd will not
be able to observe the HTTP transactions on the connection.
{{< /note >}}
(Note that HTTPS calls to or from meshed pods are treated as TCP, not as HTTP.
Because the client initiates the TLS connection, Linkerd is not be able to
decrypt the connection to observe the HTTP transactions.)

## Configuring protocol detection

In some cases, Linkerd's protocol detection cannot function because it is not
provided with enough client data. This can result in a 10-second delay in
creating the connection as the protocol detection code waits for more data.
This situation is often encountered when using "server-speaks-first" protocols,
or protocols where the server sends data before the client does, and can be
avoided by supplying Linkerd with some additional configuration.

{{< note >}}
Regardless of the underlying protocol, client-initiated TLS connections do not
require any additional configuration, as TLS itself is a client-speaks-first
protocol.
If you are experiencing 10-second delays when establishing connections, you are
likely running into a protocol detection timeout. This section will help you
understand how to fix this.
{{< /note >}}

In some cases, Linkerd's protocol detection will time out because it doesn't
see any bytes from the client. This situation is commonly encountered when
using "server-speaks-first" protocols where the server sends data before the
client does, such as SMTP, or protocols that proactively establish connections
without sending data, such as Memcache. In this case, the connection will
proceed as a TCP connection after a 10-second protocol detection delay.

To avoid this delay, you will need to provide some configuration for Linkerd.
There are two basic mechanisms for configuring protocol detection: _opaque
ports_ and _skip ports_. Marking a port as _opaque_ instructs Linkerd to proxy
the connection as a TCP stream and not to attempt protocol detection. Marking a
port as _skip_ bypasses the proxy entirely. Opaque ports are generally
preferred (as Linkerd can provide mTLS, TCP-level metrics, etc), but crucially,
opaque ports can only be used for services inside the cluster.

By default, Linkerd automatically marks some ports as opaque, including the
default ports for SMTP, MySQL, PostgresQL, and Memcache. Services that speak
those protocols, use the default ports, and are inside the cluster do not need
further configuration.

The following table summarizes some common server-speaks-first protocols and
the configuration necessary to handle them. The "on-cluster config" column
refers to the configuration when the destination is *on* the same cluster; the
"off-cluster config" to when the destination is external to the cluster.

| Protocol | Default port(s) | On-cluster config | Off-cluster config |
|-----------------|-----------------|-------------------|--------------------|
| SMTP | 25, 587 | none\* | skip ports |
| MySQL | 3306 | none\* | skip ports |
| MySQL with Galera replication | 3306, 4444, 4567, 4568 | none\* | skip ports |
| PostgreSQL | 5432 | none\* | skip ports |
| Redis | 6379 | none\* | skip ports |
| ElasticSearch | 9300 | none\* | skip ports |
| Memcache | 11211 | none\* | skip ports |

_\* No configuration is required if the standard port is used. If a
non-standard port is used, you must mark the port as opaque._
ports_ and _skip ports_. Marking a port as _opaque_ instructs Linkerd to skip
protocol detection and immediately proxy the connection as a TCP stream;
marking a port as a _skip port_ bypasses the proxy entirely. Opaque ports are
generally preferred (as Linkerd can provide mTLS, TCP-level metrics, etc), but
can only be used for services inside the cluster.

By default, Linkerd automatically marks the ports for some server-speaks-first
protocol as opaque. Services that speak those protocols over the default ports
to destinations inside the cluster do not need further configuration.
Linkerd's default list of opaque ports in the 2.10 release is 25 (SMTP), 443
(client-initiated TLS), 587 (SMTP), 3306 (MySQL), 5432 (Postgres), and 11211
(Memcache). Note that this may change in future releases.

The following table contains common protocols that may require configuration.

| Protocol | Default port(s) | Notes |
|-----------------|-----------------|-------|
| SMTP | 25, 587 | |
| MySQL | 3306 | |
| MySQL with Galera | 3306, 4444, 4567, 4568 | Ports 4444, 4567, and 4568 are not in Linkerd's default set of opaque ports |
| PostgreSQL | 5432 | |
| Redis | 6379 | |
| ElasticSearch | 9300 | Not in Linkerd's default set of opaque ports |
| Memcache | 11211 | |

If you are using one of those protocols, follow this decision tree to determine
which configuration you need to apply.

* Is the protocol wrapped in TLS?
* Yes: no configuration required.
* No: is the destination on the cluster?
* Yes: is the port in Linkerd's default list of opaque ports?
* Yes: no configuration required.
* No: mark port(s) as opaque.
* No: mark port(s) as skip.

## Marking a port as opaque

Expand All @@ -84,8 +91,7 @@ workloads in that namespace.

{{< note >}}
Since this annotation informs the behavior of meshed _clients_, it can be
applied to services that use server-speaks-first protocols even if the service
itself is not meshed.
applied to unmeshed services as well as meshed services.
{{< /note >}}

Setting the opaque-ports annotation can be done by using the `--opaque-ports`
Expand All @@ -104,7 +110,7 @@ Multiple ports can be provided as a comma-delimited string. The values you
provide will replace, not augment, the default list of opaque ports.
{{< /note >}}

## Skipping the proxy
## Marking a port as skip

Sometimes it is necessary to bypass the proxy altogether. For example, when
connecting to a server-speaks-first destination that is outside of the cluster,
Expand Down
6 changes: 6 additions & 0 deletions linkerd.io/content/2.11/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "Overview"
---
<!-- markdownlint-disable -->
<meta http-equiv="Refresh" content="0; url=overview/">
<!-- markdownlint-enable -->
18 changes: 18 additions & 0 deletions linkerd.io/content/2.11/checks/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0; url=../tasks/troubleshooting/">
<script type="text/javascript">
window.onload = function() {
var hash = window.location.hash;
window.location.href = window.location.origin + "/2.11/tasks/troubleshooting/" + hash;
}
</script>
<title>Linkerd Check Redirection</title>
</head>
<body>
If you are not redirected automatically, follow this
<a href='../tasks/troubleshooting/'>link</a>.
</body>
</html>
14 changes: 14 additions & 0 deletions linkerd.io/content/2.11/features/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
+++
title = "Features"
weight = 3
[sitemap]
priority = 1.0
+++

Linkerd offers many features, outlined below. For our walkthroughs and guides,
please see the [Linkerd task docs]({{% ref "../tasks" %}}). For a reference,
see the [Linkerd reference docs]({{% ref "../reference" %}}).

## Linkerd's features

{{% sectiontoc "features" %}}
127 changes: 127 additions & 0 deletions linkerd.io/content/2.11/features/automatic-mtls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
+++
title = "Automatic mTLS"
description = "Linkerd automatically enables mutual Transport Layer Security (TLS) for all communication between meshed applications."
weight = 4
aliases = [
"../automatic-tls"
]
+++

By default, Linkerd automatically enables mutually-authenticated Transport
Layer Security (mTLS) for all TCP traffic between meshed pods. This means that
Linkerd adds authenticated, encrypted communication to your application with
no extra work on your part. (And because the Linkerd control plane also runs
on the data plane, this means that communication between Linkerd's control
plane components are also automatically secured via mTLS.)

See [Caveats and future work](#caveats-and-future-work) below for some details.

## What is mTLS?

A full definition of mTLS is outside the scope of this doc. For an overview of
what mTLS is and how it works in Kuberentes clusters, we suggest reading
through [A Kubernetes engineer's guide to
mTLS](https://buoyant.io/mtls-guide/).

## Which traffic can Linkerd automatically mTLS?

Linkerd transparently applies mTLS to all TCP communication between meshed
pods. However, there are still ways in which you may still have non-mTLS
traffic in your system, including:

* Traffic to or from non-meshed pods (e.g. Kubernetes healthchecks)
* Traffic on ports that were marked as [skip ports](../protocol-detection/),
which bypass the proxy entirely.

You can [verify which traffic is mTLS'd](../../tasks/validating-your-traffic/)
in a variety of ways. External systems such as [Buoyant
Cloud](https://buoyant.io/cloud) can also automatically generate reports of TLS
traffic patterns on your cluster.

## Operational concerns

Linkerd's mTLS requires some preparation for production use, especially for
long-lived clusters or clusters that expect to have cross-cluster traffic.

The trust anchor generated by the default `linkerd install` CLI command expires
after 365 days. After that, it must be [manually
rotated](../../tasks/manually-rotating-control-plane-tls-credentials/)—a
non-trivial task. Alternatively, you can [provide the trust anchor
yourself](../../tasks/generate-certificates/) and control the expiration date,
e.g. setting it to 10 years rather than one year.

Kubernetes clusters that make use of Linkerd's [multi-cluster
communication](../multicluster/) must share a trust anchor. Thus, the default
`linkerd install` setup will not work for this situation and you must provide
an explicit trust anchor.

Similarly, the default cluster issuer certificate and key expire after a year.
These must be [rotated before they
expire](../../tasks/manually-rotating-control-plane-tls-credentials/).
Alternatively, you can [set up automatic rotation with
`cert-manager`](../../tasks/automatically-rotating-control-plane-tls-credentials/).

External systems such as [Buoyant Cloud](https://buoyant.io/cloud) can be used
to monitor cluster credentials and to send reminders if they are close to
expiration.

## How does Linkerd's mTLS implementation work?

The [Linkerd control plane](../../reference/architecture/) contains a certificate
authority (CA) called `identity`. This CA issues TLS certificates to each
Linkerd data plane proxy. Each certificate is bound to the [Kubernetes
ServiceAccount](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
identity of the containing pod. These TLS certificates expire after 24 hours
and are automatically rotated. The proxies use these certificates to encrypt
and authenticate TCP traffic to other proxies.

On the control plane side, Linkerd maintains a set of credentials in the
cluster: a trust anchor, and an issuer certificate and private key. These
credentials can be generated by Linkerd during install time, or optionally
provided by an external source, e.g. [Vault](https://vaultproject.io) or
[cert-manager](https://github.com/jetstack/cert-manager). The issuer
certificate and private key are stored in a [Kubernetes
Secret](https://kubernetes.io/docs/concepts/configuration/secret/); this Secret
is placed in the `linkerd` namespace and can only be read by the service
account used by the [Linkerd control plane](../../reference/architecture/)'s
`identity` component.

On the data plane side, each proxy is passed the trust anchor in an environment
variable. At startup, the proxy generates a private key, stored in a [tmpfs
emptyDir](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) which
stays in memory and never leaves the pod. The proxy connects to the control
plane's `identity` component, validating the connection to `identity` with the
trust anchor, and issues a [certificate signing request
(CSR)](https://en.wikipedia.org/wiki/Certificate_signing_request). The CSR
contains an initial certificate with identity set to the pod's [Kubernetes
ServiceAccount](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/),
and the actual service account token, so that `identity` can validate that the
CSR is valid. After validation, the signed trust bundle is returned to the
proxy, which can use it as both a client and server certificate. These
certificates are scoped to 24 hours and dynamically refreshed using the same
mechanism.

Finally, when a proxy receives an outbound connection from the application
container within its pod, it looks up that desitnation with the Linkerd control
plane. If it's in the Kubernetes cluster, the control plane provides the proxy
with the destination's endpoint addresses, along with metadata including an
identity name. When the proxy connects to the destination, it initiates a TLS
handshake and verifies that that the destination proxy's certificate is signed
by the trust anchor and contains the expected identity.

## Caveats and future work

There are a few known gaps in Linkerd's ability to automatically encrypt and
authenticate all communication in the cluster. These gaps will be fixed in
future releases:

* Linkerd does not currently *enforce* mTLS. Any unencrypted requests inside
the mesh will be opportunistically upgraded to mTLS. Any requests originating
from inside or outside the mesh will not be automatically mTLS'd by Linkerd.
This will be addressed in a future Linkerd release, likely as an opt-in
behavior as it may break some existing applications.

* Ideally, the ServiceAccount token that Linkerd uses would not be shared with
other potential uses of that token. In future Kubernetes releases, Kubernetes
will support audience/time-bound ServiceAccount tokens, and Linkerd will use
those instead.
Loading

0 comments on commit e9ae777

Please sign in to comment.