jsonnet: create function responsible for node-exporter objects

This commit is contained in:
paulfantom
2021-01-05 15:15:44 +01:00
parent 19376df824
commit 5b8feb783c
3 changed files with 269 additions and 297 deletions

View File

@@ -1,5 +1,7 @@
local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonnet'; local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonnet';
local nodeExporter = import './node-exporter/node-exporter.libsonnet';
(import 'github.com/brancz/kubernetes-grafana/grafana/grafana.libsonnet') + (import 'github.com/brancz/kubernetes-grafana/grafana/grafana.libsonnet') +
(import './kube-state-metrics/kube-state-metrics.libsonnet') + (import './kube-state-metrics/kube-state-metrics.libsonnet') +
(import 'github.com/kubernetes/kube-state-metrics/jsonnet/kube-state-metrics-mixin/mixin.libsonnet') + (import 'github.com/kubernetes/kube-state-metrics/jsonnet/kube-state-metrics-mixin/mixin.libsonnet') +
@@ -16,6 +18,11 @@ local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonne
(import './alerts/alerts.libsonnet') + (import './alerts/alerts.libsonnet') +
(import './rules/rules.libsonnet') + (import './rules/rules.libsonnet') +
{ {
nodeExporter: nodeExporter({
namespace: $._config.namespace,
version: '1.0.1',
imageRepo: 'quay.io/prometheus/node-exporter',
}),
kubePrometheus+:: { kubePrometheus+:: {
namespace: { namespace: {
apiVersion: 'v1', apiVersion: 'v1',
@@ -83,7 +90,6 @@ local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonne
}, },
}).deploymentMixin, }).deploymentMixin,
grafana+:: { grafana+:: {
local dashboardDefinitions = super.dashboardDefinitions, local dashboardDefinitions = super.dashboardDefinitions,
@@ -196,10 +202,6 @@ local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonne
requests: { cpu: '100m', memory: '150Mi' }, requests: { cpu: '100m', memory: '150Mi' },
limits: { cpu: '100m', memory: '150Mi' }, limits: { cpu: '100m', memory: '150Mi' },
}, },
'node-exporter': {
requests: { cpu: '102m', memory: '180Mi' },
limits: { cpu: '250m', memory: '180Mi' },
},
}, },
prometheus+:: { rules: $.prometheusRules + $.prometheusAlerts }, prometheus+:: { rules: $.prometheusRules + $.prometheusAlerts },
grafana+:: { grafana+:: {

View File

@@ -1,93 +1,64 @@
{ local defaults = {
local krp = self, local defaults = self,
config+:: { namespace: error 'must provide namespace',
kubeRbacProxy: { image: 'quay.io/brancz/kube-rbac-proxy:v0.8.0',
image: error 'must provide image', ports: error 'must provide ports',
name: error 'must provide name',
securePortName: error 'must provide securePortName',
securePort: error 'must provide securePort',
secureListenAddress: error 'must provide secureListenAddress', secureListenAddress: error 'must provide secureListenAddress',
upstream: error 'must provide upstream', upstream: error 'must provide upstream',
tlsCipherSuites: error 'must provide tlsCipherSuites', resources: {
}, requests: { cpu: '10m', memory: '20Mi' },
limits: { cpu: '20m', memory: '40Mi' },
}, },
tlsCipherSuites: [
'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', // required by h2: http://golang.org/cl/30721
'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', // required by h2: http://golang.org/cl/30721
specMixin:: { // 'TLS_RSA_WITH_RC4_128_SHA', // insecure: https://access.redhat.com/security/cve/cve-2013-2566
local sm = self, // 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', // insecure: https://access.redhat.com/articles/2548661
config+:: { // 'TLS_RSA_WITH_AES_128_CBC_SHA', // disabled by h2
kubeRbacProxy: { // 'TLS_RSA_WITH_AES_256_CBC_SHA', // disabled by h2
image: error 'must provide image', // 'TLS_RSA_WITH_AES_128_CBC_SHA256', // insecure: https://access.redhat.com/security/cve/cve-2013-0169
name: error 'must provide name', // 'TLS_RSA_WITH_AES_128_GCM_SHA256', // disabled by h2
securePortName: error 'must provide securePortName', // 'TLS_RSA_WITH_AES_256_GCM_SHA384', // disabled by h2
securePort: error 'must provide securePort', // 'TLS_ECDHE_ECDSA_WITH_RC4_128_SHA', // insecure: https://access.redhat.com/security/cve/cve-2013-2566
secureListenAddress: error 'must provide secureListenAddress', // 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA', // disabled by h2
upstream: error 'must provide upstream', // 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA', // disabled by h2
tlsCipherSuites: error 'must provide tlsCipherSuites', // 'TLS_ECDHE_RSA_WITH_RC4_128_SHA', // insecure: https://access.redhat.com/security/cve/cve-2013-2566
}, // 'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA', // insecure: https://access.redhat.com/articles/2548661
}, // 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', // disabled by h2
spec+: { // 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', // disabled by h2
template+: { // 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256', // insecure: https://access.redhat.com/security/cve/cve-2013-0169
spec+: { // 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', // insecure: https://access.redhat.com/security/cve/cve-2013-0169
containers+: [{
name: krp.config.kubeRbacProxy.name, // disabled by h2 means: https://github.com/golang/net/blob/e514e69ffb8bc3c76a71ae40de0118d794855992/http2/ciphers.go
image: krp.config.kubeRbacProxy.image,
'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',
'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305',
'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305',
],
};
function(params) {
local krp = self,
config:: defaults + params,
// Safety check
assert std.isObject(krp.config.resources),
name: krp.config.name,
image: krp.config.image,
args: [ args: [
'--logtostderr', '--logtostderr',
'--secure-listen-address=' + krp.config.kubeRbacProxy.secureListenAddress, '--secure-listen-address=' + krp.config.secureListenAddress,
'--tls-cipher-suites=' + std.join(',', krp.config.kubeRbacProxy.tlsCipherSuites), '--tls-cipher-suites=' + std.join(',', krp.config.tlsCipherSuites),
'--upstream=' + krp.config.kubeRbacProxy.upstream, '--upstream=' + krp.config.upstream,
],
ports: [
{ name: krp.config.kubeRbacProxy.securePortName, containerPort: krp.config.kubeRbacProxy.securePort },
], ],
resources: krp.config.resources,
ports: krp.config.ports,
securityContext: { securityContext: {
runAsUser: 65532, runAsUser: 65532,
runAsGroup: 65532, runAsGroup: 65532,
runAsNonRoot: true, runAsNonRoot: true,
}, },
}],
},
},
},
},
deploymentMixin:: {
local dm = self,
config+:: {
kubeRbacProxy: {
image: error 'must provide image',
name: error 'must provide name',
securePortName: error 'must provide securePortName',
securePort: error 'must provide securePort',
secureListenAddress: error 'must provide secureListenAddress',
upstream: error 'must provide upstream',
tlsCipherSuites: error 'must provide tlsCipherSuites',
},
},
deployment+: krp.specMixin {
config+:: {
kubeRbacProxy+: dm.config.kubeRbacProxy,
},
},
},
statefulSetMixin:: {
local sm = self,
config+:: {
kubeRbacProxy: {
image: error 'must provide image',
name: error 'must provide name',
securePortName: error 'must provide securePortName',
securePort: error 'must provide securePort',
secureListenAddress: error 'must provide secureListenAddress',
upstream: error 'must provide upstream',
tlsCipherSuites: error 'must provide tlsCipherSuites',
},
},
statefulSet+: krp.specMixin {
config+:: {
kubeRbacProxy+: sm.config.kubeRbacProxy,
},
},
},
} }

View File

@@ -1,33 +1,43 @@
{ local krp = (import '../kube-rbac-proxy/container.libsonnet');
_config+:: {
namespace: 'default',
versions+:: { nodeExporter: 'v1.0.1' },
imageRepos+:: { nodeExporter: 'quay.io/prometheus/node-exporter' },
nodeExporter+:: { local defaults = {
local defaults = self,
namespace: error 'must provide namespace',
version: error 'must provide version',
imageRepo: error 'must provide version',
// image: "",
resources: {
requests: { cpu: '102m', memory: '180Mi' },
limits: { cpu: '250m', memory: '180Mi' },
},
listenAddress: '127.0.0.1', listenAddress: '127.0.0.1',
port: 9100, port: 9100,
labels: { commonLabels:: {
'app.kubernetes.io/name': 'node-exporter', 'app.kubernetes.io/name': 'node-exporter',
'app.kubernetes.io/version': $._config.versions.nodeExporter, 'app.kubernetes.io/version': defaults.version,
'app.kubernetes.io/component': 'exporter', 'app.kubernetes.io/component': 'exporter',
'app.kubernetes.io/part-of': 'kube-prometheus', 'app.kubernetes.io/part-of': 'kube-prometheus',
}, },
selectorLabels: { selectorLabels:: {
[labelName]: $._config.nodeExporter.labels[labelName] [labelName]: defaults.commonLabels[labelName]
for labelName in std.objectFields($._config.nodeExporter.labels) for labelName in std.objectFields(defaults.commonLabels)
if !std.setMember(labelName, ['app.kubernetes.io/version']) if !std.setMember(labelName, ['app.kubernetes.io/version'])
}, },
}, };
},
function(params) {
local ne = self,
config:: defaults + params,
// Safety check
assert std.isObject(ne.config.resources),
nodeExporter+:: {
clusterRoleBinding: { clusterRoleBinding: {
apiVersion: 'rbac.authorization.k8s.io/v1', apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'ClusterRoleBinding', kind: 'ClusterRoleBinding',
metadata: { metadata: {
name: 'node-exporter', name: 'node-exporter',
labels: $._config.nodeExporter.labels, labels: ne.config.commonLabels,
}, },
roleRef: { roleRef: {
apiGroup: 'rbac.authorization.k8s.io', apiGroup: 'rbac.authorization.k8s.io',
@@ -37,7 +47,7 @@
subjects: [{ subjects: [{
kind: 'ServiceAccount', kind: 'ServiceAccount',
name: 'node-exporter', name: 'node-exporter',
namespace: $._config.namespace, namespace: ne.config.namespace,
}], }],
}, },
@@ -46,7 +56,7 @@
kind: 'ClusterRole', kind: 'ClusterRole',
metadata: { metadata: {
name: 'node-exporter', name: 'node-exporter',
labels: $._config.nodeExporter.labels, labels: ne.config.commonLabels,
}, },
rules: [ rules: [
{ {
@@ -58,96 +68,7 @@
apiGroups: ['authorization.k8s.io'], apiGroups: ['authorization.k8s.io'],
resources: ['subjectaccessreviews'], resources: ['subjectaccessreviews'],
verbs: ['create'], verbs: ['create'],
},
],
},
daemonset:
local nodeExporter = {
name: 'node-exporter',
image: $._config.imageRepos.nodeExporter + ':' + $._config.versions.nodeExporter,
args: [
'--web.listen-address=' + std.join(':', [$._config.nodeExporter.listenAddress, std.toString($._config.nodeExporter.port)]),
'--path.sysfs=/host/sys',
'--path.rootfs=/host/root',
'--no-collector.wifi',
'--no-collector.hwmon',
'--collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/)',
],
volumeMounts: [
{ name: 'sys', mountPath: '/host/sys', mountPropagation: 'HostToContainer', readOnly: true },
{ name: 'root', mountPath: '/host/root', mountPropagation: 'HostToContainer', readOnly: true },
],
resources: $._config.resources['node-exporter'],
};
local proxy = {
name: 'kube-rbac-proxy',
image: $._config.imageRepos.kubeRbacProxy + ':' + $._config.versions.kubeRbacProxy,
args: [
'--logtostderr',
'--secure-listen-address=[$(IP)]:' + $._config.nodeExporter.port,
'--tls-cipher-suites=' + std.join(',', $._config.tlsCipherSuites),
'--upstream=http://127.0.0.1:' + $._config.nodeExporter.port + '/',
],
env: [
{ name: 'IP', valueFrom: { fieldRef: { fieldPath: 'status.podIP' } } },
],
// Keep `hostPort` here, rather than in the node-exporter container
// because Kubernetes mandates that if you define a `hostPort` then
// `containerPort` must match. In our case, we are splitting the
// host port and container port between the two containers.
// We'll keep the port specification here so that the named port
// used by the service is tied to the proxy container. We *could*
// forgo declaring the host port, however it is important to declare
// it so that the scheduler can decide if the pod is schedulable.
ports: [
{ name: 'https', containerPort: $._config.nodeExporter.port, hostPort: $._config.nodeExporter.port },
],
resources: $._config.resources['kube-rbac-proxy'],
securityContext: {
runAsUser: 65532,
runAsGroup: 65532,
runAsNonRoot: true,
},
};
{
apiVersion: 'apps/v1',
kind: 'DaemonSet',
metadata: {
name: 'node-exporter',
namespace: $._config.namespace,
labels: $._config.nodeExporter.labels,
},
spec: {
selector: { matchLabels: $._config.nodeExporter.selectorLabels },
updateStrategy: {
type: 'RollingUpdate',
rollingUpdate: { maxUnavailable: '10%' },
},
template: {
metadata: { labels: $._config.nodeExporter.labels },
spec: {
nodeSelector: { 'kubernetes.io/os': 'linux' },
tolerations: [{
operator: 'Exists',
}], }],
containers: [nodeExporter, proxy],
volumes: [
{ name: 'sys', hostPath: { path: '/sys' } },
{ name: 'root', hostPath: { path: '/' } },
],
serviceAccountName: 'node-exporter',
securityContext: {
runAsUser: 65534,
runAsNonRoot: true,
},
hostPID: true,
hostNetwork: true,
},
},
},
}, },
serviceAccount: { serviceAccount: {
@@ -155,8 +76,25 @@
kind: 'ServiceAccount', kind: 'ServiceAccount',
metadata: { metadata: {
name: 'node-exporter', name: 'node-exporter',
namespace: $._config.namespace, namespace: ne.config.namespace,
labels: $._config.nodeExporter.labels, labels: ne.config.commonLabels,
},
},
service: {
apiVersion: 'v1',
kind: 'Service',
metadata: {
name: 'node-exporter',
namespace: ne.config.namespace,
labels: ne.config.commonLabels,
},
spec: {
ports: [
{ name: 'https', targetPort: 'https', port: ne.config.port },
],
selector: ne.config.selectorLabels,
clusterIP: 'None',
}, },
}, },
@@ -165,13 +103,13 @@
kind: 'ServiceMonitor', kind: 'ServiceMonitor',
metadata: { metadata: {
name: 'node-exporter', name: 'node-exporter',
namespace: $._config.namespace, namespace: ne.config.namespace,
labels: $._config.nodeExporter.labels, labels: ne.config.commonLabels,
}, },
spec: { spec: {
jobLabel: 'app.kubernetes.io/name', jobLabel: 'app.kubernetes.io/name',
selector: { selector: {
matchLabels: $._config.nodeExporter.selectorLabels, matchLabels: ne.config.selectorLabels,
}, },
endpoints: [{ endpoints: [{
port: 'https', port: 'https',
@@ -194,20 +132,81 @@
}, },
}, },
service: { daemonset:
apiVersion: 'v1', local nodeExporter = {
kind: 'Service', name: 'node-exporter',
image: ne.config.imageRepo + ':v' + ne.config.version,
args: [
'--web.listen-address=' + std.join(':', [ne.config.listenAddress, std.toString(ne.config.port)]),
'--path.sysfs=/host/sys',
'--path.rootfs=/host/root',
'--no-collector.wifi',
'--no-collector.hwmon',
'--collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/)',
],
volumeMounts: [
{ name: 'sys', mountPath: '/host/sys', mountPropagation: 'HostToContainer', readOnly: true },
{ name: 'root', mountPath: '/host/root', mountPropagation: 'HostToContainer', readOnly: true },
],
resources: ne.config.resources,
};
local kubeRbacProxy = krp({
name: 'kube-rbac-proxy',
//image: krpImage,
upstream: 'http://127.0.0.1:' + ne.config.port + '/',
secureListenAddress: '[$(IP)]:' + ne.config.port,
// Keep `hostPort` here, rather than in the node-exporter container
// because Kubernetes mandates that if you define a `hostPort` then
// `containerPort` must match. In our case, we are splitting the
// host port and container port between the two containers.
// We'll keep the port specification here so that the named port
// used by the service is tied to the proxy container. We *could*
// forgo declaring the host port, however it is important to declare
// it so that the scheduler can decide if the pod is schedulable.
ports: [
{ name: 'https', containerPort: ne.config.port, hostPort: ne.config.port },
],
}) + {
env: [
{ name: 'IP', valueFrom: { fieldRef: { fieldPath: 'status.podIP' } } },
]
};
{
apiVersion: 'apps/v1',
kind: 'DaemonSet',
metadata: { metadata: {
name: 'node-exporter', name: 'node-exporter',
namespace: $._config.namespace, namespace: ne.config.namespace,
labels: $._config.nodeExporter.labels, labels: ne.config.commonLabels,
}, },
spec: { spec: {
ports: [ selector: { matchLabels: ne.config.selectorLabels },
{ name: 'https', targetPort: 'https', port: $._config.nodeExporter.port }, updateStrategy: {
type: 'RollingUpdate',
rollingUpdate: { maxUnavailable: '10%' },
},
template: {
metadata: { labels: ne.config.commonLabels },
spec: {
nodeSelector: { 'kubernetes.io/os': 'linux' },
tolerations: [{
operator: 'Exists',
}],
containers: [nodeExporter, kubeRbacProxy],
volumes: [
{ name: 'sys', hostPath: { path: '/sys' } },
{ name: 'root', hostPath: { path: '/' } },
], ],
selector: $._config.nodeExporter.selectorLabels, serviceAccountName: 'node-exporter',
clusterIP: 'None', securityContext: {
runAsUser: 65534,
runAsNonRoot: true,
},
hostPID: true,
hostNetwork: true,
},
}, },
}, },
}, },