serving icon indicating copy to clipboard operation
serving copied to clipboard

Support GRPC and HTTP2 without explicit port labeling

Open rgregg opened this issue 6 years ago • 27 comments

In what area(s)?

/area networking

Describe the feature

Today to use GRPC or HTTP/2 for ingress into your service, you have to explicitly label the ports (see the GRPC sample: https://github.com/knative/docs/blob/master/docs/serving/samples/grpc-ping-go/sample.yaml)

However, the Runtime Contract states that the platform will perform automatic detection between HTTP/1.1, QUIC, and HTTP/2.

Unless overridden by setting the name field on the inbound port, the platform will perform automatic detection as described above. Developers SHOULD prefer to use automatic content negotiation where available

rgregg avatar Jun 06 '19 18:06 rgregg

I have a proposal out to update this in the runtime contract to reflect our current behavior. Discussion on it can be seen here: https://github.com/knative/serving/pull/4035/files#r283535192

I suggest the update to the contract as we do not have line of sight to implementing this as it has strong dependencies on features in Envoy and Istio which AFAIK are not being worked on. Some background on how we landed this without automatic upgrade can be seen in this comment: https://github.com/knative/serving/pull/2539#issuecomment-444585549.

dgerd avatar Jun 06 '19 18:06 dgerd

Please do not close this issue by changing the runtime contract, this should be considered as a bug for Knative, even if fixing it will be hard due to Knative's use of Istio.

As a developer, I should not have to opt-into using HTTP2 to use HTTP2.

steren avatar Jun 13 '19 22:06 steren

Having the explicit choice for what protocol your app supports feels like a feature. This can help to catch errors in expectations that have performance implications in the differences between HTTP/1 and HTTP/2.

While the automatic detection could be a useful default, given the underlying dependencies in our stack cannot support those requirements. It's unclear Knative can even support this without significant work in Envoy and Istio.

Changing the runtime contract and aligning the expectations in the contract with what we can deliver feels like the right decision. We can re-evaluate that decision in the future if/when Envoy improves this experience.

rgregg avatar Jun 13 '19 22:06 rgregg

Please at least keep this open as a feature request.

steren avatar Jun 13 '19 22:06 steren

I commented this somewhere else, but pasting here and elaborating.

Our support today looks like:

(empty): HTTP/1.1 only "h2c": HTTP/2 only "http1": HTTP/1.1 only

This makes (empty) == "http1" in todays world.

I have concerns with making (empty) automatically upgrade to HTTP/2.0 in the future and leave the "http1" as the option with no upgrade. This breaks the equality between (empty) and "http1" which has the potential to 1) be breaking 2) be surprising to developers. I don't want to rule it out as our considerations and our understanding of developer expectations could change by the time we are able to implement this, but we should discuss at that time how automatic HTTP upgrading works and if it should be the default behavior.

I am fine keeping this issue open to track automatic HTTP/2.0 upgrades as a feature request.

dgerd avatar Jun 14 '19 00:06 dgerd

Concur with Dan. When we can, we should rather support auto and keep defaulting to http/1.1.

vagababov avatar Jun 14 '19 02:06 vagababov

/assign tanzeeb

tcnghia avatar Dec 05 '19 18:12 tcnghia

Issues go stale after 90 days of inactivity. Mark the issue as fresh by adding the comment /remove-lifecycle stale. Stale issues rot after an additional 30 days of inactivity and eventually close. If this issue is safe to close now please do so by adding the comment /close.

Send feedback to Knative Productivity Slack channel or file an issue in knative/test-infra.

/lifecycle stale

Issues go stale after 90 days of inactivity. Mark the issue as fresh by adding the comment /remove-lifecycle stale. Stale issues rot after an additional 30 days of inactivity and eventually close. If this issue is safe to close now please do so by adding the comment /close.

Send feedback to Knative Productivity Slack channel or file an issue in knative/test-infra.

/lifecycle stale

@tanzeeb You still look at this? With 1.5 or 1.6 can we do it? /remove-lifecycle stale

vagababov avatar Jun 03 '20 16:06 vagababov

@rafaeltello is looking at it now

/assign @rafaeltello

tanzeeb avatar Jun 05 '20 04:06 tanzeeb

I think we need to reopen question adding 'auto' vs changing "" default meaning. The current spec : https://knative.dev/docs/reference/serving-api/#serving.knative.dev/v1.RevisionTemplateSpec (see podSpec inside spec) "delegates" name declaration to k8S
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#containerport-v1-core
which in turn declares port name as " If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services."

looking at the IANA service names https://tools.ietf.org/html/rfc6335 it seem that RC comes with syntactic rules as well as a registration process/database https://www.iana.org/protocols . (see "Hypertext Transfer Protocol (HTTP) Upgrade Token Registry" link for the reference to "h2c" registration ) Having said that I think kNative / k8s customers are still free to name their ports what they like (within syntactical rules), but kNative as a platform wold probably need to to pursue IANA registration if we want to come up with a a special value like "auto" (per proposal above, or change k8s spec).
Given that I would propose to to revert back to the original plan of "" string meaning auto detection and breaking "http1" == "" equivalency. I and Rafael are working on a spec ( will share within in a week or so). Just wanted to give participants an early heads up on this plan adjustment.

igorbelianski avatar Jul 22 '20 21:07 igorbelianski

Design : https://docs.google.com/document/d/1cGmJsBht6vTwqvWvfRnAEmQ1NPQOpZHjR082t2L8Wl4/edit?usp=sharing

igorbelianski avatar Jul 29 '20 01:07 igorbelianski

My $0.02 from writing the initial runtime spec.

The intent was that an empty name would mean that Knative would send the initial request as HTTP/1 with an h2c upgrade option where possible, i.e. section 3.2 of RFC7540. This would look like (copy-pasting):

GET / HTTP/1.1
     Host: server.example.com
     Connection: Upgrade, HTTP2-Settings
     Upgrade: h2c
     HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

Where the HTTP2-Settings would be supplied by either the client or by the intermediate Knative routing stack. In the case of a request which was issued with HTTP2 settings which couldn't be downgraded to HTTP/1, the request would be dropped (e.g. in the queue-proxy) if the user container refused the h2c upgrade.

In the case of an h2c upgrade, the client responds with a 101 and then continues using HTTP/2 framing, so the response body could use all the HTTP/2 features. The spec also mentions that an OPTIONS request may be made to probe for h2c; I'd be highly surprised if OPTIONS was implemented to perform mutations.

Note that the h2c upgrade is incompatible with the websocket upgrade, so if the connection from the client already had an upgrade header, the h2c header shouldn't be injected.

evankanderson avatar Oct 08 '20 18:10 evankanderson

I think there is subtle difference of what protocol and what backend can support, when there is an ingress proxy in between. client -> H2 -> ingress proxy -> (some protocol) -> backend

Without prior knowledge, I don't know how ingress proxy could determine what it should use or what it could use.

For example, for a non-streaming H2 request, ingress proxy could downgrade it to H1 to a H1 only backend. For a gRPC request (also H2), ingress proxy should not downgrade. For a H1 request, ingress proxy could upgrade to H2 only backend.

Does it mean we need to layer ALPN? client -> ALPN0 -> ingress proxy -> ALPN1 -> backend

And ALPN0 depends on ALPN1 based on different combinations?

wlhee avatar Oct 08 '20 19:10 wlhee

I don't think the backend is ever serving TLS, so I don't think ALPN figures into it.

What's the rationale for blocking gRPC 2->1? I'd think it would show up as POSTs of protobuf body, which the user-container might not know what to do with. Is the implementation simplified if gRPC is explicitly blocked? Right now, I don't think we do anything special with gRPC compared with other methods.

evankanderson avatar Oct 08 '20 21:10 evankanderson

For HTTP/2 with Prior Knowledge, I think the user needs to specify h2c as a string.

Note that today Knative is not implementing the SHOULD offer an HTTP/2.0 upgrade option part of the spec, which is okay since it is a SHOULD.

evankanderson avatar Oct 08 '20 21:10 evankanderson

I don't think the backend is ever serving TLS, so I don't think ALPN figures into it.

What's the rationale for blocking gRPC 2->1? I'd think it would show up as POSTs of protobuf body, which the user-container might not know what to do with. Is the implementation simplified if gRPC is explicitly blocked? Right now, I don't think we do anything special with gRPC compared with other methods.

I think the main reason is gRPC 2 -> 1 doesn't quite work smoothly coz H1 is not a full duplex protocol but gRPC assume bidirectional streaming underneath.

wlhee avatar Oct 17 '20 21:10 wlhee

This issue is stale because it has been open for 90 days with no activity. It will automatically close after 30 more days of inactivity. Reopen the issue with /reopen. Mark the issue as fresh by adding the comment /remove-lifecycle stale.

github-actions[bot] avatar Jan 16 '21 02:01 github-actions[bot]

/lifecycle freeze

We still want this, I believe?

markusthoemmes avatar Jan 18 '21 07:01 markusthoemmes

Per discussion with @ZhiminXiang , we will be creating multiple issues to better track progress in this area. #10856 -> Health prober work (almost done in #10628) #10857 -> Queue proxy #10858 -> Activator

Once these three are complete, we can enable E2E tests, and discuss a timeline to enable the feature.

rafaeltello avatar Feb 26 '21 19:02 rafaeltello

/triage accepted

evankanderson avatar Mar 18 '21 18:03 evankanderson

@rafaeltello Are you continuing work on the queue proxy/activator issues?

dprotaso avatar Jun 02 '21 13:06 dprotaso

I don't think @rafaeltello will continue working on it.

ZhiminXiang avatar Jun 02 '21 15:06 ZhiminXiang

Is anyone going to work on this? This is an important issue that needs to be resolved.

AyushChothe avatar Jun 20 '24 19:06 AyushChothe

@AyushChothe just to confirm you're aware that you can set the containerPort.name to h2c and it will use http2 cleartext?

dprotaso avatar Aug 01 '24 16:08 dprotaso

@AyushChothe just to confirm you're aware that you can set the containerPort.name to h2c and it will use http2 cleartext?

@dprotaso Yes, I know that. We need the feature to upgrade the port from http1 to h2c without explicit labeling, i.e if the sidecar probe detects the support for HTTP/2.

AyushChothe avatar Aug 01 '24 16:08 AyushChothe