-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Support set user-defined port to queue-proxy #2190
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here (e.g. What to do if you already signed the CLAIndividual signers
Corporate signers
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Leon-Liangming: 0 warnings.
In response to this:
Fixes #2101
Proposed Changes
- Support set user-defined port to queue-proxy
Release Note
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
I signed it! |
CLAs look good, thanks! |
/assign @josephburnett @mattmoor |
/assign @ZhiminXiang |
/ok-to-test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be careful about releasing this PR and document it clearly in our release notes since this PR directly affects current user behavior on the configuration of user-container port.
/test pull-knative-serving-unit-tests |
/test pull-knative-serving-integration-tests |
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
8a0461a
to
c76f7a7
Compare
CLAs look good, thanks! |
ab7eb1a
to
341b6d3
Compare
/test pull-knative-serving-go-coverage-dev |
/lgtm |
/approve /assign @josephburnett |
/assign @mattmoor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, thanks! Awesome to see this.
couple nits, which I think will simplify this a bit (both conceptually and the testing diffs).
I'd also like to see us add e2e coverage for this, as it is something that could break without tripping unit tests. Suggestions:
- Add a simple conformance test (copy the "Service" test and specify a port via env var).
- Modify the autoscaling test to do the same with a randomly chosen port (my interest in this test is it's exercising of the activator).
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really close. Thanks a lot!
I only have some more minor comments regarding the warning messages.
/approve |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Leon-Liangming, tcnghia If they are not already assigned, you can assign the PR to them by writing 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 |
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/assign @dgerd
Dan, this touches on two spaces you are wading into. Can you TAL?
// Expose containerPort as env PORT. | ||
userEnv = corev1.EnvVar{ | ||
Name: userPortEnvName, | ||
Value: strconv.Itoa(v1alpha1.RevisionContainerUserPortDefaultValue), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like the most flexible/stable way to set this env var would be through the downward API, if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this "PORT" env create by func buildUserPortEnv
in deploy.go, maybe use this func is ok, but If we want to use this func, we need to change this internal func to global func .
I think if more tests need this env in the future, we can write a test func for this.
Any further suggestions here?
# limitations under the License. | ||
|
||
apiVersion: serving.knative.dev/v1alpha1 | ||
kind: Configuration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use Service instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Configuration
is enough to my e2e test, copy from "helloworld_shell_test.go". I just want to do the same test about "helloworld_shell_test.go" or "TestHelloWorld" use user-defined port.
} | ||
|
||
// CreateConfigAndRouteFromYaml will create Route and Config by yaml file. | ||
func CreateConfigAndRouteFromYaml( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we create/delete using the same methods as other tests?
If we are going to change how we deploy test stuff, I'd rather we do it holistically (and not in this already large change). cc @dgerd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it had cover the all tests, Only TestHelloWorldFromShell
and TestHelloWorldUserPort
create resource by yaml now.
The following is the coverage report on pkg/.
|
de796c6
to
ad4bec8
Compare
The following is the coverage report on pkg/.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the work here. This is a great improvement!
} | ||
} | ||
|
||
if len(ports) == 1 && ports[0].Name != "user-port" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should actually enforce that there is no name on the port for now. We can preserve the name 'user-port' on the deployment; however, the name is intended to be used for HTTP negotiation when specified on Configuration. Allowing it or requiring it to be 'user-port' would not allow us to implement the runtime contract. See https://github.com/knative/serving/blob/master/docs/runtime-contract.md#inbound-network-connectivity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so it means accept any name of the port ?
hmm, it's about how to set user-port by user, it seems we didn't discuss about that clearly. @mattmoor @evankanderson Do you have any suggestions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify my understanding of the contract, there should only ever be 1 port in the Configuration Spec (or configuration section of Service Spec). Configuration.Spec.Container.Ports[0].Name should either be "" or "http1" or "h2c". Since we currently only implement automatic detection it probably makes sense to only accept "" for Name.
When the revision is created by Knative, the revision creates a K8s Deployment object from the spec. The port name on the Deployment is currently being set to 'user-port', and I think it makes sense to keep this set for clarity that the 'user-port' containerPort on the deployment was set from Configuration.Spec.Container.Ports[0].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To quote the spec (because apparently I had deep discussions about this 6 months ago, and was smarter than I am when looking at this issue for 10 minutes today):
Only one inbound
containerPort
SHALL be specified in thecore.v1.Container
specification. ThehostPort
parameter SHOULD NOT be set by the developer or the platform provider, as it can interfere with ingress autoscaling. Regardless of its source, the selected port will be made available in thePORT
environment variable.The platform provider SHOULD configure the platform to perform HTTPS termination and protocol transformation e.g. between QUIC or HTTP/2 and HTTP/1.1. Developers should not need to implement multiple transports between the platform and their code. Unless overridden by setting the
name
field on the inbound port, the platform will perform automatic detection as described above. If thecore.v1.Container.ports[0].name
is set to one of the following values, HTTP negotiation will be disabled and the following protocol will be used:
http1
: HTTP/1.1 transport and will not attempt to upgrade to h2c..h2c:
HTTP/2 transport, as described in section 3.4 of the HTTP2 spec (Starting HTTP/2 with Prior Knowledge)Developers SHOULD prefer to use automatic content negotiation where available, and MUST NOT set the name field to arbitrary values, as additional transports may be defined in the future.
All of the above is about the Container object specified in the Revision. The underlying implementation (e.g. creating a Deployment to back the Revision) can use whatever names it wants. The content-negotiation information needs to be forwarded to queue-proxy (this is not done today).
|
||
userPort, found := getUserPort(rev) | ||
if !found { | ||
createAndSetDefaultUserPort(userContainer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here seems a bit strange that you return the default port when not found, but then don't use in createAndSetDefaultUserPort.
To me it would feel a bit more natural if getUserPort returned 0 for userPort when false, and createAndSetDefaultUserPort returned the default userPort. Otherwise you are relying on userPort to be equal to what createAndSetDefaultUserPort set which could easily become a bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get your point.
According to @mattmoor's comment,
#discussion_r227053050
Instead of passing in additional EnvVars can we instead factor a function getUserPort(Revision) -> int64 and call it both here and queue.go?
get port from revision, used in two places, userPort need to get default port if can't find userport.
I change it to use getUserPort
's result in createAndSetDefaultUserPort
to resolve this pb.
readinessProbe: | ||
httpGet: | ||
path: / | ||
initialDelaySeconds: 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is recommended that this be set to 0. Since this is an example that I imagine may be copied from in the future it would be nice to have this set to 0 if possible. See https://github.com/knative/serving/blob/master/docs/runtime-contract.md#meta-requests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok.
container.Env = append(container.Env, portEnv) | ||
} | ||
|
||
func assertServiceUserPortSet(t *testing.T, clients *test.Clients, names test.ResourceNames, assertUserPort string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types of assertions here would be more appropriate for e2e tests. We can keep them here with a flag; however, the conformance tests must not depend on K8s resources. They should only make sure that KNative objects have the correct state (i.e. Configuration, Revision, Route, Service) See https://github.com/knative/serving/blob/master/test/conformance/README.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get it , I will remove it, and this assert had coverd by e2e test.
} | ||
|
||
if userContainerPortEnv.Value == assertUserPort { | ||
t.Fatalf("user container's port is not expect. %v", userContainerPortEnv.Value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is helpful to have both the expected value and observed value. Can you add the assertUserPort value here and below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
} | ||
assertServiceResourcesUpdated(t, logger, clients, names, routeDomain, "1", "What a spaceport!") | ||
|
||
logger.Info("Check queue-proxy container's user-port Env and user container's PORT Env.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than checking the set port variable on the kubernetes object you could have a test container that starts up on $PORT and returns "$PORT" when called. You could validate that when the service is ready the container returns success (200) and the port reported back is the port that was specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get it.
t.Fatalf("Configuration %s was not updated with the new revision: %v", names.Config, err) | ||
} | ||
deploymentName := | ||
config.Status.LatestCreatedRevisionName + "-deployment" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can you pull this out to a getDeployment method in test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
log.Print("Hello world app started.") | ||
|
||
http.HandleFunc("/", handler) | ||
http.ListenAndServe(":8888", nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you listen on the environment variable port rather than 8888? That would be further validation that the environment variable is completely plumbed through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Checking in to see how this is going. Is there anything I can do to help here? This is a big part of #2258 , and would love to see this get checked in. |
@Leon-Liangming Any updates here? |
I have some time and a desire to get this merged into master for the 0.3 release. I am going to pull your commits, rebase them, and make the suggested changes above. I will reference this pull request with the new one. Let me know if you have any questions or concerns. |
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and enviornment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258 Reduce number of type conversions Allow h2c and http1 on for port name Code Review Comments Clean up port validation
Closing this in favor of Dan's PR, which picks up where this leaves off. |
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258 Reduce number of type conversions Allow h2c and http1 on for port name Code Review Comments Clean up port validation
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR knative#2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to knative#2258 Reduce number of type conversions Allow h2c and http1 on for port name Code Review Comments Clean up port validation
This change allows for a user to add a port to their Container object in Configuration. The single port provided is used by the queue-proxy to as the port used to connect to the user container. This port is available as environment variable "PORT" on the user container and environment variable "USER_PORT" on the queue-proxy. This change is built upon PR #2190 by Leon-Liangming. It squashes the following commits: * change queue-proxy user-port env name * rebase master, fix uint test * remove "activator" istio-proxy , set "sidecar.istio.io/inject" to false * add e2e test for user-port && review comments modify && open acitvator's istio-proxy * set more validation info about user-port && modify e2e test * change validation info && e2e test * more review comments modify * Allow only 1 unnamed port * Passing conformance tests Related to #2258 Reduce number of type conversions Allow h2c and http1 on for port name Code Review Comments Clean up port validation
Fixes #2101
Proposed Changes
Release Note