Skip to content
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

Add lease collector #1038

Merged
merged 1 commit into from
Jan 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Per group of metrics there is one file for each metrics. See each file for speci
- [Horizontal Pod Autoscaler Metrics](horizontalpodautoscaler-metrics.md)
- [Ingress Metrics](ingress-metrics.md)
- [Job Metrics](job-metrics.md)
- [Lease Metrics](lease-metrics.md)
- [LimitRange Metrics](limitrange-metrics.md)
- [MutatingWebhookConfiguration Metrics](mutatingwebhookconfiguration.md)
- [Namespace Metrics](namespace-metrics.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Usage of ./kube-state-metrics:
--add_dir_header If true, adds the file directory to the header
--alsologtostderr log to standard error as well as files
--apiserver string The URL of the apiserver to use as a master
--collectors string Comma-separated list of collectors to be enabled. Defaults to "certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments"
--collectors string Comma-separated list of collectors to be enabled. Defaults to "certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments"
--disable-node-non-generic-resource-metrics Disable node non generic resource request and limit metrics
--disable-pod-non-generic-resource-metrics Disable pod non generic resource request and limit metrics
--enable-gzip-encoding Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.
Expand Down
6 changes: 6 additions & 0 deletions docs/lease-metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Lease Metrics

| Metric name| Metric type | Labels/tags | Status |
| ---------- | ----------- | ----------- | ----------- |
| kube_lease_owner | Gauge | `lease`=&lt;lease-name&gt; <br> `owner_kind`=&lt;onwer kind&gt; <br> `owner_name`=&lt;owner name&gt; | EXPERIMENTAL |
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to be in lexical order too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

| kube_lease_renew_time | Gauge | `lease`=&lt;lease-name&gt; | EXPERIMENTAL |
7 changes: 7 additions & 0 deletions examples/autosharding/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,10 @@ rules:
verbs:
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- list
- watch
7 changes: 7 additions & 0 deletions examples/standard/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,10 @@ rules:
verbs:
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- list
- watch
6 changes: 6 additions & 0 deletions internal/store/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
certv1beta1 "k8s.io/api/certificates/v1beta1"
coordinationv1 "k8s.io/api/coordination/v1"
v1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
policy "k8s.io/api/policy/v1beta1"
Expand Down Expand Up @@ -168,6 +169,7 @@ var availableStores = map[string]func(f *Builder) cache.Store{
"horizontalpodautoscalers": func(b *Builder) cache.Store { return b.buildHPAStore() },
"ingresses": func(b *Builder) cache.Store { return b.buildIngressStore() },
"jobs": func(b *Builder) cache.Store { return b.buildJobStore() },
"leases": func(b *Builder) cache.Store { return b.buildLeases() },
"limitranges": func(b *Builder) cache.Store { return b.buildLimitRangeStore() },
"mutatingwebhookconfigurations": func(b *Builder) cache.Store { return b.buildMutatingWebhookConfigurationStore() },
"namespaces": func(b *Builder) cache.Store { return b.buildNamespaceStore() },
Expand Down Expand Up @@ -314,6 +316,10 @@ func (b *Builder) buildVPAStore() cache.Store {
return b.buildStore(vpaMetricFamilies, &vpaautoscaling.VerticalPodAutoscaler{}, createVPAListWatchFunc(b.vpaClient))
}

func (b *Builder) buildLeases() cache.Store {
return b.buildStore(leaseMetricFamilies, &coordinationv1.Lease{}, createLeaseListWatch)
}

func (b *Builder) buildStore(
metricFamilies []generator.FamilyGenerator,
expectedType interface{},
Expand Down
113 changes: 113 additions & 0 deletions internal/store/lease.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package store

import (
coordinationv1 "k8s.io/api/coordination/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"

"k8s.io/kube-state-metrics/pkg/metric"
generator "k8s.io/kube-state-metrics/pkg/metric_generator"
)

var (
descLeaseLabelsDefaultLabels = []string{"lease"}

leaseMetricFamilies = []generator.FamilyGenerator{
{
Name: "kube_lease_owner",
Type: metric.Gauge,
Help: "Information about the Lease's owner.",
GenerateFunc: wrapLeaseFunc(func(l *coordinationv1.Lease) *metric.Family {
labelKeys := []string{"owner_kind", "owner_name"}

owners := l.GetOwnerReferences()
if len(owners) == 0 {
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: labelKeys,
LabelValues: []string{"<none>", "<none>"},
Value: 1,
},
},
}
}
ms := make([]*metric.Metric, len(owners))

for i, owner := range owners {
ms[i] = &metric.Metric{
LabelKeys: labelKeys,
LabelValues: []string{owner.Kind, owner.Name},
Value: 1,
}
}

return &metric.Family{
Metrics: ms,
}
}),
},
{
Name: "kube_lease_renew_time",
Type: metric.Gauge,
Help: "Kube lease renew time.",
GenerateFunc: wrapLeaseFunc(func(l *coordinationv1.Lease) *metric.Family {
ms := []*metric.Metric{}

if !l.Spec.RenewTime.IsZero() {
ms = append(ms, &metric.Metric{
Value: float64(l.Spec.RenewTime.Unix()),
})
}
return &metric.Family{
Metrics: ms,
}
}),
},
}
)

func wrapLeaseFunc(f func(*coordinationv1.Lease) *metric.Family) func(interface{}) *metric.Family {
return func(obj interface{}) *metric.Family {
lease := obj.(*coordinationv1.Lease)

metricFamily := f(lease)

for _, m := range metricFamily.Metrics {
m.LabelKeys = append(descLeaseLabelsDefaultLabels, m.LabelKeys...)
m.LabelValues = append([]string{lease.Name}, m.LabelValues...)
}

return metricFamily
}
}

func createLeaseListWatch(kubeClient clientset.Interface, _ string) cache.ListerWatcher {
return &cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
return kubeClient.CoordinationV1().Leases("kube-node-lease").List(opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
return kubeClient.CoordinationV1().Leases("kube-node-lease").Watch(opts)
},
}
}
74 changes: 74 additions & 0 deletions internal/store/lease_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
tariq1890 marked this conversation as resolved.
Show resolved Hide resolved
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package store

import (
"testing"
"time"

coordinationv1 "k8s.io/api/coordination/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

generator "k8s.io/kube-state-metrics/pkg/metric_generator"
)

func TestLeaseStore(t *testing.T) {
const metadata = `
# HELP kube_lease_owner Information about the Lease's owner.
# TYPE kube_lease_owner gauge
# HELP kube_lease_renew_time Kube lease renew time.
# TYPE kube_lease_renew_time gauge
`

var (
cases = []generateMetricsTestCase{
{
Obj: &coordinationv1.Lease{
ObjectMeta: metav1.ObjectMeta{
Generation: 2,
Name: "kube-master",
CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)},
OwnerReferences: []metav1.OwnerReference{
{
Kind: "Node",
Name: "kube-master",
},
},
},
Spec: coordinationv1.LeaseSpec{
RenewTime: &metav1.MicroTime{Time: time.Unix(1500000000, 0)},
},
},
Want: metadata + `
kube_lease_owner{lease="kube-master",owner_kind="Node",owner_name="kube-master"} 1
kube_lease_renew_time{lease="kube-master"} 1.5e+09
`,
MetricNames: []string{
"kube_lease_owner",
"kube_lease_renew_time",
},
},
}
)
for i, c := range cases {
c.Func = generator.ComposeMetricGenFuncs(leaseMetricFamilies)
c.Headers = generator.ExtractMetricFamilyHeaders(leaseMetricFamilies)
if err := c.run(); err != nil {
t.Errorf("unexpected collecting result in %dth run:\n%v", i, err)
}
}
}
7 changes: 7 additions & 0 deletions jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ local k = import 'ksonnet/ksonnet.beta.4/k.libsonnet';
'networkpolicies',
]) +
rulesType.withVerbs(['list', 'watch']),

rulesType.new() +
rulesType.withApiGroups(['coordination.k8s.io']) +
rulesType.withResources([
'leases',
]) +
rulesType.withVerbs(['list', 'watch']),
];

clusterRole.new() +
Expand Down
1 change: 1 addition & 0 deletions pkg/options/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
"horizontalpodautoscalers": struct{}{},
"ingresses": struct{}{},
"jobs": struct{}{},
"leases": struct{}{},
"limitranges": struct{}{},
"mutatingwebhookconfigurations": struct{}{},
"namespaces": struct{}{},
Expand Down
14 changes: 14 additions & 0 deletions tests/manifests/lease.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
name: kube-master
namespace: kube-node-lease
ownerReferences:
- apiVersion: v1
kind: Node
name: kube-master
uid: 71c6ca9d-7a35-4380-b2ae-aca4d47800df
spec:
holderIdentity: kube-master
leaseDurationSeconds: 40
renewTime: "2020-01-26T09:52:23.548762Z"