-
Notifications
You must be signed in to change notification settings - Fork 4.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
Introduce integration framework backend #2017
Introduce integration framework backend #2017
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2017 +/- ##
==========================================
+ Coverage 59.35% 59.47% +0.12%
==========================================
Files 545 551 +6
Lines 11556 11626 +70
==========================================
+ Hits 6859 6915 +56
- Misses 4524 4538 +14
Partials 173 173
Continue to review full report at Codecov.
|
3104b78
to
4892b54
Compare
79eb78e
to
8e06def
Compare
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.
Sorry for late review. I thought I commented. Now realized that I didn't click submit.
|
||
import "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
// IntegrationID is a unique identification string that every integrated app has to provide. |
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 provide in-comment example of what an id would be? And where I can find other IDs to avoid conflicts.
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 could keep all of them as const values in this file. WDYT?
I don't think we have to worry about name collisions here, so simple integration name string should be sufficient for the foreseeable future.
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.
Having all IDs here LGTM.
// TODO(floreks): Support more information like 'installed' and 'enabled'. | ||
type IntegrationState struct { | ||
Connected bool `json:"connected"` | ||
LastChecked v1.Time `json:"lastChecked"` |
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.
From this I see that our backend code will have state. Can you comment on scalability of this? I.e., how would this work if I have two or twenty dashboard UI replicas?
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.
Until storage sync will be implemented we will not have consistent behavior here with multiple pods since we don't know to which instance kubernetes will proxy the request.
I will implement it next so all data will be kept in a configmap (in the beginning) and backend will be able to sync them across multiple replicas. Backend should be stateless but I didn't want to make this PR bigger by adding storage manager and synchronization.
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.
Storage sync is kind of cache to config map?
What happens if addon is removed with kubectl and the variable connected is still set to true? Does the user get a lot of error message until synchronisation? Do we listen on apiserver or poll?
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 was thinking about using watch for dashboard's config map. This way it would be always up to date. Some kind of subscribe/notify mechanism will be needed together with watch to make sure that state is correct.
manager IntegrationManager | ||
} | ||
|
||
// Install creates new endpoints for integrations. |
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 not sure this comment explains what the installation means. And this is the interesting part :) Can you comment? What happens after installation?
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'll describe it better. Right now it's very simple and just exposes integration state but other integrations might want to install their own endpoints also.
import "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
// IntegrationID is a unique identification string that every integrated app has to provide. | ||
type IntegrationID 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.
What's the format of integration ID? Can it be any 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.
See previous comment.
result := make([]api.Integration, 0) | ||
|
||
// Append all types of integrations | ||
result = append(result, self.Metric().List()...) |
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 be a static list somewhere in a dedicated file. It is hard to find it here. Among business logic code.
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 was thinking about that at some point but this list would be empty in the beginning and would have to be filled by some function. In example to create MetricClient integration for heapster we need host and ClientManager
args so we can't easily initialize this list.
Additionally slices in go are not thread-safe so keeping static array and operating on it from multiple places might cause some troubles.
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.
Yeah. I meant that we could have integrations-list.go file with this array. Filled the same way you do here, but in a separate file so that the place I register integrations is only one.
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.
Ahh... this makes sense :) I will do that.
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.
Done
187dc5a
to
1c9864c
Compare
We could think about combining our config-map to keep settings with the component config proposal: https://docs.google.com/document/d/1arP4T9Qkp2SovlJZ_y790sBeiWXDO6SG10pZ_UUU-Lc/edit# |
Unfortunately I don't have access to see it. |
hmm...it is public this is issue tracker: kubernetes/enhancements#115 |
integrationManager := integration.NewIntegrationManager(clientManager) | ||
err = integrationManager.Metric(). | ||
ConfigureHeapster(*argHeapsterHost). | ||
Enable(integrationapi.HeapsterIntegrationID) |
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 the long run, could we move argHeapsterHost into the config map?
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, what is the intended workflow if a user wants to use Prometheus instead of Heapster. Or maybe has already Prometheus installed and then deploys dashboard?
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.
Any integration still requires some code to be pushed upstream. We'd need to implement prometheus client that implements MetricClient
interface.
Normally with settings page user will be able to check state of integrations, i.e. if prometheus is not installed in the cluster then user goes to settings page clicks install near prometheus integration and then enables it. That would automatically disable other metric clients.
Once we have more options to choose from we can disable default one and let user decide which one to enable.
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 wonder if this is the right approach. I have not checked the api or anything lately, but my understanding that we do not have to care about which monitoring system is installed. We just use the api facade from apiserver. Also, installing a monitoring system might not be as easy as installing e.g. tiller.
The old issue: #1310
However, we should care about the integration of Graphana.
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 have not checked the api or anything lately, but my understanding that we do not have to care about which monitoring system is installed.
There were only plans to introduce interfaces directly in kubernetes that will scrape metrics and work independent of chosen monitoring solution. Unfortunately it is not there and I don't know if or when it will be introduced. Since there is no such facade then we have to take care of that for now.
Anyway if they introduce such API then it will be easy to get rid of monitoring specific code and just rely on this new API.
Also, installing a monitoring system might not be as easy as installing e.g. tiller.
Installing integration is not the hard part. For supported integrations we can versionize required yaml files on our repository and just use them to deploy what's needed (heapster + influx, tiller, etc.).
However, we should care about the integration of Graphana.
Do we? I thought integrations should improve dashboard's experience and grafana is an external UI for monitoring. How would such integration look like?
dc97be9
to
17eac14
Compare
kubeadm also plans an addon manager: https://docs.google.com/document/d/1Laov9RCOPIexxTMACG6Ffkko9sFMrrZ2ClWEecjYYVg/edit# we have to think were we want to draw the line so we do not have redundancy. In gerneral we should focus on frontend integration. |
Integrations have the benefit of providing better UX experience for users but might require more work and code to be pushed upstream. On the other hand addons could be created by everyone and be maintained independent of dashboard. Also they seem to be more flexible. Both options have some advantages and disadvantages. IMO integrations are good for popular tools used by many people, like helm. Addons could maybe be able to customize and add simple views. |
18950e9
to
813bf04
Compare
I was wondering which extention should be handled by addon-manager and which extention by Dashboard? So, should we draw some line somewere or accept duplication? IMHO we should check addon manager concepts and also discuss with other SIGs |
813bf04
to
73bb5f8
Compare
Kops addon manager: |
73bb5f8
to
3a5e6d8
Compare
I think we can merge this part. It does not change current behavior nor add state. It is mostly refactor and also few small bug fixes for getting heapster metrics. Additionally if heapster is not found or is unhealthy on the backend start then it will be disabled so there won't be any unnecessary requests made. |
There are still lots of things to be done. I have decided to take care of config storage and sync in next PRs as this will be already a big change. Any comments are appreciated.
Major changes
IntegrationManager
that will be responsible for providing state of integration app (installed, connected, enabled, etc.) and listing all integrations.MetricManager
as a dependency ofIntegrationManager
. It represents group of metric integrations like heapster, prometheus, etc. It will be responsible for controlling status of all metric integrations and providing active metric client.MetricClient
interface as a layer of abstraction between resources and metric api. All metric integrations will have to implement that interface.MetricClient
.Rules for introducing new integration would be:
Integration
interface to make sure that every integration app has unique ID and can do a health check to make sure if we can enable it.Integration
that will make sure that every 'group' can handle integrations, i.e. install/uninstall or enable/disable them.Later on they should support storage thus implement necessary methods that will make sure that state of integrations is persisted and up to date.
TODO
graphs are working, sparklines not)