Commit Graph

91 Commits

Author SHA1 Message Date
Oliver Gould f28df3af98
chore(deps): remove unused k8s-gateway-api dependency (#13844) 2025-03-20 15:21:21 -05:00
Alex Leong 4c471cfbd9
refactor(policy): Use gateway API bindings from the official gateway-api crate (#13643)
This change removes our dependency on the hand-rolled kubernetes gateway API bindings from the `k8s-gateway-api` crate and replaces them with the official generated bindings from the `gateway-api` crate.

Signed-off-by: Alex Leong <alex@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-02-26 12:40:21 -08:00
Oliver Gould 1c23be1260
chore(cargo): use workspace dependencies for kube and hyper (#13672)
In preparation of an upcoming dependency bump, this change updates our Cargo
workspace to use workspace dependencies.
2025-02-17 14:44:54 -08:00
Alex Leong c6e77598ab
refactor(policy): Prepare for Gateway API type binding library switch (#13654)
We refactor the policy-controller in anticipation of switching from the `k8s-gateway-api` crate to the `gateway-api` crate for Gateway API type bindings.  This change does not introduce any functional changes or changes in dependencies but instead prepares for the dependency change by introducing a number of type aliases to coincide with the type names in the `gateway-api` crate.

---------

Signed-off-by: Alex Leong <alex@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-02-17 11:20:38 -08:00
dependabot[bot] a950716591
build(deps): bump ipnet from 2.10.1 to 2.11.0 (#13576)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/commits/2.11.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 08:45:36 -08:00
dependabot[bot] 9cac815f13
build(deps): bump thiserror from 1.0.68 to 2.0.4 (#13435)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.68 to 2.0.4.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.68...2.0.4)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-06 20:01:04 +00:00
Oliver Gould 17b2692d58
build(deps): bump linkerd/dev from v43 to v44 (#13428)
* 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
2024-12-06 11:38:36 -08:00
Oliver Gould 43335fd906
build(deps): bump kubert from 0.21.2 to 0.22.0 (#13399)
This change introduces a timeout into the kubernetes lease logic so that patches
may not get stuck indefinitely.

This change also modifies our Cargo.tomls so that kubert and its related
dependencies (kube and k8s-openapi) are defined at the workspace-level.
2024-11-26 16:47:45 -05:00
Oliver Gould 5a4b9fd236
chore(policy): polish policy controller logging (#13379)
There are a few things about the policy controller logging that can be cleaned
up for consistency and clarity:

* We frequently log ERROR messages when processing resources with unexpected
  values. These messages are more appropriately emitted at WARN--we want to
  surface these situations, but they are not really exceptional.
* The leadership status of the status controller is not logged at INFO level, so
  it's not possible to know about status changes without DEBUG logging.
* We generally use Sentence-cased log messages when emitting user-facing
  messages. There are a few situations where we are not consistent.
* The status controller reconciliation logging is somewhat noisy and misleading.
* The status controller does not log any messages when patching resources.

```
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder has changed
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder has changed
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder has changed
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
DEBUG status::Index: linkerd_policy_controller_k8s_status::index: Lease holder reconciling cluster index.name=linkerd-destination-74d7fdc45d-xfb8l
```

The "Lease holder has changed" message actually indicates that the _lease_ has
changed, though the holder may be unchanged.

To improve logging clarity, this change does the following:

* Adds an INFO level log when the leadership status of the controller changes.
* Adds an INFO level log when the status controller patches resources.
* Adds DEBUG level logs when the status controller patches resources.
* Reconciliation housekeeping logging is moved to TRACE level.
* Consistently uses sentence capitalization in user-facing log messages
* Reduces ERROR messages to WARN when handling invalid user-provided data
  (including cluster resources). This ensures that ERRORs are reserved for
  exceptional policy controller states.
2024-11-25 17:12:42 +00:00
Oliver Gould 6e38368ef0
chore(policy): fix HttpLocalRateLimit type casing (#13324)
Our other types (e.g. HttpRoute) follow the Rust convention of using "Http"
instead of "HTTP".

This commit updates the policy controller to reflect this convention.

No user-facing changes.
2024-11-14 11:13:02 -08:00
Alejandro Pedraza ce6c172749
Implement status handling for HTTPLocalRateLimitPolicy CRD (#13314)
This adds the status stanza to the HTTPLocalRateLimitPolicy CRD, and implements its handling in the policy status controller.

For the controller to accept an HTTPLocalRateLimitPolicy CR it checks that:
- The targetRef is an existing Server
- If there are multiple HTTPLocalRateLimitPolicy CRs pointing to the same server, only accept the oldest one, or if created at the same time, the first in alphabetical order (that logic was moved from the inbound indexer to the status controller).

6cd7dc22c: Update RL CRD and RBAC to allow patching its status
69aee0129: Update golden files
60f25b716: Implement status handling for HTTPLocalRateLimitPolicy CRD
fc99d3adf: Update existing unit tests
0204acf65: New unit tests

## Examples

Not accepted CR:
```yaml
...
status:
  conditions:
  - lastTransitionTime: "2024-11-12T23:10:05Z"
    message: ""
    reason: RateLimitReasonAlreadyExists
    status: "False"
    type: Accepted
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: web-http
```

Accepted CR:
```yaml
...
status:
  conditions:
  - lastTransitionTime: "2024-11-12T23:10:05Z"
    message: ""
    reason: Accepted
    status: "True"
    type: Accepted
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: web-http
```
2024-11-13 17:31:12 -05:00
Alejandro Pedraza caf8e82e7a
feat(policy): add HTTPLocalRateLimitPolicy (#13231)
This adds the HTTPLocalRateLimitPolicy CRD, which is indexed by the policy controller and exposed by the inbound API.

- 81ebc08bd: HTTPLocalRateLimitPolicy CRD and related changes
- 01afd2304: policy controller central changes
- b09892529: rust tests updates and additions
- 2f455973c: golden files updates.

## Testing

In a cluster with linkerd and emojivoto injected, deploy these resources:

```yaml
 apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
  namespace: emojivoto
  name: web-http
spec:
  # permissive policy, so we don't require setting up authz
  accessPolicy: all-unauthenticated
  podSelector:
    matchLabels:
      app: web-svc
  port: http
  proxyProtocol: HTTP/1
```
```yaml
apiVersion: policy.linkerd.io/v1alpha1
kind: HTTPLocalRateLimitPolicy
metadata:
  namespace: emojivoto
  name: web-rl
spec:
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: web-http
  total:
    requestsPerSecond: 100
  identity:
    requestsPerSecond: 20
  overrides:
  - requestsPerSecond: 10
    clientRefs:
    - kind: ServiceAccount
      namespace: emojivoto
      name: default
```

```console
$ kubectl -n emojivoto get httplocalratelimitpolicies.policy.linkerd.io
NAME     TARGET_KIND   TARGET_NAME   TOTAL_RPS   IDENTITY_RPS
web-rl   Server        web-http      100         20
```

Then see how the RL policy is exposed at the inbound API under the protocol section, with `linkerd dg policy -n emojivoto po/web-85f6fb8564-jp67d 8080`:

```yaml
...
protocol:
  Kind:
    Http1:
      local_rate_limit:
        identity:
          requestsPerSecond: 20
        metadata:
          Kind:
            Resource:
              group: policy.linkerd.io
              kind: httplocalratelimitpolicy
              name: web-rl
        overrides:
        - clients:
            identities:
            - name: default.emojivoto.serviceaccount.identity.linkerd.cluster.local
          limit:
            requestsPerSecond: 10
        total:
          requestsPerSecond: 100
...
```
2024-11-08 16:24:24 -08:00
Zahari Dichev b0f087c193
policy: Serve EgressNetwork responses (#13206)
This PR adds a few notable changes associated with the egress functionality of Linkerd:

- `EgressNetwork` objects are indexed into the outbound index
- outbound policy lookups are classfieid as either in-cluster or egress based on the `ip:port` combination
- `TCPRoute`, `TLSRoute`, `GRPCRoute` and `HTTPRoute` attachments are reflected for both `EgressNetwork` and `Service` targets
- the default traffic policy for `EgressNetwork` is honored by returning the appropriate default (failure/success) routes for all protocols

Note that this PR depends on an unreleased version of the linkerd2-proxy-api repo.

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2024-10-27 21:34:35 +02:00
Zahari Dichev 3e2f31dc7a
Add `EgressNetwork` and routes statuses (#13181)
This PR adds an `EgressNetwork` CRD, which purpose is to describe networks that are external to the cluster. 
In addition to that it also adds `TLSRoute` and `TCPRoute` gateway api CRDs.

Most of the work in this change is focused on introducing these CRDs and correctly setting their status based on route specificity rules described in: https://gateway-api.sigs.k8s.io/geps/gep-1426/#route-types.

Notable changes include: 

- ability to attach TCP and TLS routes to both `EgressNetworks` and `Service` objects
- implemented conflict resolutions between routes
- admission validation on the newly introduced resources
- module + integration tests

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2024-10-19 18:40:32 +03:00
dependabot[bot] 4f3e5aa529
build(deps): bump ipnet from 2.9.0 to 2.10.0 (#13054)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.9.0 to 2.10.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/compare/2.9.0...2.10.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 10:41:33 -07:00
Alejandro Pedraza a9fa176dd1
Audit access policy implementation (#12846)
Followup to #12845

This expands the policy controller index in the following ways:

- Adds the new Audit variant to the DefaultPolicy enum
- Expands the function that synthesizes the authorizations for a given default policy (DefaultPolicy::default_authzs) so that it also creates an Unauthenticated client auth and a allow-all NetworkMatch for the new Audit default policy.
- Now that a Server can have a default policy different than Deny, when generating InboundServer authorizations (PolicyIndex::client_authzs) make sure to append the default authorizations when DefaultPolicy is Allow or Audit

Also, the admission controller ensures the new accessPolicy field contains a valid value.

## Tests

New integration tests added:

- e2e_audit.rs exercising first the audit policy in Server, and then at the namespace level
- in admit_server.rs a new test checks invalid accessPolicy values are rejected.
- in inbound_api.rs server_with_audit_policy verifies the synthesized audit authorization is returned for a Server with accessPolicy=audit

> [!NOTE]
> Please check linkerd/website#1805 for how this is supposed to work from the user's perspective.
2024-07-26 13:34:22 -05:00
Alejandro Pedraza 71291fe7bc
Add `accessPolicy` field to Server CRD (#12845)
Followup to #12844

This new field defines the default policy for Servers, i.e. if a request doesn't match the policy associated to a Server then this policy applies. The values are the same as for `proxy.defaultInboundPolicy` and the `config.linkerd.io/default-inbound-policy` annotation (all-unauthenticated, all-authenticated, cluster-authenticated, cluster-unauthenticated, deny), plus a new value "audit". The default is "deny", thus remaining backwards-compatible.

This field is also exposed as an additional printer column.
2024-07-22 09:01:09 -05:00
Alex Leong 1785592091
Manage GrpcRoute resource status (#12748)
We add support for GrpcRoute resources in the policy-controller's status controller.  This means that the policy controller will watch GrpcRoute resources in the cluster and keep their status up to date, in the same way that it currently does for HttpRoute resources.

Signed-off-by: Alex Leong <alex@buoyant.io>
2024-06-21 06:48:33 -07:00
Alex Leong ff5e485550
Add timeout and metrics to HttpRoute status patching (#12250)
When the policy controller updates the status of an HttpRoute resource, we currently have little observability into if those updates are failing or how long they are taking.  We also have no timeout in place to protect the policy controller from extremely slow or hanging status update requests.

We add a generous 5 second timeout for these API calls and add metrics to track success, failures, timeouts, and duration.

```
# HELP resource_status_patch_succeeded_total Counter patches successfully applied to HTTPRoutes.
# TYPE resource_status_patch_succeeded_total counter
resource_status_patch_succeeded_total_total 1711
# HELP resource_status_patch_failed_total Counter patches that fail to apply to HTTPRoutes.
# TYPE resource_status_patch_failed_total counter
resource_status_patch_failed_total_total 0
# HELP resource_status_patch_timeout_total Counter patches that time out when applying to HTTPRoutes.
# TYPE resource_status_patch_timeout_total counter
resource_status_patch_timeout_total_total 0
# HELP resource_status_patch_duration_seconds Histogram of time taken to apply patches to HTTPRoutes.
# TYPE resource_status_patch_duration_seconds histogram
resource_status_patch_duration_seconds_sum 8.930499397
resource_status_patch_duration_seconds_count 1711
resource_status_patch_duration_seconds_bucket{le="0.01"} 1656
resource_status_patch_duration_seconds_bucket{le="0.025"} 1694
resource_status_patch_duration_seconds_bucket{le="0.05"} 1707
resource_status_patch_duration_seconds_bucket{le="0.1"} 1710
resource_status_patch_duration_seconds_bucket{le="0.25"} 1711
resource_status_patch_duration_seconds_bucket{le="0.5"} 1711
resource_status_patch_duration_seconds_bucket{le="1.0"} 1711
resource_status_patch_duration_seconds_bucket{le="2.5"} 1711
resource_status_patch_duration_seconds_bucket{le="5.0"} 1711
resource_status_patch_duration_seconds_bucket{le="+Inf"} 1711
```

Signed-off-by: Alex Leong <alex@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2024-03-21 09:50:03 -07:00
Matei David 98e38a66b6
Rename meshTls to meshTLS in ExternalWorkload CRD (#12098)
The ExternalWorkload resource we introduced has a minor naming
inconsistency; `Tls` in `meshTls` is not capitalised. Other resources
that we have (e.g. authentication resources) capitalise TLS (and so does
Go, it follows a similar naming convention).

We fix this in the workload resource by changing the field's name and
bumping the version to `v1beta1`.

Upgrading the control plane version will continue to work without
downtime. However, if an existing resource exists, the policy controller
will not completely initialise. It will not enter a crashloop backoff,
but it will also not become ready until the resource is edited or
deleted.

Signed-off-by: Matei David <matei@buoyant.io>
2024-02-20 11:00:13 -08:00
Matei David dbd72cc283
Relax validation for ExternalWorkload Status fields (#11979)
ExternalWorkload resources require that status condition has almost all of its
fields set (with the exception of a date field). The original inspiration for
this design was the HTTPRoute object.

When using the resource, it is more practical to handle many of the fields as
optional; it is cumbersome to fill out the fields when creating an
ExternalWorkload. We change the settings to be in-line with a [Pod] object
instead.

[Pod]:
7d1a2f7a73/core/v1/types.go (L3063-L3084)


---------

Signed-off-by: Matei David <matei@buoyant.io>
2024-01-24 14:12:32 +00:00
Matei David 3f4925bfdb
Improve server-side validation for ExternalWorkload (#11900)
We introduced an ExternalWorkload CRD along with bindings for mesh
expansion. Currently, the CRD allows users to create ExternalWorkload
resources without adding a meshTls strategy.

This change adds some more validation restrictions to the CRD definition
(i.e. server side validation). When a meshTls strategy is used, we
require both identity and serverName to be present. We also mark meshTls
as the only required field in the spec. Every ExternalWorkload regardless
of the direction of its traffic must have it set.

WorkloadIPs and ports now become optional to allow resources to be
created only to configure outbound discovery (VM to workload)
and inbound policy discovery (VM).

---------

Signed-off-by: Matei David <matei@buoyant.io>
2024-01-11 10:04:39 +00:00
Zahari Dichev 5e32446111
policy: add externalWorkloadSelector to Server resource (#11899)
This PR adds the ability for a `Server` resource to select over `ExternalWorkload`
resources in addition to `Pods`. For the time being, only one of these selector types
can be specified. This has been realized via incrementing the version of the resource
to `v1beta2`

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2024-01-09 13:26:20 +02:00
Matei David 9fbd3c0290
Introduce bindings for ExternalWorkload resources (#11888)
We introduced an ExternalWorkload CRD for mesh expansion. This change
follows up by adding bindings for Rust and Go code.

For Go code:
* We add a new schema and ExternalWorkload types
* We also update the code-gen script to generate informers
* We add a new informer type to our abstractions built on-top of
  client-go, including a function to check if a client has access to the
  resource.

For Rust code:
* We add ExternalWorkload bindings to the policy controller.

---------

Signed-off-by: Matei David <matei@buoyant.io>
2024-01-08 14:04:20 +00:00
Oliver Gould 5d18b54b77
deps: Update Rust kube ecosystem (#11873)
* kube 0.87.1
* k8s-openapi 0.20.0
* kubert 0.21.1
* k8s-gateway-api 0.15
* ring 0.17

Furthermore, the policy controller's metrics endpoint has been updated
to include tokio runtime metrics.
2024-01-03 11:06:05 -08:00
Oliver Gould 8c577aa163
policy: Set correct backend metadata (#11842)
The policy controller sets incorrect backend metadata when (1) there is
no explicit backend reference specified, and (2) when a backend
reference crosses namespaces.

This change fixes these backend references so that proxy logs and
metrics have the proper metadata references. Outbound policy tests are
updated to validate this.
2023-12-27 15:53:49 -08:00
Oliver Gould 5f100b3195
Bump min Kubernetes API to v1.22 (#11737)
New versions of the k8s-openapi crate drop support for Kubernetes 1.21.
Kubernetes v1.22 has been considered EOL by the upstream project since
2022-07-08. Major cloud providers have EOL'd it as well (GKE's current
MSKV is 1.24).

This change updates the MSKV to v1.22. It also updates the max version
in _test-helpers.sh to v1.28.
2023-12-11 12:15:56 -08:00
dependabot[bot] ba7eb051fa
build(deps): bump ipnet from 2.7.2 to 2.9.0 (#11703)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.7.2 to 2.9.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/commits/2.9.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-06 06:49:30 -08:00
Alex Leong 8579c10d87
Add wait conditions to combat flakiness (#11368)
We intermittently see flaky policy integration test failures like:

```
 failures:
    either

thread 'either' panicked at 'assertion failed: `(left == right)`
  left: `7`,
 right: `0`: blessed uninjected curl must succeed', policy-test/tests/e2e_server_authorization.rs:293:9
```

This test failure is saying that the curl process is returning an exit code of 7 instead of the expected exit code of 0.  This exit code indicates that curl failed to establish a connection.  https://everything.curl.dev/usingcurl/returns

It's unclear why this connection occasionally fails in CI and I have not been able to reproduce this failure locally.

However, by looking at the logic of the integration test, we can see that the integration test creates the `web` Service and the `web` Pod and waits for that pod to become ready before unblocking the curl from executing.  This means that, theoretically, there could be a race condition between the test and the kubernetes endpoints controller.  As soon as the web pod becomes ready, the endpoints controller will update the endpoints resource for the `web` Service and at the same time, our test will unblock the curl command.  If the test wins this race, it is possible that curl will run before the endpoints resource has been updated.

We add an additional wait condition to the test to wait until the endpoints resource has an endpoint before unblocking curl.

Since I could not reproduce the test failure locally, it is impossible to say if this is actually the cause of the flakiness or if this change fixes it.

Signed-off-by: Alex Leong <alex@buoyant.io>
2023-09-15 17:05:27 -07:00
Eliza Weisman 161d1a72f4
policy: update to `kube-rs` v0.85 and friends (#11255)
This branch updates the policy-controller's dependency on Kubert to
v0.18, `kube-rs` to v0.85, `k8s-gateway-api` to v0.13, and `k8s-openapi`
to v0.19.

All of these crates depend on `kube-rs` and `k8s-openapi`, so they must
all be updated together in one commit. Therefore, this branch updates
all these dependencies.
2023-08-15 15:55:56 -07:00
Alex Leong bb29114762
Add ResponseHeaderModifier filter (#11106)
Adds support for the ResponseHeaderModifier outbound HTTP filter in the policy controller.  

Signed-off-by: Alex Leong <alex@buoyant.io>
2023-07-27 13:35:00 -07:00
Kevin Ingelman b02a6a0d83
Add codegen for httproute v1beta3 (#11008)
Add go client codegen for HttpRoute v1beta3. This will be necessary for any of the go controllers (i.e. metrics-api) or go CLI commands to interact with HttpRoute v1beta3 resources in kubernetes.

Signed-off-by: Kevin Ingelman <ki@buoyant.io>
2023-06-14 15:01:56 -07:00
Eliza Weisman ce97e0786f
implement GEP-1742 timeouts in the policy controller (#10975)
PR #10969 adds support for the GEP-1742 `timeouts` field to the
HTTPRoute CRD. This branch implements actual support for these fields in
the policy controller. The timeout fields are now read and used to set
the timeout fields added to the proxy-api in
linkerd/linkerd2-proxy-api#243.

In addition, I've added code to ensure that the timeout fields are
parsed correctly when a JSON manifest is deserialized. The current
implementation represents timeouts in the bindings as a Rust
`std::time::Duration` type. `Duration` does implement
`serde::Deserialize` and `serde::Serialize`, but its serialization
implementation attempts to (de)serialize it as a struct consisting of a
number of seconds and a number of subsecond nanoseconds. The timeout
fields are instead supposed to be represented as strings in the Go
standard library's `time.ParseDuration` format. Therefore, I've added a
newtype which wraps the Rust `std::time::Duration` and implements the
same parsing logic as Go. Eventually, I'd like to upstream the
implementation of this to `kube-rs`; see kube-rs/kube#1222 for details.

Depends on #10969
Depends on linkerd/linkerd2-proxy-api#243

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2023-06-02 11:32:40 -07:00
Alex Leong 2303788d14
Add timeout to HttpRoute CRD and bindings (#10969)
Add a new version to the HttpRoute CRD: `v1beta3`.  This version adds a new `timeouts` struct to the http route rule.  This mirrors a corresponding new field in the Gateway API, as described in [GEP-1742](https://github.com/kubernetes-sigs/gateway-api/pull/1997).  This field is currently unused, but will eventually be read by the policy controller and used to configure timeouts enforced by the proxy.

The diff between v1beta2 and v1beta3 is:

```
                    timeouts:
                      description: "Timeouts defines the timeouts that can be configured
                        for an HTTP request. \n Support: Core \n <gateway:experimental>"
                      properties:
                        backendRequest:
                          description: "BackendRequest specifies a timeout for an
                            individual request from the gateway to a backend service.
                            Typically used in conjunction with automatic retries,
                            if supported by an implementation. Default is the value
                            of Request timeout. \n Support: Extended"
                          format: duration
                          type: string
                        request:
                          description: "Request specifies a timeout for responding
                            to client HTTP requests, disabled by default. \n For example,
                            the following rule will timeout if a client request is
                            taking longer than 10 seconds to complete: \n ``` rules:
                            - timeouts: request: 10s backendRefs: ... ``` \n Support:
                            Core"
                          format: duration
                          type: string
                      type: object
```

We update the `storage` version of HttpRoute to be v1beta3 but continue to serve all versions.  Since this new field is optional, the Kubernetes API will be able to automatically convert between versions.

Signed-off-by: Alex Leong <alex@buoyant.io>
2023-06-01 15:02:11 -07:00
dependabot[bot] e5830ad05b
build(deps): bump linkerd/dev from 39 to 40 (#10825)
* build(deps): bump linkerd/dev from 39 to 40

Bumps [linkerd/dev](https://github.com/linkerd/dev) from 39 to 40.
- [Release notes](https://github.com/linkerd/dev/releases)
- [Commits](https://github.com/linkerd/dev/compare/v39...v40)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Alex Leong <alex@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alex Leong <alex@buoyant.io>
2023-05-09 10:57:19 -07:00
Matei David 2b6760c824
Add status support for BackendReferences (#10601)
A route may have two conditions in a parent status: a condition that
states whether it has been accepted by the parents, and a condition that
states whether all backend references -- that traffic matched against
route is sent to -- have resolved successfully. Currently, the policy
controller does not support the latter.

This change introduces support for checking and setting a backendRef
specific condition. A successful condition (ResolvedRefs = True) is met
when all backend references point to a supported type, and that type
exists in the cluster. Currently, only Service objects are supported. A
nonexistent object, or an unsupported kind will reject the entire
condition; the particular reason will be reflected in the condition's
message.

Since statuses are set on a route's parents, the same condition will
apply to _all_ parents in a route (since there is no way to elicit
different backends for different parents).

If a route does not have any backend references, then the parent
reference type will be used. As such, any parents that are not Services
will automatically get an invalid backend condition (exception to the
rule in the third paragraph where a condition is shared by all parents).
When the parent is supported (i.e a Service) we needn't check its
existence since the parent condition will already reflect that.

---

Signed-off-by: Matei David <matei@buoyant.io>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2023-03-29 12:31:33 +01:00
Alex Leong af219d4bb0
Implement outbound policy API in the policy controller (#10485)
Implement the outbound policy API as defined in the proxy api: https://github.com/linkerd/linkerd2-proxy-api/blob/main/proto/outbound.proto 

This API is consumed by the proxy for the routing of outbound traffic.  It is intended to replace the GetProfile API which is currently served by the destination controller.  It has not yet been released in a proxy-api release, so we take a git dependency on it in the mean time.

This PR adds a new index to the policy controller which indexes HTTPRoutes and Services and uses this information to serve the outbound API.  We also add outbound API tests to validate the behavior of this implementation.

Signed-off-by: Alex Leong <alex@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2023-03-09 21:14:20 -08:00
Oliver Gould 6c83ec7acd
policy: Update HTTPRoute type to v1beta2 (#10484)
The policy controller uses the v1alpha1 HTTPRoute type as its internal
representation of HTTPRoute resources. This change updates the resource
version to v1beta2 in anticipation of adding outbound policy support.

To do so, we need to update the e2e tests to create HTTPRoute resources
properly. They currently include a `port` value, though it is not
allowed by our validator. The older resource type does not support this
field and so it was silently ignored.
2023-03-09 14:20:40 -08:00
Matei David c9b9caec27
Bump k8s-gateway to v0.11.0 (#10474)
The previous version k8s-gateway (`v0.10.0`) did not include backendRefs
for HTTP Routes, since the policy controller did not use them for any
specific task or validation. BackendRef support is currently being added
for the status controller, and will be used as more and more route
functionality is added to Linkerd.

This change bumps k8s-gateway to the most recent version and updates the
internal model of the route to include backendRefs. Additionally, fixes
any compiler issues that cropped up from adding a field to the struct.

Signed-off-by: Matei David <matei@buoyant.io>
2023-03-08 12:44:19 -08:00
Kevin Leimkuhler 40f0bc2360
Add lease claims to status controller (#10424)
This adds lease claims to the policy status controller so that upon startup, a
status controller attempts to claim the `status-controller` lease in the
`linkerd` namespace. With this lease, we can enforce leader election and ensure
that only one status controller on a cluster is attempting to patch HTTPRoute’s
`status` field.

Upon startup, the status controller now attempts to create the
`status-controller` lease — it will handle failure if the lease is already
present on the cluster. It then spawns a task for attempting to claim this lease
and sends all claim updates to the index `Index`.

Currently, `Index.claims` is not used, but in follow-up changes we can check
against the current claim for determining if the status controller is the
current leader on the cluster. If it is, we can make decisions about sending
updates or not to the controller `Controller`.

### Testing
Currently I’ve only manually tested this, but integration tests will definitely
be helpful follow-ups. For manually testing, I’ve asserted that the
`status-controller` is claimed when one or more status controllers startup and
are running on a cluster. I’ve also asserted that when the current leader is
deleted, another status controller claims the lease. Below is the summary of how
I tested it

```shell
$ linkerd install --ha |kubectl apply -f -
…

$ kubectl get -n linkerd leases status-controller
NAME                HOLDER                                 AGE
status-controller   linkerd-destination-747b456876-dcwlb   15h

$ kubectl delete -n linkerd pod linkerd-destination-747b456876-dcwlb
pod "linkerd-destination-747b456876-dcwlb" deleted

$ kubectl get -n linkerd leases status-controller
NAME                HOLDER                                 AGE
status-controller   linkerd-destination-747b456876-5zpwd   15h
```

Signed-off-by: Kevin Leimkuhler <kleimkuhler@icloud.com>
2023-03-06 17:48:41 -07:00
Kevin Leimkuhler b18d6bba9f
Update kubert to 0.14.0 (#10407)
Signed-off-by: Kevin Leimkuhler <kleimkuhler@icloud.com>
2023-02-28 08:21:36 -07:00
dependabot[bot] 8ac0edd87c
build(deps): update kubert (0.13) and related k8s dependencies (#10360)
This branch updates the dependency on `kubert` to 0.13.0. 

- [Release notes](https://github.com/olix0r/kubert/releases)
- [Commits](https://github.com/olix0r/kubert/compare/release/v0.12.0...release/v0.13.0)

 Since `kubert` and other Kubernetes API dependencies must be updated in
lockstep, this branch also updates `kube` to 0.78, `k8s-openapi` to
0.13, and `k8s-gateway-api` to 0.9.

`kube-runtime` now depends on a version of the `base64` crate which has
diverged significantly from the version `rustls-pemfile` depends on.
Since both `base64` deps are transitive dependencies which we have no
control over, this branch adds a `cargo deny` exception for duplicate
dependencies on `base64`.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
2023-02-21 16:45:21 -08:00
Kevin Leimkuhler 24171e4e62
Add policy status controller (#10236)
### Overview
This adds a policy status controller which is responsible for patching Linkerd’s
HTTPRoute resource with a `status` field. The `status` field has a list of
parent statuses — one status for each of its parent references. Each status
indicates whether or not this parent has “accepted” the HTTPRoute.

The status controller runs on its own task in the policy controller and watches
for updates to the resources that it cares about, similar to the policy
controller’s index. One of the main differences is that while the policy
controller’s index watches many resources, the status controller currently only
cares about HTTPRoutes and Servers; HTTPRoutes can still only have parent
references that are Servers so we don’t currently need to consider any other
parent reference resources.

The status controller maintains its own index of resources so that it is
completely separated from the policy controller’s index. This allows the index
to be simpler in both its structure, how it handles `apply` and `delete`, and
what information it needs to store.

### Follow-ups
There are several important follow-ups to this change. #10124 contains changes
for the policy controller index filtering out HTTPRoutes that are not accepted
by a Server. We don’t want those changes yet. Leaving those out, the status
controller does not actually have any affect on Linkerd policy in the cluster.

We can probably add additional logging several places in the status controller;
that may even take place as part of the reviews on this. Additionally, we could
try queue size for updates to be processed.

Currently if the status controller fails in any of its potential places, we do
not re-queue updates. We probably should do that so that it is more robust
against failure.

In an HA installation, there could be multiple status controllers trying to
patch the same resource. We should explore the k8s lease API so that only one
status controller can patch a resource at a time.

### Implementation
The status controller `Controller` has a k8s client for patching resources,
`index` for tracking resources, and an `updates` channel which handles
asynchronous updates to resources.

#### Index
`Index` synchronously observes changes to resources. It determines which Servers
accept each HTTPRoute and generates a status patch for that HTTPRoute. Again,
the status contains a list of parent statuses, one for each of the HTTPRoutes
parent references.

When a Server is added or deleted, the status controller needs to recalculate
the status for all HTTPRoutes. This is because an HTTPRoute can reference
Servers in other namespaces, so if a Server is added or deleted anywhere in the
cluster it could affect any of the HTTPRoutes on the cluster.

When an HTTPRoute is added, we need to determine the status only for that
HTTPRoute. When it’s deleted we just need to make sure it’s removed from the
index.

The patches that the `Index` creates are sent to the `Controller` which is
responsible only for applying those patches to HTTPRoutes.

#### Controller
`Controller` asynchronously processes updates and applies patches to HTTPRoutes.

Signed-off-by: Kevin Leimkuhler <kleimkuhler@icloud.com>
2023-02-15 11:56:04 -07:00
Eliza Weisman 3b7dc12a62
policy: include colliding Server in validation error (#10187)
Currently, when the policy controller's validating admission webhook
rejects a Server because it collides with an existing one, it's
difficult to determine which resource the new Server would collide with
(see #10153). Therefore, we should update the error message to include
the existing Server. Additionally, the current error message uses the
word "identical", which suggests to the user that the two Server specs
have the same pod selector. However, this may not actually be the case:
the conflict occurs if the two Servers' pod selectors would select *any*
overlapping pods.

This branch changes the error message to include the name and namespace
of the existing Server whose pod selector overlaps with the new Server.
Additionally, I've reworded the error message to avoid the use of
"identical", and tried to make it clearer that the collision is because
the pod selectors would select one or more overlapping pods, rather than
selecting all the same pods.

Fixes #10153
2023-02-11 12:07:37 -08:00
Alex Leong 03727b753b
Add v1beta2 version to HTTPRoute CRD (#9973)
Fixes #9965

Adds a `path` property to the RedirectRequestFilter in all versions.  This property was absent from the CRD even though it appears in the gateway API documentation and is represented in the internal types.  Adding this property to the CRD will also users to specify it.

Add a new version to the HTTPRoute CRD: v1beta2.  This new version includes two changes from v1beta1:

* Added `port` property to `parentRef` for use when the parentRef is a Service
* Added `backendRefs` property to HTTPRoute rules

We switch the storage version of the HTTPRoute CRD from v1alpha1 to v1beta2 so that these new fields may be persisted.

We also update the policy admission controller to allow an HTTPRoute parentRef type to be Service (in addition to Server).

Signed-off-by: Alex Leong <alex@buoyant.io>
2023-01-23 08:56:35 -08:00
dependabot[bot] 6c7844e4ce
build(deps): bump ipnet from 2.6.0 to 2.7.0 (#9995)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.6.0 to 2.7.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/compare/2.6.0...2.7.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 10:49:39 -08:00
dependabot[bot] 9490987b31
build(deps): bump ipnet from 2.5.1 to 2.6.0 (#9967)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.5.1 to 2.6.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/commits/2.6.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-08 11:41:05 -08:00
dependabot[bot] 93a29d156d
build(deps): bump kubert from 0.11.1 to 0.12.0 (#9847)
* build(deps): bump kubert from 0.11.1 to 0.12.0

Bumps [kubert](https://github.com/olix0r/kubert) from 0.11.1 to 0.12.0.
- [Release notes](https://github.com/olix0r/kubert/releases)
- [Commits](https://github.com/olix0r/kubert/compare/release/v0.11.1...release/v0.12.0)

---
updated-dependencies:
- dependency-name: kubert
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump kube to v0.76

Signed-off-by: Oliver Gould <ver@buoyant.io>

* Update k8s-gateway-api to v0.8

Signed-off-by: Oliver Gould <ver@buoyant.io>

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Oliver Gould <ver@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2022-11-18 15:18:29 -08:00
Eliza Weisman cf1ce81eb0
policy: fix backwards `NotIn` label selector (#9433)
The implementation of the `NotIn` pod selector expression in the policy
controller is backwards. If a value exists for the label in the
expression, and it is contained in the `NotIn` set, the expression will
return `true`, and it will return `false` when the value is _not_ in the
set. This is because it calls `values.contains(v)`, just like the `In`
expression.
2022-09-27 08:47:52 -07:00
Oliver Gould c809610e55
Update Rust Kubernetes dependencies (#9454)
* Update kubert to v0.10
* Update kube-rs to v0.75 (fixes #9339)
* Update k8s-openapi to v0.16
* Update k8s-gateway-api to v0.7

Signed-off-by: Oliver Gould <ver@buoyant.io>
2022-09-27 08:43:36 -07:00