Include sidecar containers requests and limits (#2848)
* include sidecar container metrics * apply code review suggestionsmine
parent
6fc151bda2
commit
8a16b57c09
|
|
@ -132,7 +132,7 @@ func (p Pod) Render(o interface{}, ns string, row *model1.Row) error {
|
|||
if pwm.MX != nil {
|
||||
ccmx = pwm.MX.Containers
|
||||
}
|
||||
c, r := gatherCoMX(po.Spec.Containers, ccmx)
|
||||
c, r := gatherCoMX(&po.Spec, ccmx)
|
||||
phase := p.Phase(&po)
|
||||
row.ID = client.MetaFQN(po.ObjectMeta)
|
||||
|
||||
|
|
@ -223,7 +223,11 @@ func (p *PodWithMetrics) DeepCopyObject() runtime.Object {
|
|||
return p
|
||||
}
|
||||
|
||||
func gatherCoMX(cc []v1.Container, ccmx []mv1beta1.ContainerMetrics) (c, r metric) {
|
||||
func gatherCoMX(spec *v1.PodSpec, ccmx []mv1beta1.ContainerMetrics) (c, r metric) {
|
||||
cc := make([]v1.Container, 0, len(spec.InitContainers)+len(spec.Containers))
|
||||
cc = append(cc, filterRestartableInitCO(spec.InitContainers)...)
|
||||
cc = append(cc, spec.Containers...)
|
||||
|
||||
rcpu, rmem := cosRequests(cc)
|
||||
r.cpu, r.mem = rcpu.MilliValue(), rmem.Value()
|
||||
|
||||
|
|
@ -490,3 +494,13 @@ func hasPodReadyCondition(conditions []v1.PodCondition) bool {
|
|||
func restartableInitCO(p *v1.ContainerRestartPolicy) bool {
|
||||
return p != nil && *p == v1.ContainerRestartPolicyAlways
|
||||
}
|
||||
|
||||
func filterRestartableInitCO(cc []v1.Container) []v1.Container {
|
||||
rcc := make([]v1.Container, 0, len(cc))
|
||||
for _, c := range cc {
|
||||
if c.RestartPolicy != nil && *c.RestartPolicy == v1.ContainerRestartPolicyAlways {
|
||||
rcc = append(rcc, c)
|
||||
}
|
||||
}
|
||||
return rcc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,16 +295,78 @@ func Test_restartableInitCO(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_filterRestartableInitCO(t *testing.T) {
|
||||
always := v1.ContainerRestartPolicyAlways
|
||||
|
||||
uu := map[string]struct {
|
||||
cc []v1.Container
|
||||
ecc []v1.Container
|
||||
}{
|
||||
"empty": {
|
||||
cc: []v1.Container{},
|
||||
ecc: []v1.Container{},
|
||||
},
|
||||
"restartable": {
|
||||
cc: []v1.Container{
|
||||
{
|
||||
Name: "c1",
|
||||
RestartPolicy: &always,
|
||||
},
|
||||
},
|
||||
ecc: []v1.Container{
|
||||
{
|
||||
Name: "c1",
|
||||
RestartPolicy: &always,
|
||||
},
|
||||
},
|
||||
},
|
||||
"not-restartable": {
|
||||
cc: []v1.Container{
|
||||
{
|
||||
Name: "c1",
|
||||
},
|
||||
},
|
||||
ecc: []v1.Container{},
|
||||
},
|
||||
"mixed": {
|
||||
cc: []v1.Container{
|
||||
{
|
||||
Name: "c1",
|
||||
},
|
||||
{
|
||||
Name: "c2",
|
||||
RestartPolicy: &always,
|
||||
},
|
||||
},
|
||||
ecc: []v1.Container{
|
||||
{
|
||||
Name: "c2",
|
||||
RestartPolicy: &always,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.ecc, filterRestartableInitCO(u.cc))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_gatherPodMx(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
cc []v1.Container
|
||||
spec *v1.PodSpec
|
||||
mx []mv1beta1.ContainerMetrics
|
||||
c, r metric
|
||||
perc string
|
||||
}{
|
||||
"single": {
|
||||
cc: []v1.Container{
|
||||
makeContainer("c1", false, "10m", "1Mi", "20m", "2Mi"),
|
||||
spec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
makeContainer("c1", false, "10m", "1Mi", "20m", "2Mi"),
|
||||
},
|
||||
},
|
||||
mx: []mv1beta1.ContainerMetrics{
|
||||
makeCoMX("c1", "1m", "22Mi"),
|
||||
|
|
@ -322,10 +384,12 @@ func Test_gatherPodMx(t *testing.T) {
|
|||
perc: "10",
|
||||
},
|
||||
"multi": {
|
||||
cc: []v1.Container{
|
||||
makeContainer("c1", false, "11m", "22Mi", "111m", "44Mi"),
|
||||
makeContainer("c2", false, "93m", "1402Mi", "0m", "2804Mi"),
|
||||
makeContainer("c3", false, "11m", "34Mi", "0m", "69Mi"),
|
||||
spec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
makeContainer("c1", false, "11m", "22Mi", "111m", "44Mi"),
|
||||
makeContainer("c2", false, "93m", "1402Mi", "0m", "2804Mi"),
|
||||
makeContainer("c3", false, "11m", "34Mi", "0m", "69Mi"),
|
||||
},
|
||||
},
|
||||
r: metric{
|
||||
cpu: 11 + 93 + 11,
|
||||
|
|
@ -344,12 +408,37 @@ func Test_gatherPodMx(t *testing.T) {
|
|||
},
|
||||
perc: "46",
|
||||
},
|
||||
"sidecar": {
|
||||
spec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
makeContainer("c1", false, "11m", "22Mi", "111m", "44Mi"),
|
||||
},
|
||||
InitContainers: []v1.Container{
|
||||
makeContainer("c2", true, "93m", "1402Mi", "0m", "2804Mi"),
|
||||
},
|
||||
},
|
||||
r: metric{
|
||||
cpu: 11 + 93,
|
||||
mem: (22 + 1402) * client.MegaByte,
|
||||
lcpu: 111 + 0,
|
||||
lmem: (44 + 2804) * client.MegaByte,
|
||||
},
|
||||
mx: []mv1beta1.ContainerMetrics{
|
||||
makeCoMX("c1", "1m", "22Mi"),
|
||||
makeCoMX("c2", "51m", "1275Mi"),
|
||||
},
|
||||
c: metric{
|
||||
cpu: 1 + 51,
|
||||
mem: (22 + 1275) * client.MegaByte,
|
||||
},
|
||||
perc: "50",
|
||||
},
|
||||
}
|
||||
|
||||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
c, r := gatherCoMX(u.cc, u.mx)
|
||||
c, r := gatherCoMX(u.spec, u.mx)
|
||||
assert.Equal(t, u.c.cpu, c.cpu)
|
||||
assert.Equal(t, u.c.mem, c.mem)
|
||||
assert.Equal(t, u.c.lcpu, c.lcpu)
|
||||
|
|
@ -427,18 +516,19 @@ func Test_podRequests(t *testing.T) {
|
|||
|
||||
// Helpers...
|
||||
|
||||
func makeContainer(n string, init bool, rc, rm, lc, lm string) v1.Container {
|
||||
func makeContainer(n string, restartable bool, rc, rm, lc, lm string) v1.Container {
|
||||
always := v1.ContainerRestartPolicyAlways
|
||||
var res v1.ResourceRequirements
|
||||
if init {
|
||||
res = v1.ResourceRequirements{}
|
||||
} else {
|
||||
res = v1.ResourceRequirements{
|
||||
Requests: makeRes(rc, rm),
|
||||
Limits: makeRes(lc, lm),
|
||||
}
|
||||
var rp *v1.ContainerRestartPolicy
|
||||
res = v1.ResourceRequirements{
|
||||
Requests: makeRes(rc, rm),
|
||||
Limits: makeRes(lc, lm),
|
||||
}
|
||||
if restartable {
|
||||
rp = &always
|
||||
}
|
||||
|
||||
return v1.Container{Name: n, Resources: res}
|
||||
return v1.Container{Name: n, Resources: res, RestartPolicy: rp}
|
||||
}
|
||||
|
||||
func makeRes(c, m string) v1.ResourceList {
|
||||
|
|
|
|||
|
|
@ -198,6 +198,22 @@ func TestPodInitRender(t *testing.T) {
|
|||
assert.Equal(t, e, r.Fields[:19])
|
||||
}
|
||||
|
||||
func TestPodSidecarRender(t *testing.T) {
|
||||
pom := render.PodWithMetrics{
|
||||
Raw: load(t, "po_sidecar"),
|
||||
MX: makePodMX("sleep", "100m", "40Mi"),
|
||||
}
|
||||
|
||||
var po render.Pod
|
||||
r := model1.NewRow(14)
|
||||
err := po.Render(&pom, "", &r)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "default/sleep", r.ID)
|
||||
e := model1.Fields{"default", "sleep", "0", "●", "1/1", "Running", "0", "100", "40", "50:250", "50:80", "200", "40", "80", "50", "10.244.0.8", "kind-control-plane", "<none>", "<none>"}
|
||||
assert.Equal(t, e, r.Fields[:19])
|
||||
}
|
||||
|
||||
func TestCheckPodStatus(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
pod v1.Pod
|
||||
|
|
|
|||
|
|
@ -0,0 +1,293 @@
|
|||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"creationTimestamp": "2024-08-24T01:54:32Z",
|
||||
"name": "sleep",
|
||||
"namespace": "default",
|
||||
"resourceVersion": "17852",
|
||||
"uid": "35079257-0ffb-4b09-b2c1-3c0d416f2523"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"command": [
|
||||
"/bin/sleep",
|
||||
"60"
|
||||
],
|
||||
"image": "istio/base",
|
||||
"imagePullPolicy": "Always",
|
||||
"name": "sleep",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "230m",
|
||||
"memory": "40Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "30m",
|
||||
"memory": "10Mi"
|
||||
}
|
||||
},
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"enableServiceLinks": true,
|
||||
"initContainers": [
|
||||
{
|
||||
"command": [
|
||||
"/bin/sleep",
|
||||
"1"
|
||||
],
|
||||
"image": "istio/base",
|
||||
"imagePullPolicy": "Always",
|
||||
"name": "init",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "333m",
|
||||
"memory": "333Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "333m",
|
||||
"memory": "333Mi"
|
||||
}
|
||||
},
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"command": [
|
||||
"/bin/sleep",
|
||||
"60"
|
||||
],
|
||||
"image": "istio/base",
|
||||
"imagePullPolicy": "Always",
|
||||
"name": "sidecar",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "20m",
|
||||
"memory": "40Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "20m",
|
||||
"memory": "40Mi"
|
||||
}
|
||||
},
|
||||
"restartPolicy": "Always",
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodeName": "kind-control-plane",
|
||||
"preemptionPolicy": "PreemptLowerPriority",
|
||||
"priority": 0,
|
||||
"restartPolicy": "Never",
|
||||
"schedulerName": "default-scheduler",
|
||||
"securityContext": {},
|
||||
"serviceAccount": "default",
|
||||
"serviceAccountName": "default",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"tolerations": [
|
||||
{
|
||||
"effect": "NoExecute",
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"effect": "NoExecute",
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "kube-api-access-mphcq",
|
||||
"projected": {
|
||||
"defaultMode": 420,
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
],
|
||||
"name": "kube-root-ca.crt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
},
|
||||
"path": "namespace"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conditions": [
|
||||
{
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2024-08-24T01:54:36Z",
|
||||
"status": "True",
|
||||
"type": "PodReadyToStartContainers"
|
||||
},
|
||||
{
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2024-08-24T01:54:38Z",
|
||||
"status": "True",
|
||||
"type": "Initialized"
|
||||
},
|
||||
{
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2024-08-24T01:54:39Z",
|
||||
"status": "True",
|
||||
"type": "Ready"
|
||||
},
|
||||
{
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2024-08-24T01:54:39Z",
|
||||
"status": "True",
|
||||
"type": "ContainersReady"
|
||||
},
|
||||
{
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2024-08-24T01:54:32Z",
|
||||
"status": "True",
|
||||
"type": "PodScheduled"
|
||||
}
|
||||
],
|
||||
"containerStatuses": [
|
||||
{
|
||||
"containerID": "containerd://a1848056a183e40afe3189fc4920bd565930180ebdf2f9e2daf778ea8105f93e",
|
||||
"image": "docker.io/istio/base:latest",
|
||||
"imageID": "docker.io/istio/base@sha256:61673929bc39a86dca7d978b27fc632d3e590bc59cd8b2f386408751d007c91e",
|
||||
"lastState": {},
|
||||
"name": "sleep",
|
||||
"ready": true,
|
||||
"restartCount": 0,
|
||||
"started": true,
|
||||
"state": {
|
||||
"running": {
|
||||
"startedAt": "2024-08-24T01:54:38Z"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true,
|
||||
"recursiveReadOnly": "Disabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"hostIP": "172.18.0.2",
|
||||
"hostIPs": [
|
||||
{
|
||||
"ip": "172.18.0.2"
|
||||
}
|
||||
],
|
||||
"initContainerStatuses": [
|
||||
{
|
||||
"containerID": "containerd://75295261e5d751382c9a6ffa4477b84af2934686c360dcba2d8a6b9bc0f8cada",
|
||||
"image": "docker.io/istio/base:latest",
|
||||
"imageID": "docker.io/istio/base@sha256:61673929bc39a86dca7d978b27fc632d3e590bc59cd8b2f386408751d007c91e",
|
||||
"lastState": {},
|
||||
"name": "init",
|
||||
"ready": true,
|
||||
"restartCount": 0,
|
||||
"started": false,
|
||||
"state": {
|
||||
"terminated": {
|
||||
"containerID": "containerd://75295261e5d751382c9a6ffa4477b84af2934686c360dcba2d8a6b9bc0f8cada",
|
||||
"exitCode": 0,
|
||||
"finishedAt": "2024-08-24T01:54:37Z",
|
||||
"reason": "Completed",
|
||||
"startedAt": "2024-08-24T01:54:35Z"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true,
|
||||
"recursiveReadOnly": "Disabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"containerID": "containerd://7a0d216a09630040c5b165c42cc9d2a95d541d95b6ac0a5ca604bf767d1b2cf0",
|
||||
"image": "docker.io/istio/base:latest",
|
||||
"imageID": "docker.io/istio/base@sha256:61673929bc39a86dca7d978b27fc632d3e590bc59cd8b2f386408751d007c91e",
|
||||
"lastState": {},
|
||||
"name": "sidecar",
|
||||
"ready": true,
|
||||
"restartCount": 0,
|
||||
"started": true,
|
||||
"state": {
|
||||
"running": {
|
||||
"startedAt": "2024-08-24T01:54:38Z"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||
"name": "kube-api-access-mphcq",
|
||||
"readOnly": true,
|
||||
"recursiveReadOnly": "Disabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"phase": "Running",
|
||||
"podIP": "10.244.0.8",
|
||||
"podIPs": [
|
||||
{
|
||||
"ip": "10.244.0.8"
|
||||
}
|
||||
],
|
||||
"qosClass": "Burstable",
|
||||
"startTime": "2024-08-24T01:54:32Z"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue