diff --git a/jsonnet/kube-prometheus/kube-prometheus.libsonnet b/jsonnet/kube-prometheus/kube-prometheus.libsonnet
index 67bea5a8c9585811ab95722ac0ebe4ec479348a1..443511d6c199f8fc2559a1502a86b27333417440 100644
--- a/jsonnet/kube-prometheus/kube-prometheus.libsonnet
+++ b/jsonnet/kube-prometheus/kube-prometheus.libsonnet
@@ -3,6 +3,8 @@ local kubeRbacProxyContainer = import './kube-rbac-proxy/containerMixin.libsonne
 local nodeExporter = import './node-exporter/node-exporter.libsonnet';
 local alertmanager = import './alertmanager/alertmanager.libsonnet';
 
+local prometheusAdapter = import './prometheus-adapter/prometheus-adapter.libsonnet';
+
 (import 'github.com/brancz/kubernetes-grafana/grafana/grafana.libsonnet') +
 (import './kube-state-metrics/kube-state-metrics.libsonnet') +
 (import 'github.com/kubernetes/kube-state-metrics/jsonnet/kube-state-metrics-mixin/mixin.libsonnet') +
@@ -12,7 +14,6 @@ local alertmanager = import './alertmanager/alertmanager.libsonnet';
 (import 'github.com/prometheus-operator/prometheus-operator/jsonnet/prometheus-operator/prometheus-operator.libsonnet') +
 (import 'github.com/prometheus-operator/prometheus-operator/jsonnet/mixin/mixin.libsonnet') +
 (import './prometheus/prometheus.libsonnet') +
-(import './prometheus-adapter/prometheus-adapter.libsonnet') +
 (import 'github.com/kubernetes-monitoring/kubernetes-mixin/mixin.libsonnet') +
 (import 'github.com/prometheus/prometheus/documentation/prometheus-mixin/mixin.libsonnet') +
 (import './alerts/alerts.libsonnet') +
@@ -29,6 +30,12 @@ local alertmanager = import './alertmanager/alertmanager.libsonnet';
     version: '0.21.0',
     image: 'quay.io/prometheus/alertmanager:v0.21.0',
   }),
+  prometheusAdapter: prometheusAdapter({
+    namespace: $._config.namespace,
+    version: '0.8.2',
+    image: 'directxman12/k8s-prometheus-adapter:v0.8.2',
+    prometheusURL: 'http://prometheus-' + $._config.prometheus.name + '.' + $._config.namespace + '.svc.cluster.local:9090/',
+  }),
   kubePrometheus+:: {
     namespace: {
       apiVersion: 'v1',
diff --git a/jsonnet/kube-prometheus/prometheus-adapter/prometheus-adapter.libsonnet b/jsonnet/kube-prometheus/prometheus-adapter/prometheus-adapter.libsonnet
index 55950bf0cb8e0abecbb7cf613b0ea07e19bde775..4dceb06f396f8c6a3a23a9ea3eb4ea93f244fd42 100644
--- a/jsonnet/kube-prometheus/prometheus-adapter/prometheus-adapter.libsonnet
+++ b/jsonnet/kube-prometheus/prometheus-adapter/prometheus-adapter.libsonnet
@@ -1,191 +1,198 @@
-{
-  _config+:: {
-    namespace: 'default',
-
-    versions+:: { prometheusAdapter: 'v0.8.2' },
-    imageRepos+:: { prometheusAdapter: 'directxman12/k8s-prometheus-adapter' },
+local defaults = {
+  local defaults = self,
+  name: 'prometheus-adapter',
+  namespace: error 'must provide namespace',
+  version: error 'must provide version',
+  image: error 'must provide image',
+  resources: {
+    requests: { cpu: '102m', memory: '180Mi' },
+    limits: { cpu: '250m', memory: '180Mi' },
+  },
+  listenAddress: '127.0.0.1',
+  port: 9100,
+  commonLabels:: {
+    'app.kubernetes.io/name': 'prometheus-adapter',
+    'app.kubernetes.io/version': defaults.version,
+    'app.kubernetes.io/component': 'metrics-adapter',
+    'app.kubernetes.io/part-of': 'kube-prometheus',
+  },
+  selectorLabels:: {
+    [labelName]: defaults.commonLabels[labelName]
+    for labelName in std.objectFields(defaults.commonLabels)
+    if !std.setMember(labelName, ['app.kubernetes.io/version'])
+  },
 
-    prometheusAdapter+:: {
-      name: 'prometheus-adapter',
-      namespace: $._config.namespace,
-      labels: {
-        'app.kubernetes.io/name': 'prometheus-adapter',
-        'app.kubernetes.io/version': $._config.versions.prometheusAdapter,
-        'app.kubernetes.io/component': 'metrics-adapter',
-        'app.kubernetes.io/part-of': 'kube-prometheus',
-      },
-      selectorLabels: {
-        [labelName]: $._config.prometheusAdapter.labels[labelName]
-        for labelName in std.objectFields($._config.prometheusAdapter.labels)
-        if !std.setMember(labelName, ['app.kubernetes.io/version'])
-      },
-      prometheusURL: 'http://prometheus-' + $._config.prometheus.name + '.' + $._config.namespace + '.svc.cluster.local:9090/',
-      config: {
-        resourceRules: {
-          cpu: {
-            containerQuery: 'sum(irate(container_cpu_usage_seconds_total{<<.LabelMatchers>>,container!="POD",container!="",pod!=""}[5m])) by (<<.GroupBy>>)',
-            nodeQuery: 'sum(1 - irate(node_cpu_seconds_total{mode="idle"}[5m]) * on(namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{<<.LabelMatchers>>}) by (<<.GroupBy>>)',
-            resources: {
-              overrides: {
-                node: { resource: 'node' },
-                namespace: { resource: 'namespace' },
-                pod: { resource: 'pod' },
-              },
-            },
-            containerLabel: 'container',
+  prometheusURL: error 'must provide prometheusURL',
+  config: {
+    resourceRules: {
+      cpu: {
+        containerQuery: 'sum(irate(container_cpu_usage_seconds_total{<<.LabelMatchers>>,container!="POD",container!="",pod!=""}[5m])) by (<<.GroupBy>>)',
+        nodeQuery: 'sum(1 - irate(node_cpu_seconds_total{mode="idle"}[5m]) * on(namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{<<.LabelMatchers>>}) by (<<.GroupBy>>)',
+        resources: {
+          overrides: {
+            node: { resource: 'node' },
+            namespace: { resource: 'namespace' },
+            pod: { resource: 'pod' },
           },
-          memory: {
-            containerQuery: 'sum(container_memory_working_set_bytes{<<.LabelMatchers>>,container!="POD",container!="",pod!=""}) by (<<.GroupBy>>)',
-            nodeQuery: 'sum(node_memory_MemTotal_bytes{job="node-exporter",<<.LabelMatchers>>} - node_memory_MemAvailable_bytes{job="node-exporter",<<.LabelMatchers>>}) by (<<.GroupBy>>)',
-            resources: {
-              overrides: {
-                instance: { resource: 'node' },
-                namespace: { resource: 'namespace' },
-                pod: { resource: 'pod' },
-              },
-            },
-            containerLabel: 'container',
+        },
+        containerLabel: 'container',
+      },
+      memory: {
+        containerQuery: 'sum(container_memory_working_set_bytes{<<.LabelMatchers>>,container!="POD",container!="",pod!=""}) by (<<.GroupBy>>)',
+        nodeQuery: 'sum(node_memory_MemTotal_bytes{job="node-exporter",<<.LabelMatchers>>} - node_memory_MemAvailable_bytes{job="node-exporter",<<.LabelMatchers>>}) by (<<.GroupBy>>)',
+        resources: {
+          overrides: {
+            instance: { resource: 'node' },
+            namespace: { resource: 'namespace' },
+            pod: { resource: 'pod' },
           },
-          window: '5m',
         },
+        containerLabel: 'container',
       },
+      window: '5m',
     },
   },
+};
 
-  prometheusAdapter+:: {
-    apiService: {
-      apiVersion: 'apiregistration.k8s.io/v1',
-      kind: 'APIService',
-      metadata: {
-        name: 'v1beta1.metrics.k8s.io',
-        labels: $._config.prometheusAdapter.labels,
-      },
-      spec: {
-        service: {
-          name: $.prometheusAdapter.service.metadata.name,
-          namespace: $._config.prometheusAdapter.namespace,
-        },
-        group: 'metrics.k8s.io',
-        version: 'v1beta1',
-        insecureSkipTLSVerify: true,
-        groupPriorityMinimum: 100,
-        versionPriority: 100,
+function(params) {
+  local pa = self,
+  config:: defaults + params,
+  // Safety check
+  assert std.isObject(pa.config.resources),
+
+  apiService: {
+    apiVersion: 'apiregistration.k8s.io/v1',
+    kind: 'APIService',
+    metadata: {
+      name: 'v1beta1.metrics.k8s.io',
+      labels: pa.config.commonLabels,
+    },
+    spec: {
+      service: {
+        name: $.service.metadata.name,
+        namespace: pa.config.namespace,
       },
+      group: 'metrics.k8s.io',
+      version: 'v1beta1',
+      insecureSkipTLSVerify: true,
+      groupPriorityMinimum: 100,
+      versionPriority: 100,
     },
+  },
 
-    configMap: {
-      apiVersion: 'v1',
-      kind: 'ConfigMap',
-      metadata: {
-        name: 'adapter-config',
-        namespace: $._config.prometheusAdapter.namespace,
-        labels: $._config.prometheusAdapter.labels,
-      },
-      data: { 'config.yaml': std.manifestYamlDoc($._config.prometheusAdapter.config) },
+  configMap: {
+    apiVersion: 'v1',
+    kind: 'ConfigMap',
+    metadata: {
+      name: 'adapter-config',
+      namespace: pa.config.namespace,
+      labels: pa.config.commonLabels,
     },
+    data: { 'config.yaml': std.manifestYamlDoc(pa.config.config) },
+  },
 
-    serviceMonitor: {
-      apiVersion: 'monitoring.coreos.com/v1',
-      kind: 'ServiceMonitor',
-      metadata: {
-        name: $._config.prometheusAdapter.name,
-        namespace: $._config.prometheusAdapter.namespace,
-        labels: $._config.prometheusAdapter.labels,
+  serviceMonitor: {
+    apiVersion: 'monitoring.coreos.com/v1',
+    kind: 'ServiceMonitor',
+    metadata: {
+      name: pa.config.name,
+      namespace: pa.config.namespace,
+      labels: pa.config.commonLabels,
+    },
+    spec: {
+      selector: {
+        matchLabels: pa.config.selectorLabels,
       },
-      spec: {
-        selector: {
-          matchLabels: $._config.prometheusAdapter.selectorLabels,
-        },
-        endpoints: [
-          {
-            port: 'https',
-            interval: '30s',
-            scheme: 'https',
-            tlsConfig: {
-              insecureSkipVerify: true,
-            },
-            bearerTokenFile: '/var/run/secrets/kubernetes.io/serviceaccount/token',
+      endpoints: [
+        {
+          port: 'https',
+          interval: '30s',
+          scheme: 'https',
+          tlsConfig: {
+            insecureSkipVerify: true,
           },
-        ],
-      },
+          bearerTokenFile: '/var/run/secrets/kubernetes.io/serviceaccount/token',
+        },
+      ],
     },
+  },
 
-    service: {
-      apiVersion: 'v1',
-      kind: 'Service',
-      metadata: {
-        name: $._config.prometheusAdapter.name,
-        namespace: $._config.prometheusAdapter.namespace,
-        labels: $._config.prometheusAdapter.labels,
-      },
-      spec: {
-        ports: [
-          { name: 'https', targetPort: 6443, port: 443 },
-        ],
-        selector: $._config.prometheusAdapter.selectorLabels,
-      },
+  service: {
+    apiVersion: 'v1',
+    kind: 'Service',
+    metadata: {
+      name: pa.config.name,
+      namespace: pa.config.namespace,
+      labels: pa.config.commonLabels,
+    },
+    spec: {
+      ports: [
+        { name: 'https', targetPort: 6443, port: 443 },
+      ],
+      selector: pa.config.selectorLabels,
     },
+  },
 
-    deployment:
-      local c = {
-        name: $._config.prometheusAdapter.name,
-        image: $._config.imageRepos.prometheusAdapter + ':' + $._config.versions.prometheusAdapter,
-        args: [
-          '--cert-dir=/var/run/serving-cert',
-          '--config=/etc/adapter/config.yaml',
-          '--logtostderr=true',
-          '--metrics-relist-interval=1m',
-          '--prometheus-url=' + $._config.prometheusAdapter.prometheusURL,
-          '--secure-port=6443',
-        ],
-        ports: [{ containerPort: 6443 }],
-        volumeMounts: [
-          { name: 'tmpfs', mountPath: '/tmp', readOnly: false },
-          { name: 'volume-serving-cert', mountPath: '/var/run/serving-cert', readOnly: false },
-          { name: 'config', mountPath: '/etc/adapter', readOnly: false },
-        ],
-      };
+  deployment:
+    local c = {
+      name: pa.config.name,
+      image: pa.config.image,
+      args: [
+        '--cert-dir=/var/run/serving-cert',
+        '--config=/etc/adapter/config.yaml',
+        '--logtostderr=true',
+        '--metrics-relist-interval=1m',
+        '--prometheus-url=' + pa.config.prometheusURL,
+        '--secure-port=6443',
+      ],
+      ports: [{ containerPort: 6443 }],
+      volumeMounts: [
+        { name: 'tmpfs', mountPath: '/tmp', readOnly: false },
+        { name: 'volume-serving-cert', mountPath: '/var/run/serving-cert', readOnly: false },
+        { name: 'config', mountPath: '/etc/adapter', readOnly: false },
+      ],
+    };
 
-      {
-        apiVersion: 'apps/v1',
-        kind: 'Deployment',
-        metadata: {
-          name: $._config.prometheusAdapter.name,
-          namespace: $._config.prometheusAdapter.namespace,
-          labels: $._config.prometheusAdapter.labels,
-        },
-        spec: {
-          replicas: 1,
-          selector: { matchLabels: $._config.prometheusAdapter.selectorLabels },
-          strategy: {
-            rollingUpdate: {
-              maxSurge: 1,
-              maxUnavailable: 0,
-            },
+    {
+      apiVersion: 'apps/v1',
+      kind: 'Deployment',
+      metadata: {
+        name: pa.config.name,
+        namespace: pa.config.namespace,
+        labels: pa.config.commonLabels,
+      },
+      spec: {
+        replicas: 1,
+        selector: { matchLabels: pa.config.selectorLabels },
+        strategy: {
+          rollingUpdate: {
+            maxSurge: 1,
+            maxUnavailable: 0,
           },
-          template: {
-            metadata: { labels: $._config.prometheusAdapter.labels },
-            spec: {
-              containers: [c],
-              serviceAccountName: $.prometheusAdapter.serviceAccount.metadata.name,
-              nodeSelector: { 'kubernetes.io/os': 'linux' },
-              volumes: [
-                { name: 'tmpfs', emptyDir: {} },
-                { name: 'volume-serving-cert', emptyDir: {} },
-                { name: 'config', configMap: { name: 'adapter-config' } },
-              ],
-            },
+        },
+        template: {
+          metadata: { labels: pa.config.commonLabels },
+          spec: {
+            containers: [c],
+            serviceAccountName: $.serviceAccount.metadata.name,
+            nodeSelector: { 'kubernetes.io/os': 'linux' },
+            volumes: [
+              { name: 'tmpfs', emptyDir: {} },
+              { name: 'volume-serving-cert', emptyDir: {} },
+              { name: 'config', configMap: { name: 'adapter-config' } },
+            ],
           },
         },
       },
+    },
 
     serviceAccount: {
       apiVersion: 'v1',
       kind: 'ServiceAccount',
       metadata: {
-        name: $._config.prometheusAdapter.name,
-        namespace: $._config.prometheusAdapter.namespace,
-        labels: $._config.prometheusAdapter.labels,
+        name: pa.config.name,
+        namespace: pa.config.namespace,
+        labels: pa.config.commonLabels,
       },
     },
 
@@ -193,8 +200,8 @@
       apiVersion: 'rbac.authorization.k8s.io/v1',
       kind: 'ClusterRole',
       metadata: {
-        name: $._config.prometheusAdapter.name,
-        labels: $._config.prometheusAdapter.labels,
+        name: pa.config.name,
+        labels: pa.config.commonLabels,
       },
       rules: [{
         apiGroups: [''],
@@ -207,18 +214,18 @@
       apiVersion: 'rbac.authorization.k8s.io/v1',
       kind: 'ClusterRoleBinding',
       metadata: {
-        name: $._config.prometheusAdapter.name,
-        labels: $._config.prometheusAdapter.labels,
+        name: pa.config.name,
+        labels: pa.config.commonLabels,
       },
       roleRef: {
         apiGroup: 'rbac.authorization.k8s.io',
         kind: 'ClusterRole',
-        name: $.prometheusAdapter.clusterRole.metadata.name,
+        name: $.clusterRole.metadata.name,
       },
       subjects: [{
         kind: 'ServiceAccount',
-        name: $.prometheusAdapter.serviceAccount.metadata.name,
-        namespace: $._config.prometheusAdapter.namespace,
+        name: $.serviceAccount.metadata.name,
+        namespace: pa.config.namespace,
       }],
     },
 
@@ -227,7 +234,7 @@
       kind: 'ClusterRoleBinding',
       metadata: {
         name: 'resource-metrics:system:auth-delegator',
-        labels: $._config.prometheusAdapter.labels,
+        labels: pa.config.commonLabels,
       },
       roleRef: {
         apiGroup: 'rbac.authorization.k8s.io',
@@ -236,8 +243,8 @@
       },
       subjects: [{
         kind: 'ServiceAccount',
-        name: $.prometheusAdapter.serviceAccount.metadata.name,
-        namespace: $._config.prometheusAdapter.namespace,
+        name: $.serviceAccount.metadata.name,
+        namespace: pa.config.namespace,
       }],
     },
 
@@ -246,7 +253,7 @@
       kind: 'ClusterRole',
       metadata: {
         name: 'resource-metrics-server-resources',
-        labels: $._config.prometheusAdapter.labels,
+        labels: pa.config.commonLabels,
       },
       rules: [{
         apiGroups: ['metrics.k8s.io'],
@@ -264,7 +271,7 @@
           'rbac.authorization.k8s.io/aggregate-to-admin': 'true',
           'rbac.authorization.k8s.io/aggregate-to-edit': 'true',
           'rbac.authorization.k8s.io/aggregate-to-view': 'true',
-        } + $._config.prometheusAdapter.labels,
+        } + pa.config.commonLabels,
       },
       rules: [{
         apiGroups: ['metrics.k8s.io'],
@@ -279,7 +286,7 @@
       metadata: {
         name: 'resource-metrics-auth-reader',
         namespace: 'kube-system',
-        labels: $._config.prometheusAdapter.labels,
+        labels: pa.config.commonLabels,
       },
       roleRef: {
         apiGroup: 'rbac.authorization.k8s.io',
@@ -288,9 +295,8 @@
       },
       subjects: [{
         kind: 'ServiceAccount',
-        name: $.prometheusAdapter.serviceAccount.metadata.name,
-        namespace: $._config.prometheusAdapter.namespace,
+        name: $.serviceAccount.metadata.name,
+        namespace: pa.config.namespace,
       }],
     },
-  },
 }