这是indexloc提供的服务,不要输入任何密码
Skip to content

Pass serviceAccountToken to freezer service #11917

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

Merged
merged 11 commits into from
Sep 28, 2021

Conversation

psschwei
Copy link
Contributor

@psschwei psschwei commented Sep 3, 2021

Fixes #11904

Proposed Changes

  • Pass serviceAccountToken to freezer service via projected volume

Release Note

Pass serviceAccountToken to freezer service via projected volume

This is part of the work to add the Pod Freezer capability to knative (see #11694 for more details)

WIP until #11802 and #11820 merge

@knative-prow-robot knative-prow-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Sep 3, 2021
@google-cla google-cla bot added the cla: yes Indicates the PR's author has signed the CLA. label Sep 3, 2021
@codecov
Copy link

codecov bot commented Sep 3, 2021

Codecov Report

Merging #11917 (0ddf6f2) into main (cc5ff9b) will decrease coverage by 0.03%.
The diff coverage is 67.74%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #11917      +/-   ##
==========================================
- Coverage   87.49%   87.46%   -0.04%     
==========================================
  Files         196      196              
  Lines        9515     9531      +16     
==========================================
+ Hits         8325     8336      +11     
- Misses        917      921       +4     
- Partials      273      274       +1     
Impacted Files Coverage Δ
cmd/queue/main.go 0.49% <0.00%> (-0.01%) ⬇️
pkg/reconciler/revision/resources/deploy.go 96.87% <ø> (ø)
pkg/queue/concurrency_state.go 73.77% <75.00%> (+0.69%) ⬆️
pkg/reconciler/revision/resources/queue.go 98.12% <100.00%> (+0.02%) ⬆️
pkg/reconciler/revision/background.go 89.32% <0.00%> (-1.95%) ⬇️
pkg/apis/serving/k8s_validation.go 96.13% <0.00%> (+0.01%) ⬆️
pkg/reconciler/configuration/configuration.go 86.15% <0.00%> (+1.53%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f75b47c...0ddf6f2. Read the comment docs.

@knative-prow-robot knative-prow-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 6, 2021
@knative-prow-robot knative-prow-robot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Sep 8, 2021
@knative-prow-robot knative-prow-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 13, 2021
@psschwei
Copy link
Contributor Author

psschwei commented Sep 13, 2021

The test failures are for pkg/http/handler: TestIdleTimeoutHandler/successful_writes_prevent_timeout and pkg/http/handler: TestIdleTimeoutHandler, and this PR didn't touch pkg/http/handler, so thinking these are flakes...

@knative-prow-robot knative-prow-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 14, 2021
@knative-prow-robot knative-prow-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 15, 2021
@psschwei psschwei changed the title [WIP] Pass serviceAccountToken to freezer service Pass serviceAccountToken to freezer service Sep 22, 2021
@knative-prow-robot knative-prow-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 22, 2021
@psschwei
Copy link
Contributor Author

This one's ready now
/assign @markusthoemmes @julz

return concurrencyStateRequest(endpoint, "resume")
}

type Token struct {
Copy link
Member

Choose a reason for hiding this comment

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

Might be worth using atomic.Value for this: https://pkg.go.dev/go.uber.org/atomic#Value

//
// tempFile := createTempTokenFile(logger)
// defer os.Remove(tempFile.Name())
func createTempTokenFile(logger *zap.SugaredLogger) *os.File {
Copy link
Member

Choose a reason for hiding this comment

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

Would t.TempDir work here? That would automatically clean up the dir when the test exits. (We should avoid ioutil package for new code, all the methods now have equivalents elsewhere).

refreshToken(&tokenCfg, tokenMountPath)
go func() {
for {
time.Sleep(1 * time.Minute)
Copy link
Member

Choose a reason for hiding this comment

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

Rather than doing the token stuff here, what do you think about pulling it out in to the Pause and Resume request structs? They're already abstracting how the Handler should contact the endpoint, so it seems odd (to me) for Handler to have the token code rather than them (I'm imagining something like a type concurrencyStateRequest struct { token atomic.Value } struct with Pause and Resume functions).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It did cross my mind, though I was leaning towards having the Pause/Resume functions grab the refreshed token when called, rather than running a goroutine in the handler to keep it refreshed. I had a little nagging worry that getting the token in the pause/resume functions might end up grabbing the wrong value vs. getting it in the handler (though to be fair it was a fleeting thought and I didn't really pursue it too far). That said, let me give it another go.

(Figures that I juuuuust dropped the request struct from the previous PR 😄 )

Copy link
Contributor Author

@psschwei psschwei Sep 23, 2021

Choose a reason for hiding this comment

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

@julz before I go too far down the refactor train, would something like this be along these lines of what you're thinking?

type ConcurrencyEndpoint struct {
	endpoint string
	token atomic.Value
}

func (c ConcurrencyEndpoint) Pause() error { c.Request("pause") }

func (c ConcurrencyEndpoint) Resume() error { c.Request("resume") }

func (c ConcurrencyEndpoint) Request(request string) func() error { /* send request */ }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out the end of the line wasn't all that far away... got this added in the last batch of commits


"go.uber.org/atomic"
"go.uber.org/zap"
)

//nolint:gosec // Filepath, not hardcoded credentials
const ConcurrencyStateTokenVolumeMountPath = "/var/run/secrets/tokens"
const ConcurrencyStateTokenName = "state-token"
const ConcurrencyStateToken = ConcurrencyStateTokenVolumeMountPath + "/" + ConcurrencyStateTokenName
Copy link
Member

Choose a reason for hiding this comment

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

these consts having to be exported and shared between pkg/deploy and pkg/queue are a bit sad, wonder if there's a way we could avoid that. What if we got the token path from an env variable? That seems a bit more decoupled and maybe a bit cleaner (this is how we used to handle a similar thing in the past where we looked for some info via the downward api).

Copy link
Member

Choose a reason for hiding this comment

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

bump ^

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FWIW, exporting/sharing constant names seems to be a fairly common pattern to pass values to pkg/deploy (queue.Name and queue.RequestQueueDrainPath are passed this way, as well as several from networking). Would it make sense to convert them all to environmental variables (all meaning the QP ones)? If so, perhaps that would be better done in a separate PR.

If that's the route we want to go, for now I could either leave the CE constants where they are or move them to pkg/queue/constants.go

Copy link
Member

@julz julz Sep 28, 2021

Choose a reason for hiding this comment

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

I'm not really convinced queue.Name and queue.RequestQueueDrainPath (or the port related constants in networking) are a very good parallel here, since they're properties of the queue, not properties of how the queue is deployed. The main issue is that we're exporting three separate related constants, which makes the api of pkg/queue more complicated (and coupled) than it needs to be. If instead we passed the mounted location of the token, this would be a fair bit simpler and cleaner.

FWIW this is what we did both times we previously did a feature involving mounting a volume in QP (1, 2), and it seemed quite nice that way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough, was just checking if we should also update the other ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 240 to 241
tempDir := t.TempDir()
tokenFile := createTempTokenFile(logger, tempDir)
Copy link
Member

Choose a reason for hiding this comment

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

I think we can use os.WriteFile here and drop createTempTokenFile.

Suggested change
tempDir := t.TempDir()
tokenFile := createTempTokenFile(logger, tempDir)
tokenPath := filepath.Join(t.TempDir(), "secret")
if err := os.WriteFile(tokenPath, []byte("0123456789"), 0700); err != nil {
t.Fatal(err)
}

return tokenFile
}

func createConcurrencyEndpoint(e, m, t string) ConcurrencyEndpoint {
Copy link
Member

Choose a reason for hiding this comment

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

I think I'd convert this in to a NewConcurrencyEndpoint constructor so this is generally useful outside the test (and so consumers of the struct can't get themselves in trouble using it before the token has been stored).

if err != nil {
return fmt.Errorf("unable to create request: %w", err)
}
c.RefreshToken()
Copy link
Member

Choose a reason for hiding this comment

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

this seems like we're refreshing the token on every request rather than on a timer, but if so we don't really need the atomic, and RefreshToken doesn't need to be exported? Maybe worth converting this to something like:

ce := NewConcurrencyEndpoint(endpoint, tokenPath)
go func() {
  for range time.NewTicker(1 * time.Minute).C {
    ce.RefreshToken()
  }
}()

(which would also let us add a test for RefreshToken, which would be nice).


"go.uber.org/atomic"
"go.uber.org/zap"
)

//nolint:gosec // Filepath, not hardcoded credentials
const ConcurrencyStateTokenVolumeMountPath = "/var/run/secrets/tokens"
const ConcurrencyStateTokenName = "state-token"
const ConcurrencyStateToken = ConcurrencyStateTokenVolumeMountPath + "/" + ConcurrencyStateTokenName
Copy link
Member

Choose a reason for hiding this comment

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

bump ^

Copy link
Member

@julz julz left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

@@ -337,6 +337,9 @@ func makeQueueContainer(rev *v1.Revision, cfg *config.Config) (*corev1.Container
}, {
Name: "CONCURRENCY_STATE_ENDPOINT",
Value: cfg.Deployment.ConcurrencyStateEndpoint,
}, {
Name: "CONCURRENCY_STATE_TOKEN",
Value: concurrencyStateToken,
Copy link
Member

@julz julz Sep 28, 2021

Choose a reason for hiding this comment

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

I think I'd be tempted to do the Join here so we could drop this constant (just to avoid having 3 package-global constants for this), but maybe we can do that up in a follow-up / next time we touch this (if you agree)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

works for me

@knative-prow-robot knative-prow-robot added the lgtm Indicates that a PR is ready to be merged. label Sep 28, 2021
@knative-prow-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: julz, psschwei

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

@knative-prow-robot knative-prow-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Sep 28, 2021
@knative-prow-robot knative-prow-robot merged commit 67429ed into knative:main Sep 28, 2021
@psschwei psschwei deleted the freeze-pass-token branch October 15, 2021 15:17
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. area/API API objects and controllers area/autoscale area/networking cla: yes Indicates the PR's author has signed the CLA. lgtm Indicates that a PR is ready to be merged. 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.

Pass serviceAccountToken to freezer service
4 participants