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

Add support for VirtualService delegate #1209

Merged
merged 5 commits into from Apr 3, 2020

Conversation

hzxuzhonghu
Copy link
Member

Based on this proposal, added http route rules chaining.

@googlebot googlebot added the cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA. label Dec 18, 2019
@istio-testing istio-testing added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Dec 18, 2019
@hzxuzhonghu hzxuzhonghu force-pushed the vs-delegate branch 2 times, most recently from d8509db to ff1a006 Compare December 18, 2019 07:29
// metadata:
// name: productpage
// namespace: nsA
// spec:
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 strange that the delegate VirtualService has no hosts. I would have expected:

hosts:
- productpage.nsA.svc.cluster.local

Otherwise, where are the rules for routing internal requests to the reviews service? Won't I need to create another VS with exactly the same contents (+ the hosts field) to define the rules for internal calls from inside the mesh to the productpage service?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, why I note this is that:
Here we need to distinguish if this is a delegate or root VS, we don't want the delegate rule function alone. Because in addition to the matching rules, there are some fields like headers, if the delegate function alone, the result may be not intended.

Copy link
Contributor

@frankbu frankbu Dec 21, 2019

Choose a reason for hiding this comment

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

In general, I would say the same behavior would be expected for a delegate or standalone VS for the same target. Can you give me a specific example of where they need to be different?

I also think that if there really is a difference between a delegate and a standalone VS, you should either use a different structure for delegates (e.g., kind: VirtualServiceDelegate), or at least have some clear way to mark it as a delegate (e.g., maybe a special reserved host value). Using a VS with no hosts to represent a delegate seems a little like a hack.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I also think that if there really is a difference between a delegate and a standalone VS, you should either use a different structure for delegates (e.g., kind: VirtualServiceDelegate), or at least have some clear way to mark it as a delegate (e.g., maybe a special reserved host value).

Indeed it has a difference, say multi delegates should work as referred orders, but if we donot know whether they are delegates, the routing rule will be applied un ordered.

So, in order to remove the hack way, a field indicates it is a delegate sounds good to me.

Copy link
Member

Choose a reason for hiding this comment

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

I'll repeat what I'll say over and over again: we should do what HTTPRoute does

@rshriram
Copy link
Member

rshriram commented Dec 22, 2019

Here is one thought.

Virtual service can have a separate include section that specifies names of other virtual services and conditions under which these virtual services should be included.

Eg

 host: foo.com
 IncludeVirtualServices:
 - resource: ns1/vs1
    condition:
     - httpMatch:
         urimatchHasPrefix: /barbar

This will cause pilot to only include the http rules that have /barbar as a prefix or exact match in the vs1 virtual service in the ns1 namespace.

Now that said, @louiscryan & @frankbu the problem with delegation now is how to deal with the imports at gateway. Gateway hosts can specify something like ns1/*.bar.com - wherein the semantics is that only virtual services matching *.bar.com from ns1 namespace will be included by the gateway. If such a virtual service in ns1 namespace then delegates to ns2 namespace, do we import even though the gateway didn’t say so ? If we do, the semantics will be confusing. If we don’t and force people to put all the delegated vs in the ns1 namespace only, then the effectiveness of delegation is less as the motivation for delegation is that the gateway admin in say istio-system can define the top level virtual service alone while delegating the specific virtual services to the namespaces that own the destination hosts of the virtual services.

@hzxuzhonghu
Copy link
Member Author

kind: HTTPRoute
name: http-app-3
namespace: internal-app
rules:
- match:
    http:
      host: bar.com
      path:
        prefix: /store
  action:
    backend:                            # Delegated to another team that
      name: delegate-1                  # manages "bar.com/store". This is
      namespace: other-team             # a reference to another route 
      kind: HTTPRoute # in a different namespace.
      apiGroup: networking.k8s.io
  ...
---
kind: HTTPRoute
name: delegate-1
namespace: other-team
rules:
- match:
    http:
      host: bar.com
      path: 
        prefix: /store
  action:
    backend:
      name: store-app
  ...

This is what k8s community proposed, cross namespace reference in istio also exists from the beginning, like DestinationRule, gateway and virtualservice, etc.

@hzxuzhonghu
Copy link
Member Author

 host: foo.com
 IncludeVirtualServices:
 - resource: ns1/vs1
    condition:
     - httpMatch:
         urimatchHasPrefix: /barbar

By this we can introduce a new struct with simplified matching conditions(maybe just has uri, headers and query params), which can simplify the merging semantics in the original proposal.

@howardjohn
Copy link
Member

I think we should stick to what the have in the k8s API so we can converge. Adding different behavior just makes users confused

@howardjohn
Copy link
Member

also we should probably be designing this in the design doc not a pr

@rshriram
Copy link
Member

I think we should stick to what the have in the k8s API so we can converge. Adding different behavior just makes users confused

Lets first do what makes sense in our api as users today will be confused if this is incongruent with what we have. K8s api has to evolve. We dont want to restrict delegation to just http. Delegation is possible with sni routing and tcp routing as well. A top level include with match conditions will allow us to delegate for all scenarios in Istio

@howardjohn
Copy link
Member

Lets first do what makes sense in our api as users today will be confused if this is incongruent with what we have. K8s api has to evolve. We dont want to restrict delegation to just http. Delegation is possible with sni routing and tcp routing as well. A top level include with match conditions will allow us to delegate for all scenarios in Istio

For what its worth, the k8s apis also support tls/tcp delegation. We don't need to completely restrict ourselves to their API but I do think its valuable to draw inspiration from it, and when we do drift from it make sure we are actually getting value from it

@hzxuzhonghu
Copy link
Member Author

I have already supplemented tcp/tls delegate days ago, please have a look if you have a chance.

@hzxuzhonghu
Copy link
Member Author

FYI, basically it aligns with istio in high level.

K8s gateway
https://github.com/kubernetes-sigs/service-apis/blob/12ca3b8264c51d49ec5b31d351aae19a57c0eccc/api/v1alpha1/gateway_types.go#L53-L62

type GatewaySpec struct {
	// Class used for this Gateway. This is the name of a GatewayClass resource.
	Class string `json:"class"`
	// Listeners associated with this Gateway. Listeners define what addresses,
	// ports, protocols are bound on this Gateway.
	Listeners []Listener `json:"listeners"`
	// Routes associated with this Gateway. Routes define
	// protocol-specific routing to backends (e.g. Services).
	Routes []core.TypedLocalObjectReference `json:"routes"`
}

HTTPRoute

https://github.com/kubernetes-sigs/service-apis/blob/12ca3b8264c51d49ec5b31d351aae19a57c0eccc/api/v1alpha1/httproute_types.go#L24-L53

// HTTPRouteSpec defines the desired state of HTTPRoute
type HTTPRouteSpec struct {
	// Hosts is a list of Host definitions.
	Hosts []HTTPRouteHost `json:"hosts,omitempty"`

	// Default is the default host to use. Default.Hostnames must
	// be an empty list.
	//
	// +optional
	Default *HTTPRouteHost `json:"default"`
}

// HTTPRouteHost is the configuration for a given host.
type HTTPRouteHost struct {
	// Hostnames are a list of hosts names that match this host
	// block.
	//
	// TODO: RFC link
	Hostnames []string `json:"hostnames"`

	// Rules are a list of HTTP matchers, filters and actions.
	Rules []HTTPRouteRule `json:"rules"`

	// Extension is an optional, implementation-specific extension
	// to the "host" block.
	//
	// Support: custom
	//
	// +optional
	Extension *core.TypedLocalObjectReference `json:"extension"`
}

@istio-testing istio-testing added the needs-rebase Indicates a PR needs to be rebased before being merged label Feb 13, 2020
@istio-testing istio-testing added needs-rebase Indicates a PR needs to be rebased before being merged and removed needs-rebase Indicates a PR needs to be rebased before being merged labels Feb 13, 2020
@istio-policy-bot istio-policy-bot added the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Mar 10, 2020
@istio-testing istio-testing removed the needs-rebase Indicates a PR needs to be rebased before being merged label Mar 10, 2020
@hzxuzhonghu hzxuzhonghu removed the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Mar 10, 2020
@istio-policy-bot istio-policy-bot added the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Mar 10, 2020
@hzxuzhonghu
Copy link
Member Author

/test gencheck_api

@istio-policy-bot istio-policy-bot removed the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Mar 10, 2020
@istio-testing istio-testing added the needs-rebase Indicates a PR needs to be rebased before being merged label Mar 23, 2020
@istio-testing istio-testing removed the needs-rebase Indicates a PR needs to be rebased before being merged label Mar 24, 2020
// 1. Only one tier of delegate can be set.
// 2. The delegate's Match conditions must be a strict subset of the root's,
// otherwise there is a conflict and the TCPRoute will not take effect.
Delegate delegate = 3;
Copy link
Member

Choose a reason for hiding this comment

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

skip delegate for tcp. We have no way of setting parent match conditions

Copy link
Member Author

Choose a reason for hiding this comment

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

ok

Copy link
Contributor

@ramaraochavali ramaraochavali left a comment

Choose a reason for hiding this comment

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

Left couple of couple of minor comments, otherwise LGTM

// It can be set only when `Route` and `Redirect` are empty, and the route rules of the
// delegate VirtualService will be merged with that in the current one.
// **NOTE**:
// 1. Only one tier of delegate is supported.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: /s/"Only one tier of delegate is supported"/"Only one level delegation is supported"

// 1. Only one tier of delegate is supported.
// 2. The delegate's HTTPMatchRequest must be a strict subset of the root's,
// otherwise there is a conflict and the HTTPRoute will not take effect.
Delegate delegate = 20;
Copy link
Contributor

Choose a reason for hiding this comment

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

can we make this oneof (HttpRoute, HttpRedirect, Delegate)?

Copy link
Member Author

Choose a reason for hiding this comment

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

I would like to make this a separate pr.

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems possible

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. not a problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants