-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
pkg/generator: Generate all manifests needed for Prometheus integration #241
Conversation
cc @spahl |
pkg/generator/deploy_tmpl.go
Outdated
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
name: {{.ProjectName}} | ||
k8s-app: {{.ProjectName}} |
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 change name
to k8s-app
?
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 introduced k8s-app
label for service and servicemonitor. I just changed to have the same label everywhere.
If needed I can change to use name
label in service and servicemonitor
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.
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.
Okay for using name
label.
Should I use name
label in service
and servicemonitor
too ?
Could you update the commit message title format as shown in https://github.com/operator-framework/operator-sdk/blob/master/CONTRIBUTING.MD#format-of-the-commit-message? |
pkg/generator/deploy_tmpl.go
Outdated
spec: | ||
containers: | ||
- name: {{.ProjectName}} | ||
image: {{.Image}} | ||
ports: | ||
- containerPort: 9090 |
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 name
this port? and then use that in the service as targetPort: name
. That leaves us flexibility to change the port in the future without having to change the service.
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 ! 👍
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.
containerPort is now name metrics
and use in the service as targetPort: metrics
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.
Make the port number a variable like {{.MetricsPort}}
and define a new parameter in gen_deploy.go
type OperatorYaml struct {
ProjectName string
Image string
MetricsPort int
}
That way we can set MetricsPort to a constant defined elsewhere.
finally change all |
This PR LGTM, though it does bother me a little that we have "9090" hard coded in 4 places. Not sure it's worth putting in the template data, but if we really wanted to do a followup. |
I agree with you, an another way could be to add a config file pass to the generator when
|
I'd personally lean pretty hard on 'only give users 1 way to do it and make sure that way is the right way'. I'm definitely in favor of us putting the port into the code and not making it optional. My only (tiny) bit of unease is that it's in the code 4 times instead of 1. Fewer options make users less able to get into weird situations we don't test or aren't able to help them with. |
I feel like hard-coding ports is going to a problem if you ever need to run another program that could use that port as a side-car to the operator. |
In that case, we cannot prevent futur usage , so user will have to change promport in main.go and metrics port in manifest files |
32862b0
to
00a2432
Compare
We should follow up with the discussion at #222 (comment) before we decide if we want to move forward with this approach. |
Update done according to #222 |
pkg/generator/gen_main_test.go
Outdated
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// Prometheus metrics port | ||
const promPort = ":9090" |
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 use a less common port number at a higher range like 90000.
Also can you define the port number as a global constant somewhere other than the test file like in k8sutil/constants.go. That way we can use it everywhere in the generator package without redefining it.
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.
Or something that's actually in the ephemeral port range like 60K. 90K is out of range.
pkg/generator/deploy_tmpl.go
Outdated
@@ -54,6 +59,10 @@ spec: | |||
valueFrom: | |||
fieldRef: | |||
fieldPath: metadata.namespace | |||
- name: OPERATOR_NAME |
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.
Similarly can you make the OPERATOR_NAME
and WATCH_NAMESPACE
strings as variables in the template so we can set them using the namespace constants defined in k8sutil/constants.go.
type OperatorYaml struct {
ProjectName string
Image string
NameEnv string
NamespaceEnv string
MetricsPort int
}
@hasbro17 according to your review:
|
…der-func pkg/generator: Create generic file rendering function
pkg/generator/templates.go
Outdated
@@ -529,14 +551,19 @@ spec: | |||
containers: | |||
- name: {{.ProjectName}} | |||
image: {{.Image}} | |||
ports: | |||
- containerPort: {{.MetricsPort}} | |||
name: metrics |
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 string metrics
is being used here and in InitOperatorService()
.
We should make this a constant in k8sutil/constants.go.
And then pass it as a parameter name: {{.MetricsPortName}}
.
pkg/generator/gen_main.go
Outdated
@@ -55,6 +58,7 @@ func renderMainFile(w io.Writer, repo, apiVersion, kind string) error { | |||
SDKVersionImport: versionImport, | |||
APIVersion: apiVersion, | |||
Kind: kind, | |||
MetricsPort: k8sutil.GetPrometheusMetricsPort(), |
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 don't think we need to convert this to a string. We can just use k8sutil.PrometheusMetricsPort
.
And in the template down below we can change it to:
go http.ListenAndServe(":{{.MetricsPort}}", nil)
Gopkg.toml
Outdated
@@ -6,6 +6,10 @@ | |||
name = "github.com/spf13/cobra" | |||
version = "0.0.2" | |||
|
|||
[[override]] | |||
name = "github.com/prometheus/client_golang" |
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 package isn't really used in the SDK itself right now so we can remove this. We'll add it back in later once we actually use this to record default metrics inside the SDK.
For now we can add it to the Gopkg.toml template of the operator:
https://github.com/operator-framework/operator-sdk/blob/master/pkg/generator/templates.go#L372
pkg/generator/gen_main_test.go
Outdated
sdk "github.com/operator-framework/operator-sdk/pkg/sdk" | ||
k8sutil "github.com/operator-framework/operator-sdk/pkg/util/k8sutil" | ||
sdkVersion "github.com/operator-framework/operator-sdk/version" | ||
stub "github.com/example-inc/app-operator/pkg/stub" |
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 keep the tab size to 4 as it is for all the other templates.
pkg/generator/templates.go
Outdated
sdk "{{.OperatorSDKImport}}" | ||
k8sutil "{{.K8sutilImport}}" | ||
sdkVersion "{{.SDKVersionImport}}" | ||
stub "{{.StubImport}}" |
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.
Change tab size back to 4
pkg/generator/templates.go
Outdated
} | ||
err = sdk.Create(service) | ||
if err != nil { | ||
logrus.Infof("Failed to create operator service: %v", err) |
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 ignore the error if the service already exists as it's very likely that the operator pod can restart.
import "k8s.io/apimachinery/pkg/api/errors"
...
if err != nil && !errors.IsAlreadyExists(err) {
logrus.Infof("Failed to create operator service: %v", err)
return
}
pkg/generator/templates.go
Outdated
logrus.Infof("Failed to create operator service: %v", err) | ||
return | ||
} | ||
logrus.Infof("Service %s have been created", service.Name) |
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.
logrus.Infof("Metrics service %s created", service.Name)
@etiennecoutaud Thanks for the update. I've tested this out locally and it works fine. |
pkg/generator: final cleanup of generator.go
@hasbro17 I completley failed my rebase 😄, anyway the refactor was too heavy. I will close this PR and reopen a clean one. Is it normally that generator refactor remove all unit tests ? |
@etiennecoutaud No that was my mistake. We removed them by accident as part of the refactor. We're going to revert that #315 |
No problem, I close this PR and wait for #315. |
@etiennecoutaud Can you reopen this in another PR. I think #315 will only change the main template unit test which should be easy to rebase once it's merged. Also looking back I think it's best if we keep the generated code to a minimum and keep the port exposing and service creation utility in the SDK. So the generated main.go should look like: func main() {
printVersion()
sdk.ExposeMetricsPort()
resource := "app.example.com/v1alpha1"
kind := "App"
namespace, err := k8sutil.GetWatchNamespace()
if err != nil {
logrus.Fatalf("Failed to get watch namespace: %v", err)
}
resyncPeriod := 5
logrus.Infof("Watching %s, %s, %s, %d", resource, kind, namespace, resyncPeriod)
sdk.Watch(resource, kind, namespace, resyncPeriod)
sdk.Handle(stub.NewHandler())
sdk.Run(context.TODO())
} And sdk.ExposeMetricsPort() can be defined in func ExposeMetricsPort() {
http.Handle("/"+k8sutil.PrometheusMetricsPortName, promhttp.Handler())
go http.ListenAndServe(":"+k8sutil. PrometheusMetricsPort, nil)
service, err := k8sutil.InitOperatorService()
if err != nil {
logrus.Fatalf("Failed to init operator service: %v", err)
}
err = sdk.Create(service)
if err != nil && !errors.IsAlreadyExists(err) {
logrus.Infof("Failed to create operator service: %v", err)
return
}
logrus.Infof("Metrics service %s created", service.Name)
} This way we can actually use the constants for the metrics port and not have them generated as a number and string in the operator's main.go. It also keeps main.go small. |
Yes sure, I will before the end of the week. |
Refer to #222
Generate kubernetes manifest files to integrate operator with Prometheus