Merge pull request #25933 from timstclair/subcontainers
Automatic merge from submit-queue Handle cAdvisor partial failures Kubernetes side of https://github.com/google/cadvisor/issues/1286 Partially fixes https://github.com/kubernetes/kubernetes/issues/25131 (Depends on cAdvisor Godeps bump https://github.com/kubernetes/kubernetes/pull/25914) /cc @kubernetes/sig-node
This commit is contained in:
commit
f1e528eab6
@ -150,7 +150,7 @@ func (cc *cadvisorClient) VersionInfo() (*cadvisorapi.VersionInfo, error) {
|
|||||||
|
|
||||||
func (cc *cadvisorClient) SubcontainerInfo(name string, req *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) {
|
func (cc *cadvisorClient) SubcontainerInfo(name string, req *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) {
|
||||||
infos, err := cc.SubcontainersInfo(name, req)
|
infos, err := cc.SubcontainersInfo(name, req)
|
||||||
if err != nil {
|
if err != nil && len(infos) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ func (cc *cadvisorClient) SubcontainerInfo(name string, req *cadvisorapi.Contain
|
|||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
result[info.Name] = info
|
result[info.Name] = info
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *cadvisorClient) MachineInfo() (*cadvisorapi.MachineInfo, error) {
|
func (cc *cadvisorClient) MachineInfo() (*cadvisorapi.MachineInfo, error) {
|
||||||
|
@ -24,11 +24,11 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||||
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
||||||
|
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
@ -133,14 +133,14 @@ func parseStatsRequest(request *restful.Request) (StatsRequest, error) {
|
|||||||
func (h *handler) handleStats(request *restful.Request, response *restful.Response) {
|
func (h *handler) handleStats(request *restful.Request, response *restful.Response) {
|
||||||
query, err := parseStatsRequest(request)
|
query, err := parseStatsRequest(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, "/stats", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root container stats.
|
// Root container stats.
|
||||||
statsMap, err := h.provider.GetRawContainerInfo("/", query.cadvisorRequest(), false)
|
statsMap, err := h.provider.GetRawContainerInfo("/", query.cadvisorRequest(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, fmt.Sprintf("/stats %v", query), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeResponse(response, statsMap["/"])
|
writeResponse(response, statsMap["/"])
|
||||||
@ -150,7 +150,7 @@ func (h *handler) handleStats(request *restful.Request, response *restful.Respon
|
|||||||
func (h *handler) handleSummary(request *restful.Request, response *restful.Response) {
|
func (h *handler) handleSummary(request *restful.Request, response *restful.Response) {
|
||||||
summary, err := h.summaryProvider.Get()
|
summary, err := h.summaryProvider.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, "/stats/summary", err)
|
||||||
} else {
|
} else {
|
||||||
writeResponse(response, summary)
|
writeResponse(response, summary)
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ func (h *handler) handleSummary(request *restful.Request, response *restful.Resp
|
|||||||
func (h *handler) handleSystemContainer(request *restful.Request, response *restful.Response) {
|
func (h *handler) handleSystemContainer(request *restful.Request, response *restful.Response) {
|
||||||
query, err := parseStatsRequest(request)
|
query, err := parseStatsRequest(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, "/stats/container", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,8 +169,13 @@ func (h *handler) handleSystemContainer(request *restful.Request, response *rest
|
|||||||
stats, err := h.provider.GetRawContainerInfo(
|
stats, err := h.provider.GetRawContainerInfo(
|
||||||
containerName, query.cadvisorRequest(), query.Subcontainers)
|
containerName, query.cadvisorRequest(), query.Subcontainers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
if _, ok := stats[containerName]; ok {
|
||||||
return
|
// If the failure is partial, log it and return a best-effort response.
|
||||||
|
glog.Errorf("Partial failure issuing GetRawContainerInfo(%v): %v", query, err)
|
||||||
|
} else {
|
||||||
|
handleError(response, fmt.Sprintf("/stats/container %v", query), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
writeResponse(response, stats)
|
writeResponse(response, stats)
|
||||||
}
|
}
|
||||||
@ -181,7 +186,7 @@ func (h *handler) handleSystemContainer(request *restful.Request, response *rest
|
|||||||
func (h *handler) handlePodContainer(request *restful.Request, response *restful.Response) {
|
func (h *handler) handlePodContainer(request *restful.Request, response *restful.Response) {
|
||||||
query, err := parseStatsRequest(request)
|
query, err := parseStatsRequest(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, request.Request.URL.String(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +208,7 @@ func (h *handler) handlePodContainer(request *restful.Request, response *restful
|
|||||||
pod, ok := h.provider.GetPodByName(params["namespace"], params["podName"])
|
pod, ok := h.provider.GetPodByName(params["namespace"], params["podName"])
|
||||||
if !ok {
|
if !ok {
|
||||||
glog.V(4).Infof("Container not found: %v", params)
|
glog.V(4).Infof("Container not found: %v", params)
|
||||||
handleError(response, kubecontainer.ErrContainerNotFound)
|
response.WriteError(http.StatusNotFound, kubecontainer.ErrContainerNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stats, err := h.provider.GetContainerInfo(
|
stats, err := h.provider.GetContainerInfo(
|
||||||
@ -213,7 +218,7 @@ func (h *handler) handlePodContainer(request *restful.Request, response *restful
|
|||||||
query.cadvisorRequest())
|
query.cadvisorRequest())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(response, err)
|
handleError(response, fmt.Sprintf("%s %v", request.Request.URL.String(), query), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeResponse(response, stats)
|
writeResponse(response, stats)
|
||||||
@ -226,13 +231,14 @@ func writeResponse(response *restful.Response, stats interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleError serializes an error object into an HTTP response.
|
// handleError serializes an error object into an HTTP response.
|
||||||
func handleError(response *restful.Response, err error) {
|
// request is provided for logging.
|
||||||
|
func handleError(response *restful.Response, request string, err error) {
|
||||||
switch err {
|
switch err {
|
||||||
case kubecontainer.ErrContainerNotFound:
|
case kubecontainer.ErrContainerNotFound:
|
||||||
response.WriteError(http.StatusNotFound, err)
|
response.WriteError(http.StatusNotFound, err)
|
||||||
default:
|
default:
|
||||||
msg := fmt.Sprintf("Internal Error: %v", err)
|
msg := fmt.Sprintf("Internal Error: %v", err)
|
||||||
glog.Errorf("HTTP InternalServerError: %s", msg)
|
glog.Errorf("HTTP InternalServerError serving %s: %s", request, msg)
|
||||||
response.WriteErrorString(http.StatusInternalServerError, msg)
|
response.WriteErrorString(http.StatusInternalServerError, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,26 +68,33 @@ func (sp *summaryProviderImpl) Get() (*stats.Summary, error) {
|
|||||||
}
|
}
|
||||||
infos, err := sp.provider.GetContainerInfoV2("/", options)
|
infos, err := sp.provider.GetContainerInfoV2("/", options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
if _, ok := infos["/"]; ok {
|
||||||
|
// If the failure is partial, log it and return a best-effort response.
|
||||||
|
glog.Errorf("Partial failure issuing GetContainerInfoV2: %v", err)
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("failed GetContainerInfoV2: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(timstclair): Consider returning a best-effort response if any of the following errors
|
||||||
|
// occur.
|
||||||
node, err := sp.provider.GetNode()
|
node, err := sp.provider.GetNode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed GetNode: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeConfig := sp.provider.GetNodeConfig()
|
nodeConfig := sp.provider.GetNodeConfig()
|
||||||
rootFsInfo, err := sp.provider.RootFsInfo()
|
rootFsInfo, err := sp.provider.RootFsInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed RootFsInfo: %v", err)
|
||||||
}
|
}
|
||||||
imageFsInfo, err := sp.provider.ImagesFsInfo()
|
imageFsInfo, err := sp.provider.ImagesFsInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed DockerImagesFsInfo: %v", err)
|
||||||
}
|
}
|
||||||
imageStats, err := sp.runtime.ImageStats()
|
imageStats, err := sp.runtime.ImageStats()
|
||||||
if err != nil || imageStats == nil {
|
if err != nil || imageStats == nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed ImageStats: %v", err)
|
||||||
}
|
}
|
||||||
sb := &summaryBuilder{sp.fsResourceAnalyzer, node, nodeConfig, rootFsInfo, imageFsInfo, *imageStats, infos}
|
sb := &summaryBuilder{sp.fsResourceAnalyzer, node, nodeConfig, rootFsInfo, imageFsInfo, *imageStats, infos}
|
||||||
return sb.build()
|
return sb.build()
|
||||||
|
Loading…
Reference in New Issue
Block a user