Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions linkerd.io/content/2-edge/features/cni.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,17 @@ The most important flags are:
### Allowing initContainer networking

When using the Linkerd CNI plugin the required `iptables` rules are in effect
before the pod is scheduled. Also, the `linkerd-proxy` is not started until
after all `initContainers` have completed. This means no `initContainer` will
have network access because its packets will be caught by `iptables` and the
`linkerd-proxy` will not yet be available.
before the pod is scheduled. As of Linkerd 2.20, the proxy runs by default as
a [native sidecar container](native-sidecars/), starting before the
application's `initContainers`, so those containers have network access and no
extra configuration is needed.

However, if you have
[disabled native sidecars](native-sidecars/#disabling-native-sidecars-in-linkerd),
the `linkerd-proxy` is not started until after all `initContainers` have
completed. This means no `initContainer` will have network access because its
packets will be caught by `iptables` and the `linkerd-proxy` will not yet be
available.

It is possible to bypass these `iptables` rules by running the `initContainer`
as the UID of the proxy (by default `2102`). Processes run as this UID are
Expand Down
14 changes: 10 additions & 4 deletions linkerd.io/content/2-edge/features/native-sidecars.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ sidecar containers in Kubernetes, including:
2. There are a variety of startup race conditions with meshed pods when init
containers also need network access.

## Enabling native sidecars in Linkerd
As of Linkerd 2.20, native sidecars are enabled by default: the proxy is
injected as an init container with a `restartPolicy` of `Always`, rather than
as a regular container.

Native sidecars can be enabled by setting
`config.beta.linkerd.io/proxy-enable-native-sidecar` annotation at the level of
individual namespaces or workloads, or by setting it globally at install time.
## Disabling native sidecars in Linkerd

If for any reason you want to disable this mode and have the proxy be injected
alongside regular containers, set the
`config.linkerd.io/proxy-enable-native-sidecar: false` annotation at the
namespace or workload level, or disable the mode globally by setting the Helm
chart value `proxy.nativeSidecar: false`.
5 changes: 4 additions & 1 deletion linkerd.io/content/2-edge/features/proxy-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ For each pod, two containers are injected:
that configures `iptables` to automatically forward all incoming and outgoing
TCP traffic through the proxy. (Note that this container is not injected if
the [Linkerd CNI Plugin](cni/) has been enabled.)
1. `linkerd-proxy`, the Linkerd data plane proxy itself.
1. `linkerd-proxy`, the Linkerd data plane proxy itself. As of Linkerd 2.20,
the proxy is injected by default as a
[native sidecar container](native-sidecars/), i.e. as an init container with
a `restartPolicy` of `Always`, rather than as a regular container.

Note that simply adding the annotation to a resource with pre-existing pods will
not automatically inject those pods. You will need to update the pods (e.g. with
Expand Down
10 changes: 6 additions & 4 deletions linkerd.io/content/2-edge/reference/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ containers to the pod, along with the relevant start-time configuration.
## Data plane

The Linkerd data plane comprises ultralight _micro-proxies_ which are deployed
as sidecar containers inside application pods. These proxies transparently
intercept TCP connections to and from each pod, thanks to iptables rules put in
place by the [linkerd-init](#linkerd-init-container) (or, alternatively, by
Linkerd's [CNI plugin](../features/cni/)).
as sidecar containers inside application pods. As of Linkerd 2.20, the proxy
is deployed by default as a
[native sidecar container](../features/native-sidecars/). These proxies
transparently intercept TCP connections to and from each pod, thanks to
iptables rules put in place by the [linkerd-init](#linkerd-init-container)
(or, alternatively, by Linkerd's [CNI plugin](../features/cni/)).

### Proxy

Expand Down
13 changes: 10 additions & 3 deletions linkerd.io/content/2-edge/tasks/adding-your-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,25 @@ kubectl get -n NAMESPACE deploy -o yaml | linkerd inject - | kubectl apply -f -

To verify that your services have been added to the mesh, you can query
Kubernetes for the list of containers in the pods and ensure that the proxy is
listed:
listed. As of Linkerd 2.20, the proxy runs by default as a
[native sidecar container](../features/native-sidecars/), so it appears among
the pod's init containers:

```bash
kubectl -n NAMESPACE get po -o jsonpath='{.items[0].spec.containers[*].name}'
kubectl -n NAMESPACE get po -o jsonpath='{.items[0].spec.initContainers[*].name}'
```

If everything was successful, you'll see `linkerd-proxy` in the output, e.g.:

```bash
linkerd-proxy CONTAINER
linkerd-init linkerd-proxy
```

If you have
[disabled native sidecars](../features/native-sidecars/#disabling-native-sidecars-in-linkerd),
the proxy runs as a regular container instead, and will show up in
`{.items[0].spec.containers[*].name}`.

## Handling MySQL, SMTP, and other non-HTTP protocols

Linkerd's [protocol detection](../features/protocol-detection/) works by looking
Expand Down
78 changes: 16 additions & 62 deletions linkerd.io/content/2-edge/tasks/graceful-shutdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ signal.
Linkerd offers a few options to configure pods and containers to gracefully
shutdown.

- `--wait-before-seconds`: can be used as an install value (either through the
CLI or through Helm), or alternatively, through a
[configuration annotation](../reference/proxy-configuration/). This will add a
`preStop` hook to the proxy container to delay its handling of the TERM
signal. This will only work when the conditions described above are satisfied
(i.e container runtime sends the TERM signal)
- `config.linkerd.io/shutdown-grace-period`: is an annotation that can be used
on workloads to configure the graceful shutdown time for the _proxy_. If the
period elapses before the proxy has had a chance to gracefully shut itself
Expand All @@ -92,68 +86,28 @@ shutdown.
shutdown, typically the entrypoint for containers need to be changed to
linkerd-await.

Depending on the usecase, one option (or utility) might be preferred over the
other. To aid with some common cases, suggestions are given below on what to do
when confronted with slow updating clients and with job resources that will not
complete.

## Slow Updating Clients

Before Kubernetes terminates a pod, it first removes that pod from the endpoints
resource of any services that pod is a member of. This means that clients of
that service should stop sending traffic to the pod before it is terminated.
However, certain clients can be slow to receive the endpoints update and may
attempt to send requests to the terminating pod after that pod's proxy has
already received the TERM signal and begun graceful shutdown. Those requests
will fail.

To mitigate this, use the `--wait-before-exit-seconds` flag with
`linkerd inject` to delay the Linkerd proxy's handling of the TERM signal for a
given number of seconds using a `preStop` hook. This delay gives slow clients
additional time to receive the endpoints update before beginning graceful
shutdown. To achieve max benefit from the option, the main container should have
its own `preStop` hook with the sleep command inside which has a smaller period
than is set for the proxy sidecar. And none of them must be bigger than
`terminationGracePeriodSeconds` configured for the entire pod.

For example,

```yaml
# application container
lifecycle:
preStop:
exec:
command:
- /bin/bash
- -c
- sleep 20

# for entire pod
terminationGracePeriodSeconds: 160
```

## Graceful shutdown of Job and Cronjob Resources

Pods which are part of Job or Cronjob resources will run until all of the
containers in the pod complete. However, the Linkerd proxy container runs
continuously until it receives a TERM signal. Since Kubernetes does not give the
proxy a means to know when the Cronjob has completed, by default, Job and
Cronjob pods which have been meshed will continue to run even once the main
container has completed. You can address this either by running Linkerd as a
native sidecar or by manually shutting down the proxy.

### Native Sidecar

If you use the `--set proxy.nativeSidecar=true` flag when installing Linkerd,
the Linkerd proxy will run as a
[sidecar container](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/)
and will automatically shutdown when the main containers in the pod terminate.
Native sidecars were added in Kubernetes v1.28 and are available by default in
Kubernetes v1.29.
containers in the pod complete. Since Linkerd 2.20 the proxy runs by default as
a [native sidecar container](../features/native-sidecars/), which automatically
shuts down when the main containers in the pod terminate, so meshed Jobs and
Cronjobs complete without any extra configuration.

This is only an issue if you have [disabled native
sidecars](../features/native-sidecars/#disabling-native-sidecars-in-linkerd),
which is no longer the default. In that case the proxy runs as a regular
container that runs continuously until it receives a TERM signal, and since
Kubernetes does not give the proxy a means to know when the Job has completed,
meshed Job and Cronjob pods will continue to run even once the main container
has completed. You can address this by manually shutting down the proxy, after
the application container completes. This triggers a graceful shutdown allowing
meshed Job and Cronjob pods to complete.

### Manual shutdown

Alternatively, you can issue a POST to the `/shutdown` endpoint on the proxy
If native sidecars are disabled, you can issue a POST to the `/shutdown`
endpoint on the proxy
once the application completes (e.g. via
`curl -X POST http://localhost:4191/shutdown`). This will terminate the proxy
gracefully and allow the Job or Cronjob to complete. These shutdown requests
Expand Down
13 changes: 8 additions & 5 deletions linkerd.io/content/2-edge/tasks/grafana.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ instructions on how to easily import the same charts published on
{{< note >}}

Grafana's official Helm chart uses an initContainer to download Linkerd's
configuration and dashboards. If you use the CNI plugin, when you add grafana's
pod into the mesh its initContainer will run before the proxy is started and the
traffic cannot flow. You should either avoid meshing grafana's pod, skip
outbound port 443 via `config.linkerd.io/skip-outbound-ports: "443"` annotation
or run the container with the proxy's UID. See
configuration and dashboards. If you use the CNI plugin and have
[disabled native sidecars](../features/native-sidecars/#disabling-native-sidecars-in-linkerd)
(which are enabled by default as of Linkerd 2.20), when you add grafana's pod
into the mesh its initContainer will run before the proxy is started and the
traffic cannot flow. In that case you should either avoid meshing grafana's
pod, skip outbound port 443 via the
`config.linkerd.io/skip-outbound-ports: "443"` annotation, or run the container
with the proxy's UID. See

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running multiple processes under the same UID feels like a general anti-pattern. I understand we recommend it elsewhere, should we continue to promote it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One advantage of this approach is that it keeps that specific init container out of the mesh, whereas the annotation alternative would apply to all containers in the pod. That said, I can see your point; it may be worth discussing further. If you feel strongly about it, please feel free to open a ticket so we can track it

[Allowing initContainer networking](../features/cni/#allowing-initcontainer-networking)

{{< /note >}}
Expand Down
Loading