Skip to content

Commit ca9de35

Browse files
committed
feat(views): kubernetes chart
1 parent 2aa7b0e commit ca9de35

File tree

7 files changed

+406
-31
lines changed

7 files changed

+406
-31
lines changed

charts/kubernetes/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,8 @@ values.schema.deref.json: values.schema.json
3333
.PHONY: lint
3434
lint: chart
3535
ct lint --charts .
36+
37+
38+
.PHONY: install
39+
install:
40+
helm install kubernetes . --values values.test.yaml

charts/kubernetes/README.md

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,11 @@ A Helm chart for the Kubernetes bundle of Flanksource Mission Control
88
|-----|------|---------|-------------|
99
| clusterName | string | `""` | |
1010
| kubeconfig | object | `{}` | |
11-
| kubernetesConnection.cnrm.clusterResource | string | `""` | |
12-
| kubernetesConnection.cnrm.clusterResourceNamespace | string | `""` | |
13-
| kubernetesConnection.cnrm.gke.cluster | string | `""` | |
14-
| kubernetesConnection.cnrm.gke.connection | string | `""` | |
15-
| kubernetesConnection.cnrm.gke.credentials | object | `{}` | |
16-
| kubernetesConnection.cnrm.gke.endpoint | string | `""` | |
17-
| kubernetesConnection.cnrm.gke.projectID | string | `""` | |
18-
| kubernetesConnection.cnrm.gke.skipTLSVerify | bool | `false` | |
19-
| kubernetesConnection.cnrm.gke.zone | string | `""` | |
11+
| kubernetesConnection.cnrm | string | `nil` | |
2012
| kubernetesConnection.connection | string | `""` | |
21-
| kubernetesConnection.eks.accessKey | object | `{}` | |
22-
| kubernetesConnection.eks.assumeRole | string | `""` | |
23-
| kubernetesConnection.eks.cluster | string | `""` | |
24-
| kubernetesConnection.eks.connection | string | `""` | |
25-
| kubernetesConnection.eks.endpoint | string | `""` | |
26-
| kubernetesConnection.eks.region | string | `""` | |
27-
| kubernetesConnection.eks.secretKey | object | `{}` | |
28-
| kubernetesConnection.eks.sessionToken | object | `{}` | |
29-
| kubernetesConnection.eks.skipTLSVerify | bool | `false` | |
30-
| kubernetesConnection.gke.cluster | string | `""` | |
31-
| kubernetesConnection.gke.connection | string | `""` | |
32-
| kubernetesConnection.gke.credentials | object | `{}` | |
33-
| kubernetesConnection.gke.endpoint | string | `""` | |
34-
| kubernetesConnection.gke.projectID | string | `""` | |
35-
| kubernetesConnection.gke.skipTLSVerify | bool | `false` | |
36-
| kubernetesConnection.gke.zone | string | `""` | |
37-
| kubernetesConnection.kubeconfig | object | `{}` | |
13+
| kubernetesConnection.eks | string | `nil` | |
14+
| kubernetesConnection.gke | string | `nil` | |
15+
| kubernetesConnection.kubeconfig | string | `nil` | |
3816
| labels | object | `{}` | |
3917
| metrics.enabled | bool | `true` | |
4018
| metrics.queries | object | `{"gke":{"cluster_cpu":"1000 * sum(rate(kubernetes_io:container_cpu_core_usage_time{container_name!=\"\",cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}[5m]))","cluster_max_cpu":"1000 * sum(kubernetes_io:container_cpu_limit_cores{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}})","cluster_max_memory":"sum(kubernetes_io:container_memory_limit_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}})","cluster_memory":"sum(kubernetes_io:container_memory_used_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}})","cluster_name":"","namespace_cpu":"sum(rate(label_replace(kubernetes_io:container_cpu_core_usage_time{container_name!=\"\",cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"namespace\",\"$1\",\"namespace_name\", \"(.+)\")[5m])) by (namespace)","namespace_memory":"sum(label_replace(kubernetes_io:container_memory_used_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"namespace\",\"$1\",\"namespace_name\", \"(.+)\")) by (namespace)","node_cpu":"sum(rate(label_replace(kubernetes_io:node_cpu_core_usage_time{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"node\",\"$1\",\"node_name\", \"(.+)\")[5m:])) by (node)","node_memory":"sum(label_replace(kubernetes_io:container_memory_used_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"node\",\"$1\",\"node_name\", \"(.+)\")) by (node)","node_storage":"sum(label_replace(kubernetes_io:node_ephemeral_storage_used_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"node\",\"$1\",\"node_name\", \"(.+)\")) by (node)","pod_cpu":"sum(rate(label_replace(kubernetes_io:container_cpu_core_usage_time{container_name!=\"\",cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"pod\",\"$1\",\"pod_name\", \"(.+)\")[5m:])) by (pod)","pod_memory":"sum(label_replace(kubernetes_io:container_memory_used_bytes{cluster_name=\"{{.Values.metrics.queries.gke.cluster_name}}\"{{.Values.prometheus.labels}}}, \"pod\",\"$1\",\"pod_name\", \"(.+)\")) by (pod)"},"prometheus":{"cluster_cpu":"1000 * sum(rate(container_cpu_usage_seconds_total{container!=\"\"{{.Values.prometheus.labels}}}[5m]))","cluster_max_cpu":"1000 * sum(kube_pod_container_resource_limits{resource=\"cpu\"{{.Values.prometheus.labels}}})","cluster_max_memory":"sum(kube_pod_container_resource_limits{resource=\"memory\"{{.Values.prometheus.labels}}})","cluster_memory":"sum(container_memory_working_set_bytes{container!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}})","namespace_cpu":"1000 * sum(rate(container_cpu_usage_seconds_total{container!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}}[5m])) by (namespace)","namespace_memory":"sum(container_memory_working_set_bytes{container!=\"\",pod!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}} * on(pod, namespace) group_left kube_pod_status_phase{phase=\"Running\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}} > 0) by (namespace)","node_cpu":"1000 * sum(rate(container_cpu_usage_seconds_total{container!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}}[5m])) by (node)","node_memory":"sum(container_memory_working_set_bytes{container!=\"\",pod!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}} * on(pod, namespace) group_left kube_pod_status_phase{phase=\"Running\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}} > 0) by (node)","node_storage":"max by (instance) (avg_over_time(node_filesystem_avail_bytes{mountpoint=\"/\",fstype!=\"rootfs\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}}[5m]))","pod_cpu":"1000 * sum(rate(container_cpu_usage_seconds_total{container!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}}[5m])) by (pod)","pod_memory":"sum(container_memory_working_set_bytes{container!=\"\"{{.Values.prometheus.labels | default .Values.prometheusLabels}}}) by (pod)"}}` | queries to retrieve cpu/memory metrics for cluster/node/pod |
@@ -174,6 +152,13 @@ A Helm chart for the Kubernetes bundle of Flanksource Mission Control
174152
| topology.ingress.nameExpr | string | `"r.config.spec.rules.size() > 0 ? r.config.spec.rules[0].host : r.name"` | |
175153
| topology.name | string | `"{{ .Values.clusterName }}"` | |
176154
| topology.schedule | string | `"@every 5m"` | |
155+
| views.cluster.enabled | bool | `true` | |
156+
| views.cluster.sidebar | bool | `true` | |
157+
| views.enabled | bool | `true` | |
158+
| views.helm_releases.enabled | bool | `true` | |
159+
| views.helm_releases.sidebar | bool | `true` | |
160+
| views.pods.enabled | bool | `true` | if true, the view will be enabled A prometheus connection is required. |
161+
| views.pods.sidebar | bool | `true` | |
177162

178163
## Maintainers
179164

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{{- if and .Values.views.enabled .Values.views.helm_releases.enabled }}
2+
apiVersion: mission-control.flanksource.com/v1
3+
kind: View
4+
metadata:
5+
name: helm_releases
6+
labels:
7+
{{- include "kubernetes.labels" . | nindent 4 }}
8+
spec:
9+
display:
10+
title: Helm Releases
11+
icon: rocket
12+
{{- if .Values.views.helm_releases.sidebar }}
13+
sidebar: true
14+
{{- end }}
15+
panels:
16+
- name: Health
17+
description: Helm Releases grouped by health
18+
type: piechart
19+
piechart:
20+
showLabels: true
21+
colors:
22+
healthy: "#28C19B"
23+
unhealthy: "#F04E6E"
24+
unknown: "#666666"
25+
warning: "#F4B23C"
26+
query: SELECT COUNT(*) AS count, health FROM helm_releases GROUP BY health
27+
- name: Status
28+
description: Helm Releases grouped by status
29+
type: piechart
30+
piechart:
31+
colors:
32+
InstallSucceeded: "#28C19B"
33+
RollbackSucceeded: "#F4B23C"
34+
UpgradeFailed: "#F04E6E"
35+
UpgradeSucceeded: "#5965F2"
36+
Reconciling: "#666666"
37+
query: SELECT COUNT(*) AS count, status FROM helm_releases GROUP BY status
38+
columns:
39+
- name: id
40+
type: string
41+
description: The id of the deployment.
42+
primaryKey: true
43+
hidden: true
44+
- name: application
45+
type: string
46+
description: The application name.
47+
url:
48+
config: row.id
49+
- name: namespace
50+
type: string
51+
description: The namespace name.
52+
filter:
53+
type: multiselect
54+
url:
55+
config: f("name=$(tags.namespace) tags.cluster=$(tags.cluster) type=Kubernetes::Namespace", row)
56+
- name: chart
57+
type: string
58+
description: The chart name.
59+
- name: version
60+
type: string
61+
description: The version of the deployment.
62+
- name: status
63+
type: status
64+
description: The status of the deployment.
65+
filter:
66+
type: multiselect
67+
- name: health
68+
type: health
69+
description: The health of the deployment.
70+
filter:
71+
type: multiselect
72+
- name: lastUpdated
73+
type: datetime
74+
description: The last updated time.
75+
queries:
76+
helm_releases:
77+
configs:
78+
tagSelector: "cluster={{ .Values.clusterName }}"
79+
types:
80+
- Kubernetes::HelmRelease
81+
mapping:
82+
application: row.name
83+
namespace: row.tags.namespace
84+
chart: row.config.status.history[0].chartName
85+
version: row.config.status.history[0].chartVersion
86+
lastUpdated: row.updated_at
87+
{{- end }}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{{- if and .Values.views.enabled .Values.views.cluster.enabled .Values.prometheus.connection }}
2+
apiVersion: mission-control.flanksource.com/v1
3+
kind: View
4+
metadata:
5+
name: cluster-overview
6+
labels:
7+
{{- include "kubernetes-view.labels" . | nindent 4 }}
8+
spec:
9+
display:
10+
title: Cluster
11+
icon: overview
12+
{{- if .Values.views.cluster.sidebar }}
13+
sidebar: true
14+
{{- end }}
15+
plugins:
16+
- configTab:
17+
types:
18+
- Kubernetes::Cluster
19+
panels:
20+
- name: Resources
21+
description: Count of resources grouped by type
22+
type: table
23+
query: SELECT * FROM resource_count_by_type
24+
- name: Total CPU Cores
25+
description: Total CPU cores available
26+
type: number
27+
query: SELECT value FROM cpu_cores_count
28+
- name: Total Memory Available
29+
description: Total memory available (GB)
30+
type: number
31+
number:
32+
unit: GB
33+
precision: 2
34+
query: SELECT value FROM memory_available_count
35+
- name: Current Memory Usage
36+
description: Current memory usage (GB)
37+
type: number
38+
number:
39+
unit: GB
40+
query: SELECT value FROM memory_usage_count
41+
queries:
42+
cpu_cores_count:
43+
prometheus:
44+
connection: {{ .Values.prometheus.connection }}
45+
query: |
46+
sum(kube_node_status_allocatable{resource="cpu"})
47+
memory_available_count:
48+
prometheus:
49+
connection: {{ .Values.prometheus.connection }}
50+
query: |
51+
sum(kube_node_status_allocatable{resource="memory"}) / 1024 / 1024 / 1024
52+
memory_usage_count:
53+
prometheus:
54+
connection: {{ .Values.prometheus.connection }}
55+
query: |
56+
sum(container_memory_working_set_bytes{container!="POD"}) / 1024 / 1024 / 1024
57+
resource_count_by_type:
58+
prometheus:
59+
connection: {{ .Values.prometheus.connection }}
60+
query: |
61+
(label_replace(count(kube_node_info), "resource_type", "Nodes", "", "")) or
62+
(label_replace(count(kube_namespace_status_phase{phase="Active"}), "resource_type", "Namespaces", "", "")) or
63+
(label_replace(count(kube_pod_status_phase{phase="Running"}), "resource_type", "Running Pods", "", "")) or
64+
(label_replace(count(kube_deployment_status_replicas), "resource_type", "Deployments", "", "")) or
65+
(label_replace(count(kube_statefulset_status_replicas), "resource_type", "StatefulSets", "", "")) or
66+
(label_replace(count(kube_daemonset_status_number_ready), "resource_type", "DaemonSets", "", "")) or
67+
(label_replace(count(kube_persistentvolume_info), "resource_type", "Persistent Volumes", "", "")) or
68+
(label_replace(count(kube_persistentvolumeclaim_info), "resource_type", "Persistent Volume Claims", "", "")) or
69+
(label_replace(count(kube_ingress_info), "resource_type", "Ingresses", "", "")) or
70+
(label_replace(count(kube_cronjob_info), "resource_type", "CronJobs", "", ""))
71+
{{- end }}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{{- if and .Values.views.enabled .Values.views.pods.enabled .Values.prometheus.connection }}
2+
apiVersion: mission-control.flanksource.com/v1
3+
kind: View
4+
metadata:
5+
name: pods
6+
labels:
7+
{{- include "kubernetes.labels" . | nindent 4 }}
8+
spec:
9+
display:
10+
title: Pods
11+
icon: pod
12+
{{- if .Values.views.pods.sidebar }}
13+
sidebar: true
14+
{{- end }}
15+
columns:
16+
- name: namespace
17+
type: badge
18+
primaryKey: true
19+
filter:
20+
type: multiselect
21+
- name: name
22+
type: string
23+
primaryKey: true
24+
url:
25+
config: row.id
26+
- name: status
27+
type: status
28+
icon: row.health
29+
filter:
30+
type: multiselect
31+
- name: health
32+
type: health
33+
hidden: true
34+
filter:
35+
type: multiselect
36+
- name: memory
37+
type: gauge
38+
unit: bytes
39+
description: Memory usage
40+
gauge:
41+
max: row.memory_limit
42+
thresholds:
43+
- percent: 0
44+
color: green
45+
- percent: 50
46+
color: orange
47+
- percent: 80
48+
color: red
49+
- name: cpu
50+
type: gauge
51+
unit: millicore
52+
gauge:
53+
max: row.cpu_limit
54+
thresholds:
55+
- percent: 0
56+
color: '#8BC34A'
57+
- percent: 50
58+
color: '#FF8C42'
59+
- percent: 80
60+
color: '#E8589C'
61+
- name: updated_at
62+
type: datetime
63+
merge: |
64+
SELECT
65+
pod.id,
66+
pod.name,
67+
json_extract(pod.tags, '$.namespace') AS namespace,
68+
pod.status,
69+
pod.health,
70+
pod.updated_at,
71+
CAST(memory.value AS TEXT) as memory,
72+
to_bytes(COALESCE(
73+
json_extract(pod.config, '$.spec.containers[0].resources.limits.memory'),
74+
''
75+
)) AS memory_limit,
76+
COALESCE(CAST(cpu.value AS TEXT), '0') as cpu,
77+
to_millicores(COALESCE(
78+
json_extract(pod.config, '$.spec.containers[0].resources.limits.cpu'),
79+
''
80+
)) AS cpu_limit
81+
FROM pod
82+
LEFT JOIN memory
83+
ON pod.name = memory.pod
84+
AND json_extract(pod.tags, '$.namespace') = memory.namespace
85+
LEFT JOIN cpu
86+
ON pod.name = cpu.pod
87+
AND json_extract(pod.tags, '$.namespace') = cpu.namespace
88+
ORDER BY namespace, name
89+
queries:
90+
memory:
91+
columns:
92+
namespace: string
93+
pod: string
94+
value: decimal
95+
prometheus:
96+
connection: {{ .Values.prometheus.connection }}
97+
query: |
98+
sum by (namespace, pod) (
99+
container_memory_working_set_bytes{
100+
container!="POD", # Skip The pause/infra container
101+
image!="" # Skip dead containers
102+
}
103+
)
104+
cpu:
105+
columns:
106+
namespace: string
107+
pod: string
108+
value: decimal
109+
prometheus:
110+
connection: {{ .Values.prometheus.connection }}
111+
query: |
112+
sum by (namespace, pod) (
113+
irate(container_cpu_usage_seconds_total{
114+
container!="POD", # Skip The pause/infra container
115+
image!="" # Skip dead containers
116+
}[30s])
117+
) * 1000
118+
pod:
119+
configs:
120+
tagSelector: "cluster={{ .Values.clusterName }}"
121+
types:
122+
- Kubernetes::Pod
123+
mapping:
124+
created: row.created_at
125+
{{- end }}

0 commit comments

Comments
 (0)