Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removes TrafficSplit in favor of ForwardToTarget #57

Merged
merged 1 commit into from Jul 29, 2020

Conversation

danehans
Copy link
Contributor

@danehans danehans commented Jan 30, 2020

Currently, TrafficSplit is scaffolding. This PR removes TrafficSplit in favor of implementing traffic splitting within ForwardToTarget.

  1. Pluralizes forwardTo to allow forwarding to multiple targets (i.e. destination objects).
  2. Introduces the weight target attribute used by forwardTo to distribute traffic among multiple targets.

Partially fixes #58.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jan 30, 2020
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jan 30, 2020
@danehans
Copy link
Contributor Author

/assign @bowei

@danehans
Copy link
Contributor Author

fixes issue: #58

@bowei bowei added this to Discussion items in Main Jan 30, 2020
@hbagdi
Copy link
Contributor

hbagdi commented Feb 13, 2020

What decision parameters are we using here to limit the scope of what is included in the core API and what is part of extensions? This is one of those areas where implementations will have different implementations and behaviors.

// Support: extended
//
// +optional
Filter *TrafficSplitFilter `json:"filter,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: Should Filter be invalid for passthrough tls connections?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think yes. This should be valid only for HTTP routes. Filter should not be interpreted for TCP routes all together, no matter it is plain-text or TLS pass through.

@danehans danehans mentioned this pull request Feb 14, 2020
@danehans
Copy link
Contributor Author

@hbagdi I believe the decision is "do most implementations support this feature". How it's supported is up to the implementation. IMO most implementations do support percentage-based traffic splitting. Do you disagree? Are there any other properties presented in this PR that you feel most implementations do not support... maybe Selector?

@hbagdi
Copy link
Contributor

hbagdi commented Feb 14, 2020

I think selector is not a problem. Traffic splitting itself is a common enough construct but not all providers, especially cloud providers and managed offerings don't support injecting headers specifically for different splits. Most have support for injecting headers but not different headers in context of splits.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 14, 2020
@danehans
Copy link
Contributor Author

@hbagdi thanks for the feedback. I created #108 to discuss this in more detail.

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Feb 26, 2020
@danehans
Copy link
Contributor Author

Most have support for injecting headers but not different headers in context of splits.

@hbagdi I marked the Filter field as "Extended". This is the same field from HTTPRoute. The primary difference from HTTPRoute is TrafficSplit performs the Filter, i.e. add/remove header, post routing decision. Can you help me better understand why Filter is a non-issue for HTTPRoute but is an issue for TrafficSplit?

@hbagdi
Copy link
Contributor

hbagdi commented Feb 27, 2020

I marked the Filter field as "Extended". This is the same field from HTTPRoute. The primary difference from HTTPRoute is TrafficSplit performs the Filter, i.e. add/remove header, post routing decision. Can you help me better understand why Filter is a non-issue for HTTPRoute but is an issue for TrafficSplit?

I think it is fair to add support for filters and transformation but it would be better to do that in one place rather several different. How do you plan to connect TrafficSplit with Route?

@danehans
Copy link
Contributor Author

TODO:

  1. Update spec to state where the type should be referenced from.
  2. Get input from implementors on the best match>filter>action ordering. For example, Knative requires filtering post routing.

}

// TrafficSplitHeaderFilter defines the filter behavior for a request match.
type TrafficSplitHeaderFilter struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems to me this is more of Action, i.e. what happens to a request, than Filter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Manipulating a request is considered a filter in terms of Service API's. PTAL at the route types as a reference implementation.

// Support: Extended
//
// +optional
Add map[string]string `json:"add,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

If a header with a given name already exists in the request, will this become a replace? Or it should be configurable, i.e. whether add or replace?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yiyangy I believe that is implementation-specific. cc: @bowei @youngnick

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, for Contour we chose to make Add include an implicit replace in the case the header already existed, but I don't know if we want to dictate that at this level.

Copy link
Contributor Author

@danehans danehans May 7, 2020

Choose a reason for hiding this comment

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

@yiyangy note that api/v1alpha1/trafficsplit_types.go has been removed in the latest iteration of the PR.

// Support: Extended
//
// +optional
Selector *metav1.LabelSelector `json:"selector,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Shall this Selector be at the upper level i.e. TrafficSplitSpec? In the sense that for all the traffic matches Selector, the traffic is split among multiple rules with each rule carrying a weight. In case I misunderstand, could you please maybe give an example to elaborate on the use of Selector?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yiyangy config/samples/networking_v1alpha1_trafficsplit.yaml provides an example, PTAL.

@danehans
Copy link
Contributor Author

I think it is fair to add support for filters and transformation but it would be better to do that in one place rather several different. How do you plan to connect TrafficSplit with Route?

@hbagdi xRoute performs transformations prior to routing traffic. We need the ability to support post-routing transformations for use cases such as Knative. This is why I added TrafficSplitFilter as a field of the TrafficSplitRule type. Do you have suggestions on how to handle pre and post filtering across the different objects? Should filters be a separate object that is referenced by the route/trafficfilter types?

The following is an example usage of TrafficSplit. The HTTPRoute forwards traffic for host "foo.com/bar" to a TrafficSplit named "my-trafficsplit", which splits traffic to service "my-trafficsplit-svc", forwarding 80% of the traffic to endpoints labeled "app=v1" and 20% to endpoints labeled "app=v2". The example removes header "bar" and adds header "my-header: foo" before forwarding traffic to the service:

kind: HTTPRoute
apiVersion: networking.x.k8s.io/v1alpha1
metadata:
  name: http-app-1
  namespace: default
spec:
  hosts:
    - hostnames:
        - "foo.com"
      rules:
        - match:
            path: /bar
          action:
            forwardTo:
              resource: trafficsplit
              group: networking.x.k8s.io/v1alpha1
              name: my-trafficsplit
---
apiVersion: networking.x.k8s.io/v1alpha1
kind: TrafficSplit
metadata:
  name: my-trafficsplit
spec:
  rules:
    - destination:
        group: core
        resource: service
        name: my-trafficsplit-svc
      selector:
        app: v1
      weight: 80
      filter:
        headers:
          add:
            my-header: foo
          remove:
            - bar
    - destination:
        group: core
        resource: service
        name: my-trafficsplit-svc
      selector:
        app: v2
      weight: 20
      filter:
        headers:
          add:
            my-added-header: foo
          remove:
            - bar

@danehans danehans force-pushed the split branch 2 times, most recently from f74e0fc to a9a1497 Compare March 18, 2020 17:17
@jpeach
Copy link
Contributor

jpeach commented Mar 18, 2020

This could easily be confused with the SMI trafficsplit. I'm not sure that we should add more CRD types, it seems likely that if we go down this path, the number of types will grow very large.

I cases like this, I think that a brief implementation survey is useful to give context to the design. Many ingress controllers already have support for this feature; how do they do it and what are the outcomes of theirs approaches?

@bowei
Copy link
Contributor

bowei commented Mar 18, 2020

It's a good question regarding traffic spit, someone on the SMI side even mentioned trying to merge these two or to use the same resource, trying to find the reference.

@hbagdi hbagdi mentioned this pull request Mar 24, 2020
5 tasks

// Weight specifies the proportion of traffic to be forwarded to a targetRef.
// A valid weight value is 0-100. The sum of weights across targetRefs must
// equal 100. If only one targetRef is specified, weight is ignored and all
Copy link
Contributor

Choose a reason for hiding this comment

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

Another option is that instead of weight specifying the fraction, the fraction of traffic to be forwarded to a targetRef is computed as weight / (sum of all weights in targetRefs). Then the constraint of "A valid weight value is 0-100. The sum of weights across targetRefs must equal 100" can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yiyangy thanks for the review. I've updated the godocs based on your feedback.

@robscott
Copy link
Member

After some discussion about multicluster implications last week, I spent some time writing a doc that shows how this could work with multicluster services. At a high level, the theory is that traffic splitting as defined by Service APIs is focused on splitting traffic between Services. In a multicluster scenario, traffic can further be segmented by configuring how much traffic is distributed to each cluster. That would be accomplished either on the Service or ServiceExport resource. I've run that by @JeremyOT to confirm that this is compatible with his vision of multicluster services, and it sounds like it is.

Would love additional feedback on that doc to ensure the approach makes sense. The doc is entirely based on the approach proposed by this PR, just translating it to multicluster use cases. If there's general consensus on that, I think we're good to proceed here as well.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 14, 2020
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 22, 2020
Comment on lines 313 to 315
// If only one targetRef is specified, weight is ignored and all traffic is
// forwarded to the targetRef. If multiple targetRefs are specified without
// weight, traffic is evenly distributed across all targetRefs.
Copy link
Member

Choose a reason for hiding this comment

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

Consider making weight required and using CRD defaults to set a default value. We can simplify by e.g. using weight: 1 when not specified. This makes behavior intuitive when a weight isn't supplied, and makes weighting functionality more discoverable as users will see a value to play with when viewing their configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JeremyOT commit 9abadaa updates weight based on your feedback above. Thanks for the review.

@danehans danehans force-pushed the split branch 2 times, most recently from 9abadaa to d91ef3b Compare July 27, 2020 16:52
Copy link
Contributor

@hbagdi hbagdi left a comment

Choose a reason for hiding this comment

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

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 27, 2020
@hbagdi
Copy link
Contributor

hbagdi commented Jul 27, 2020

/assign @bowei

@hbagdi hbagdi removed their assignment Jul 27, 2020
Copy link
Member

@robscott robscott left a comment

Choose a reason for hiding this comment

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

Thanks for the work on this! Just had a couple small nits.

/lgtm

Comment on lines 45 to 48
// Weight specifies the proportion of traffic to be forwarded to a targetRef,
// computed as weight/(sum of all weights in targetRefs). The following example
// sends 70% of traffic to service "my-trafficsplit-sv1" and 30% of the traffic
// to service "my-trafficsplit-sv2":
Copy link
Member

Choose a reason for hiding this comment

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

Nit: It would be good to clarify that weight is not actually a percentage and that all weights do not need to add up to 100.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@robscott commit d7e4c20 addresses your comment above.

Comment on lines 58 to 59
// If only one targetRef is specified, weight is ignored and all traffic is
// forwarded to the targetRef. If unspecified, defaults to 1.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I don't think we need this clarification. Weight doesn't need to be ignored. If there is only forwardTo it is guaranteed to include 100% of the total weight, even if that is only 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@robscott commit d7e4c20 addresses your comment above.

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 29, 2020
@robscott
Copy link
Member

Thanks!

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 29, 2020
@bowei
Copy link
Contributor

bowei commented Jul 29, 2020

/approve

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bowei, danehans

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 29, 2020
@k8s-ci-robot k8s-ci-robot merged commit 843813d into kubernetes-sigs:master Jul 29, 2020
Main automation moved this from Discussion items to Done Jul 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
No open projects
Main
  
Done
Development

Successfully merging this pull request may close these issues.

Backend Object Traffic Manipulation