Skip to content

Commit c509506

Browse files
committed
aggregator: separate out status controller metrics
Signed-off-by: Dr. Stefan Schimanski <[email protected]>
1 parent 10496b3 commit c509506

File tree

5 files changed

+59
-52
lines changed

5 files changed

+59
-52
lines changed

staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"net/http"
23+
"sync"
2324
"time"
2425

2526
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -37,6 +38,7 @@ import (
3738
utilfeature "k8s.io/apiserver/pkg/util/feature"
3839
"k8s.io/client-go/kubernetes"
3940
"k8s.io/client-go/transport"
41+
"k8s.io/component-base/metrics/legacyregistry"
4042
"k8s.io/component-base/tracing"
4143
v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
4244
v1helper "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
@@ -50,10 +52,14 @@ import (
5052
openapiv3controller "k8s.io/kube-aggregator/pkg/controllers/openapiv3"
5153
openapiv3aggregator "k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator"
5254
statuscontrollers "k8s.io/kube-aggregator/pkg/controllers/status"
55+
availabilitymetrics "k8s.io/kube-aggregator/pkg/controllers/status/metrics"
5356
apiservicerest "k8s.io/kube-aggregator/pkg/registry/apiservice/rest"
5457
openapicommon "k8s.io/kube-openapi/pkg/common"
5558
)
5659

60+
// making sure we only register metrics once into legacy registry
61+
var registerIntoLegacyRegistryOnce sync.Once
62+
5763
func init() {
5864
// we need to add the options (like ListOptions) to empty v1
5965
metav1.AddToGroupVersion(aggregatorscheme.Scheme, schema.GroupVersion{Group: "", Version: "v1"})
@@ -314,6 +320,14 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
314320
})
315321
}
316322

323+
// create shared (remote and local) availability metrics
324+
// TODO: decouple from legacyregistry
325+
metrics := availabilitymetrics.New()
326+
registerIntoLegacyRegistryOnce.Do(func() { err = metrics.Register(legacyregistry.Register, legacyregistry.CustomRegister) })
327+
if err != nil {
328+
return nil, err
329+
}
330+
317331
// If the AvailableConditionController is disabled, we don't need to start the informers
318332
// and the controller.
319333
if !c.ExtraConfig.DisableAvailableConditionController {
@@ -325,6 +339,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
325339
proxyTransportDial,
326340
(func() ([]byte, []byte))(s.proxyCurrentCertKeyContent),
327341
s.serviceResolver,
342+
metrics,
328343
)
329344
if err != nil {
330345
return nil, err

staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,16 @@ import (
3939
"k8s.io/client-go/tools/cache"
4040
"k8s.io/client-go/transport"
4141
"k8s.io/client-go/util/workqueue"
42-
"k8s.io/component-base/metrics/legacyregistry"
4342
"k8s.io/klog/v2"
4443
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
4544
apiregistrationv1apihelper "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
4645
apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
4746
informers "k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1"
4847
listers "k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1"
4948
"k8s.io/kube-aggregator/pkg/controllers"
49+
availabilitymetrics "k8s.io/kube-aggregator/pkg/controllers/status/metrics"
5050
)
5151

52-
// making sure we only register metrics once into legacy registry
53-
var registerIntoLegacyRegistryOnce sync.Once
54-
5552
type certKeyFunc func() ([]byte, []byte)
5653

5754
// ServiceResolver knows how to convert a service reference into an actual location.
@@ -88,7 +85,7 @@ type AvailableConditionController struct {
8885
cacheLock sync.RWMutex
8986

9087
// metrics registered into legacy registry
91-
metrics *availabilityMetrics
88+
metrics *availabilitymetrics.Metrics
9289
}
9390

9491
// NewAvailableConditionController returns a new AvailableConditionController.
@@ -100,6 +97,7 @@ func NewAvailableConditionController(
10097
proxyTransportDial *transport.DialHolder,
10198
proxyCurrentCertKeyContent certKeyFunc,
10299
serviceResolver ServiceResolver,
100+
metrics *availabilitymetrics.Metrics,
103101
) (*AvailableConditionController, error) {
104102
c := &AvailableConditionController{
105103
apiServiceClient: apiServiceClient,
@@ -116,7 +114,7 @@ func NewAvailableConditionController(
116114
),
117115
proxyTransportDial: proxyTransportDial,
118116
proxyCurrentCertKeyContent: proxyCurrentCertKeyContent,
119-
metrics: newAvailabilityMetrics(),
117+
metrics: metrics,
120118
}
121119

122120
// resync on this one because it is low cardinality and rechecking the actual discovery
@@ -148,15 +146,6 @@ func NewAvailableConditionController(
148146

149147
c.syncFn = c.sync
150148

151-
// TODO: decouple from legacyregistry
152-
var err error
153-
registerIntoLegacyRegistryOnce.Do(func() {
154-
err = c.metrics.Register(legacyregistry.Register, legacyregistry.CustomRegister)
155-
})
156-
if err != nil {
157-
return nil, err
158-
}
159-
160149
return c, nil
161150
}
162151

@@ -385,7 +374,7 @@ func (c *AvailableConditionController) sync(key string) error {
385374
// apiservices. Doing that means we don't want to quickly issue no-op updates.
386375
func (c *AvailableConditionController) updateAPIServiceStatus(originalAPIService, newAPIService *apiregistrationv1.APIService) (*apiregistrationv1.APIService, error) {
387376
// update this metric on every sync operation to reflect the actual state
388-
c.setUnavailableGauge(newAPIService)
377+
c.metrics.SetUnavailableGauge(newAPIService)
389378

390379
if equality.Semantic.DeepEqual(originalAPIService.Status, newAPIService.Status) {
391380
return newAPIService, nil
@@ -412,7 +401,7 @@ func (c *AvailableConditionController) updateAPIServiceStatus(originalAPIService
412401
return nil, err
413402
}
414403

415-
c.setUnavailableCounter(originalAPIService, newAPIService)
404+
c.metrics.SetUnavailableCounter(originalAPIService, newAPIService)
416405
return newAPIService, nil
417406
}
418407

@@ -599,28 +588,3 @@ func (c *AvailableConditionController) deleteEndpoints(obj interface{}) {
599588
c.queue.Add(apiService)
600589
}
601590
}
602-
603-
// setUnavailableGauge set the metrics so that it reflect the current state base on availability of the given service
604-
func (c *AvailableConditionController) setUnavailableGauge(newAPIService *apiregistrationv1.APIService) {
605-
if apiregistrationv1apihelper.IsAPIServiceConditionTrue(newAPIService, apiregistrationv1.Available) {
606-
c.metrics.SetAPIServiceAvailable(newAPIService.Name)
607-
return
608-
}
609-
610-
c.metrics.SetAPIServiceUnavailable(newAPIService.Name)
611-
}
612-
613-
// setUnavailableCounter increases the metrics only if the given service is unavailable and its APIServiceCondition has changed
614-
func (c *AvailableConditionController) setUnavailableCounter(originalAPIService, newAPIService *apiregistrationv1.APIService) {
615-
wasAvailable := apiregistrationv1apihelper.IsAPIServiceConditionTrue(originalAPIService, apiregistrationv1.Available)
616-
isAvailable := apiregistrationv1apihelper.IsAPIServiceConditionTrue(newAPIService, apiregistrationv1.Available)
617-
statusChanged := isAvailable != wasAvailable
618-
619-
if statusChanged && !isAvailable {
620-
reason := "UnknownReason"
621-
if newCondition := apiregistrationv1apihelper.GetAPIServiceConditionByType(newAPIService, apiregistrationv1.Available); newCondition != nil {
622-
reason = newCondition.Reason
623-
}
624-
c.metrics.UnavailableCounter(newAPIService.Name, reason).Inc()
625-
}
626-
}

staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"testing"
2626
"time"
2727

28+
availabilitymetrics "k8s.io/kube-aggregator/pkg/controllers/status/metrics"
2829
"k8s.io/utils/pointer"
2930

3031
v1 "k8s.io/api/core/v1"
@@ -133,7 +134,7 @@ func setupAPIServices(apiServices []*apiregistration.APIService) (*AvailableCond
133134
workqueue.NewTypedItemExponentialFailureRateLimiter[string](5*time.Millisecond, 30*time.Second),
134135
workqueue.TypedRateLimitingQueueConfig[string]{Name: "AvailableConditionController"},
135136
),
136-
metrics: newAvailabilityMetrics(),
137+
metrics: availabilitymetrics.New(),
137138
}
138139
for _, svc := range apiServices {
139140
c.addAPIService(svc)
@@ -395,7 +396,7 @@ func TestSync(t *testing.T) {
395396
endpointsLister: v1listers.NewEndpointsLister(endpointsIndexer),
396397
serviceResolver: &fakeServiceResolver{url: testServer.URL},
397398
proxyCurrentCertKeyContent: func() ([]byte, []byte) { return emptyCert(), emptyCert() },
398-
metrics: newAvailabilityMetrics(),
399+
metrics: availabilitymetrics.New(),
399400
}
400401
c.sync(tc.apiServiceName)
401402

@@ -447,7 +448,7 @@ func TestUpdateAPIServiceStatus(t *testing.T) {
447448
fakeClient := fake.NewSimpleClientset()
448449
c := AvailableConditionController{
449450
apiServiceClient: fakeClient.ApiregistrationV1().(apiregistrationclient.APIServicesGetter),
450-
metrics: newAvailabilityMetrics(),
451+
metrics: availabilitymetrics.New(),
451452
}
452453

453454
c.updateAPIServiceStatus(foo, foo)

staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics.go renamed to staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics/metrics.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package apiserver
17+
package metrics
1818

1919
import (
2020
"sync"
2121

2222
"k8s.io/component-base/metrics"
23+
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
24+
apiregistrationv1apihelper "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
2325
)
2426

2527
/*
@@ -41,14 +43,14 @@ var (
4143
)
4244
)
4345

44-
type availabilityMetrics struct {
46+
type Metrics struct {
4547
unavailableCounter *metrics.CounterVec
4648

4749
*availabilityCollector
4850
}
4951

50-
func newAvailabilityMetrics() *availabilityMetrics {
51-
return &availabilityMetrics{
52+
func New() *Metrics {
53+
return &Metrics{
5254
unavailableCounter: metrics.NewCounterVec(
5355
&metrics.CounterOpts{
5456
Name: "aggregator_unavailable_apiservice_total",
@@ -62,7 +64,7 @@ func newAvailabilityMetrics() *availabilityMetrics {
6264
}
6365

6466
// Register registers apiservice availability metrics.
65-
func (m *availabilityMetrics) Register(
67+
func (m *Metrics) Register(
6668
registrationFunc func(metrics.Registerable) error,
6769
customRegistrationFunc func(metrics.StableCollector) error,
6870
) error {
@@ -80,7 +82,7 @@ func (m *availabilityMetrics) Register(
8082
}
8183

8284
// UnavailableCounter returns a counter to track apiservices marked as unavailable.
83-
func (m *availabilityMetrics) UnavailableCounter(apiServiceName, reason string) metrics.CounterMetric {
85+
func (m *Metrics) UnavailableCounter(apiServiceName, reason string) metrics.CounterMetric {
8486
return m.unavailableCounter.WithLabelValues(apiServiceName, reason)
8587
}
8688

@@ -91,6 +93,31 @@ type availabilityCollector struct {
9193
availabilities map[string]bool
9294
}
9395

96+
// SetUnavailableGauge set the metrics so that it reflect the current state base on availability of the given service
97+
func (m *Metrics) SetUnavailableGauge(newAPIService *apiregistrationv1.APIService) {
98+
if apiregistrationv1apihelper.IsAPIServiceConditionTrue(newAPIService, apiregistrationv1.Available) {
99+
m.SetAPIServiceAvailable(newAPIService.Name)
100+
return
101+
}
102+
103+
m.SetAPIServiceUnavailable(newAPIService.Name)
104+
}
105+
106+
// SetUnavailableCounter increases the metrics only if the given service is unavailable and its APIServiceCondition has changed
107+
func (m *Metrics) SetUnavailableCounter(originalAPIService, newAPIService *apiregistrationv1.APIService) {
108+
wasAvailable := apiregistrationv1apihelper.IsAPIServiceConditionTrue(originalAPIService, apiregistrationv1.Available)
109+
isAvailable := apiregistrationv1apihelper.IsAPIServiceConditionTrue(newAPIService, apiregistrationv1.Available)
110+
statusChanged := isAvailable != wasAvailable
111+
112+
if statusChanged && !isAvailable {
113+
reason := "UnknownReason"
114+
if newCondition := apiregistrationv1apihelper.GetAPIServiceConditionByType(newAPIService, apiregistrationv1.Available); newCondition != nil {
115+
reason = newCondition.Reason
116+
}
117+
m.UnavailableCounter(newAPIService.Name, reason).Inc()
118+
}
119+
}
120+
94121
// Check if apiServiceStatusCollector implements necessary interface.
95122
var _ metrics.StableCollector = &availabilityCollector{}
96123

staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics_test.go renamed to staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics/metrics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package apiserver
17+
package metrics
1818

1919
import (
2020
"strings"

0 commit comments

Comments
 (0)