Commit c4214f74 authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #24918 from Random-Liu/add-docker-operation-timeout

Automatic merge from submit-queue Kubelet: Add docker operation timeout For #23563. Based on #24748, only the last 2 commits are new. This PR: 1) Add timeout for all docker operations. 2) Add docker operation timeout metrics 3) Cleanup kubelet stats and add runtime operation error and timeout rate monitoring. 4) Monitor runtime operation error and timeout rate in kubelet perf. @yujuhong /cc @gmarek Because of the metrics change. /cc @kubernetes/sig-node
parents def76394 148588e6
...@@ -38,13 +38,18 @@ func newInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterfac ...@@ -38,13 +38,18 @@ func newInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterfac
// recordOperation records the duration of the operation. // recordOperation records the duration of the operation.
func recordOperation(operation string, start time.Time) { func recordOperation(operation string, start time.Time) {
metrics.DockerOperations.WithLabelValues(operation).Inc()
metrics.DockerOperationsLatency.WithLabelValues(operation).Observe(metrics.SinceInMicroseconds(start)) metrics.DockerOperationsLatency.WithLabelValues(operation).Observe(metrics.SinceInMicroseconds(start))
} }
// recordError records error for metric if an error occurred. // recordError records error for metric if an error occurred.
func recordError(operation string, err error) { func recordError(operation string, err error) {
if err != nil { if err != nil {
metrics.DockerErrors.WithLabelValues(operation).Inc() if _, ok := err.(operationTimeout); ok {
metrics.DockerOperationsTimeout.WithLabelValues(operation).Inc()
}
// Docker operation timeout error is also a docker error, so we don't add else here.
metrics.DockerOperationsErrors.WithLabelValues(operation).Inc()
} }
} }
......
...@@ -32,8 +32,10 @@ const ( ...@@ -32,8 +32,10 @@ const (
PodStartLatencyKey = "pod_start_latency_microseconds" PodStartLatencyKey = "pod_start_latency_microseconds"
PodStatusLatencyKey = "generate_pod_status_latency_microseconds" PodStatusLatencyKey = "generate_pod_status_latency_microseconds"
ContainerManagerOperationsKey = "container_manager_latency_microseconds" ContainerManagerOperationsKey = "container_manager_latency_microseconds"
DockerOperationsKey = "docker_operations_latency_microseconds" DockerOperationsLatencyKey = "docker_operations_latency_microseconds"
DockerErrorsKey = "docker_errors" DockerOperationsKey = "docker_operations"
DockerOperationsErrorsKey = "docker_operations_errors"
DockerOperationsTimeoutKey = "docker_operations_timeout"
PodWorkerStartLatencyKey = "pod_worker_start_latency_microseconds" PodWorkerStartLatencyKey = "pod_worker_start_latency_microseconds"
PLEGRelistLatencyKey = "pleg_relist_latency_microseconds" PLEGRelistLatencyKey = "pleg_relist_latency_microseconds"
PLEGRelistIntervalKey = "pleg_relist_interval_microseconds" PLEGRelistIntervalKey = "pleg_relist_interval_microseconds"
...@@ -94,16 +96,32 @@ var ( ...@@ -94,16 +96,32 @@ var (
DockerOperationsLatency = prometheus.NewSummaryVec( DockerOperationsLatency = prometheus.NewSummaryVec(
prometheus.SummaryOpts{ prometheus.SummaryOpts{
Subsystem: KubeletSubsystem, Subsystem: KubeletSubsystem,
Name: DockerOperationsKey, Name: DockerOperationsLatencyKey,
Help: "Latency in microseconds of Docker operations. Broken down by operation type.", Help: "Latency in microseconds of Docker operations. Broken down by operation type.",
}, },
[]string{"operation_type"}, []string{"operation_type"},
) )
DockerErrors = prometheus.NewCounterVec( DockerOperations = prometheus.NewCounterVec(
prometheus.CounterOpts{
Subsystem: KubeletSubsystem,
Name: DockerOperationsKey,
Help: "Cumulative number of Docker operations by operation type.",
},
[]string{"operation_type"},
)
DockerOperationsErrors = prometheus.NewCounterVec(
prometheus.CounterOpts{
Subsystem: KubeletSubsystem,
Name: DockerOperationsErrorsKey,
Help: "Cumulative number of Docker operation errors by operation type.",
},
[]string{"operation_type"},
)
DockerOperationsTimeout = prometheus.NewCounterVec(
prometheus.CounterOpts{ prometheus.CounterOpts{
Subsystem: KubeletSubsystem, Subsystem: KubeletSubsystem,
Name: DockerErrorsKey, Name: DockerOperationsTimeoutKey,
Help: "Cumulative number of Docker errors by operation type.", Help: "Cumulative number of Docker operation timeout by operation type.",
}, },
[]string{"operation_type"}, []string{"operation_type"},
) )
...@@ -137,7 +155,9 @@ func Register(containerCache kubecontainer.RuntimeCache) { ...@@ -137,7 +155,9 @@ func Register(containerCache kubecontainer.RuntimeCache) {
prometheus.MustRegister(SyncPodsLatency) prometheus.MustRegister(SyncPodsLatency)
prometheus.MustRegister(PodWorkerStartLatency) prometheus.MustRegister(PodWorkerStartLatency)
prometheus.MustRegister(ContainersPerPodCount) prometheus.MustRegister(ContainersPerPodCount)
prometheus.MustRegister(DockerErrors) prometheus.MustRegister(DockerOperations)
prometheus.MustRegister(DockerOperationsErrors)
prometheus.MustRegister(DockerOperationsTimeout)
prometheus.MustRegister(newPodAndContainerCollector(containerCache)) prometheus.MustRegister(newPodAndContainerCollector(containerCache))
prometheus.MustRegister(PLEGRelistLatency) prometheus.MustRegister(PLEGRelistLatency)
prometheus.MustRegister(PLEGRelistInterval) prometheus.MustRegister(PLEGRelistInterval)
......
...@@ -134,7 +134,6 @@ func parseMetrics(data string, knownMetrics map[string][]string, output *Metrics ...@@ -134,7 +134,6 @@ func parseMetrics(data string, knownMetrics map[string][]string, output *Metrics
if isKnownMetric || isCommonMetric { if isKnownMetric || isCommonMetric {
(*output)[name] = append((*output)[name], metric) (*output)[name] = append((*output)[name], metric)
} else { } else {
glog.Warningf("Unknown metric %v", metric)
if unknownMetrics != nil { if unknownMetrics != nil {
unknownMetrics.Insert(name) unknownMetrics.Insert(name)
} }
......
...@@ -18,6 +18,8 @@ package metrics ...@@ -18,6 +18,8 @@ package metrics
import ( import (
"fmt" "fmt"
"io/ioutil"
"net/http"
"time" "time"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
...@@ -71,7 +73,9 @@ var NecessaryKubeletMetrics = map[string][]string{ ...@@ -71,7 +73,9 @@ var NecessaryKubeletMetrics = map[string][]string{
"kubelet_containers_per_pod_count": {"quantile"}, "kubelet_containers_per_pod_count": {"quantile"},
"kubelet_containers_per_pod_count_count": {}, "kubelet_containers_per_pod_count_count": {},
"kubelet_containers_per_pod_count_sum": {}, "kubelet_containers_per_pod_count_sum": {},
"kubelet_docker_errors": {"operation_type"}, "kubelet_docker_operations": {"operation_type"},
"kubelet_docker_operations_errors": {"operation_type"},
"kubelet_docker_operations_timeout": {"operation_type"},
"kubelet_docker_operations_latency_microseconds": {"operation_type", "quantile"}, "kubelet_docker_operations_latency_microseconds": {"operation_type", "quantile"},
"kubelet_docker_operations_latency_microseconds_count": {"operation_type"}, "kubelet_docker_operations_latency_microseconds_count": {"operation_type"},
"kubelet_docker_operations_latency_microseconds_sum": {"operation_type"}, "kubelet_docker_operations_latency_microseconds_sum": {"operation_type"},
...@@ -126,6 +130,22 @@ func NewKubeletMetrics() KubeletMetrics { ...@@ -126,6 +130,22 @@ func NewKubeletMetrics() KubeletMetrics {
return KubeletMetrics(result) return KubeletMetrics(result)
} }
// GrabKubeletMetricsWithoutProxy retrieve metrics from the kubelet on the given node using a simple GET over http.
// Currently only used in integration tests.
func GrabKubeletMetricsWithoutProxy(nodeName string) (KubeletMetrics, error) {
metricsEndpoint := "http://%s/metrics"
resp, err := http.Get(fmt.Sprintf(metricsEndpoint, nodeName))
if err != nil {
return KubeletMetrics{}, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return KubeletMetrics{}, err
}
return parseKubeletMetrics(string(body))
}
func parseKubeletMetrics(data string) (KubeletMetrics, error) { func parseKubeletMetrics(data string) (KubeletMetrics, error) {
result := NewKubeletMetrics() result := NewKubeletMetrics()
if err := parseMetrics(data, NecessaryKubeletMetrics, (*Metrics)(&result), nil); err != nil { if err := parseMetrics(data, NecessaryKubeletMetrics, (*Metrics)(&result), nil); err != nil {
......
...@@ -189,6 +189,7 @@ func verifyCPULimits(expected framework.ContainersCPUSummary, actual framework.N ...@@ -189,6 +189,7 @@ func verifyCPULimits(expected framework.ContainersCPUSummary, actual framework.N
var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() { var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() {
var nodeNames sets.String var nodeNames sets.String
f := framework.NewDefaultFramework("kubelet-perf") f := framework.NewDefaultFramework("kubelet-perf")
var om *framework.RuntimeOperationMonitor
var rm *framework.ResourceMonitor var rm *framework.ResourceMonitor
BeforeEach(func() { BeforeEach(func() {
...@@ -197,12 +198,15 @@ var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() { ...@@ -197,12 +198,15 @@ var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() {
for _, node := range nodes.Items { for _, node := range nodes.Items {
nodeNames.Insert(node.Name) nodeNames.Insert(node.Name)
} }
om = framework.NewRuntimeOperationMonitor(f.Client)
rm = framework.NewResourceMonitor(f.Client, framework.TargetContainers(), containerStatsPollingPeriod) rm = framework.NewResourceMonitor(f.Client, framework.TargetContainers(), containerStatsPollingPeriod)
rm.Start() rm.Start()
}) })
AfterEach(func() { AfterEach(func() {
rm.Stop() rm.Stop()
result := om.GetLatestRuntimeOperationErrorRate()
framework.Logf("runtime operation error metrics:\n%s", framework.FormatRuntimeOperationErrorRate(result))
}) })
framework.KubeDescribe("regular resource usage tracking", func() { framework.KubeDescribe("regular resource usage tracking", func() {
// We assume that the scheduler will make reasonable scheduling choices // We assume that the scheduler will make reasonable scheduling choices
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment