Skip to content

Commit 365fee0

Browse files
dgrisonnetk8s-publishing-bot
authored andcommitted
apiserver/etcd3: fix segv during metric collection
Fix a segfault when collecting the storage size metrics when the getters used to collect the data on etcd haven't been initialized properly. This happens when the EtcdOptions are not applied which is the case for aggregated apiservers that don't care about storage. Signed-off-by: Damien Grisonnet <[email protected]> Kubernetes-commit: c6efaf16c1ed07ce37485b7a272628f653cbf06f
1 parent 6090ec8 commit 365fee0

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

pkg/storage/etcd3/metrics/metrics.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ var (
8585
[]string{"endpoint"},
8686
)
8787
storageSizeDescription = compbasemetrics.NewDesc("apiserver_storage_size_bytes", "Size of the storage database file physically allocated in bytes.", []string{"cluster"}, nil, compbasemetrics.ALPHA, "")
88-
storageMonitor = &monitorCollector{}
88+
storageMonitor = &monitorCollector{monitorGetter: func() ([]Monitor, error) { return nil, nil }}
8989
etcdEventsReceivedCounts = compbasemetrics.NewCounterVec(
9090
&compbasemetrics.CounterOpts{
9191
Subsystem: "apiserver",

pkg/storage/etcd3/metrics/metrics_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package metrics
1818

1919
import (
20+
"context"
2021
"errors"
2122
"strings"
2223
"testing"
@@ -179,3 +180,60 @@ etcd_request_errors_total{operation="foo",type="bar"} 1
179180
})
180181
}
181182
}
183+
184+
func TestStorageSizeCollector(t *testing.T) {
185+
registry := metrics.NewKubeRegistry()
186+
registry.CustomMustRegister(storageMonitor)
187+
188+
testCases := []struct {
189+
desc string
190+
getterOverride func() ([]Monitor, error)
191+
err error
192+
want string
193+
}{
194+
{
195+
desc: "fake etcd getter",
196+
getterOverride: func() ([]Monitor, error) {
197+
return []Monitor{fakeEtcdMonitor{storageSize: 1e9}}, nil
198+
},
199+
err: nil,
200+
want: `# HELP apiserver_storage_size_bytes [ALPHA] Size of the storage database file physically allocated in bytes.
201+
# TYPE apiserver_storage_size_bytes gauge
202+
apiserver_storage_size_bytes{cluster="etcd-0"} 1e+09
203+
`,
204+
},
205+
{
206+
desc: "getters not configured",
207+
getterOverride: nil,
208+
err: nil,
209+
want: ``,
210+
},
211+
}
212+
213+
for _, test := range testCases {
214+
t.Run(test.desc, func(t *testing.T) {
215+
defer registry.Reset()
216+
if test.getterOverride != nil {
217+
oldGetter := storageMonitor.monitorGetter
218+
defer SetStorageMonitorGetter(oldGetter)
219+
SetStorageMonitorGetter(test.getterOverride)
220+
}
221+
if err := testutil.GatherAndCompare(registry, strings.NewReader(test.want), "apiserver_storage_size_bytes"); err != nil {
222+
t.Fatal(err)
223+
}
224+
})
225+
}
226+
227+
}
228+
229+
type fakeEtcdMonitor struct {
230+
storageSize int64
231+
}
232+
233+
func (m fakeEtcdMonitor) Monitor(_ context.Context) (StorageMetrics, error) {
234+
return StorageMetrics{Size: m.storageSize}, nil
235+
}
236+
237+
func (m fakeEtcdMonitor) Close() error {
238+
return nil
239+
}

0 commit comments

Comments
 (0)