-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Enable refactoring queue-proxy binary with out-of-tree extensions #13133
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
Conversation
Fixes knative#13118 Alternative to knative#13122 Proposed Changes Enabling downstream and anyone creating an image of queue proxy to extend queue proxy This extendibility is a step to enable the runtime security proposal here Release Note Refactored queue-proxy binary to more easily support out-of-tree extension.
Hi @davidhadas. Thanks for your PR. I'm waiting for a knative member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
Codecov Report
@@ Coverage Diff @@
## main #13133 +/- ##
==========================================
- Coverage 86.78% 86.72% -0.07%
==========================================
Files 196 196
Lines 14410 14416 +6
==========================================
- Hits 12506 12502 -4
- Misses 1609 1619 +10
Partials 295 295
Continue to review full report at Codecov.
|
/ok-to-test |
I think initially this would belong in a sandbox/private repo rather than in serving core.
My gut reaction to this one is "no", as I'd assume that any needed changes could be done in the configs rather than needing to change them. Is there a particular use case you have in mind? |
pkg/queue/sharedmain/main.go
Outdated
Env | ||
} | ||
|
||
type Env struct { | ||
ServingNamespace string `split_words:"true" required:"true"` | ||
ServingRevision string `split_words:"true" required:"true"` | ||
ServingConfiguration string `split_words:"true" required:"true"` | ||
ServingPodIP string `split_words:"true" required:"true"` | ||
ServingPod string `split_words:"true" required:"true"` | ||
ServingService string `split_words:"true"` // optional |
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.
a couple of minor nits:
- maybe don't rename the
config
struct ? - perhaps a more descriptive name than
Env
(PodDetails
? Caveat here is that I'm terrible at naming...) - I'd put
Env
under the metrics config section (i.e. where the old fields were removed)
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.
Note that Env struct is identical in content to:
type RequestLogRevision struct from https://pkg.go.dev/knative.dev/serving/pkg/http#RequestLogRevision which is also being used later in main.go, How about naming it "Revision"
I am not sure it should be under
// Metrics 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.
I think "Env" is a good name, as it's describing the "environment" (i.e. Pod) where the queue-proxy is running.
A few bits (like ServingService
) won't vary per queue-proxy, but this struct seems to be "where am I on the map" rather than "what am I doing".
/assign @davidhadas |
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 looks like this shouldn't collide with the internal encryption work, which is nice!
I'm going to let @psschwei / @dprotaso do the final approval, but this LGTM.
A few smaller comments / nits. I appreciate the goal of reducing code movement throughout the file, but I think there might be a bigger benefit of consistently using the state in Defaults
, rather than mirroring it into/out of the struct at strategic times. (In particular if we added a second extension point in the future.)
pkg/queue/sharedmain/main.go
Outdated
Env | ||
} | ||
|
||
type Env struct { | ||
ServingNamespace string `split_words:"true" required:"true"` | ||
ServingRevision string `split_words:"true" required:"true"` | ||
ServingConfiguration string `split_words:"true" required:"true"` | ||
ServingPodIP string `split_words:"true" required:"true"` | ||
ServingPod string `split_words:"true" required:"true"` | ||
ServingService string `split_words:"true"` // optional |
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 "Env" is a good name, as it's describing the "environment" (i.e. Pod) where the queue-proxy is running.
A few bits (like ServingService
) won't vary per queue-proxy, but this struct seems to be "where am I on the map" rather than "what am I doing".
type Defaults struct { | ||
Ctx context.Context | ||
Logger *zap.SugaredLogger | ||
Transport http.RoundTripper | ||
Env 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.
Hmm, I'm wondering if Main
should be a method on Defaults
.
I suspect not.
I'm also wondering about the name... Configuration
, Process
, Execution
, QueueProxy
?
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 list includes two parts:
- parameters whose value is determined by the service and provided for the extensions to use (but not to change)
- parameters whose default is determined by the service and provided for the extensions such that may change them
Maybe we should have divided this struct into two:
type Defaults {
Ctx context.Context
Transport http.RoundTripper
}
type Config {
Env
Logger *zap.SugaredLogger
}
type QueueProxy struct {
Invariables Config
Mutables Defaults
}
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 wouldn't split, I'd just note in comments which ones are considered mutable and which ones aren't.
Since they're exported types, an overview comment on the Defaults
and Env
structs themselves wouldn't be a bad idea.
pkg/queue/sharedmain/main.go
Outdated
d := &Defaults{ | ||
Ctx: signals.NewContext(), | ||
} |
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'd prefer to make d
concrete here, rather than a pointer.
return err | ||
} | ||
|
||
d.Env = env.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.
I can see that you're slicing the "where I'm at" out of the larger configuration. I'm wondering whether we should simply pass along all the config
/privateEnv
, and accept that plugins could (for example) adjust EnableProfiling
without other high-level config.
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 could enable splitting out envconfig
into a pluggable module, though I'm not sure I'd recommend it, since I think we want that functionality enabled by default rather than every caller needing to say sharedmain.EnvConfig
.
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 ensures that extensions receive a copy of the Env and cannot change the Env used by the service which I think is appropriate 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.
I think just having a read-only Env
is ok for now - I think as people request more we can move properties from private => public with a discussion
}.String()), | ||
zap.String(logkey.Pod, env.ServingPod)) | ||
|
||
d.Logger = logger |
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.
Why not put this on 147? Reducing code movement?
I'd be inclined to s/logger/d.Logger/
throughout.
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 ensures that extensions receive a copy of the logger and cannot change the logger used by the service which I think is appropriate 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.
I'm ok either way.
Longer term I would expect the logger be pluggable in the future
func WithLogger(l *zap.SugaredLogger) func(q *Defaults) {
return func(d *Defaults) {
d.Logger = l
return
}
}
pkg/queue/sharedmain/main.go
Outdated
ctx := d.Ctx | ||
transport := d.Transport |
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.
Again, I'd be inclined to substitute these throughout.
pkg/queue/sharedmain/main.go
Outdated
|
||
// allow extensions to read d and return modified context and transport | ||
for _, opts := range opts { | ||
opts(d) |
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.
Slight preference for opts(&d)
to make it clear that d
is modified in-place here, but I don't care strongly.
/retest |
Tests fail, but it does not seem like a code issue |
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.
In general this LGTM but want to give Dave a chance to comment before merging.
/assign @dprotaso
type Defaults struct { | ||
Ctx context.Context | ||
Logger *zap.SugaredLogger | ||
Transport http.RoundTripper | ||
Env 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.
I wouldn't split, I'd just note in comments which ones are considered mutable and which ones aren't.
Since they're exported types, an overview comment on the Defaults
and Env
structs themselves wouldn't be a bad idea.
if sharedmain.Main() != nil { | ||
os.Exit(1) | ||
} |
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 also probably log the error 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.
Since we let downstream change this file, I think it is best if we log inside sharedmain to ensure consistent logging.
/retest |
1 similar comment
/retest |
@davidhadas: The specified target(s) for
The following commands are available to trigger optional jobs:
Use
In response to this:
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. |
return err | ||
} | ||
|
||
d.Env = env.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.
I think just having a read-only Env
is ok for now - I think as people request more we can move properties from private => public with a discussion
}.String()), | ||
zap.String(logkey.Pod, env.ServingPod)) | ||
|
||
d.Logger = logger |
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'm ok either way.
Longer term I would expect the logger be pluggable in the future
func WithLogger(l *zap.SugaredLogger) func(q *Defaults) {
return func(d *Defaults) {
d.Logger = l
return
}
}
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: davidhadas, dprotaso 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 |
This builds on knative#13133 to make it possible to adjust settings on the *httputil.ReverseProxy that queue-proxy uses, or to replace it entirely with any http.Handler, using the out-of-tree extension pattern.
This builds on knative#13133 to make it possible to adjust settings on the *httputil.ReverseProxy that queue-proxy uses, or to replace it entirely with any http.Handler, using the out-of-tree extension pattern.
* Make queue-proxy's reverse proxy handler extendable This builds on #13133 to make it possible to adjust settings on the *httputil.ReverseProxy that queue-proxy uses, or to replace it entirely with any http.Handler, using the out-of-tree extension pattern. * Ensure configured Transport is used If an integrator customizes the Transport in an Options function, we want to apply the provided Transport to our default httputil.ReverseProxy regardless of which Option sets the Transport and regardless of whether or not other Option functions replace our default http.Handler. Add some tests for this since the interactions beteween Options.Transport and Options.ProxyHandler can be subtle.
Fixes #13118
Alternative to #13122
Proposed Changes
Release Note
Refactored queue-proxy binary to more easily support out-of-tree extension.