mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-20 09:33:52 +00:00
deprecate cAdvisor json metrics collected by Kubelet
- remove unused code for cadvisor json metrics collected Signed-off-by: pacoxu <paco.xu@daocloud.io>
This commit is contained in:
@@ -62,7 +62,6 @@ func isSubpath(subpath, path string) bool {
|
||||
// /stats/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=stats
|
||||
// /metrics/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=metrics
|
||||
// /logs/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=log
|
||||
// /spec/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=spec
|
||||
func (n nodeAuthorizerAttributesGetter) GetRequestAttributes(u user.Info, r *http.Request) authorizer.Attributes {
|
||||
|
||||
apiVerb := ""
|
||||
@@ -105,8 +104,6 @@ func (n nodeAuthorizerAttributesGetter) GetRequestAttributes(u user.Info, r *htt
|
||||
case isSubpath(requestPath, logsPath):
|
||||
// "log" to match other log subresources (pods/log, etc)
|
||||
attrs.Subresource = "log"
|
||||
case isSubpath(requestPath, specPath):
|
||||
attrs.Subresource = "spec"
|
||||
}
|
||||
|
||||
klog.V(5).InfoS("Node request attributes", "user", attrs.GetUser().GetName(), "verb", attrs.GetVerb(), "resource", attrs.GetResource(), "subresource", attrs.GetSubresource())
|
||||
|
@@ -131,13 +131,9 @@ func AuthzTestCases() []AuthzTestCase {
|
||||
"/portForward/{podNamespace}/{podID}/{uid}": "proxy",
|
||||
"/run/{podNamespace}/{podID}/{containerName}": "proxy",
|
||||
"/run/{podNamespace}/{podID}/{uid}/{containerName}": "proxy",
|
||||
"/runningpods/": "proxy",
|
||||
"/spec/": "spec",
|
||||
"/stats/": "stats",
|
||||
"/stats/container": "stats",
|
||||
"/stats/summary": "stats",
|
||||
"/stats/{namespace}/{podName}/{uid}/{containerName}": "stats",
|
||||
"/stats/{podName}/{containerName}": "stats",
|
||||
"/runningpods/": "proxy",
|
||||
"/stats/": "stats",
|
||||
"/stats/summary": "stats",
|
||||
}
|
||||
testCases := []AuthzTestCase{}
|
||||
for path, subresource := range testPaths {
|
||||
|
@@ -84,7 +84,6 @@ const (
|
||||
cadvisorMetricsPath = "/metrics/cadvisor"
|
||||
resourceMetricsPath = "/metrics/resource"
|
||||
proberMetricsPath = "/metrics/probes"
|
||||
specPath = "/spec/"
|
||||
statsPath = "/stats/"
|
||||
logsPath = "/logs/"
|
||||
pprofBasePath = "/debug/pprof/"
|
||||
@@ -142,13 +141,12 @@ func ListenAndServeKubeletServer(
|
||||
resourceAnalyzer stats.ResourceAnalyzer,
|
||||
kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
||||
tlsOptions *TLSOptions,
|
||||
auth AuthInterface,
|
||||
enableCAdvisorJSONEndpoints bool) {
|
||||
auth AuthInterface) {
|
||||
|
||||
address := net.ParseIP(kubeCfg.Address)
|
||||
port := uint(kubeCfg.Port)
|
||||
klog.InfoS("Starting to listen", "address", address, "port", port)
|
||||
handler := NewServer(host, resourceAnalyzer, auth, enableCAdvisorJSONEndpoints, kubeCfg)
|
||||
handler := NewServer(host, resourceAnalyzer, auth, kubeCfg)
|
||||
s := &http.Server{
|
||||
Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)),
|
||||
Handler: &handler,
|
||||
@@ -168,9 +166,9 @@ func ListenAndServeKubeletServer(
|
||||
}
|
||||
|
||||
// ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet.
|
||||
func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint, enableCAdvisorJSONEndpoints bool) {
|
||||
func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint) {
|
||||
klog.InfoS("Starting to listen read-only", "address", address, "port", port)
|
||||
s := NewServer(host, resourceAnalyzer, nil, enableCAdvisorJSONEndpoints, nil)
|
||||
s := NewServer(host, resourceAnalyzer, nil, nil)
|
||||
|
||||
server := &http.Server{
|
||||
Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)),
|
||||
@@ -222,7 +220,6 @@ func NewServer(
|
||||
host HostInterface,
|
||||
resourceAnalyzer stats.ResourceAnalyzer,
|
||||
auth AuthInterface,
|
||||
enableCAdvisorJSONEndpoints bool,
|
||||
kubeCfg *kubeletconfiginternal.KubeletConfiguration) Server {
|
||||
server := Server{
|
||||
host: host,
|
||||
@@ -235,7 +232,7 @@ func NewServer(
|
||||
if auth != nil {
|
||||
server.InstallAuthFilter()
|
||||
}
|
||||
server.InstallDefaultHandlers(enableCAdvisorJSONEndpoints)
|
||||
server.InstallDefaultHandlers()
|
||||
if kubeCfg != nil && kubeCfg.EnableDebuggingHandlers {
|
||||
server.InstallDebuggingHandlers()
|
||||
// To maintain backward compatibility serve logs and pprof only when enableDebuggingHandlers is also enabled
|
||||
@@ -312,7 +309,7 @@ func (s *Server) getMetricMethodBucket(method string) string {
|
||||
|
||||
// InstallDefaultHandlers registers the default set of supported HTTP request
|
||||
// patterns with the restful Container.
|
||||
func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
|
||||
func (s *Server) InstallDefaultHandlers() {
|
||||
s.addMetricsBucketMatcher("healthz")
|
||||
healthz.InstallHandler(s.restfulCont,
|
||||
healthz.PingHealthz,
|
||||
@@ -331,7 +328,7 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
|
||||
s.restfulCont.Add(ws)
|
||||
|
||||
s.addMetricsBucketMatcher("stats")
|
||||
s.restfulCont.Add(stats.CreateHandlers(statsPath, s.host, s.resourceAnalyzer, enableCAdvisorJSONEndpoints))
|
||||
s.restfulCont.Add(stats.CreateHandlers(statsPath, s.host, s.resourceAnalyzer))
|
||||
|
||||
s.addMetricsBucketMatcher("metrics")
|
||||
s.addMetricsBucketMatcher("metrics/cadvisor")
|
||||
@@ -387,19 +384,6 @@ func (s *Server) InstallDefaultHandlers(enableCAdvisorJSONEndpoints bool) {
|
||||
s.restfulCont.Handle(proberMetricsPath,
|
||||
compbasemetrics.HandlerFor(p, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),
|
||||
)
|
||||
|
||||
s.addMetricsBucketMatcher("spec")
|
||||
if enableCAdvisorJSONEndpoints {
|
||||
ws := new(restful.WebService)
|
||||
ws.
|
||||
Path(specPath).
|
||||
Produces(restful.MIME_JSON)
|
||||
ws.Route(ws.GET("").
|
||||
To(s.getSpec).
|
||||
Operation("getSpec").
|
||||
Writes(cadvisorapi.MachineInfo{}))
|
||||
s.restfulCont.Add(ws)
|
||||
}
|
||||
}
|
||||
|
||||
// InstallDebuggingHandlers registers the HTTP request patterns that serve logs or run commands/containers
|
||||
@@ -718,16 +702,6 @@ func (s *Server) getLogs(request *restful.Request, response *restful.Response) {
|
||||
s.host.ServeLogs(response, request.Request)
|
||||
}
|
||||
|
||||
// getSpec handles spec requests against the Kubelet.
|
||||
func (s *Server) getSpec(request *restful.Request, response *restful.Response) {
|
||||
info, err := s.host.GetCachedMachineInfo()
|
||||
if err != nil {
|
||||
response.WriteError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(info)
|
||||
}
|
||||
|
||||
type execRequestParams struct {
|
||||
podNamespace string
|
||||
podName string
|
||||
|
@@ -17,9 +17,7 @@ limitations under the License.
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -57,7 +55,6 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cri/streaming"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward"
|
||||
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/cri/streaming/remotecommand"
|
||||
@@ -348,7 +345,6 @@ func newServerTestWithDebuggingHandlers(kubeCfg *kubeletconfiginternal.KubeletCo
|
||||
fw.fakeKubelet,
|
||||
stats.NewResourceAnalyzer(fw.fakeKubelet, time.Minute),
|
||||
fw.fakeAuth,
|
||||
true,
|
||||
kubeCfg)
|
||||
fw.serverUnderTest = &server
|
||||
fw.testHTTPServer = httptest.NewServer(fw.serverUnderTest)
|
||||
@@ -363,185 +359,6 @@ func getPodName(name, namespace string) string {
|
||||
return name + "_" + namespace
|
||||
}
|
||||
|
||||
func TestContainerInfo(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
expectedInfo := &cadvisorapi.ContainerInfo{}
|
||||
podID := "somepod"
|
||||
expectedPodID := getPodName(podID, "")
|
||||
expectedContainerName := "goodcontainer"
|
||||
fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) {
|
||||
if podID != expectedPodID || containerName != expectedContainerName {
|
||||
return nil, fmt.Errorf("bad podID or containerName: podID=%v; containerName=%v", podID, containerName)
|
||||
}
|
||||
return expectedInfo, nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + fmt.Sprintf("/stats/%v/%v", podID, expectedContainerName))
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var receivedInfo cadvisorapi.ContainerInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&receivedInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("received invalid json data: %v", err)
|
||||
}
|
||||
if !receivedInfo.Eq(expectedInfo) {
|
||||
t.Errorf("received wrong data: %#v", receivedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerInfoWithUidNamespace(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
expectedInfo := &cadvisorapi.ContainerInfo{}
|
||||
podID := "somepod"
|
||||
expectedNamespace := "custom"
|
||||
expectedPodID := getPodName(podID, expectedNamespace)
|
||||
expectedContainerName := "goodcontainer"
|
||||
fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) {
|
||||
if podID != expectedPodID || string(uid) != testUID || containerName != expectedContainerName {
|
||||
return nil, fmt.Errorf("bad podID or uid or containerName: podID=%v; uid=%v; containerName=%v", podID, uid, containerName)
|
||||
}
|
||||
return expectedInfo, nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + fmt.Sprintf("/stats/%v/%v/%v/%v", expectedNamespace, podID, testUID, expectedContainerName))
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var receivedInfo cadvisorapi.ContainerInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&receivedInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("received invalid json data: %v", err)
|
||||
}
|
||||
if !receivedInfo.Eq(expectedInfo) {
|
||||
t.Errorf("received wrong data: %#v", receivedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerNotFound(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
podID := "somepod"
|
||||
expectedNamespace := "custom"
|
||||
expectedContainerName := "slowstartcontainer"
|
||||
fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *cadvisorapi.ContainerInfoRequest) (*cadvisorapi.ContainerInfo, error) {
|
||||
return nil, kubecontainer.ErrContainerNotFound
|
||||
}
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + fmt.Sprintf("/stats/%v/%v/%v/%v", expectedNamespace, podID, testUID, expectedContainerName))
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("Received status %d expecting %d", resp.StatusCode, http.StatusNotFound)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
func TestRootInfo(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
expectedInfo := &cadvisorapi.ContainerInfo{
|
||||
ContainerReference: cadvisorapi.ContainerReference{
|
||||
Name: "/",
|
||||
},
|
||||
}
|
||||
fw.fakeKubelet.rawInfoFunc = func(req *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) {
|
||||
return map[string]*cadvisorapi.ContainerInfo{
|
||||
expectedInfo.Name: expectedInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + "/stats")
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var receivedInfo cadvisorapi.ContainerInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&receivedInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("received invalid json data: %v", err)
|
||||
}
|
||||
if !receivedInfo.Eq(expectedInfo) {
|
||||
t.Errorf("received wrong data: %#v, expected %#v", receivedInfo, expectedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubcontainerContainerInfo(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
const kubeletContainer = "/kubelet"
|
||||
const kubeletSubContainer = "/kubelet/sub"
|
||||
expectedInfo := map[string]*cadvisorapi.ContainerInfo{
|
||||
kubeletContainer: {
|
||||
ContainerReference: cadvisorapi.ContainerReference{
|
||||
Name: kubeletContainer,
|
||||
},
|
||||
},
|
||||
kubeletSubContainer: {
|
||||
ContainerReference: cadvisorapi.ContainerReference{
|
||||
Name: kubeletSubContainer,
|
||||
},
|
||||
},
|
||||
}
|
||||
fw.fakeKubelet.rawInfoFunc = func(req *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) {
|
||||
return expectedInfo, nil
|
||||
}
|
||||
|
||||
request := fmt.Sprintf("{\"containerName\":%q, \"subcontainers\": true}", kubeletContainer)
|
||||
resp, err := http.Post(fw.testHTTPServer.URL+"/stats/container", "application/json", bytes.NewBuffer([]byte(request)))
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var receivedInfo map[string]*cadvisorapi.ContainerInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&receivedInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("Received invalid json data: %v", err)
|
||||
}
|
||||
if len(receivedInfo) != len(expectedInfo) {
|
||||
t.Errorf("Received wrong data: %#v, expected %#v", receivedInfo, expectedInfo)
|
||||
}
|
||||
|
||||
for _, containerName := range []string{kubeletContainer, kubeletSubContainer} {
|
||||
if _, ok := receivedInfo[containerName]; !ok {
|
||||
t.Errorf("Expected container %q to be present in result: %#v", containerName, receivedInfo)
|
||||
}
|
||||
if !receivedInfo[containerName].Eq(expectedInfo[containerName]) {
|
||||
t.Errorf("Invalid result for %q: Expected %#v, received %#v", containerName, expectedInfo[containerName], receivedInfo[containerName])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineInfo(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
expectedInfo := &cadvisorapi.MachineInfo{
|
||||
NumCores: 4,
|
||||
MemoryCapacity: 1024,
|
||||
}
|
||||
fw.fakeKubelet.machineInfoFunc = func() (*cadvisorapi.MachineInfo, error) {
|
||||
return expectedInfo, nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + "/spec")
|
||||
if err != nil {
|
||||
t.Fatalf("Got error GETing: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var receivedInfo cadvisorapi.MachineInfo
|
||||
err = json.NewDecoder(resp.Body).Decode(&receivedInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("received invalid json data: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(&receivedInfo, expectedInfo) {
|
||||
t.Errorf("received wrong data: %#v", receivedInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeLogs(t *testing.T) {
|
||||
fw := newServerTest()
|
||||
defer fw.testHTTPServer.Close()
|
||||
@@ -1470,12 +1287,8 @@ func TestMetricBuckets(t *testing.T) {
|
||||
"run": {url: "/run/podNamespace/podID/containerName", bucket: "run"},
|
||||
"run with uid": {url: "/run/podNamespace/podID/uid/containerName", bucket: "run"},
|
||||
"runningpods": {url: "/runningpods/", bucket: "runningpods"},
|
||||
"spec": {url: "/spec/", bucket: "spec"},
|
||||
"stats": {url: "/stats/", bucket: "stats"},
|
||||
"stats container sub": {url: "/stats/container", bucket: "stats"},
|
||||
"stats summary sub": {url: "/stats/summary", bucket: "stats"},
|
||||
"stats containerName with uid": {url: "/stats/namespace/podName/uid/containerName", bucket: "stats"},
|
||||
"stats containerName": {url: "/stats/podName/containerName", bucket: "stats"},
|
||||
"invalid path": {url: "/junk", bucket: "other"},
|
||||
"invalid path starting with good": {url: "/healthzjunk", bucket: "other"},
|
||||
}
|
||||
@@ -1530,34 +1343,6 @@ func TestDebuggingDisabledHandlers(t *testing.T) {
|
||||
for _, p := range paths {
|
||||
verifyEndpointResponse(t, fw, p, "Debug endpoints are disabled.\n")
|
||||
}
|
||||
|
||||
// test some other paths, make sure they're working
|
||||
containerInfo := &cadvisorapi.ContainerInfo{
|
||||
ContainerReference: cadvisorapi.ContainerReference{
|
||||
Name: "/",
|
||||
},
|
||||
}
|
||||
fw.fakeKubelet.rawInfoFunc = func(req *cadvisorapi.ContainerInfoRequest) (map[string]*cadvisorapi.ContainerInfo, error) {
|
||||
return map[string]*cadvisorapi.ContainerInfo{
|
||||
containerInfo.Name: containerInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(fw.testHTTPServer.URL + "/stats")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
machineInfo := &cadvisorapi.MachineInfo{
|
||||
NumCores: 4,
|
||||
MemoryCapacity: 1024,
|
||||
}
|
||||
fw.fakeKubelet.machineInfoFunc = func() (*cadvisorapi.MachineInfo, error) {
|
||||
return machineInfo, nil
|
||||
}
|
||||
|
||||
resp, err = http.Get(fw.testHTTPServer.URL + "/spec")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
}
|
||||
|
||||
func TestDisablingLogAndProfilingHandler(t *testing.T) {
|
||||
|
@@ -17,12 +17,8 @@ limitations under the License.
|
||||
package stats
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
restful "github.com/emicklei/go-restful"
|
||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||
@@ -31,7 +27,6 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
@@ -113,31 +108,20 @@ type handler struct {
|
||||
}
|
||||
|
||||
// CreateHandlers creates the REST handlers for the stats.
|
||||
func CreateHandlers(rootPath string, provider Provider, summaryProvider SummaryProvider, enableCAdvisorJSONEndpoints bool) *restful.WebService {
|
||||
func CreateHandlers(rootPath string, provider Provider, summaryProvider SummaryProvider) *restful.WebService {
|
||||
h := &handler{provider, summaryProvider}
|
||||
|
||||
ws := &restful.WebService{}
|
||||
ws.Path(rootPath).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
type endpoint struct {
|
||||
endpoints := []struct {
|
||||
path string
|
||||
handler restful.RouteFunction
|
||||
}
|
||||
|
||||
endpoints := []endpoint{
|
||||
}{
|
||||
{"/summary", h.handleSummary},
|
||||
}
|
||||
|
||||
if enableCAdvisorJSONEndpoints {
|
||||
endpoints = append(endpoints,
|
||||
endpoint{"", h.handleStats},
|
||||
endpoint{"/container", h.handleSystemContainer},
|
||||
endpoint{"/{podName}/{containerName}", h.handlePodContainer},
|
||||
endpoint{"/{namespace}/{podName}/{uid}/{containerName}", h.handlePodContainer},
|
||||
)
|
||||
}
|
||||
|
||||
for _, e := range endpoints {
|
||||
for _, method := range []string{"GET", "POST"} {
|
||||
ws.Route(ws.
|
||||
@@ -150,72 +134,6 @@ func CreateHandlers(rootPath string, provider Provider, summaryProvider SummaryP
|
||||
return ws
|
||||
}
|
||||
|
||||
type statsRequest struct {
|
||||
// The name of the container for which to request stats.
|
||||
// Default: /
|
||||
// +optional
|
||||
ContainerName string `json:"containerName,omitempty"`
|
||||
|
||||
// Max number of stats to return.
|
||||
// If start and end time are specified this limit is ignored.
|
||||
// Default: 60
|
||||
// +optional
|
||||
NumStats int `json:"num_stats,omitempty"`
|
||||
|
||||
// Start time for which to query information.
|
||||
// If omitted, the beginning of time is assumed.
|
||||
// +optional
|
||||
Start time.Time `json:"start,omitempty"`
|
||||
|
||||
// End time for which to query information.
|
||||
// If omitted, current time is assumed.
|
||||
// +optional
|
||||
End time.Time `json:"end,omitempty"`
|
||||
|
||||
// Whether to also include information from subcontainers.
|
||||
// Default: false.
|
||||
// +optional
|
||||
Subcontainers bool `json:"subcontainers,omitempty"`
|
||||
}
|
||||
|
||||
func (r *statsRequest) cadvisorRequest() *cadvisorapi.ContainerInfoRequest {
|
||||
return &cadvisorapi.ContainerInfoRequest{
|
||||
NumStats: r.NumStats,
|
||||
Start: r.Start,
|
||||
End: r.End,
|
||||
}
|
||||
}
|
||||
|
||||
func parseStatsRequest(request *restful.Request) (statsRequest, error) {
|
||||
// Default request.
|
||||
query := statsRequest{
|
||||
NumStats: 60,
|
||||
}
|
||||
|
||||
err := json.NewDecoder(request.Request.Body).Decode(&query)
|
||||
if err != nil && err != io.EOF {
|
||||
return query, err
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// Handles root container stats requests to /stats
|
||||
func (h *handler) handleStats(request *restful.Request, response *restful.Response) {
|
||||
query, err := parseStatsRequest(request)
|
||||
if err != nil {
|
||||
handleError(response, "/stats", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Root container stats.
|
||||
statsMap, err := h.provider.GetRawContainerInfo("/", query.cadvisorRequest(), false)
|
||||
if err != nil {
|
||||
handleError(response, fmt.Sprintf("/stats %v", query), err)
|
||||
return
|
||||
}
|
||||
writeResponse(response, statsMap["/"])
|
||||
}
|
||||
|
||||
// Handles stats summary requests to /stats/summary
|
||||
// If "only_cpu_and_memory" GET param is true then only cpu and memory is returned in response.
|
||||
func (h *handler) handleSummary(request *restful.Request, response *restful.Response) {
|
||||
@@ -244,74 +162,6 @@ func (h *handler) handleSummary(request *restful.Request, response *restful.Resp
|
||||
}
|
||||
}
|
||||
|
||||
// Handles non-kubernetes container stats requests to /stats/container/
|
||||
func (h *handler) handleSystemContainer(request *restful.Request, response *restful.Response) {
|
||||
query, err := parseStatsRequest(request)
|
||||
if err != nil {
|
||||
handleError(response, "/stats/container", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Non-Kubernetes container stats.
|
||||
containerName := path.Join("/", query.ContainerName)
|
||||
stats, err := h.provider.GetRawContainerInfo(
|
||||
containerName, query.cadvisorRequest(), query.Subcontainers)
|
||||
if err != nil {
|
||||
if _, ok := stats[containerName]; ok {
|
||||
// If the failure is partial, log it and return a best-effort response.
|
||||
klog.ErrorS(err, "Partial failure issuing GetRawContainerInfo", "query", query)
|
||||
} else {
|
||||
handleError(response, fmt.Sprintf("/stats/container %v", query), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
writeResponse(response, stats)
|
||||
}
|
||||
|
||||
// Handles kubernetes pod/container stats requests to:
|
||||
// /stats/<pod name>/<container name>
|
||||
// /stats/<namespace>/<pod name>/<uid>/<container name>
|
||||
func (h *handler) handlePodContainer(request *restful.Request, response *restful.Response) {
|
||||
query, err := parseStatsRequest(request)
|
||||
if err != nil {
|
||||
handleError(response, request.Request.URL.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
// Default parameters.
|
||||
params := map[string]string{
|
||||
"namespace": metav1.NamespaceDefault,
|
||||
"uid": "",
|
||||
}
|
||||
for k, v := range request.PathParameters() {
|
||||
params[k] = v
|
||||
}
|
||||
|
||||
if params["podName"] == "" || params["containerName"] == "" {
|
||||
response.WriteErrorString(http.StatusBadRequest,
|
||||
fmt.Sprintf("Invalid pod container request: %v", params))
|
||||
return
|
||||
}
|
||||
|
||||
pod, ok := h.provider.GetPodByName(params["namespace"], params["podName"])
|
||||
if !ok {
|
||||
klog.V(4).InfoS("Container not found", "pod", klog.KRef(params["namespace"], params["podName"]))
|
||||
response.WriteError(http.StatusNotFound, kubecontainer.ErrContainerNotFound)
|
||||
return
|
||||
}
|
||||
stats, err := h.provider.GetContainerInfo(
|
||||
kubecontainer.GetPodFullName(pod),
|
||||
types.UID(params["uid"]),
|
||||
params["containerName"],
|
||||
query.cadvisorRequest())
|
||||
|
||||
if err != nil {
|
||||
handleError(response, fmt.Sprintf("%s %v", request.Request.URL.String(), query), err)
|
||||
return
|
||||
}
|
||||
writeResponse(response, stats)
|
||||
}
|
||||
|
||||
func writeResponse(response *restful.Response, stats interface{}) {
|
||||
if err := response.WriteAsJson(stats); err != nil {
|
||||
klog.ErrorS(err, "Error writing response")
|
||||
|
Reference in New Issue
Block a user