diff --git a/Makefile b/Makefile index ea6889e311480b485d09cd52d66dea0effca5369..0c4cc0794662bbf449473c4b103e3243e4ae0c1b 100644 --- a/Makefile +++ b/Makefile @@ -63,4 +63,4 @@ test-in-docker: .PHONY: generate generate-in-docker test test-in-docker fmt $(JB_BINARY): - go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@v0.2.0 + go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@v0.3.1 diff --git a/go.mod b/go.mod index 77b15efc9acfe086a7c7d251d3f041e4fc411a84..bf7efcac143dcc0edbd1ca5223edb26a07a3c8b4 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d // indirect github.com/imdario/mergo v0.3.7 // indirect github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be // indirect - github.com/jsonnet-bundler/jsonnet-bundler v0.2.0 + github.com/jsonnet-bundler/jsonnet-bundler v0.3.1 github.com/kr/pretty v0.2.0 // indirect github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-isatty v0.0.10 // indirect diff --git a/go.sum b/go.sum index 6496f5b64002822940a0e272406991b8b51ccf1a..47a5710463bc1edb2bb91db3a10d13762808f291 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,8 @@ github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPU github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jsonnet-bundler/jsonnet-bundler v0.2.0 h1:qL1v+2mjdEOmvNJp+ab+wQH81TQY71w1A666CRUg+1U= github.com/jsonnet-bundler/jsonnet-bundler v0.2.0/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= +github.com/jsonnet-bundler/jsonnet-bundler v0.3.1 h1:KmNzitX12fFoyqjhU8cRifEB5D8x1NT1UAcK7FQ0zpY= +github.com/jsonnet-bundler/jsonnet-bundler v0.3.1/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/jsonnet/kube-prometheus/kube-prometheus.libsonnet b/jsonnet/kube-prometheus/kube-prometheus.libsonnet index 71715250f0b12831fc50590725f35c00936997c5..92262460c79480f5d916aadb8da6feca5c01d1a8 100644 --- a/jsonnet/kube-prometheus/kube-prometheus.libsonnet +++ b/jsonnet/kube-prometheus/kube-prometheus.libsonnet @@ -50,7 +50,62 @@ local configMapList = k3.core.v1.configMapList; preserveUnknownFields: null, }), }, - }, + service+: { + spec+: { + ports: [ + { + name: 'https', + port: 8443, + targetPort: 'https', + }, + ], + }, + }, + serviceMonitor+: { + spec+: { + endpoints: [ + { + port: 'https', + scheme: 'https', + honorLabels: true, + bearerTokenFile: '/var/run/secrets/kubernetes.io/serviceaccount/token', + tlsConfig: { + insecureSkipVerify: true, + }, + }, + ] + }, + }, + clusterRole+: { + rules+: [ + { + apiGroups: ['authentication.k8s.io'], + resources: ['tokenreviews'], + verbs: ['create'], + }, + { + apiGroups: ['authorization.k8s.io'], + resources: ['subjectaccessreviews'], + verbs: ['create'], + }, + ], + }, + } + + ((import 'kube-prometheus/kube-rbac-proxy/container.libsonnet') { + config+:: { + kubeRbacProxy: { + local cfg = self, + image: $._config.imageRepos.kubeRbacProxy + ':' + $._config.versions.kubeRbacProxy, + name: 'kube-rbac-proxy', + securePortName: 'https', + securePort: 8443, + secureListenAddress: ':%d' % self.securePort, + upstream: 'http://127.0.0.1:8080/', + tlsCipherSuites: $._config.tlsCipherSuites, + }, + }, + }).deploymentMixin, + grafana+:: { dashboardDefinitions: configMapList.new(super.dashboardDefinitions), serviceMonitor: { diff --git a/jsonnetfile.json b/jsonnetfile.json index ad5fe5bcde374c76bae252210ee2b77196a23005..73f156870b69fc7383a3a0b12f612989ac827b2f 100644 --- a/jsonnetfile.json +++ b/jsonnetfile.json @@ -1,7 +1,7 @@ { + "version": 1, "dependencies": [ { - "name": "kube-prometheus", "source": { "local": { "directory": "jsonnet/kube-prometheus" @@ -9,5 +9,6 @@ }, "version": "" } - ] + ], + "legacyImports": true } diff --git a/jsonnetfile.lock.json b/jsonnetfile.lock.json index c887ca49b280cc46b31dba78a8de7701ff442d32..4939273854c14502ef1bc1c6b0d21c4b4f94c9d4 100644 --- a/jsonnetfile.lock.json +++ b/jsonnetfile.lock.json @@ -1,7 +1,17 @@ { + "version": 1, "dependencies": [ { - "name": "etcd-mixin", + "source": { + "git": { + "remote": "https://github.com/brancz/kubernetes-grafana", + "subdir": "grafana" + } + }, + "version": "539a90dbf63c812ad0194d8078dd776868a11c81", + "sum": "b8faWX1qqLGyN67sA36oRqYZ5HX+tHBRMPtrWRqIysE=" + }, + { "source": { "git": { "remote": "https://github.com/coreos/etcd", @@ -12,18 +22,26 @@ "sum": "Ko3qhNfC2vN/houLh6C0Ryacjv70gl0DVPGU/PQ4OD0=" }, { - "name": "grafana", "source": { "git": { - "remote": "https://github.com/brancz/kubernetes-grafana", - "subdir": "grafana" + "remote": "https://github.com/coreos/prometheus-operator", + "subdir": "jsonnet/prometheus-operator" } }, - "version": "539a90dbf63c812ad0194d8078dd776868a11c81", - "sum": "b8faWX1qqLGyN67sA36oRqYZ5HX+tHBRMPtrWRqIysE=" + "version": "378d36df448366414de53a66a64020cd053002b7", + "sum": "vegTm8VSDazwYflBQGLkjs3ystWahwUv0fUyuMbpNRg=" + }, + { + "source": { + "git": { + "remote": "https://github.com/grafana/grafonnet-lib", + "subdir": "grafonnet" + } + }, + "version": "c459106d2d2b583dd3a83f6c75eb52abee3af764", + "sum": "CeM3LRgUCUJTolTdMnerfMPGYmhClx7gX5ajrQVEY2Y=" }, { - "name": "grafana-builder", "source": { "git": { "remote": "https://github.com/grafana/jsonnet-libs", @@ -34,38 +52,37 @@ "sum": "slxrtftVDiTlQK22ertdfrg4Epnq97gdrLI63ftUfaE=" }, { - "name": "grafonnet", "source": { "git": { - "remote": "https://github.com/grafana/grafonnet-lib", - "subdir": "grafonnet" + "remote": "https://github.com/ksonnet/ksonnet-lib", + "subdir": "" } }, - "version": "c459106d2d2b583dd3a83f6c75eb52abee3af764", - "sum": "CeM3LRgUCUJTolTdMnerfMPGYmhClx7gX5ajrQVEY2Y=" + "version": "0d2f82676817bbf9e4acf6495b2090205f323b9f", + "sum": "h28BXZ7+vczxYJ2sCt8JuR9+yznRtU/iA6DCpQUrtEg=", + "name": "ksonnet" }, { - "name": "ksonnet", "source": { "git": { - "remote": "https://github.com/ksonnet/ksonnet-lib", + "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin", "subdir": "" } }, - "version": "0d2f82676817bbf9e4acf6495b2090205f323b9f", - "sum": "h28BXZ7+vczxYJ2sCt8JuR9+yznRtU/iA6DCpQUrtEg=" + "version": "b2d7f762bd22be3ba5e7d54a1fcecfe1092f214b", + "sum": "NqrJQnQnRDzkCbrHg7L1zX8XPAzfoE4DS2XBEj6WC8g=" }, { - "name": "kube-prometheus", "source": { - "local": { - "directory": "jsonnet/kube-prometheus" + "git": { + "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin", + "subdir": "lib/promgrafonnet" } }, - "version": "" + "version": "b2d7f762bd22be3ba5e7d54a1fcecfe1092f214b", + "sum": "VhgBM39yv0f4bKv8VfGg4FXkg573evGDRalip9ypKbc=" }, { - "name": "kube-state-metrics", "source": { "git": { "remote": "https://github.com/kubernetes/kube-state-metrics", @@ -76,7 +93,6 @@ "sum": "cJjGZaLBjcIGrLHZLjRPU9c3KL+ep9rZTb9dbALSKqA=" }, { - "name": "kube-state-metrics-mixin", "source": { "git": { "remote": "https://github.com/kubernetes/kube-state-metrics", @@ -87,18 +103,16 @@ "sum": "E1GGavnf9PCWBm4WVrxWnc0FIj72UcbcweqGioWrOdU=" }, { - "name": "kubernetes-mixin", "source": { "git": { - "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin", - "subdir": "" + "remote": "https://github.com/metalmatze/slo-libsonnet", + "subdir": "slo-libsonnet" } }, - "version": "b2d7f762bd22be3ba5e7d54a1fcecfe1092f214b", - "sum": "NqrJQnQnRDzkCbrHg7L1zX8XPAzfoE4DS2XBEj6WC8g=" + "version": "437c402c5f3ad86c3c16db8471f1649284fef0ee", + "sum": "2Zcyku1f558VrUpMaJnI78fahDksPLcS1idmxxwcQ7Q=" }, { - "name": "node-mixin", "source": { "git": { "remote": "https://github.com/prometheus/node_exporter", @@ -109,7 +123,6 @@ "sum": "VKdF0zPMSCiuIuXWblSz2VOeBaXzQ7fp40vz9sxj+Bo=" }, { - "name": "prometheus", "source": { "git": { "remote": "https://github.com/prometheus/prometheus", @@ -117,40 +130,17 @@ } }, "version": "1c321ed047ac57e34688e40a55349c9dfe2b72c8", - "sum": "u1YS9CVuBTcw2vks0PZbLb1gtlI/7bVGDVBZsjWFLTw=" - }, - { - "name": "prometheus-operator", - "source": { - "git": { - "remote": "https://github.com/coreos/prometheus-operator", - "subdir": "jsonnet/prometheus-operator" - } - }, - "version": "378d36df448366414de53a66a64020cd053002b7", - "sum": "vegTm8VSDazwYflBQGLkjs3ystWahwUv0fUyuMbpNRg=" + "sum": "u1YS9CVuBTcw2vks0PZbLb1gtlI/7bVGDVBZsjWFLTw=", + "name": "prometheus" }, { - "name": "promgrafonnet", "source": { - "git": { - "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin", - "subdir": "lib/promgrafonnet" - } - }, - "version": "b2d7f762bd22be3ba5e7d54a1fcecfe1092f214b", - "sum": "VhgBM39yv0f4bKv8VfGg4FXkg573evGDRalip9ypKbc=" - }, - { - "name": "slo-libsonnet", - "source": { - "git": { - "remote": "https://github.com/metalmatze/slo-libsonnet", - "subdir": "slo-libsonnet" + "local": { + "directory": "jsonnet/kube-prometheus" } }, - "version": "437c402c5f3ad86c3c16db8471f1649284fef0ee", - "sum": "2Zcyku1f558VrUpMaJnI78fahDksPLcS1idmxxwcQ7Q=" + "version": "" } - ] + ], + "legacyImports": false } diff --git a/manifests/prometheus-operator-serviceMonitor.yaml b/manifests/prometheus-operator-serviceMonitor.yaml index be604c37c16e89d36262fc4985fb208f24a6f19e..571f5e25564a1041d492b6d180166f77093d6034 100644 --- a/manifests/prometheus-operator-serviceMonitor.yaml +++ b/manifests/prometheus-operator-serviceMonitor.yaml @@ -9,8 +9,12 @@ metadata: namespace: monitoring spec: endpoints: - - honorLabels: true - port: http + - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + honorLabels: true + port: https + scheme: https + tlsConfig: + insecureSkipVerify: true selector: matchLabels: app.kubernetes.io/component: controller diff --git a/manifests/setup/prometheus-operator-clusterRole.yaml b/manifests/setup/prometheus-operator-clusterRole.yaml index 4bcb185d1fd1581a3b39ab7b67a00935351ea028..054414f22befde4f88d514699d88dcb676395f52 100644 --- a/manifests/setup/prometheus-operator-clusterRole.yaml +++ b/manifests/setup/prometheus-operator-clusterRole.yaml @@ -87,3 +87,15 @@ rules: - get - list - watch +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/manifests/setup/prometheus-operator-deployment.yaml b/manifests/setup/prometheus-operator-deployment.yaml index c595b0aeb4f4e674b23442ad18e6b44339f8a3de..2aeec68203434374111d7060c5c7feefd2b8031d 100644 --- a/manifests/setup/prometheus-operator-deployment.yaml +++ b/manifests/setup/prometheus-operator-deployment.yaml @@ -40,6 +40,18 @@ spec: memory: 100Mi securityContext: allowPrivilegeEscalation: false + - args: + - --logtostderr + - --secure-listen-address=:8443 + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://127.0.0.1:8080/ + image: quay.io/coreos/kube-rbac-proxy:v0.4.1 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + securityContext: + runAsUser: 65534 nodeSelector: beta.kubernetes.io/os: linux securityContext: diff --git a/manifests/setup/prometheus-operator-service.yaml b/manifests/setup/prometheus-operator-service.yaml index 51f7a06c132427f5974209d39536fd9d54135ea8..fbb448d99f92d6dfb972bd449fa53d590aa9df96 100644 --- a/manifests/setup/prometheus-operator-service.yaml +++ b/manifests/setup/prometheus-operator-service.yaml @@ -10,9 +10,9 @@ metadata: spec: clusterIP: None ports: - - name: http - port: 8080 - targetPort: http + - name: https + port: 8443 + targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/name: prometheus-operator diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index eb73108c7234e473fafe1bc2de36940347f03670..36b6a14bf943b0d853fe487a599375c80af296ae 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -123,7 +123,7 @@ func TestDroppedMetrics(t *testing.T) { if err != nil { log.Fatal(err) } - for _, k := range md.Data { + for _, k := range md { // check if the metric' help text contains Deprecated if strings.Contains(k.Help, "Deprecated") { // query prometheus for the Deprecated metric @@ -138,3 +138,27 @@ func TestDroppedMetrics(t *testing.T) { } } + +func TestTargetsScheme(t *testing.T) { + // query targets for all endpoints + tgs, err := promClient.targets() + if err != nil { + log.Fatal(err) + } + + // exclude jobs from checking for http endpoints + // TODO(paulfantom): This should be reduced as we secure connections for those components + exclude := map[string]bool{ + "alertmanager-main": true, + "prometheus-k8s": true, + "kube-dns": true, + "grafana": true, + } + + for _, k := range tgs.Active { + job := k.Labels["job"] + if k.DiscoveredLabels["__scheme__"] == "http" && !exclude[string(job)] { + log.Fatalf("target exposing metrics over HTTP instead of HTTPS: %+v", k) + } + } +} diff --git a/tests/e2e/prometheus_client.go b/tests/e2e/prometheus_client.go index 89e25c0a3faa7af1a6638b22976c441473ef8c51..a932c0b580cf1d99d8231eab5f55b3dfdcd07c0d 100644 --- a/tests/e2e/prometheus_client.go +++ b/tests/e2e/prometheus_client.go @@ -22,6 +22,7 @@ import ( "k8s.io/client-go/kubernetes" "github.com/Jeffail/gabs" + promv1 "github.com/prometheus/client_golang/api/prometheus/v1" ) type prometheusClient struct { @@ -32,6 +33,42 @@ func newPrometheusClient(kubeClient kubernetes.Interface) *prometheusClient { return &prometheusClient{kubeClient} } +// Response hold API response in a form similar to apiResponse struct from prometheus/client_golang +// https://github.com/prometheus/client_golang/blob/master/api/prometheus/v1/api.go +type Response struct { + Status string `json:"status"` + Data json.RawMessage `json:"data"` +} + +// apiRequest makes a request against specified Prometheus API endpoint +func (c *prometheusClient) apiRequest(endpoint string, selector string, query string) (Response, error) { + req := c.kubeClient.CoreV1().RESTClient().Get(). + Namespace("monitoring"). + Resource("pods"). + SubResource("proxy"). + Name("prometheus-k8s-0:9090"). + Suffix(endpoint).Param(selector, query) + + var data Response + b, err := req.DoRaw() + if err != nil { + return data, err + } + + r := bytes.NewReader(b) + decoder := json.NewDecoder(r) + err = decoder.Decode(&data) + if err != nil { + return data, err + } + + if data.Status != "success" { + return data, fmt.Errorf("status of returned response was not successful; status: %s", data.Status) + } + + return data, err +} + // Query makes a request against the Prometheus /api/v1/query endpoint. func (c *prometheusClient) query(query string) (int, error) { req := c.kubeClient.CoreV1().RESTClient().Get(). @@ -55,40 +92,36 @@ func (c *prometheusClient) query(query string) (int, error) { return n, err } -type Metadata struct { - Status string `json:"status,omitempty"` - Data []Data `json:"data,omitempty"` -} - -type Data struct { - Metric string `json:"metric,omitempty"` - Help string `json:"help,omitempty"` -} - // metadata makes a request against the Prometheus /api/v1/targets/metadata endpoint. // It returns all the metrics and its metadata. -func (c *prometheusClient) metadata(query string) (Metadata, error) { - req := c.kubeClient.CoreV1().RESTClient().Get(). - Namespace("monitoring"). - Resource("pods"). - SubResource("proxy"). - Name("prometheus-k8s-0:9090"). - Suffix("/api/v1/targets/metadata").Param("match_target", query) +func (c *prometheusClient) metadata(query string) ([]promv1.MetricMetadata, error) { + var metadata []promv1.MetricMetadata + rsp, err := c.apiRequest("/api/v1/targets/metadata", "match_target", query) - var data Metadata - b, err := req.DoRaw() + r := bytes.NewReader(rsp.Data) + decoder := json.NewDecoder(r) + err = decoder.Decode(&metadata) if err != nil { - return data, err + return metadata, err } + return metadata, err +} - r := bytes.NewReader(b) - decoder := json.NewDecoder(r) - err = decoder.Decode(&data) +// targets makes a request against the Prometheus /api/v1/targets endpoint. +// It returns all targets registered in prometheus. +func (c *prometheusClient) targets() (promv1.TargetsResult, error) { + var targets promv1.TargetsResult + rsp, err := c.apiRequest("/api/v1/targets", "state", "any") if err != nil { - return data, err + return targets, err } - if data.Status != "success" { - return data, fmt.Errorf("status of returned response was not successful; status: %s", data.Status) + + r := bytes.NewReader(rsp.Data) + decoder := json.NewDecoder(r) + err = decoder.Decode(&targets) + if err != nil { + return targets, err } - return data, err + + return targets, err }