-
Notifications
You must be signed in to change notification settings - Fork 475
critest: test metric descriptors #1931
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
base: master
Are you sure you want to change the base?
Changes from all commits
7865637
7ac79fe
125e9c3
01b03eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,16 +20,66 @@ import ( | |||||
| "context" | ||||||
| "os" | ||||||
| "path/filepath" | ||||||
| "strings" | ||||||
| "time" | ||||||
|
|
||||||
| . "github.com/onsi/ginkgo/v2" | ||||||
| . "github.com/onsi/gomega" | ||||||
| "google.golang.org/grpc/codes" | ||||||
| grpcstatus "google.golang.org/grpc/status" | ||||||
| internalapi "k8s.io/cri-api/pkg/apis" | ||||||
| runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" | ||||||
|
|
||||||
| "sigs.k8s.io/cri-tools/pkg/common" | ||||||
| "sigs.k8s.io/cri-tools/pkg/framework" | ||||||
| ) | ||||||
|
|
||||||
| // expectedMetricDescriptorNames contains all expected metric descriptor names | ||||||
| // based on metrics returned by kubelet with CRI-O and cadvisor on the legacy cadvisor stats provider | ||||||
| // on kubernetes 1.35. | ||||||
| var expectedMetricDescriptorNames = []string{ | ||||||
| "container_blkio_device_usage_total", | ||||||
| "container_cpu_system_seconds_total", | ||||||
| "container_cpu_usage_seconds_total", | ||||||
| "container_cpu_user_seconds_total", | ||||||
| "container_file_descriptors", | ||||||
| "container_fs_reads_bytes_total", | ||||||
| "container_fs_reads_total", | ||||||
| "container_fs_usage_bytes", | ||||||
| "container_fs_writes_bytes_total", | ||||||
| "container_fs_writes_total", | ||||||
| "container_last_seen", | ||||||
| "container_memory_cache", | ||||||
| "container_memory_failcnt", | ||||||
| "container_memory_failures_total", | ||||||
| "container_memory_mapped_file", | ||||||
| "container_memory_max_usage_bytes", | ||||||
| "container_memory_rss", | ||||||
| "container_memory_swap", | ||||||
| "container_memory_usage_bytes", | ||||||
| "container_memory_working_set_bytes", | ||||||
| "container_network_receive_bytes_total", | ||||||
| "container_network_receive_errors_total", | ||||||
| "container_network_receive_packets_dropped_total", | ||||||
| "container_network_receive_packets_total", | ||||||
| "container_network_transmit_bytes_total", | ||||||
| "container_network_transmit_errors_total", | ||||||
| "container_network_transmit_packets_dropped_total", | ||||||
| "container_network_transmit_packets_total", | ||||||
| "container_oom_events_total", | ||||||
| "container_processes", | ||||||
| "container_sockets", | ||||||
| "container_spec_cpu_period", | ||||||
| "container_spec_cpu_shares", | ||||||
| "container_spec_memory_limit_bytes", | ||||||
| "container_spec_memory_reservation_limit_bytes", | ||||||
| "container_spec_memory_swap_limit_bytes", | ||||||
| "container_start_time_seconds", | ||||||
| "container_threads", | ||||||
| "container_threads_max", | ||||||
| "container_ulimits_soft", | ||||||
| } | ||||||
|
|
||||||
| var _ = framework.KubeDescribe("PodSandbox", func() { | ||||||
| f := framework.NewDefaultCRIFramework() | ||||||
|
|
||||||
|
|
@@ -80,6 +130,62 @@ var _ = framework.KubeDescribe("PodSandbox", func() { | |||||
| podID = "" // no need to cleanup pod | ||||||
| }) | ||||||
| }) | ||||||
| Context("runtime should support metrics operations", func() { | ||||||
| var podID string | ||||||
| var podConfig *runtimeapi.PodSandboxConfig | ||||||
| BeforeEach(func() { | ||||||
| _, err := rc.ListMetricDescriptors(context.TODO()) | ||||||
| if err != nil { | ||||||
| s, ok := grpcstatus.FromError(err) | ||||||
| Expect(ok && s.Code() == codes.Unimplemented).To(BeTrue(), "Expected CRI metric descriptors call to either be not supported, or not error") | ||||||
| if s.Code() == codes.Unimplemented { | ||||||
| Skip("CRI Metrics endpoints not supported by this runtime version") | ||||||
| } | ||||||
| } | ||||||
| }) | ||||||
|
|
||||||
| AfterEach(func() { | ||||||
| if podID != "" { | ||||||
| By("stop PodSandbox") | ||||||
| Expect(rc.StopPodSandbox(context.TODO(), podID)).NotTo(HaveOccurred()) | ||||||
| By("delete PodSandbox") | ||||||
| Expect(rc.RemovePodSandbox(context.TODO(), podID)).NotTo(HaveOccurred()) | ||||||
| } | ||||||
| }) | ||||||
|
|
||||||
| It("runtime should support returning metrics descriptors [Conformance]", func() { | ||||||
| By("list metric descriptors") | ||||||
| descs := listMetricDescriptors(rc) | ||||||
|
|
||||||
| By("verify expected metric descriptors are present") | ||||||
| testMetricDescriptors(descs) | ||||||
| }) | ||||||
|
|
||||||
| It("runtime should support listing pod sandbox metrics [Conformance]", func() { | ||||||
| By("create pod sandbox") | ||||||
| podID, podConfig = framework.CreatePodSandboxForContainer(rc) | ||||||
|
|
||||||
| By("create container in pod") | ||||||
| ic := f.CRIClient.CRIImageClient | ||||||
| containerID := framework.CreateDefaultContainer(rc, ic, podID, podConfig, "container-for-metrics-") | ||||||
|
|
||||||
| By("start container") | ||||||
| startContainer(rc, containerID) | ||||||
|
|
||||||
| _, _, err := rc.ExecSync( | ||||||
| context.TODO(), containerID, []string{"/bin/sh", "-c", "for i in $(seq 1 10); do echo hi >> /var/lib/mydisktest/inode_test_file_$i; done; sync"}, | ||||||
| time.Duration(defaultExecSyncTimeout)*time.Second, | ||||||
| ) | ||||||
|
|
||||||
| Expect(err).ToNot(HaveOccurred()) | ||||||
|
|
||||||
| By("list pod sandbox metrics") | ||||||
| metrics := listPodSandboxMetrics(rc) | ||||||
|
|
||||||
| By("verify pod metrics are present") | ||||||
| testPodSandboxMetrics(metrics, podID) | ||||||
| }) | ||||||
| }) | ||||||
| }) | ||||||
|
|
||||||
| // podSandboxFound returns whether PodSandbox is found. | ||||||
|
|
@@ -166,6 +272,17 @@ func listPodSandbox(c internalapi.RuntimeService, filter *runtimeapi.PodSandboxF | |||||
| return pods | ||||||
| } | ||||||
|
|
||||||
| // listMetricDescriptors lists MetricDescriptors. | ||||||
| func listMetricDescriptors(c internalapi.RuntimeService) []*runtimeapi.MetricDescriptor { | ||||||
| By("List MetricDescriptors.") | ||||||
|
|
||||||
| descs, err := c.ListMetricDescriptors(context.TODO()) | ||||||
| framework.ExpectNoError(err, "failed to list MetricDescriptors status: %v", err) | ||||||
| framework.Logf("List MetricDescriptors succeed") | ||||||
|
|
||||||
| return descs | ||||||
| } | ||||||
|
|
||||||
| // createLogTempDir creates the log temp directory for podSandbox. | ||||||
| func createLogTempDir(podSandboxName string) (hostPath, podLogPath string) { | ||||||
| hostPath, err := os.MkdirTemp("", "podLogTest") | ||||||
|
|
@@ -196,3 +313,76 @@ func createPodSandboxWithLogDirectory(c internalapi.RuntimeService) (sandboxID s | |||||
|
|
||||||
| return framework.RunPodSandbox(c, podConfig), podConfig, hostPath | ||||||
| } | ||||||
|
|
||||||
| // testMetricDescriptors verifies that all expected metric descriptors are present. | ||||||
| func testMetricDescriptors(descs []*runtimeapi.MetricDescriptor) { | ||||||
| returnedDescriptors := make(map[string]*runtimeapi.MetricDescriptor) | ||||||
| for _, desc := range descs { | ||||||
| returnedDescriptors[desc.GetName()] = desc | ||||||
| Expect(desc.GetHelp()).NotTo(BeEmpty(), "Metric descriptor %q should have help text", desc.GetName()) | ||||||
| Expect(desc.GetLabelKeys()).NotTo(BeEmpty(), "Metric descriptor %q should have label keys", desc.GetName()) | ||||||
| } | ||||||
|
|
||||||
| missingMetrics := []string{} | ||||||
|
|
||||||
| for _, expectedName := range expectedMetricDescriptorNames { | ||||||
| _, found := returnedDescriptors[expectedName] | ||||||
| if !found { | ||||||
| missingMetrics = append(missingMetrics, expectedName) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Expect(missingMetrics).To(BeEmpty(), "Expected %s metrics to be present and they were not", strings.Join(missingMetrics, " ")) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| // listPodSandboxMetrics lists PodSandboxMetrics. | ||||||
| func listPodSandboxMetrics(c internalapi.RuntimeService) []*runtimeapi.PodSandboxMetrics { | ||||||
| By("List PodSandboxMetrics.") | ||||||
|
|
||||||
| metrics, err := c.ListPodSandboxMetrics(context.TODO()) | ||||||
| framework.ExpectNoError(err, "failed to list PodSandboxMetrics: %v", err) | ||||||
| framework.Logf("List PodSandboxMetrics succeed") | ||||||
|
|
||||||
| return metrics | ||||||
| } | ||||||
|
|
||||||
| // testPodSandboxMetrics verifies that metrics are present for the specified pod. | ||||||
| func testPodSandboxMetrics(allMetrics []*runtimeapi.PodSandboxMetrics, podID string) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are still taking in this function. Only the metrics descriptors test are needed right? |
||||||
| var podMetrics *runtimeapi.PodSandboxMetrics | ||||||
|
|
||||||
| for _, m := range allMetrics { | ||||||
| if m.GetPodSandboxId() == podID { | ||||||
| podMetrics = m | ||||||
|
|
||||||
| break | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Expect(podMetrics).NotTo(BeNil(), "Metrics for pod %q should be present", podID) | ||||||
|
|
||||||
| metricNamesFound := make(map[string]bool) | ||||||
|
|
||||||
| for _, metric := range podMetrics.GetMetrics() { | ||||||
| if !metricNamesFound[metric.GetName()] { | ||||||
| metricNamesFound[metric.GetName()] = true | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| for _, containerMetric := range podMetrics.GetContainerMetrics() { | ||||||
| for _, metric := range containerMetric.GetMetrics() { | ||||||
| if !metricNamesFound[metric.GetName()] { | ||||||
| metricNamesFound[metric.GetName()] = true | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to add an additional check here, so that the same set of lables for a given metric that were returned by |
||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| missingMetrics := []string{} | ||||||
|
|
||||||
| for _, expectedName := range expectedMetricDescriptorNames { | ||||||
| if !metricNamesFound[expectedName] { | ||||||
| missingMetrics = append(missingMetrics, expectedName) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Expect(missingMetrics).To(BeEmpty(), "Expected %s metrics to be present and they were not", strings.Join(missingMetrics, " ")) | ||||||
| } | ||||||
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.
A few of these metrics are currently not in the implementation in containerd also.
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.
do you have a list handy of the ones you aren't yet supporting? is it because you don't plan on it or haven't gotten to it yet
I think for this KEP to go beta each should really support the full set (I say knowing CRI-O is missing some)
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 containerd, the below metrics are not reported from metric descriptors
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.
These are now added as part of #12426.
Checking why the CI fails on containerd main.