├── charts ├── helm-exporter │ ├── ci │ │ └── values.yaml │ ├── templates │ │ ├── serviceaccount.yaml │ │ ├── configmap.yaml │ │ ├── role.yaml │ │ ├── tests │ │ │ └── test-connection.yaml │ │ ├── role_binding.yaml │ │ ├── service.yaml │ │ ├── ingress.yaml │ │ ├── servicemonitor.yaml │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── deployment.yaml │ │ └── grafana-dashboard.yaml │ ├── Chart.yaml │ ├── values.yaml │ └── README.md ├── deployment │ ├── templates │ │ ├── NOTES.txt │ │ ├── secret.yaml │ │ ├── middleware.yaml │ │ ├── horizontalPodAutoscaler.yaml │ │ ├── service.yaml │ │ ├── _helpers.tpl │ │ ├── customIngressRoutes.yaml │ │ ├── ingressRoute.yaml │ │ └── deployment.yaml │ ├── Chart.yaml │ ├── .helmignore │ └── values.yaml ├── pdf-generator │ ├── templates │ │ ├── serviceaccount.yaml │ │ ├── role.yaml │ │ ├── rolebinding.yaml │ │ ├── serviceprofile.yaml │ │ ├── _helpers.tpl │ │ ├── service.yaml │ │ ├── horizontalPodAutoscaler.yaml │ │ └── deployment.yaml │ ├── Chart.yaml │ ├── .helmignore │ └── values.yaml └── altinn-dashboards-grafana │ ├── values.yaml │ ├── Chart.yaml │ ├── .helmignore │ ├── templates │ ├── configmap-dashboards.yaml │ └── _helpers.tpl │ └── dashboards │ └── traefik-official.json ├── renovate.json ├── .github ├── CODEOWNERS └── workflows │ ├── release.yaml │ └── validate.yaml ├── README.md ├── LICENSE └── .gitignore /charts/helm-exporter/ci/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /charts/deployment/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. The application can be reached at: 2 | {{- range .Values.ingressRoute.routes }} 3 | {{ .match }} 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>Altinn/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ template "name" . }} 5 | namespace: {{ .Release.namespace }} 6 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for altinn-dashboards-grafana. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | -------------------------------------------------------------------------------- /charts/deployment/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart for Kubernetes 3 | # name can only be lowercase. It is used in the templates. 4 | name: deployment 5 | version: 3.8.0 6 | -------------------------------------------------------------------------------- /charts/pdf-generator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: A Helm chart for the pdf generator 3 | # name can only be lowercase. It is used in the templats. 4 | name: pdf-generator 5 | version: 1.9.0 6 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: altinn-dashboards-grafana 3 | description: Add Altinn Grafana dashboards 4 | icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png 5 | version: 1.0.1 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @altinn/team-core 2 | charts/altinn-dashboard-grafana/** @altinn/team-platform 3 | charts/deployment/** @altinn/team-altinn-studio 4 | charts/pdf-generator/** @Altinn/team-altinn-studio 5 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "helm-exporter.serviceAccountName" . }} 6 | labels: 7 | {{ include "helm-exporter.labels" . | nindent 4 }} 8 | {{- end -}} 9 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/role.yaml: -------------------------------------------------------------------------------- 1 | kind: Role 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ template "name" . }} 5 | namespace: {{ .Release.namespace }} 6 | rules: 7 | - apiGroups: ["apps"] 8 | resources: ["pdf"] 9 | verbs: ["post", "get", "list"] 10 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.config -}} 2 | kind: ConfigMap 3 | apiVersion: v1 4 | metadata: 5 | name: {{ include "helm-exporter.fullname" . }} 6 | labels: 7 | {{ include "helm-exporter.labels" . | nindent 8 }} 8 | data: 9 | config.yaml: |- 10 | {{ toYaml .Values.config | indent 6}} 11 | {{- end }} 12 | -------------------------------------------------------------------------------- /charts/deployment/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ template "fullname" . }}-secrets 5 | labels: 6 | app: {{ template "fullname" . }} 7 | chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | type: Opaque 11 | immutable: false 12 | data: {} 13 | -------------------------------------------------------------------------------- /charts/helm-exporter/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: helm-exporter 3 | description: Exporter for helm metrics 4 | type: application 5 | version: 1.2.10 6 | appVersion: latest 7 | home: https://github.com/sstarcher/helm-exporter 8 | sources: 9 | - https://github.com/sstarcher/helm-exporter 10 | maintainers: 11 | - name: sstarcher 12 | email: shane.starcher@gmail.com 13 | url: https://shanestarcher.com 14 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: {{ template "name" . }} 5 | namespace: {{ .Release.namespace }} 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: Role 9 | name: {{ template "name" . }} 10 | subjects: 11 | - kind: ServiceAccount 12 | name: {{ template "name" . }} 13 | namespace: {{ .Release.namespace }} 14 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/role.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.create -}} 2 | kind: ClusterRole 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: {{ include "helm-exporter.fullname" . }} 6 | labels: 7 | {{ include "helm-exporter.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - namespaces 13 | - secrets 14 | verbs: 15 | - get 16 | - watch 17 | - list 18 | {{- end -}} 19 | -------------------------------------------------------------------------------- /charts/deployment/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /charts/pdf-generator/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /charts/deployment/templates/middleware.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.linkerd.enabled }} 2 | apiVersion: traefik.io/v1alpha1 3 | kind: Middleware 4 | metadata: 5 | name: {{ template "fullname" . }} 6 | spec: 7 | headers: 8 | customRequestHeaders: 9 | l5d-dst-override: {{ printf "%s.default.svc.cluster.local:80" (include "fullname" .) }} 10 | --- 11 | {{- end }} 12 | 13 | {{- range $middleware := .Values.middlewares }} 14 | {{ toYaml $middleware }} 15 | --- 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/serviceprofile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: linkerd.io/v1alpha2 2 | kind: ServiceProfile 3 | # Service profile gives us linkerd metrics which includes the path/route as a metric 4 | # Useful for analysis of metrics without probes polluting the data with noise 5 | metadata: 6 | name: {{ template "name" . }}.svc.cluster.local 7 | namespace: {{ .Release.namespace }} 8 | spec: 9 | routes: 10 | - name: POST /pdf 11 | condition: 12 | method: POST 13 | pathRegex: /pdf 14 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "helm-exporter.fullname" . }}-test-connection" 5 | labels: 6 | {{ include "helm-exporter.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test-success 9 | "helm.sh/hook-delete-policy": hook-succeeded 10 | spec: 11 | containers: 12 | - name: wget 13 | image: busybox 14 | command: ['wget'] 15 | args: ['{{ include "helm-exporter.fullname" . }}:{{ .Values.service.port }}/healthz'] 16 | restartPolicy: Never 17 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/role_binding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.create -}} 2 | kind: ClusterRoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: {{ include "helm-exporter.fullname" . }} 6 | labels: 7 | {{ include "helm-exporter.labels" . | nindent 4 }} 8 | subjects: 9 | - kind: ServiceAccount 10 | namespace: {{ .Release.Namespace }} 11 | name: {{ include "helm-exporter.serviceAccountName" . }} 12 | roleRef: 13 | kind: ClusterRole 14 | name: {{ include "helm-exporter.fullname" . }} 15 | apiGroup: rbac.authorization.k8s.io 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "fullname" -}} 14 | {{- $name := default .Chart.Name .Values.nameOverride -}} 15 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/templates/configmap-dashboards.yaml: -------------------------------------------------------------------------------- 1 | {{- $files := .Files.Glob "dashboards/*.json" }} 2 | {{- if $files }} 3 | apiVersion: v1 4 | kind: ConfigMapList 5 | items: 6 | {{- range $path, $fileContents := $files }} 7 | {{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} 8 | - apiVersion: v1 9 | kind: ConfigMap 10 | metadata: 11 | name: {{ printf "%s-%s" (include "altinn-dashboards-grafana.fullname" $) $dashboardName | trunc 63 | trimSuffix "-" }} 12 | labels: 13 | grafana_dashboard: "1" 14 | data: 15 | {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} 16 | {{- end }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "name" . }} 5 | namespace: {{ .Release.namespace }} 6 | labels: 7 | app: {{ template "name" . }} 8 | chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | spec: 12 | type: {{ .Values.service.type }} 13 | ports: 14 | - port: {{ .Values.service.externalPort }} 15 | targetPort: {{ .Values.service.internalPort }} 16 | protocol: TCP 17 | name: {{ .Values.service.name }} 18 | selector: 19 | app: {{ template "name" . }} 20 | release: {{ .Release.Name }} 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # altinn-studio-charts 2 | Helm charts for Altinn Studio apps 3 | 4 | ## Usage 5 | 6 | [Helm](https://helm.sh) must be installed to use the charts. Please refer to 7 | Helm's [documentation](https://helm.sh/docs) to get started. 8 | 9 | Once Helm has been set up correctly, add the repo as follows: 10 | 11 | helm repo add altinn-studio https://charts.altinn.studio 12 | 13 | If you had already added this repo earlier, run `helm repo update` to retrieve 14 | the latest versions of the packages. 15 | 16 | You can then run `helm search repo altinn-studio` to see the charts. 17 | 18 | To install the \ chart: 19 | 20 | helm install my- altinn-studio/ 21 | 22 | To uninstall the chart: 23 | 24 | helm delete my- -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | permissions: 3 | contents: write 4 | 5 | on: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Configure Git 20 | run: | 21 | git config user.name "$GITHUB_ACTOR" 22 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 23 | 24 | - name: Run chart-releaser 25 | uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0 26 | env: 27 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" -------------------------------------------------------------------------------- /charts/deployment/templates/horizontalPodAutoscaler.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ template "fullname" . }} 6 | spec: 7 | scaleTargetRef: 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | name: {{ template "deploymentname" . }} 11 | minReplicas: {{ .Values.autoscaling.replicas.min | default 2 }} 12 | maxReplicas: {{ .Values.autoscaling.replicas.max | default 6 }} 13 | metrics: 14 | - type: Resource 15 | resource: 16 | name: cpu 17 | target: 18 | type: Utilization 19 | averageUtilization: {{ .Values.autoscaling.avgCpuUtilization | default 70}} 20 | behavior: 21 | {{ toYaml .Values.autoscaling.behavior | indent 4 }} 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "helm-exporter.fullname" . }} 5 | labels: 6 | {{- include "helm-exporter.labels" . | nindent 4 }} 7 | annotations: 8 | {{- if not .Values.serviceMonitor.create }} 9 | {{ .Values.service.customScrapeEnableAnnotation | default "prometheus.io/scrape: \"true\"" }} 10 | {{- end }} 11 | {{- if .Values.service.annotations }} 12 | {{ .Values.service.annotations | toYaml | indent 4}} 13 | {{- end }} 14 | spec: 15 | type: {{ .Values.service.type }} 16 | ports: 17 | - port: {{ .Values.service.port }} 18 | targetPort: http 19 | protocol: TCP 20 | name: http 21 | selector: 22 | {{- include "helm-exporter.selectorLabels" . | nindent 4 }} 23 | -------------------------------------------------------------------------------- /charts/deployment/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "fullname" . }} 5 | labels: 6 | app: {{ template "fullname" . }} 7 | chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | ports: 13 | - port: {{ .Values.service.externalPort }} 14 | targetPort: {{ .Values.service.internalPort }} 15 | protocol: TCP 16 | name: {{ .Values.service.name }} 17 | selector: 18 | app: {{ template "fullname" . }} 19 | release: {{ .Release.Name }} 20 | {{- if .Values.ipv6.enabled }} 21 | ipFamilyPolicy: PreferDualStack 22 | ipFamilies: 23 | - IPv4 24 | - IPv6 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/horizontalPodAutoscaler.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ template "name" . }} 6 | namespace: {{ .Release.namespace }} 7 | spec: 8 | scaleTargetRef: 9 | apiVersion: apps/v1 10 | kind: Deployment 11 | name: {{ template "name" . }} 12 | minReplicas: {{ .Values.autoscaling.replicas.min | default 2 }} 13 | maxReplicas: {{ .Values.autoscaling.replicas.max | default 10 }} 14 | metrics: 15 | - type: Resource 16 | resource: 17 | name: cpu 18 | target: 19 | type: Utilization 20 | averageUtilization: {{ .Values.autoscaling.avgCpuUtilization | default 70}} 21 | behavior: 22 | {{ toYaml .Values.autoscaling.behavior | indent 4 }} 23 | {{- end }} 24 | -------------------------------------------------------------------------------- /.github/workflows/validate.yaml: -------------------------------------------------------------------------------- 1 | name: Validate Charts 2 | permissions: 3 | contents: read 4 | 5 | on: 6 | push: 7 | branches: 8 | - '*' 9 | - '!main' 10 | - '!gh-pages' 11 | pull_request: 12 | branches: 13 | - main 14 | 15 | jobs: 16 | lint-chart: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 21 | - name: Install helm 22 | env: 23 | HELM_VERSION: "v3.6.1" 24 | run: | 25 | curl -L https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz | tar xzf - linux-amd64/helm 26 | mv linux-amd64/helm ./ 27 | - name: helm lint 28 | run: | 29 | if [ -d "charts" ]; then 30 | for d in charts/*/; do 31 | helm lint "$d"; 32 | done 33 | fi -------------------------------------------------------------------------------- /charts/deployment/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "fullname" -}} 14 | {{- $name := default .Chart.Name .Values.nameOverride -}} 15 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 16 | {{- end -}} 17 | 18 | {{/* 19 | Create a default fully qualified deployment name. 20 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 21 | */}} 22 | {{- define "deploymentname" -}} 23 | {{- $name := default .Chart.Name .Values.nameOverride -}} 24 | {{- printf "%s-%s-v2" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 25 | {{- end -}} 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Altinn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "helm-exporter.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | apiVersion: networking.k8s.io/v1 5 | kind: Ingress 6 | metadata: 7 | name: {{ $fullName }} 8 | labels: 9 | {{- include "helm-exporter.labels" . | nindent 4 }} 10 | {{- with .Values.ingress.annotations }} 11 | annotations: 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | spec: 15 | {{- if .Values.ingress.tls }} 16 | tls: 17 | {{- range .Values.ingress.tls }} 18 | - hosts: 19 | {{- range .hosts }} 20 | - {{ . | quote }} 21 | {{- end }} 22 | secretName: {{ .secretName }} 23 | {{- end }} 24 | {{- end }} 25 | rules: 26 | {{- range .Values.ingress.hosts }} 27 | - host: {{ .host | quote }} 28 | http: 29 | paths: 30 | {{- range .paths }} 31 | - path: {{ . }} 32 | pathType: ImplementationSpecific 33 | backend: 34 | service: 35 | name: {{ $fullName }} 36 | port: 37 | number: {{ $svcPort }} 38 | {{- end }} 39 | {{- end }} 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /charts/deployment/templates/customIngressRoutes.yaml: -------------------------------------------------------------------------------- 1 | {{- $linkerd := .Values.linkerd }} 2 | {{- $fullName := include "fullname" . }} 3 | 4 | {{- range $customRoute := .Values.customIngressRoutes }} 5 | --- 6 | apiVersion: traefik.io/v1alpha1 7 | kind: IngressRoute 8 | metadata: 9 | name: {{ $customRoute.name }} 10 | spec: 11 | entryPoints: 12 | {{- range $entryPoint := $customRoute.entryPoints }} 13 | - {{ $entryPoint }} 14 | {{- end }} 15 | routes: 16 | {{- range $route := $customRoute.routes }} 17 | - match: {{ $route.match | quote }} 18 | kind: {{ $route.kind }} 19 | {{- if $route.priority }} 20 | priority: {{ $route.priority }} 21 | {{- end }} 22 | services: 23 | {{- range $service := $route.services }} 24 | - name: {{ $service.name }} 25 | port: {{ $service.port }} 26 | {{- end }} 27 | {{- if or $route.middlewares $linkerd.enabled }} 28 | middlewares: 29 | {{- range $middleware := $route.middlewares }} 30 | - name: {{ $middleware.name }} 31 | {{- end }} 32 | {{- if $linkerd.enabled }} 33 | - name: {{ $fullName }} 34 | {{- end }} 35 | {{- end }} 36 | {{- end }} 37 | {{- if $customRoute.tls }} 38 | tls: {} 39 | {{- end }} 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /charts/deployment/templates/ingressRoute.yaml: -------------------------------------------------------------------------------- 1 | {{- $environment := .Values.environment }} 2 | {{- $linkerd := .Values.linkerd }} 3 | {{- $fullName := include "fullname" . }} 4 | 5 | apiVersion: traefik.io/v1alpha1 6 | kind: IngressRoute 7 | metadata: 8 | name: {{ .Values.ingressRoute.name }} 9 | spec: 10 | entryPoints: 11 | {{- range $entryPoint := .Values.ingressRoute.entryPoints }} 12 | - {{ $entryPoint }} 13 | {{- end }} 14 | routes: 15 | {{- range $route := .Values.ingressRoute.routes }} 16 | - match: {{ $route.match }} 17 | kind: {{ $route.kind }} 18 | {{- if $route.priority }} 19 | priority: {{ $route.priority }} 20 | {{- end }} 21 | services: 22 | {{- range $service := $route.services }} 23 | - name: {{ $service.name }} 24 | port: {{ $service.port }} 25 | {{- end }} 26 | {{- if $route.middlewares }} 27 | middlewares: 28 | {{- range $middleware := $route.middlewares}} 29 | - name: {{ $middleware.name }} 30 | {{- end }} 31 | {{- if $linkerd.enabled }} 32 | - name: {{ $fullName }} 33 | {{- end }} 34 | {{- end }} 35 | {{- end }} 36 | {{- if .Values.ingressRoute.tls }} 37 | tls: 38 | {{- if .Values.ingressRoute.tls.secretName }} 39 | secretName: {{ .Values.ingressRoute.tls.secretName }} 40 | {{- end }} 41 | {{- end }} 42 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{ if and .Values.serviceMonitor.create (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ include "helm-exporter.fullname" . }} 6 | labels: 7 | {{ include "helm-exporter.labels" . | nindent 4 }} 8 | {{- range $key, $value := .Values.serviceMonitor.additionalLabels }} 9 | {{ $key }}: {{ $value | quote }} 10 | {{- end }} 11 | {{- with .Values.serviceMonitor.namespace }} 12 | namespace: {{ . }} 13 | {{- end }} 14 | spec: 15 | endpoints: 16 | - port: http 17 | honorLabels: true 18 | {{- with .Values.serviceMonitor.interval }} 19 | interval: {{ . }} 20 | {{- end }} 21 | {{- with .Values.serviceMonitor.scrapeTimeout }} 22 | scrapeTimeout: {{ . }} 23 | {{- end }} 24 | {{- if .Values.serviceMonitor.metricRelabelings }} 25 | metricRelabelings: 26 | {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 4 }} 27 | {{- end }} 28 | {{- if .Values.serviceMonitor.relabelings }} 29 | relabelings: 30 | {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} 31 | {{- end }} 32 | namespaceSelector: 33 | matchNames: 34 | - {{ .Release.Namespace }} 35 | selector: 36 | matchLabels: 37 | {{- include "helm-exporter.selectorLabels" . | nindent 6 }} 38 | 39 | {{- end }} 40 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "helm-exporter.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "helm-exporter.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "helm-exporter.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "helm-exporter.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | echo "Visit http://127.0.0.1:8080 to use your application" 20 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "altinn-dashboards-grafana.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "altinn-dashboards-grafana.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "altinn-dashboards-grafana.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "altinn-dashboards-grafana.labels" -}} 37 | helm.sh/chart: {{ include "altinn-dashboards-grafana.chart" . }} 38 | {{ include "altinn-dashboards-grafana.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "altinn-dashboards-grafana.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "altinn-dashboards-grafana.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "helm-exporter.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "helm-exporter.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "helm-exporter.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "helm-exporter.labels" -}} 38 | helm.sh/chart: {{ include "helm-exporter.chart" . }} 39 | {{ include "helm-exporter.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end -}} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "helm-exporter.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "helm-exporter.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end -}} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "helm-exporter.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create -}} 59 | {{ default (include "helm-exporter.fullname" .) .Values.serviceAccount.name }} 60 | {{- else -}} 61 | {{ default "default" .Values.serviceAccount.name }} 62 | {{- end -}} 63 | {{- end -}} 64 | -------------------------------------------------------------------------------- /charts/deployment/values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 2 2 | 3 | autoscaling: 4 | enabled: true 5 | replicas: 6 | min: 2 7 | max: 6 8 | avgCpuUtilization: 75 9 | behavior: 10 | scaleUp: 11 | stabilizationWindowSeconds: 0 12 | policies: 13 | - type: Pods 14 | value: 1 15 | periodSeconds: 15 16 | scaleDown: 17 | stabilizationWindowSeconds: 300 18 | policies: 19 | - type: Pods 20 | value: 1 21 | periodSeconds: 60 22 | 23 | resources: 24 | requests: 25 | cpu: 50m 26 | memory: 256Mi 27 | 28 | podAnnotations: 29 | {} 30 | # Additional pod annotations (e.g. for mesh injection) 31 | # Enabling of linkerd in seperate value under 32 | # config.linkerd.io/proxy-cpu-request: 10m 33 | # config.linkerd.io/proxy-memory-limit: 250Mi 34 | # config.linkerd.io/proxy-memory-request: 20Mi 35 | podLabels: 36 | {} 37 | podAntiAffinity: 38 | enabled: true 39 | 40 | terminationGracePeriodSeconds: 30 41 | 42 | image: 43 | # Set "repository" name of your image for manual Helm install and upgrade. 44 | repository: 45 | tag: latest 46 | pullPolicy: Always 47 | pullSecrets: [] 48 | # - name: myRegistryKeySecretName 49 | 50 | service: 51 | name: deployment 52 | type: ClusterIP 53 | externalPort: 80 54 | # If your application is running on another port, change only the internal port. 55 | internalPort: 5005 56 | # Enable dual stack for service 57 | ipv6: 58 | enabled: true 59 | 60 | linkerd: 61 | enabled: true 62 | 63 | ingressRoute: 64 | name: Will be inserted during deploy 65 | entryPoints: 66 | - http 67 | - https 68 | routes: 69 | - match: Will be inserted during deploy 70 | kind: Rule 71 | services: 72 | - name: Will be inserted during deploy 73 | port: 80 74 | middlewares: 75 | - name: hsts-header 76 | # # Specify ssl-cert secret if not using default 77 | # tls: 78 | # secretName: ssl-cert 79 | 80 | volumeMounts: 81 | - name: datakeys 82 | mountPath: /mnt/keys 83 | - name: accesstoken 84 | mountPath: "/accesstoken" 85 | 86 | volumes: 87 | - name: datakeys 88 | persistentVolumeClaim: 89 | claimName: keys 90 | - name: accesstoken 91 | secret: 92 | secretName: accesstoken 93 | 94 | startup: 95 | enabled: false 96 | path: /health 97 | failureThreshold: 3 98 | periodSeconds: 10 99 | timeoutSeconds: 1 100 | readiness: 101 | enabled: false 102 | path: /health 103 | initialDelaySeconds: 30 104 | failureThreshold: 3 105 | periodSeconds: 3 106 | timeoutSeconds: 30 107 | liveness: 108 | enabled: false 109 | path: /health 110 | initialDelaySeconds: 3 111 | failureThreshold: 3 112 | periodSeconds: 10 113 | timeoutSeconds: 30 114 | 115 | # Custom ingress routes (additional IngressRoutes beyond the main one) 116 | # Example: 117 | # customIngressRoutes: 118 | # - name: my-custom-ingress-route 119 | # entryPoints: 120 | # - http 121 | # - https 122 | # routes: 123 | # - kind: Rule 124 | # match: Host(`example.com`)&&PathPrefix(`/custom/`) 125 | # middlewares: 126 | # - name: hsts-header 127 | # services: 128 | # - name: my-service 129 | # port: 80 130 | customIngressRoutes: [] 131 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "helm-exporter.fullname" . }} 5 | labels: 6 | {{- include "helm-exporter.labels" . | nindent 4 }} 7 | {{- with .Values.annotations }} 8 | annotations: 9 | {{ toYaml . | nindent 4 }} 10 | {{- end }} 11 | spec: 12 | replicas: {{ .Values.replicaCount }} 13 | selector: 14 | matchLabels: 15 | {{- include "helm-exporter.selectorLabels" . | nindent 6 }} 16 | template: 17 | metadata: 18 | labels: 19 | {{- include "helm-exporter.selectorLabels" . | nindent 8 }} 20 | {{- with .Values.podLabels }} 21 | {{- toYaml . | nindent 8 }} 22 | {{- end }} 23 | annotations: 24 | checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} 25 | {{- with .Values.podAnnotations }} 26 | {{- toYaml . | nindent 8 }} 27 | {{- end }} 28 | spec: 29 | {{- if .Values.imagePullSecrets }} 30 | imagePullSecrets: 31 | {{- range .Values.imagePullSecrets }} 32 | - name: {{ . }} 33 | {{- end }} 34 | {{- end }} 35 | serviceAccountName: {{ include "helm-exporter.serviceAccountName" . }} 36 | securityContext: 37 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 38 | containers: 39 | - name: {{ .Chart.Name }} 40 | securityContext: 41 | {{- toYaml .Values.securityContext | nindent 12 }} 42 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 43 | imagePullPolicy: {{ .Values.image.pullPolicy }} 44 | args: 45 | {{- if .Values.config }} 46 | - "-config" 47 | - "/config/config.yaml" 48 | {{- end }} 49 | {{- if .Values.namespaces }} 50 | - "-namespaces" 51 | - {{ .Values.namespaces | quote }} 52 | {{- end }} 53 | {{- if .Values.namespacesIgnore }} 54 | - "-namespaces-ignore" 55 | - {{ .Values.namespacesIgnore | quote }} 56 | {{- end }} 57 | {{- if not .Values.infoMetric }} 58 | - "-info-metric=false" 59 | {{- end }} 60 | {{- if not .Values.timestampMetric }} 61 | - "-timestamp-metric=false" 62 | {{- end }} 63 | {{- if not .Values.latestChartVersion }} 64 | - "-latest-chart-version=false" 65 | {{- end }} 66 | {{- if .Values.statusInMetric }} 67 | - "-status-in-metric=true" 68 | {{- end }} 69 | {{- with .Values.intervalDuration }} 70 | - "-interval-duration={{ . }}" 71 | {{- end }} 72 | {{- if .Values.env }} 73 | env: 74 | {{ toYaml .Values.env | indent 12}} 75 | {{- end }} 76 | ports: 77 | - name: http 78 | containerPort: 9571 79 | protocol: TCP 80 | livenessProbe: 81 | {{- toYaml .Values.livenessProbe | nindent 12 }} 82 | readinessProbe: 83 | {{- toYaml .Values.readinessProbe | nindent 12 }} 84 | startupProbe: 85 | {{- toYaml .Values.startupProbe | nindent 12 }} 86 | resources: 87 | {{- toYaml .Values.resources | nindent 12 }} 88 | {{- if .Values.config }} 89 | volumeMounts: 90 | - mountPath: /config 91 | name: {{ include "helm-exporter.fullname" . }} 92 | {{- end }} 93 | {{- with .Values.nodeSelector }} 94 | nodeSelector: 95 | {{- toYaml . | nindent 8 }} 96 | {{- end }} 97 | {{- with .Values.affinity }} 98 | affinity: 99 | {{- toYaml . | nindent 8 }} 100 | {{- end }} 101 | {{- with .Values.tolerations }} 102 | tolerations: 103 | {{- toYaml . | nindent 8 }} 104 | {{- end }} 105 | {{- if .Values.config }} 106 | volumes: 107 | - name: {{ include "helm-exporter.fullname" . }} 108 | configMap: 109 | name: {{ include "helm-exporter.fullname" . }} 110 | {{- end }} 111 | -------------------------------------------------------------------------------- /charts/pdf-generator/values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 3 2 | 3 | environment: development 4 | 5 | autoscaling: 6 | enabled: true 7 | replicas: 8 | # Three replicas minimum means that we can handle a spike of 3 PDF generation requests in the same instant 9 | # Seems like a reasonable minimum as these likely also spreads them across 3 AZs 10 | min: 3 11 | # The current browserless container with our current app cluster VMs 12 | # can pretty much only process 1 PDF request at a time, as that takes anywhere from 1-1.5 cpu core 13 | # for the entire duration of the PDF generation. This can be anywhere from 5 seconds to 15 seconds on average 14 | # but with a pretty nasty tail latency up to ~60 seconds. This scaling is therefore pretty aggressive currently 15 | # (and we also let the nodepool scale fairly high) 16 | # We are working on optimizing both the PDF generation process and rendring perf of the app frontend 17 | max: 60 18 | # Since the current image doesn't handle concurrent requests at all, we need to scale up pretty aggressively here 19 | # avgCpuUtilization refers to the average utilization of CPU requests across all replicas 20 | # Scaling formula: `desiredReplicas = ceil(currentReplicas * (currentMetricValue / desiredMetricValue))` 21 | # Example 1 22 | # - `ceil(3 * (51.0 / 60.0))` = 3 23 | # - `ceil(3 * (60.0 / 60.0))` = 3 24 | # - `ceil(3 * (70.0 / 60.0))` = 4 25 | # Example 2: 26 | # - `ceil(3 * (51.0 / 50.0))` = 4 27 | # - `ceil(4 * (60.0 / 50.0))` = 5 28 | # - `ceil(5 * (70.0 / 50.0))` = 7 29 | # ^ this movement is then capped by the scaleUp behavior below 30 | avgCpuUtilization: 50 31 | behavior: 32 | scaleUp: 33 | stabilizationWindowSeconds: 0 34 | policies: 35 | - type: Pods 36 | # Limits scaleup of at most 2 pods per 10 second period 37 | # With the current node size it won't take long before new nodes need to be added to the cluster 38 | value: 2 39 | periodSeconds: 10 40 | scaleDown: 41 | # When evaluating the policy, takes the max metric value from the past 5 minutes 42 | stabilizationWindowSeconds: 300 43 | policies: 44 | - type: Pods 45 | # If we've seen lots of traffic we should be careful when scaling down 46 | # So we should scale up quickly, but down slowly (at least slower) 47 | value: 1 48 | periodSeconds: 30 49 | 50 | resources: 51 | requests: 52 | # Depending on app specifics, the container can take 1-1.5 cpu cores during rendering/PDF generation 53 | # This was tuned during loadtesting 54 | cpu: 750m 55 | memory: 500Mi 56 | 57 | image: 58 | repository: altinncr.azurecr.io/browserless/chrome 59 | tag: 1-puppeteer-21.4.1 60 | pullPolicy: IfNotPresent 61 | environment: 62 | - name: TZ 63 | value: "Europe/Oslo" 64 | # Can't handle multiple requests concurrently, then latency spikes horribly and we get timeouts 65 | - name: MAX_CONCURRENT_SESSIONS 66 | value: "1" 67 | # For the average request at 5-15s we can have a queue of 3 requests 68 | # which will leave the last queued request to sometimes take 40-60 seconds 69 | # Any bigger queue than this and the client will for sure time out 70 | - name: MAX_QUEUE_LENGTH 71 | value: "3" 72 | - name: PREBOOT_CHROME 73 | value: "true" 74 | 75 | service: 76 | name: pdf-generator 77 | type: ClusterIP 78 | externalPort: 80 79 | # If your application is running on another port, change only the internal port. 80 | internalPort: 3000 81 | 82 | podAntiAffinity: 83 | enabled: true 84 | 85 | startup: 86 | enabled: true 87 | path: "/metrics" 88 | # Check startup probe fairly often as we are dependent 89 | # on agressive scaling and handling requests quickly 90 | failureThreshold: 20 91 | periodSeconds: 1 92 | timeoutSeconds: 1 93 | readiness: 94 | enabled: true 95 | path: "/metrics" 96 | initialDelaySeconds: 20 97 | failureThreshold: 3 98 | periodSeconds: 10 99 | timeoutSeconds: 5 100 | liveness: 101 | enabled: true 102 | path: "/metrics" 103 | # If we can't get metrics then we probably should just restart 104 | # This is probably a pretty useless probe 105 | initialDelaySeconds: 20 106 | failureThreshold: 3 107 | periodSeconds: 10 108 | timeoutSeconds: 5 109 | -------------------------------------------------------------------------------- /charts/pdf-generator/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ template "name" . }} 5 | namespace: {{ .Release.namespace }} 6 | labels: 7 | app: {{ template "name" . }} 8 | chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | spec: 12 | {{- if not .Values.autoscaling.enabled }} 13 | replicas: {{ .Values.replicaCount }} 14 | {{- end }} 15 | selector: 16 | matchLabels: 17 | app: {{ template "name" . }} 18 | template: 19 | metadata: 20 | labels: 21 | app: {{ template "name" . }} 22 | release: {{ .Release.Name }} 23 | annotations: 24 | linkerd.io/inject: enabled 25 | cluster-autoscaler.kubernetes.io/safe-to-evict: "true" 26 | spec: 27 | serviceAccountName: {{ template "name" . }} 28 | {{- if .Values.image.pullSecrets }} 29 | imagePullSecrets: 30 | {{- range $secret := .Values.image.pullSecrets }} 31 | - name : {{ $secret.name }} 32 | {{- end }} 33 | {{- end }} 34 | {{- if .Values.podAntiAffinity.enabled }} 35 | affinity: 36 | podAntiAffinity: 37 | preferredDuringSchedulingIgnoredDuringExecution: 38 | - podAffinityTerm: 39 | labelSelector: 40 | matchExpressions: 41 | - key: app 42 | operator: In 43 | values: 44 | - {{ template "fullname" . }} 45 | topologyKey: kubernetes.io/hostname 46 | weight: 100 47 | {{- end }} 48 | containers: 49 | - name: {{ .Chart.Name }} 50 | image: "{{ required "A valid image.repository value is required!" .Values.image.repository }}:{{ .Values.image.tag }}" 51 | imagePullPolicy: {{ .Values.image.pullPolicy }} 52 | {{- if .Values.image.environment}} 53 | env: 54 | {{- range $environment := .Values.image.environment}} 55 | - name: {{ $environment.name }} 56 | value: {{ quote $environment.value }} 57 | {{- end }} 58 | {{- end }} 59 | ports: 60 | - containerPort: {{ .Values.service.internalPort }} 61 | resources: 62 | requests: 63 | cpu: {{ .Values.resources.requests.cpu }} 64 | memory: {{ .Values.resources.requests.memory }} 65 | {{- if .Values.resources.limits }} 66 | limits: 67 | {{- if .Values.resources.limits.cpu }} 68 | cpu: {{ .Values.resources.limits.cpu }} 69 | {{- end }} 70 | {{- if .Values.resources.limits.memory }} 71 | memory: {{ .Values.resources.limits.memory }} 72 | {{- end }} 73 | {{- end }} 74 | {{- if .Values.startup.enabled}} 75 | startupProbe: 76 | httpGet: 77 | path: {{ .Values.startup.path }} 78 | port: {{ .Values.service.internalPort }} 79 | failureThreshold: {{ .Values.startup.failureThreshold }} 80 | periodSeconds: {{ .Values.startup.periodSeconds }} 81 | timeoutSeconds: {{ .Values.startup.timeoutSeconds }} 82 | {{- end }} 83 | {{- if .Values.readiness.enabled}} 84 | readinessProbe: 85 | httpGet: 86 | path: {{ .Values.readiness.path }} 87 | port: {{ .Values.service.internalPort }} 88 | initialDelaySeconds: {{ .Values.readiness.initialDelaySeconds }} 89 | failureThreshold: {{ .Values.readiness.failureThreshold }} 90 | periodSeconds: {{ .Values.readiness.periodSeconds }} 91 | timeoutSeconds: {{ .Values.readiness.timeoutSeconds }} 92 | {{- end }} 93 | {{- if .Values.liveness.enabled}} 94 | livenessProbe: 95 | httpGet: 96 | path: {{ .Values.liveness.path }} 97 | port: {{ .Values.service.internalPort }} 98 | initialDelaySeconds: {{ .Values.liveness.initialDelaySeconds }} 99 | failureThreshold: {{ .Values.liveness.failureThreshold }} 100 | periodSeconds: {{ .Values.liveness.periodSeconds }} 101 | timeoutSeconds: {{ .Values.liveness.timeoutSeconds }} 102 | {{- end }} 103 | -------------------------------------------------------------------------------- /charts/helm-exporter/values.yaml: -------------------------------------------------------------------------------- 1 | # Specifies which namespaces to query for helm 3 metrics. Defaults to all 2 | namespaces: "" 3 | # you can specify namespaces to ignore - comma separated list of regexps 4 | namespacesIgnore: "" 5 | infoMetric: true 6 | timestampMetric: true 7 | latestChartVersion: true 8 | statusInMetric: false 9 | intervalDuration: 0 10 | 11 | serviceMonitor: 12 | # Specifies whether a ServiceMonitor should be created 13 | create: false 14 | interval: 15 | scrapeTimeout: 16 | namespace: 17 | additionalLabels: {} 18 | metricRelabelings: [] 19 | relabelings: [] 20 | 21 | grafanaDashboard: 22 | # Specifies whether a Grafana dashboard should be created 23 | enabled: false 24 | # Specifies then namespace where the dashboard should be created 25 | # namespace: 26 | # Add annotations to Configmap for Grafana dashboard 27 | dashboardAnnotations: {} 28 | # k8s-sidecar-target-directory: /tmp/dashboards/myfolder 29 | 30 | replicaCount: 1 31 | 32 | image: 33 | repository: sstarcher/helm-exporter 34 | # Overrides the image tag whose default is the chart version. 35 | tag: "" 36 | pullPolicy: Always 37 | 38 | imagePullSecrets: [] 39 | nameOverride: "" 40 | fullnameOverride: "" 41 | 42 | # Liveness probe configuration 43 | livenessProbe: 44 | httpGet: 45 | path: /healthz 46 | port: http 47 | 48 | # Readiness probe configuration 49 | readinessProbe: 50 | httpGet: 51 | path: /healthz 52 | port: http 53 | 54 | # Startup probe configuration 55 | startupProbe: 56 | httpGet: 57 | path: /healthz 58 | port: http 59 | 60 | rbac: 61 | create: true 62 | 63 | serviceAccount: 64 | # Specifies whether a service account should be created 65 | create: true 66 | # The name of the service account to use. 67 | # If not set and create is true, a name is generated using the fullname template 68 | name: 69 | 70 | podSecurityContext: {} 71 | # fsGroup: 2000 72 | 73 | podAnnotations: {} 74 | podLabels: {} 75 | 76 | env: [] 77 | # e.g. no_proxy environment variable: 78 | # - name: no_proxy 79 | # value: localhost 80 | 81 | securityContext: {} 82 | # capabilities: 83 | # drop: 84 | # - ALL 85 | # readOnlyRootFilesystem: true 86 | # runAsNonRoot: true 87 | # runAsUser: 1000 88 | 89 | service: 90 | type: ClusterIP 91 | port: 9571 92 | annotations: {} 93 | 94 | ingress: 95 | enabled: false 96 | annotations: {} 97 | # kubernetes.io/ingress.class: nginx 98 | # kubernetes.io/tls-acme: "true" 99 | hosts: 100 | - host: chart-example.local 101 | paths: [] 102 | tls: [] 103 | # - secretName: chart-example-tls 104 | # hosts: 105 | # - chart-example.local 106 | 107 | resources: {} 108 | # We usually recommend not to specify default resources and to leave this as a conscious 109 | # choice for the user. This also increases chances charts run on environments with little 110 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 111 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 112 | # limits: 113 | # cpu: 100m 114 | # memory: 128Mi 115 | # requests: 116 | # cpu: 100m 117 | # memory: 128Mi 118 | 119 | nodeSelector: {} 120 | 121 | tolerations: [] 122 | 123 | affinity: {} 124 | 125 | # Configuration to specifiy from which upstream repo to get the latest helm chart version 126 | # This is useful for the case of e.g. where the name "mysql" exist for multiple charts 127 | # Also if the repo is not the default helm repo 128 | config: 129 | helmRegistries: 130 | overrideChartNames: {} 131 | # mysql: stable/test 132 | # If the helm charts are not stored on hub.helm.sh then a custom registry can be configured here. 133 | # Currently only index.yaml registry is supported (helm supports other registries as well) 134 | override: 135 | - registry: 136 | url: "" # https://some.url # Url to the index file 137 | # secretRef: 138 | # name: "chartmuseum" # Name of the secret containing the username and password 139 | # userKey: "username" # Key of the username in the secret 140 | # passKey: "password" # Key of the password in the secret 141 | charts: [] # Chart names 142 | # - splunk 143 | # - falco-eks-audit-bridge 144 | allowAllReleases: true # This allows all semver versions, like release candidates or custom suffixes. Default is false 145 | registryNames: [] # Used to filter accepted registries from helm hub 146 | -------------------------------------------------------------------------------- /charts/deployment/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ template "deploymentname" . }} 5 | labels: 6 | app: {{ template "fullname" . }} 7 | chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | spec: 11 | {{- if not .Values.autoscaling.enabled }} 12 | replicas: {{ .Values.replicaCount }} 13 | {{- end }} 14 | selector: 15 | matchLabels: 16 | app: {{ template "fullname" . }} 17 | template: 18 | metadata: 19 | labels: 20 | app: {{ template "fullname" . }} 21 | release: {{ .Release.Name }} 22 | {{- with .Values.podLabels }} 23 | {{- toYaml . | nindent 8 }} 24 | {{- end }} 25 | annotations: 26 | {{- with .Values.podAnnotations }} 27 | {{- toYaml . | nindent 8 }} 28 | {{- end }} 29 | {{- if .Values.linkerd.enabled }} 30 | linkerd.io/inject: enabled 31 | cluster-autoscaler.kubernetes.io/safe-to-evict: "true" 32 | config.linkerd.io/skip-outbound-ports: "443" 33 | {{- end }} 34 | spec: 35 | {{- if .Values.image.pullSecrets }} 36 | imagePullSecrets: 37 | {{- range $secret := .Values.image.pullSecrets }} 38 | - name : {{ $secret.name }} 39 | {{- end }} 40 | {{- end }} 41 | {{- if .Values.podAntiAffinity.enabled }} 42 | affinity: 43 | podAntiAffinity: 44 | preferredDuringSchedulingIgnoredDuringExecution: 45 | - podAffinityTerm: 46 | labelSelector: 47 | matchExpressions: 48 | - key: app 49 | operator: In 50 | values: 51 | - {{ template "fullname" . }} 52 | topologyKey: kubernetes.io/hostname 53 | weight: 100 54 | {{- end }} 55 | {{- if .Values.terminationGracePeriodSeconds }} 56 | terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} 57 | {{- end }} 58 | containers: 59 | - name: {{ .Chart.Name }} 60 | image: "{{ required "A valid image.repository value is required!" .Values.image.repository }}:{{ .Values.image.tag }}" 61 | imagePullPolicy: {{ .Values.image.pullPolicy }} 62 | env: 63 | {{- if .Values.image.environment}} 64 | {{- range $environment := .Values.image.environment}} 65 | - name: {{ $environment.name }} 66 | value: {{ quote $environment.value }} 67 | {{- end }} 68 | {{- end }} 69 | - name: ALTINN_KEYS_DIRECTORY 70 | value: "/mnt/keys" 71 | ports: 72 | - containerPort: {{ .Values.service.internalPort }} 73 | resources: 74 | requests: 75 | cpu: {{ .Values.resources.requests.cpu }} 76 | memory: {{ .Values.resources.requests.memory }} 77 | {{- if .Values.resources.limits }} 78 | limits: 79 | {{- if .Values.resources.limits.cpu }} 80 | cpu: {{ .Values.resources.limits.cpu }} 81 | {{- end }} 82 | {{- if .Values.resources.limits.memory }} 83 | memory: {{ .Values.resources.limits.memory }} 84 | {{- end }} 85 | {{- end }} 86 | securityContext: 87 | runAsUser: 1000 88 | runAsGroup: 3000 89 | allowPrivilegeEscalation: false 90 | volumeMounts: 91 | {{- range $mount := .Values.volumeMounts}} 92 | - name: {{ $mount.name }} 93 | mountPath: {{ $mount.mountPath }} 94 | {{- end }} 95 | - name: app-secrets-volume 96 | mountPath: /mnt/app-secrets 97 | readOnly: true 98 | {{- if .Values.startup.enabled}} 99 | startupProbe: 100 | httpGet: 101 | path: {{ .Values.startup.path }} 102 | port: {{ .Values.service.internalPort }} 103 | failureThreshold: {{ .Values.startup.failureThreshold }} 104 | periodSeconds: {{ .Values.startup.periodSeconds }} 105 | timeoutSeconds: {{ .Values.startup.timeoutSeconds }} 106 | {{- end }} 107 | {{- if .Values.readiness.enabled}} 108 | readinessProbe: 109 | httpGet: 110 | path: {{ .Values.readiness.path }} 111 | port: {{ .Values.service.internalPort }} 112 | initialDelaySeconds: {{ .Values.readiness.initialDelaySeconds }} 113 | failureThreshold: {{ .Values.readiness.failureThreshold }} 114 | periodSeconds: {{ .Values.readiness.periodSeconds }} 115 | timeoutSeconds: {{ .Values.readiness.timeoutSeconds }} 116 | {{- end }} 117 | {{- if .Values.liveness.enabled}} 118 | livenessProbe: 119 | httpGet: 120 | path: {{ .Values.liveness.path }} 121 | port: {{ .Values.service.internalPort }} 122 | initialDelaySeconds: {{ .Values.liveness.initialDelaySeconds }} 123 | failureThreshold: {{ .Values.liveness.failureThreshold }} 124 | periodSeconds: {{ .Values.liveness.periodSeconds }} 125 | timeoutSeconds: {{ .Values.liveness.timeoutSeconds }} 126 | {{- end }} 127 | {{- if .Values.serviceAccountName }} 128 | serviceAccountName: {{ .Values.serviceAccountName }} 129 | {{- end }} 130 | volumes: 131 | {{- range $volume := .Values.volumes }} 132 | - name: {{ $volume.name }} 133 | {{- if $volume.persistentVolumeClaim }} 134 | persistentVolumeClaim: 135 | claimName: {{ $volume.persistentVolumeClaim.claimName }} 136 | {{- end }} 137 | {{- if $volume.secret }} 138 | secret: 139 | secretName: {{ $volume.secret.secretName }} 140 | {{- end }} 141 | {{- end }} 142 | - name: app-secrets-volume 143 | secret: 144 | secretName: {{ template "fullname" . }}-secrets 145 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /charts/helm-exporter/templates/grafana-dashboard.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.grafanaDashboard.enabled }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | labels: 6 | grafana_dashboard: "1" 7 | name: grafana-helm-exporter 8 | {{- if .Values.grafanaDashboard.namespace }} 9 | namespace: {{ .Values.grafanaDashboard.namespace }} 10 | {{- else }} 11 | namespace: {{ .Release.Namespace }} 12 | {{- end}} 13 | annotations: 14 | {{- with .Values.grafanaDashboard.dashboardAnnotations }} 15 | {{- toYaml . | nindent 4 }} 16 | {{- end }} 17 | data: 18 | grafana-helm-exporter.json: |- 19 | { 20 | "annotations": { 21 | "list": [ 22 | { 23 | "builtIn": 1, 24 | "datasource": "-- Grafana --", 25 | "enable": true, 26 | "hide": true, 27 | "iconColor": "rgba(0, 211, 255, 1)", 28 | "name": "Annotations & Alerts", 29 | "type": "dashboard" 30 | } 31 | ] 32 | }, 33 | "description": "Helm stats exported to Prometheus", 34 | "editable": false, 35 | "gnetId": 9367, 36 | "graphTooltip": 0, 37 | "id": 5, 38 | "iteration": 1556325406207, 39 | "links": [], 40 | "panels": [ 41 | { 42 | "columns": [], 43 | "datasource": "Prometheus", 44 | "fontSize": "100%", 45 | "gridPos": { 46 | "h": 21, 47 | "w": 24, 48 | "x": 0, 49 | "y": 0 50 | }, 51 | "id": 2, 52 | "links": [], 53 | "pageSize": null, 54 | "scroll": true, 55 | "showHeader": true, 56 | "sort": { 57 | "col": 5, 58 | "desc": true 59 | }, 60 | "styles": [ 61 | { 62 | "alias": "Time", 63 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 64 | "pattern": "Time", 65 | "type": "hidden" 66 | }, 67 | { 68 | "alias": "", 69 | "colorMode": "cell", 70 | "colors": [ 71 | "rgba(245, 54, 54, 0.9)", 72 | "#629e51", 73 | "#1f78c1" 74 | ], 75 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 76 | "decimals": 2, 77 | "mappingType": 1, 78 | "pattern": "Value", 79 | "thresholds": [ 80 | "0", 81 | "2" 82 | ], 83 | "type": "string", 84 | "unit": "short", 85 | "valueMaps": [ 86 | { 87 | "text": "Unknown", 88 | "value": "0" 89 | }, 90 | { 91 | "text": "Deployed", 92 | "value": "1" 93 | }, 94 | { 95 | "text": "Deleted", 96 | "value": "2" 97 | }, 98 | { 99 | "text": "Superseded", 100 | "value": "3" 101 | }, 102 | { 103 | "text": "Failed", 104 | "value": "-1" 105 | }, 106 | { 107 | "text": "Deleting", 108 | "value": "5" 109 | }, 110 | { 111 | "text": "Pending Install", 112 | "value": "6" 113 | }, 114 | { 115 | "text": "Pending Upgrade", 116 | "value": "7" 117 | }, 118 | { 119 | "text": "Pending Rollback", 120 | "value": "8" 121 | } 122 | ] 123 | }, 124 | { 125 | "alias": "", 126 | "colorMode": null, 127 | "colors": [ 128 | "rgba(245, 54, 54, 0.9)", 129 | "rgba(237, 129, 40, 0.89)", 130 | "rgba(50, 172, 45, 0.97)" 131 | ], 132 | "decimals": 2, 133 | "pattern": "/.*/", 134 | "thresholds": [], 135 | "type": "number", 136 | "unit": "short" 137 | } 138 | ], 139 | "targets": [ 140 | { 141 | "expr": "min(helm_chart_info{chart=~\"$chart\", namespace=~\"$namespace\", release=~\"$release\"}) by (chart, release, namespace, version) != 2", 142 | "format": "table", 143 | "instant": true, 144 | "intervalFactor": 1, 145 | "refId": "A" 146 | } 147 | ], 148 | "title": "Helm Releases", 149 | "transform": "table", 150 | "type": "table" 151 | } 152 | ], 153 | "schemaVersion": 18, 154 | "style": "dark", 155 | "tags": [ 156 | "helm", 157 | "helm-chart-info" 158 | ], 159 | "templating": { 160 | "list": [ 161 | { 162 | "allValue": ".*", 163 | "current": { 164 | "text": "All", 165 | "value": "$__all" 166 | }, 167 | "datasource": "Prometheus", 168 | "definition": "", 169 | "hide": 0, 170 | "includeAll": true, 171 | "label": null, 172 | "multi": false, 173 | "name": "chart", 174 | "options": [], 175 | "query": "label_values(helm_chart_info, chart)", 176 | "refresh": 1, 177 | "regex": "", 178 | "skipUrlSync": false, 179 | "sort": 0, 180 | "tagValuesQuery": "", 181 | "tags": [], 182 | "tagsQuery": "", 183 | "type": "query", 184 | "useTags": false 185 | }, 186 | { 187 | "allValue": ".*", 188 | "current": { 189 | "text": "All", 190 | "value": "$__all" 191 | }, 192 | "datasource": "Prometheus", 193 | "definition": "", 194 | "hide": 0, 195 | "includeAll": true, 196 | "label": null, 197 | "multi": false, 198 | "name": "release", 199 | "options": [], 200 | "query": "label_values(helm_chart_info, release)", 201 | "refresh": 1, 202 | "regex": "", 203 | "skipUrlSync": false, 204 | "sort": 0, 205 | "tagValuesQuery": "", 206 | "tags": [], 207 | "tagsQuery": "", 208 | "type": "query", 209 | "useTags": false 210 | }, 211 | { 212 | "allValue": ".*", 213 | "current": { 214 | "text": "All", 215 | "value": "$__all" 216 | }, 217 | "datasource": "Prometheus", 218 | "definition": "", 219 | "hide": 0, 220 | "includeAll": true, 221 | "label": null, 222 | "multi": false, 223 | "name": "namespace", 224 | "options": [], 225 | "query": "label_values(helm_chart_info, namespace)", 226 | "refresh": 1, 227 | "regex": "", 228 | "skipUrlSync": false, 229 | "sort": 0, 230 | "tagValuesQuery": "", 231 | "tags": [], 232 | "tagsQuery": "", 233 | "type": "query", 234 | "useTags": false 235 | } 236 | ] 237 | }, 238 | "time": { 239 | "from": "now-24h", 240 | "to": "now" 241 | }, 242 | "timepicker": { 243 | "refresh_intervals": [ 244 | "5s", 245 | "10s", 246 | "30s", 247 | "1m", 248 | "5m", 249 | "15m", 250 | "30m", 251 | "1h", 252 | "2h", 253 | "1d" 254 | ], 255 | "time_options": [ 256 | "5m", 257 | "15m", 258 | "1h", 259 | "6h", 260 | "12h", 261 | "24h", 262 | "2d", 263 | "7d", 264 | "30d" 265 | ] 266 | }, 267 | "timezone": "", 268 | "title": "Helm Exporter", 269 | "uid": "Gqncyvfmz", 270 | "version": 1 271 | } 272 | {{- end -}} 273 | -------------------------------------------------------------------------------- /charts/helm-exporter/README.md: -------------------------------------------------------------------------------- 1 | # helm-exporter 2 | 3 | ![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square) 4 | 5 | Exporter for helm metrics 6 | 7 | **Homepage:** 8 | 9 | ## Maintainers 10 | 11 | | Name | Email | Url | 12 | | ---- | ------ | --- | 13 | | sstarcher | shane.starcher@gmail.com | https://shanestarcher.com | 14 | 15 | ## Source Code 16 | 17 | * 18 | 19 | ## Values 20 | 21 | | Key | Type | Default | Description | 22 | |----------------------------------------------------|--------|-----------------------------|----------------------------------------------------------------| 23 | | affinity | object | `{}` | | 24 | | config.helmRegistries.overrideChartNames | object | `{}` | | 25 | | config.helmRegistries.override[0].allowAllReleases | bool | `true` | | 26 | | config.helmRegistries.override[0].charts | list | `[]` | | 27 | | config.helmRegistries.override[0].registry.url | string | `""` | | 28 | | config.helmRegistries.registryNames | list | `[]` | | 29 | | env | list | `[]` | | 30 | | fullnameOverride | string | `""` | | 31 | | image.pullPolicy | string | `"Always"` | | 32 | | image.repository | string | `"sstarcher/helm-exporter"` | | 33 | | image.tag | string | `""` | | 34 | | imagePullSecrets | list | `[]` | | 35 | | infoMetric | bool | `true` | | 36 | | ingress.annotations | object | `{}` | | 37 | | ingress.enabled | bool | `false` | | 38 | | ingress.hosts[0].host | string | `"chart-example.local"` | | 39 | | ingress.hosts[0].paths | list | `[]` | | 40 | | ingress.tls | list | `[]` | | 41 | | intervalDuration | int | `0` | | 42 | | latestChartVersion | bool | `true` | | 43 | | livenessProbe | object | (see `values.yaml`) | Liveness probe configuration | 44 | | nameOverride | string | `""` | | 45 | | namespaces | string | `""` | | 46 | | nodeSelector | object | `{}` | | 47 | | podAnnotations | object | `{}` | | 48 | | podLabels | object | `{}` | | 49 | | podSecurityContext | object | `{}` | | 50 | | rbac.create | bool | `true` | | 51 | | readinessProbe | object | (see `values.yaml`) | Readiness probe configuration | 52 | | replicaCount | int | `1` | | 53 | | resources | object | `{}` | | 54 | | securityContext | object | `{}` | | 55 | | service.annotations | object | `{}` | | 56 | | service.port | int | `9571` | | 57 | | service.type | string | `"ClusterIP"` | | 58 | | serviceAccount.create | bool | `true` | | 59 | | serviceAccount.name | string | `nil` | | 60 | | serviceMonitor.additionalLabels | object | `{}` | | 61 | | serviceMonitor.create | bool | `false` | | 62 | | serviceMonitor.interval | string | `nil` | | 63 | | serviceMonitor.namespace | string | `nil` | | 64 | | serviceMonitor.scrapeTimeout | string | `nil` | | 65 | | startupProbe | object | (see `values.yaml`) | Startup probe configuration | 66 | | timestampMetric | bool | `true` | | 67 | | tolerations | list | `[]` | | 68 | | grafanaDashboard.enabled | bool | `false` | Specifies whether a Grafana dashboard should be created | 69 | | grafanaDashboard.namespace | bool | `nil` | Specifies then namespace where the dashboard should be created | 70 | 71 | ---------------------------------------------- 72 | Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) 73 | -------------------------------------------------------------------------------- /charts/altinn-dashboards-grafana/dashboards/traefik-official.json: -------------------------------------------------------------------------------- 1 | { 2 | "__inputs": [ 3 | { 4 | "name": "DS_PROMETHEUS", 5 | "label": "Prometheus", 6 | "description": "", 7 | "type": "datasource", 8 | "pluginId": "prometheus", 9 | "pluginName": "Prometheus" 10 | } 11 | ], 12 | "__elements": {}, 13 | "__requires": [ 14 | { 15 | "type": "grafana", 16 | "id": "grafana", 17 | "name": "Grafana", 18 | "version": "9.3.1" 19 | }, 20 | { 21 | "type": "panel", 22 | "id": "piechart", 23 | "name": "Pie chart", 24 | "version": "" 25 | }, 26 | { 27 | "type": "datasource", 28 | "id": "prometheus", 29 | "name": "Prometheus", 30 | "version": "1.0.0" 31 | }, 32 | { 33 | "type": "panel", 34 | "id": "stat", 35 | "name": "Stat", 36 | "version": "" 37 | }, 38 | { 39 | "type": "panel", 40 | "id": "timeseries", 41 | "name": "Time series", 42 | "version": "" 43 | } 44 | ], 45 | "annotations": { 46 | "list": [ 47 | { 48 | "builtIn": 1, 49 | "datasource": { 50 | "type": "grafana", 51 | "uid": "-- Grafana --" 52 | }, 53 | "enable": true, 54 | "hide": true, 55 | "iconColor": "rgba(0, 211, 255, 1)", 56 | "name": "Annotations & Alerts", 57 | "target": { 58 | "limit": 100, 59 | "matchAny": false, 60 | "tags": [], 61 | "type": "dashboard" 62 | }, 63 | "type": "dashboard" 64 | } 65 | ] 66 | }, 67 | "description": "Official dashboard for Traefik on Kubernetes", 68 | "editable": false, 69 | "fiscalYearStartMonth": 0, 70 | "gnetId": 17347, 71 | "graphTooltip": 0, 72 | "id": null, 73 | "links": [], 74 | "liveNow": false, 75 | "panels": [ 76 | { 77 | "collapsed": false, 78 | "gridPos": { 79 | "h": 1, 80 | "w": 24, 81 | "x": 0, 82 | "y": 0 83 | }, 84 | "id": 9, 85 | "panels": [], 86 | "title": "General", 87 | "type": "row" 88 | }, 89 | { 90 | "datasource": { 91 | "type": "prometheus", 92 | "uid": "${DS_PROMETHEUS}" 93 | }, 94 | "description": "", 95 | "fieldConfig": { 96 | "defaults": { 97 | "color": { 98 | "mode": "thresholds" 99 | }, 100 | "mappings": [], 101 | "thresholds": { 102 | "mode": "absolute", 103 | "steps": [ 104 | { 105 | "color": "green", 106 | "value": null 107 | }, 108 | { 109 | "color": "red", 110 | "value": 80 111 | } 112 | ] 113 | } 114 | }, 115 | "overrides": [] 116 | }, 117 | "gridPos": { 118 | "h": 2, 119 | "w": 5, 120 | "x": 0, 121 | "y": 1 122 | }, 123 | "id": 13, 124 | "options": { 125 | "colorMode": "value", 126 | "graphMode": "area", 127 | "justifyMode": "auto", 128 | "orientation": "auto", 129 | "reduceOptions": { 130 | "calcs": [ 131 | "lastNotNull" 132 | ], 133 | "fields": "", 134 | "values": false 135 | }, 136 | "textMode": "auto" 137 | }, 138 | "pluginVersion": "9.3.1", 139 | "targets": [ 140 | { 141 | "datasource": { 142 | "type": "prometheus", 143 | "uid": "${DS_PROMETHEUS}" 144 | }, 145 | "editorMode": "code", 146 | "expr": "count(traefik_config_reloads_total)", 147 | "legendFormat": "__auto", 148 | "range": true, 149 | "refId": "A" 150 | } 151 | ], 152 | "title": "Traefik Instances", 153 | "type": "stat" 154 | }, 155 | { 156 | "datasource": { 157 | "type": "prometheus", 158 | "uid": "${DS_PROMETHEUS}" 159 | }, 160 | "description": "", 161 | "fieldConfig": { 162 | "defaults": { 163 | "color": { 164 | "mode": "palette-classic" 165 | }, 166 | "custom": { 167 | "axisCenteredZero": false, 168 | "axisColorMode": "text", 169 | "axisLabel": "", 170 | "axisPlacement": "auto", 171 | "barAlignment": 0, 172 | "drawStyle": "line", 173 | "fillOpacity": 0, 174 | "gradientMode": "none", 175 | "hideFrom": { 176 | "legend": false, 177 | "tooltip": false, 178 | "viz": false 179 | }, 180 | "lineInterpolation": "linear", 181 | "lineWidth": 1, 182 | "pointSize": 5, 183 | "scaleDistribution": { 184 | "type": "linear" 185 | }, 186 | "showPoints": "auto", 187 | "spanNulls": false, 188 | "stacking": { 189 | "group": "A", 190 | "mode": "none" 191 | }, 192 | "thresholdsStyle": { 193 | "mode": "off" 194 | } 195 | }, 196 | "mappings": [], 197 | "thresholds": { 198 | "mode": "absolute", 199 | "steps": [ 200 | { 201 | "color": "green", 202 | "value": null 203 | }, 204 | { 205 | "color": "red", 206 | "value": 80 207 | } 208 | ] 209 | }, 210 | "unit": "reqps" 211 | }, 212 | "overrides": [] 213 | }, 214 | "gridPos": { 215 | "h": 8, 216 | "w": 7, 217 | "x": 5, 218 | "y": 1 219 | }, 220 | "id": 7, 221 | "options": { 222 | "legend": { 223 | "calcs": [ 224 | "mean", 225 | "max" 226 | ], 227 | "displayMode": "table", 228 | "placement": "bottom", 229 | "showLegend": true, 230 | "sortBy": "Max", 231 | "sortDesc": true 232 | }, 233 | "tooltip": { 234 | "mode": "multi", 235 | "sort": "desc" 236 | } 237 | }, 238 | "targets": [ 239 | { 240 | "datasource": { 241 | "type": "prometheus", 242 | "uid": "${DS_PROMETHEUS}" 243 | }, 244 | "editorMode": "code", 245 | "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[1m])) by (entrypoint)", 246 | "legendFormat": "{{entrypoint}}", 247 | "range": true, 248 | "refId": "A" 249 | } 250 | ], 251 | "title": "Requests per Entrypoint", 252 | "type": "timeseries" 253 | }, 254 | { 255 | "datasource": { 256 | "type": "prometheus", 257 | "uid": "${DS_PROMETHEUS}" 258 | }, 259 | "description": "https://medium.com/@tristan_96324/prometheus-apdex-alerting-d17a065e39d0", 260 | "fieldConfig": { 261 | "defaults": { 262 | "color": { 263 | "mode": "palette-classic" 264 | }, 265 | "custom": { 266 | "axisCenteredZero": false, 267 | "axisColorMode": "text", 268 | "axisLabel": "", 269 | "axisPlacement": "auto", 270 | "barAlignment": 0, 271 | "drawStyle": "line", 272 | "fillOpacity": 0, 273 | "gradientMode": "none", 274 | "hideFrom": { 275 | "legend": false, 276 | "tooltip": false, 277 | "viz": false 278 | }, 279 | "lineInterpolation": "linear", 280 | "lineWidth": 1, 281 | "pointSize": 5, 282 | "scaleDistribution": { 283 | "type": "linear" 284 | }, 285 | "showPoints": "auto", 286 | "spanNulls": false, 287 | "stacking": { 288 | "group": "A", 289 | "mode": "none" 290 | }, 291 | "thresholdsStyle": { 292 | "mode": "off" 293 | } 294 | }, 295 | "mappings": [], 296 | "thresholds": { 297 | "mode": "absolute", 298 | "steps": [ 299 | { 300 | "color": "green", 301 | "value": null 302 | }, 303 | { 304 | "color": "red", 305 | "value": 80 306 | } 307 | ] 308 | } 309 | }, 310 | "overrides": [] 311 | }, 312 | "gridPos": { 313 | "h": 8, 314 | "w": 12, 315 | "x": 12, 316 | "y": 1 317 | }, 318 | "id": 6, 319 | "options": { 320 | "legend": { 321 | "calcs": [ 322 | "mean", 323 | "max" 324 | ], 325 | "displayMode": "table", 326 | "placement": "bottom", 327 | "showLegend": true, 328 | "sortBy": "Max", 329 | "sortDesc": true 330 | }, 331 | "tooltip": { 332 | "mode": "multi", 333 | "sort": "desc" 334 | } 335 | }, 336 | "targets": [ 337 | { 338 | "datasource": { 339 | "type": "prometheus", 340 | "uid": "${DS_PROMETHEUS}" 341 | }, 342 | "editorMode": "code", 343 | "expr": "(sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"0.3\",code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method) + \n sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"1.2\",code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method)) / 2 / \n sum(rate(traefik_entrypoint_request_duration_seconds_count{code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method)\n", 344 | "legendFormat": "{{method}}", 345 | "range": true, 346 | "refId": "A" 347 | } 348 | ], 349 | "title": "Apdex score", 350 | "type": "timeseries" 351 | }, 352 | { 353 | "datasource": { 354 | "type": "prometheus", 355 | "uid": "${DS_PROMETHEUS}" 356 | }, 357 | "description": "Mean Distribution", 358 | "fieldConfig": { 359 | "defaults": { 360 | "color": { 361 | "mode": "palette-classic" 362 | }, 363 | "custom": { 364 | "hideFrom": { 365 | "legend": false, 366 | "tooltip": false, 367 | "viz": false 368 | } 369 | }, 370 | "mappings": [], 371 | "unit": "reqps" 372 | }, 373 | "overrides": [] 374 | }, 375 | "gridPos": { 376 | "h": 6, 377 | "w": 5, 378 | "x": 0, 379 | "y": 3 380 | }, 381 | "id": 14, 382 | "options": { 383 | "legend": { 384 | "displayMode": "list", 385 | "placement": "right", 386 | "showLegend": true, 387 | "values": [ 388 | "percent" 389 | ] 390 | }, 391 | "pieType": "pie", 392 | "reduceOptions": { 393 | "calcs": [ 394 | "mean" 395 | ], 396 | "fields": "", 397 | "values": false 398 | }, 399 | "tooltip": { 400 | "mode": "multi", 401 | "sort": "asc" 402 | } 403 | }, 404 | "targets": [ 405 | { 406 | "datasource": { 407 | "type": "prometheus", 408 | "uid": "${DS_PROMETHEUS}" 409 | }, 410 | "editorMode": "code", 411 | "expr": "sum(rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[1m])) by (method, code)", 412 | "legendFormat": "{{method}}[{{code}}]", 413 | "range": true, 414 | "refId": "A" 415 | } 416 | ], 417 | "title": "Http Code ", 418 | "type": "piechart" 419 | }, 420 | { 421 | "datasource": { 422 | "type": "prometheus", 423 | "uid": "${DS_PROMETHEUS}" 424 | }, 425 | "description": "", 426 | "fieldConfig": { 427 | "defaults": { 428 | "color": { 429 | "mode": "palette-classic" 430 | }, 431 | "custom": { 432 | "axisCenteredZero": false, 433 | "axisColorMode": "text", 434 | "axisLabel": "", 435 | "axisPlacement": "auto", 436 | "barAlignment": 0, 437 | "drawStyle": "line", 438 | "fillOpacity": 0, 439 | "gradientMode": "none", 440 | "hideFrom": { 441 | "legend": false, 442 | "tooltip": false, 443 | "viz": false 444 | }, 445 | "lineInterpolation": "linear", 446 | "lineWidth": 1, 447 | "pointSize": 5, 448 | "scaleDistribution": { 449 | "type": "linear" 450 | }, 451 | "showPoints": "auto", 452 | "spanNulls": false, 453 | "stacking": { 454 | "group": "A", 455 | "mode": "none" 456 | }, 457 | "thresholdsStyle": { 458 | "mode": "off" 459 | } 460 | }, 461 | "mappings": [], 462 | "thresholds": { 463 | "mode": "absolute", 464 | "steps": [ 465 | { 466 | "color": "green", 467 | "value": null 468 | }, 469 | { 470 | "color": "red", 471 | "value": 80 472 | } 473 | ] 474 | }, 475 | "unit": "s" 476 | }, 477 | "overrides": [] 478 | }, 479 | "gridPos": { 480 | "h": 8, 481 | "w": 12, 482 | "x": 0, 483 | "y": 9 484 | }, 485 | "id": 23, 486 | "options": { 487 | "legend": { 488 | "calcs": [ 489 | "mean", 490 | "max" 491 | ], 492 | "displayMode": "table", 493 | "placement": "right", 494 | "showLegend": true, 495 | "sortBy": "Mean", 496 | "sortDesc": true 497 | }, 498 | "tooltip": { 499 | "mode": "multi", 500 | "sort": "desc" 501 | } 502 | }, 503 | "targets": [ 504 | { 505 | "datasource": { 506 | "type": "prometheus", 507 | "uid": "${DS_PROMETHEUS}" 508 | }, 509 | "editorMode": "code", 510 | "expr": "topk(15,\n label_replace(\n traefik_service_request_duration_seconds_sum{service=~\"$service.*\",protocol=\"http\"} / \n traefik_service_request_duration_seconds_count{service=~\"$service.*\",protocol=\"http\"},\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)\n\n", 511 | "legendFormat": "{{method}}[{{code}}] on {{service}}", 512 | "range": true, 513 | "refId": "A" 514 | } 515 | ], 516 | "title": "Top slow services", 517 | "type": "timeseries" 518 | }, 519 | { 520 | "datasource": { 521 | "type": "prometheus", 522 | "uid": "${DS_PROMETHEUS}" 523 | }, 524 | "description": "", 525 | "fieldConfig": { 526 | "defaults": { 527 | "color": { 528 | "mode": "palette-classic" 529 | }, 530 | "custom": { 531 | "axisCenteredZero": false, 532 | "axisColorMode": "text", 533 | "axisLabel": "", 534 | "axisPlacement": "auto", 535 | "barAlignment": 0, 536 | "drawStyle": "line", 537 | "fillOpacity": 0, 538 | "gradientMode": "none", 539 | "hideFrom": { 540 | "legend": false, 541 | "tooltip": false, 542 | "viz": false 543 | }, 544 | "lineInterpolation": "linear", 545 | "lineWidth": 1, 546 | "pointSize": 5, 547 | "scaleDistribution": { 548 | "type": "linear" 549 | }, 550 | "showPoints": "auto", 551 | "spanNulls": false, 552 | "stacking": { 553 | "group": "A", 554 | "mode": "none" 555 | }, 556 | "thresholdsStyle": { 557 | "mode": "off" 558 | } 559 | }, 560 | "mappings": [], 561 | "thresholds": { 562 | "mode": "absolute", 563 | "steps": [ 564 | { 565 | "color": "green", 566 | "value": null 567 | }, 568 | { 569 | "color": "red", 570 | "value": 80 571 | } 572 | ] 573 | }, 574 | "unit": "reqps" 575 | }, 576 | "overrides": [] 577 | }, 578 | "gridPos": { 579 | "h": 8, 580 | "w": 12, 581 | "x": 12, 582 | "y": 9 583 | }, 584 | "id": 5, 585 | "options": { 586 | "legend": { 587 | "calcs": [ 588 | "mean", 589 | "max" 590 | ], 591 | "displayMode": "table", 592 | "placement": "right", 593 | "showLegend": true, 594 | "sortBy": "Mean", 595 | "sortDesc": true 596 | }, 597 | "tooltip": { 598 | "mode": "multi", 599 | "sort": "desc" 600 | } 601 | }, 602 | "targets": [ 603 | { 604 | "datasource": { 605 | "type": "prometheus", 606 | "uid": "${DS_PROMETHEUS}" 607 | }, 608 | "editorMode": "code", 609 | "expr": "topk(15,\n label_replace(\n sum by (service,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 610 | "legendFormat": "[{{code}}] on {{service}}", 611 | "range": true, 612 | "refId": "A" 613 | } 614 | ], 615 | "title": "Most requested services", 616 | "type": "timeseries" 617 | }, 618 | { 619 | "collapsed": true, 620 | "gridPos": { 621 | "h": 1, 622 | "w": 24, 623 | "x": 0, 624 | "y": 17 625 | }, 626 | "id": 11, 627 | "panels": [ 628 | { 629 | "datasource": { 630 | "type": "prometheus", 631 | "uid": "${DS_PROMETHEUS}" 632 | }, 633 | "description": "", 634 | "fieldConfig": { 635 | "defaults": { 636 | "color": { 637 | "mode": "palette-classic" 638 | }, 639 | "custom": { 640 | "axisCenteredZero": false, 641 | "axisColorMode": "text", 642 | "axisLabel": "", 643 | "axisPlacement": "auto", 644 | "barAlignment": 0, 645 | "drawStyle": "line", 646 | "fillOpacity": 0, 647 | "gradientMode": "none", 648 | "hideFrom": { 649 | "legend": false, 650 | "tooltip": false, 651 | "viz": false 652 | }, 653 | "lineInterpolation": "linear", 654 | "lineWidth": 1, 655 | "pointSize": 5, 656 | "scaleDistribution": { 657 | "type": "linear" 658 | }, 659 | "showPoints": "auto", 660 | "spanNulls": false, 661 | "stacking": { 662 | "group": "A", 663 | "mode": "none" 664 | }, 665 | "thresholdsStyle": { 666 | "mode": "off" 667 | } 668 | }, 669 | "mappings": [], 670 | "thresholds": { 671 | "mode": "absolute", 672 | "steps": [ 673 | { 674 | "color": "green", 675 | "value": null 676 | } 677 | ] 678 | }, 679 | "unit": "percentunit" 680 | }, 681 | "overrides": [] 682 | }, 683 | "gridPos": { 684 | "h": 8, 685 | "w": 12, 686 | "x": 0, 687 | "y": 18 688 | }, 689 | "id": 3, 690 | "options": { 691 | "legend": { 692 | "calcs": [ 693 | "mean", 694 | "max" 695 | ], 696 | "displayMode": "table", 697 | "placement": "right", 698 | "showLegend": true, 699 | "sortBy": "Max", 700 | "sortDesc": true 701 | }, 702 | "tooltip": { 703 | "mode": "multi", 704 | "sort": "desc" 705 | } 706 | }, 707 | "targets": [ 708 | { 709 | "datasource": { 710 | "type": "prometheus", 711 | "uid": "${DS_PROMETHEUS}" 712 | }, 713 | "editorMode": "code", 714 | "expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"1.2\",service=~\"$service.*\"}[5m])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[5m]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)", 715 | "legendFormat": "{{service}}", 716 | "range": true, 717 | "refId": "A" 718 | } 719 | ], 720 | "title": "Services failing SLO of 1200ms", 721 | "type": "timeseries" 722 | }, 723 | { 724 | "datasource": { 725 | "type": "prometheus", 726 | "uid": "${DS_PROMETHEUS}" 727 | }, 728 | "description": "", 729 | "fieldConfig": { 730 | "defaults": { 731 | "color": { 732 | "mode": "palette-classic" 733 | }, 734 | "custom": { 735 | "axisCenteredZero": false, 736 | "axisColorMode": "text", 737 | "axisLabel": "", 738 | "axisPlacement": "auto", 739 | "barAlignment": 0, 740 | "drawStyle": "line", 741 | "fillOpacity": 0, 742 | "gradientMode": "none", 743 | "hideFrom": { 744 | "legend": false, 745 | "tooltip": false, 746 | "viz": false 747 | }, 748 | "lineInterpolation": "linear", 749 | "lineWidth": 1, 750 | "pointSize": 5, 751 | "scaleDistribution": { 752 | "type": "linear" 753 | }, 754 | "showPoints": "auto", 755 | "spanNulls": false, 756 | "stacking": { 757 | "group": "A", 758 | "mode": "none" 759 | }, 760 | "thresholdsStyle": { 761 | "mode": "off" 762 | } 763 | }, 764 | "mappings": [], 765 | "thresholds": { 766 | "mode": "absolute", 767 | "steps": [ 768 | { 769 | "color": "green", 770 | "value": null 771 | } 772 | ] 773 | }, 774 | "unit": "percentunit" 775 | }, 776 | "overrides": [] 777 | }, 778 | "gridPos": { 779 | "h": 8, 780 | "w": 12, 781 | "x": 12, 782 | "y": 18 783 | }, 784 | "id": 4, 785 | "options": { 786 | "legend": { 787 | "calcs": [ 788 | "mean", 789 | "max" 790 | ], 791 | "displayMode": "table", 792 | "placement": "right", 793 | "showLegend": true, 794 | "sortBy": "Max", 795 | "sortDesc": true 796 | }, 797 | "tooltip": { 798 | "mode": "multi", 799 | "sort": "desc" 800 | } 801 | }, 802 | "targets": [ 803 | { 804 | "datasource": { 805 | "type": "prometheus", 806 | "uid": "${DS_PROMETHEUS}" 807 | }, 808 | "editorMode": "code", 809 | "expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"0.3\",service=~\"$service.*\"}[5m])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[5m]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)", 810 | "legendFormat": "{{service}}", 811 | "range": true, 812 | "refId": "A" 813 | } 814 | ], 815 | "title": "Services failing SLO of 300ms", 816 | "type": "timeseries" 817 | } 818 | ], 819 | "title": "SLO", 820 | "type": "row" 821 | }, 822 | { 823 | "collapsed": false, 824 | "gridPos": { 825 | "h": 1, 826 | "w": 24, 827 | "x": 0, 828 | "y": 18 829 | }, 830 | "id": 16, 831 | "panels": [], 832 | "title": "HTTP Details", 833 | "type": "row" 834 | }, 835 | { 836 | "datasource": { 837 | "type": "prometheus", 838 | "uid": "${DS_PROMETHEUS}" 839 | }, 840 | "description": "", 841 | "fieldConfig": { 842 | "defaults": { 843 | "color": { 844 | "mode": "palette-classic" 845 | }, 846 | "custom": { 847 | "axisCenteredZero": false, 848 | "axisColorMode": "text", 849 | "axisLabel": "", 850 | "axisPlacement": "auto", 851 | "barAlignment": 0, 852 | "drawStyle": "line", 853 | "fillOpacity": 0, 854 | "gradientMode": "none", 855 | "hideFrom": { 856 | "legend": false, 857 | "tooltip": false, 858 | "viz": false 859 | }, 860 | "lineInterpolation": "linear", 861 | "lineWidth": 1, 862 | "pointSize": 5, 863 | "scaleDistribution": { 864 | "type": "linear" 865 | }, 866 | "showPoints": "auto", 867 | "spanNulls": false, 868 | "stacking": { 869 | "group": "A", 870 | "mode": "none" 871 | }, 872 | "thresholdsStyle": { 873 | "mode": "off" 874 | } 875 | }, 876 | "mappings": [], 877 | "thresholds": { 878 | "mode": "absolute", 879 | "steps": [ 880 | { 881 | "color": "green", 882 | "value": null 883 | }, 884 | { 885 | "color": "red", 886 | "value": 80 887 | } 888 | ] 889 | }, 890 | "unit": "reqps" 891 | }, 892 | "overrides": [] 893 | }, 894 | "gridPos": { 895 | "h": 12, 896 | "w": 8, 897 | "x": 0, 898 | "y": 19 899 | }, 900 | "id": 17, 901 | "options": { 902 | "legend": { 903 | "calcs": [ 904 | "mean", 905 | "max" 906 | ], 907 | "displayMode": "table", 908 | "placement": "bottom", 909 | "showLegend": true, 910 | "sortBy": "Mean", 911 | "sortDesc": true 912 | }, 913 | "tooltip": { 914 | "mode": "multi", 915 | "sort": "desc" 916 | } 917 | }, 918 | "targets": [ 919 | { 920 | "datasource": { 921 | "type": "prometheus", 922 | "uid": "${DS_PROMETHEUS}" 923 | }, 924 | "editorMode": "code", 925 | "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"2..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 926 | "legendFormat": "{{method}}[{{code}}] on {{service}}", 927 | "range": true, 928 | "refId": "A" 929 | } 930 | ], 931 | "title": "2xx over 5 min", 932 | "type": "timeseries" 933 | }, 934 | { 935 | "datasource": { 936 | "type": "prometheus", 937 | "uid": "${DS_PROMETHEUS}" 938 | }, 939 | "description": "", 940 | "fieldConfig": { 941 | "defaults": { 942 | "color": { 943 | "mode": "palette-classic" 944 | }, 945 | "custom": { 946 | "axisCenteredZero": false, 947 | "axisColorMode": "text", 948 | "axisGridShow": true, 949 | "axisLabel": "", 950 | "axisPlacement": "auto", 951 | "barAlignment": 0, 952 | "drawStyle": "line", 953 | "fillOpacity": 0, 954 | "gradientMode": "none", 955 | "hideFrom": { 956 | "legend": false, 957 | "tooltip": false, 958 | "viz": false 959 | }, 960 | "lineInterpolation": "linear", 961 | "lineWidth": 1, 962 | "pointSize": 5, 963 | "scaleDistribution": { 964 | "type": "linear" 965 | }, 966 | "showPoints": "auto", 967 | "spanNulls": false, 968 | "stacking": { 969 | "group": "A", 970 | "mode": "none" 971 | }, 972 | "thresholdsStyle": { 973 | "mode": "off" 974 | } 975 | }, 976 | "mappings": [], 977 | "thresholds": { 978 | "mode": "absolute", 979 | "steps": [ 980 | { 981 | "color": "green", 982 | "value": null 983 | }, 984 | { 985 | "color": "red", 986 | "value": 80 987 | } 988 | ] 989 | }, 990 | "unit": "reqps" 991 | }, 992 | "overrides": [] 993 | }, 994 | "gridPos": { 995 | "h": 12, 996 | "w": 8, 997 | "x": 8, 998 | "y": 19 999 | }, 1000 | "id": 18, 1001 | "options": { 1002 | "legend": { 1003 | "calcs": [ 1004 | "mean", 1005 | "max" 1006 | ], 1007 | "displayMode": "table", 1008 | "placement": "bottom", 1009 | "showLegend": true, 1010 | "sortBy": "Mean", 1011 | "sortDesc": true 1012 | }, 1013 | "tooltip": { 1014 | "mode": "multi", 1015 | "sort": "desc" 1016 | } 1017 | }, 1018 | "targets": [ 1019 | { 1020 | "datasource": { 1021 | "type": "prometheus", 1022 | "uid": "${DS_PROMETHEUS}" 1023 | }, 1024 | "editorMode": "code", 1025 | "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 1026 | "legendFormat": "{{method}}[{{code}}] on {{service}}", 1027 | "range": true, 1028 | "refId": "A" 1029 | } 1030 | ], 1031 | "title": "5xx over 5 min", 1032 | "type": "timeseries" 1033 | }, 1034 | { 1035 | "datasource": { 1036 | "type": "prometheus", 1037 | "uid": "${DS_PROMETHEUS}" 1038 | }, 1039 | "description": "", 1040 | "fieldConfig": { 1041 | "defaults": { 1042 | "color": { 1043 | "mode": "palette-classic" 1044 | }, 1045 | "custom": { 1046 | "axisCenteredZero": false, 1047 | "axisColorMode": "text", 1048 | "axisGridShow": true, 1049 | "axisLabel": "", 1050 | "axisPlacement": "auto", 1051 | "barAlignment": 0, 1052 | "drawStyle": "line", 1053 | "fillOpacity": 0, 1054 | "gradientMode": "none", 1055 | "hideFrom": { 1056 | "legend": false, 1057 | "tooltip": false, 1058 | "viz": false 1059 | }, 1060 | "lineInterpolation": "linear", 1061 | "lineWidth": 1, 1062 | "pointSize": 5, 1063 | "scaleDistribution": { 1064 | "type": "linear" 1065 | }, 1066 | "showPoints": "auto", 1067 | "spanNulls": false, 1068 | "stacking": { 1069 | "group": "A", 1070 | "mode": "none" 1071 | }, 1072 | "thresholdsStyle": { 1073 | "mode": "off" 1074 | } 1075 | }, 1076 | "mappings": [], 1077 | "thresholds": { 1078 | "mode": "absolute", 1079 | "steps": [ 1080 | { 1081 | "color": "green", 1082 | "value": null 1083 | }, 1084 | { 1085 | "color": "red", 1086 | "value": 80 1087 | } 1088 | ] 1089 | }, 1090 | "unit": "reqps" 1091 | }, 1092 | "overrides": [] 1093 | }, 1094 | "gridPos": { 1095 | "h": 12, 1096 | "w": 8, 1097 | "x": 16, 1098 | "y": 19 1099 | }, 1100 | "id": 19, 1101 | "options": { 1102 | "legend": { 1103 | "calcs": [ 1104 | "mean", 1105 | "max" 1106 | ], 1107 | "displayMode": "table", 1108 | "placement": "bottom", 1109 | "showLegend": true, 1110 | "sortBy": "Mean", 1111 | "sortDesc": true 1112 | }, 1113 | "tooltip": { 1114 | "mode": "multi", 1115 | "sort": "desc" 1116 | } 1117 | }, 1118 | "targets": [ 1119 | { 1120 | "datasource": { 1121 | "type": "prometheus", 1122 | "uid": "${DS_PROMETHEUS}" 1123 | }, 1124 | "editorMode": "code", 1125 | "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code!~\"2..|5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 1126 | "legendFormat": "{{method}}[{{code}}] on {{service}}", 1127 | "range": true, 1128 | "refId": "A" 1129 | } 1130 | ], 1131 | "title": "Other codes over 5 min", 1132 | "type": "timeseries" 1133 | }, 1134 | { 1135 | "datasource": { 1136 | "type": "prometheus", 1137 | "uid": "${DS_PROMETHEUS}" 1138 | }, 1139 | "description": "", 1140 | "fieldConfig": { 1141 | "defaults": { 1142 | "color": { 1143 | "mode": "palette-classic" 1144 | }, 1145 | "custom": { 1146 | "axisCenteredZero": false, 1147 | "axisColorMode": "text", 1148 | "axisGridShow": true, 1149 | "axisLabel": "", 1150 | "axisPlacement": "auto", 1151 | "barAlignment": 0, 1152 | "drawStyle": "line", 1153 | "fillOpacity": 0, 1154 | "gradientMode": "none", 1155 | "hideFrom": { 1156 | "legend": false, 1157 | "tooltip": false, 1158 | "viz": false 1159 | }, 1160 | "lineInterpolation": "linear", 1161 | "lineWidth": 1, 1162 | "pointSize": 5, 1163 | "scaleDistribution": { 1164 | "type": "linear" 1165 | }, 1166 | "showPoints": "auto", 1167 | "spanNulls": false, 1168 | "stacking": { 1169 | "group": "A", 1170 | "mode": "none" 1171 | }, 1172 | "thresholdsStyle": { 1173 | "mode": "off" 1174 | } 1175 | }, 1176 | "mappings": [], 1177 | "thresholds": { 1178 | "mode": "absolute", 1179 | "steps": [ 1180 | { 1181 | "color": "green", 1182 | "value": null 1183 | }, 1184 | { 1185 | "color": "red", 1186 | "value": 80 1187 | } 1188 | ] 1189 | }, 1190 | "unit": "binBps" 1191 | }, 1192 | "overrides": [] 1193 | }, 1194 | "gridPos": { 1195 | "h": 8, 1196 | "w": 12, 1197 | "x": 0, 1198 | "y": 31 1199 | }, 1200 | "id": 20, 1201 | "options": { 1202 | "legend": { 1203 | "calcs": [ 1204 | "mean", 1205 | "max" 1206 | ], 1207 | "displayMode": "table", 1208 | "placement": "right", 1209 | "showLegend": true, 1210 | "sortBy": "Mean", 1211 | "sortDesc": true 1212 | }, 1213 | "tooltip": { 1214 | "mode": "multi", 1215 | "sort": "desc" 1216 | } 1217 | }, 1218 | "targets": [ 1219 | { 1220 | "datasource": { 1221 | "type": "prometheus", 1222 | "uid": "${DS_PROMETHEUS}" 1223 | }, 1224 | "editorMode": "code", 1225 | "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_requests_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 1226 | "legendFormat": "{{method}} on {{service}}", 1227 | "range": true, 1228 | "refId": "A" 1229 | } 1230 | ], 1231 | "title": "Requests Size", 1232 | "type": "timeseries" 1233 | }, 1234 | { 1235 | "datasource": { 1236 | "type": "prometheus", 1237 | "uid": "${DS_PROMETHEUS}" 1238 | }, 1239 | "description": "", 1240 | "fieldConfig": { 1241 | "defaults": { 1242 | "color": { 1243 | "mode": "palette-classic" 1244 | }, 1245 | "custom": { 1246 | "axisCenteredZero": false, 1247 | "axisColorMode": "text", 1248 | "axisGridShow": true, 1249 | "axisLabel": "", 1250 | "axisPlacement": "auto", 1251 | "barAlignment": 0, 1252 | "drawStyle": "line", 1253 | "fillOpacity": 0, 1254 | "gradientMode": "none", 1255 | "hideFrom": { 1256 | "legend": false, 1257 | "tooltip": false, 1258 | "viz": false 1259 | }, 1260 | "lineInterpolation": "linear", 1261 | "lineWidth": 1, 1262 | "pointSize": 5, 1263 | "scaleDistribution": { 1264 | "type": "linear" 1265 | }, 1266 | "showPoints": "auto", 1267 | "spanNulls": false, 1268 | "stacking": { 1269 | "group": "A", 1270 | "mode": "none" 1271 | }, 1272 | "thresholdsStyle": { 1273 | "mode": "off" 1274 | } 1275 | }, 1276 | "mappings": [], 1277 | "thresholds": { 1278 | "mode": "absolute", 1279 | "steps": [ 1280 | { 1281 | "color": "green", 1282 | "value": null 1283 | }, 1284 | { 1285 | "color": "red", 1286 | "value": 80 1287 | } 1288 | ] 1289 | }, 1290 | "unit": "binBps" 1291 | }, 1292 | "overrides": [] 1293 | }, 1294 | "gridPos": { 1295 | "h": 8, 1296 | "w": 12, 1297 | "x": 12, 1298 | "y": 31 1299 | }, 1300 | "id": 24, 1301 | "options": { 1302 | "legend": { 1303 | "calcs": [ 1304 | "mean", 1305 | "max" 1306 | ], 1307 | "displayMode": "table", 1308 | "placement": "right", 1309 | "showLegend": true, 1310 | "sortBy": "Mean", 1311 | "sortDesc": true 1312 | }, 1313 | "tooltip": { 1314 | "mode": "multi", 1315 | "sort": "desc" 1316 | } 1317 | }, 1318 | "targets": [ 1319 | { 1320 | "datasource": { 1321 | "type": "prometheus", 1322 | "uid": "${DS_PROMETHEUS}" 1323 | }, 1324 | "editorMode": "code", 1325 | "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", 1326 | "legendFormat": "{{method}} on {{service}}", 1327 | "range": true, 1328 | "refId": "A" 1329 | } 1330 | ], 1331 | "title": "Responses Size", 1332 | "type": "timeseries" 1333 | }, 1334 | { 1335 | "datasource": { 1336 | "type": "prometheus", 1337 | "uid": "${DS_PROMETHEUS}" 1338 | }, 1339 | "description": "", 1340 | "fieldConfig": { 1341 | "defaults": { 1342 | "color": { 1343 | "mode": "palette-classic" 1344 | }, 1345 | "custom": { 1346 | "axisCenteredZero": false, 1347 | "axisColorMode": "text", 1348 | "axisLabel": "", 1349 | "axisPlacement": "auto", 1350 | "barAlignment": 0, 1351 | "drawStyle": "line", 1352 | "fillOpacity": 0, 1353 | "gradientMode": "none", 1354 | "hideFrom": { 1355 | "legend": false, 1356 | "tooltip": false, 1357 | "viz": false 1358 | }, 1359 | "lineInterpolation": "linear", 1360 | "lineWidth": 1, 1361 | "pointSize": 5, 1362 | "scaleDistribution": { 1363 | "type": "linear" 1364 | }, 1365 | "showPoints": "auto", 1366 | "spanNulls": false, 1367 | "stacking": { 1368 | "group": "A", 1369 | "mode": "none" 1370 | }, 1371 | "thresholdsStyle": { 1372 | "mode": "off" 1373 | } 1374 | }, 1375 | "mappings": [], 1376 | "thresholds": { 1377 | "mode": "absolute", 1378 | "steps": [ 1379 | { 1380 | "color": "green", 1381 | "value": null 1382 | }, 1383 | { 1384 | "color": "red", 1385 | "value": 80 1386 | } 1387 | ] 1388 | }, 1389 | "unit": "short" 1390 | }, 1391 | "overrides": [] 1392 | }, 1393 | "gridPos": { 1394 | "h": 8, 1395 | "w": 12, 1396 | "x": 0, 1397 | "y": 39 1398 | }, 1399 | "id": 2, 1400 | "options": { 1401 | "legend": { 1402 | "calcs": [ 1403 | "mean", 1404 | "max" 1405 | ], 1406 | "displayMode": "table", 1407 | "placement": "right", 1408 | "showLegend": true, 1409 | "sortBy": "Max", 1410 | "sortDesc": true 1411 | }, 1412 | "tooltip": { 1413 | "mode": "multi", 1414 | "sort": "desc" 1415 | } 1416 | }, 1417 | "targets": [ 1418 | { 1419 | "datasource": { 1420 | "type": "prometheus", 1421 | "uid": "${DS_PROMETHEUS}" 1422 | }, 1423 | "editorMode": "code", 1424 | "expr": "label_replace(\n sum(traefik_service_open_connections{service=~\"$service.*\"}) by (service),\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")", 1425 | "legendFormat": "{{service}}", 1426 | "range": true, 1427 | "refId": "A" 1428 | } 1429 | ], 1430 | "title": "Connections per Service", 1431 | "type": "timeseries" 1432 | }, 1433 | { 1434 | "datasource": { 1435 | "type": "prometheus", 1436 | "uid": "${DS_PROMETHEUS}" 1437 | }, 1438 | "description": "", 1439 | "fieldConfig": { 1440 | "defaults": { 1441 | "color": { 1442 | "mode": "palette-classic" 1443 | }, 1444 | "custom": { 1445 | "axisCenteredZero": false, 1446 | "axisColorMode": "text", 1447 | "axisLabel": "", 1448 | "axisPlacement": "auto", 1449 | "barAlignment": 0, 1450 | "drawStyle": "line", 1451 | "fillOpacity": 0, 1452 | "gradientMode": "none", 1453 | "hideFrom": { 1454 | "legend": false, 1455 | "tooltip": false, 1456 | "viz": false 1457 | }, 1458 | "lineInterpolation": "linear", 1459 | "lineWidth": 1, 1460 | "pointSize": 5, 1461 | "scaleDistribution": { 1462 | "type": "linear" 1463 | }, 1464 | "showPoints": "auto", 1465 | "spanNulls": false, 1466 | "stacking": { 1467 | "group": "A", 1468 | "mode": "none" 1469 | }, 1470 | "thresholdsStyle": { 1471 | "mode": "off" 1472 | } 1473 | }, 1474 | "mappings": [], 1475 | "thresholds": { 1476 | "mode": "absolute", 1477 | "steps": [ 1478 | { 1479 | "color": "green", 1480 | "value": null 1481 | }, 1482 | { 1483 | "color": "red", 1484 | "value": 80 1485 | } 1486 | ] 1487 | }, 1488 | "unit": "short" 1489 | }, 1490 | "overrides": [] 1491 | }, 1492 | "gridPos": { 1493 | "h": 8, 1494 | "w": 12, 1495 | "x": 12, 1496 | "y": 39 1497 | }, 1498 | "id": 21, 1499 | "options": { 1500 | "legend": { 1501 | "calcs": [ 1502 | "mean", 1503 | "max" 1504 | ], 1505 | "displayMode": "table", 1506 | "placement": "right", 1507 | "showLegend": true, 1508 | "sortBy": "Max", 1509 | "sortDesc": true 1510 | }, 1511 | "tooltip": { 1512 | "mode": "multi", 1513 | "sort": "desc" 1514 | } 1515 | }, 1516 | "targets": [ 1517 | { 1518 | "datasource": { 1519 | "type": "prometheus", 1520 | "uid": "${DS_PROMETHEUS}" 1521 | }, 1522 | "editorMode": "code", 1523 | "expr": "sum(traefik_entrypoint_open_connections{entrypoint=~\"$entrypoint\"}) by (entrypoint)\n", 1524 | "legendFormat": "{{entrypoint}}", 1525 | "range": true, 1526 | "refId": "A" 1527 | } 1528 | ], 1529 | "title": "Connections per Entrypoint", 1530 | "type": "timeseries" 1531 | } 1532 | ], 1533 | "refresh": false, 1534 | "schemaVersion": 37, 1535 | "style": "dark", 1536 | "tags": [ 1537 | "traefik" 1538 | ], 1539 | "templating": { 1540 | "list": [ 1541 | { 1542 | "current": { 1543 | "selected": false, 1544 | "text": "Prometheus", 1545 | "value": "Prometheus" 1546 | }, 1547 | "hide": 0, 1548 | "includeAll": false, 1549 | "multi": false, 1550 | "name": "DS_PROMETHEUS", 1551 | "label": "datasource", 1552 | "options": [], 1553 | "query": "prometheus", 1554 | "refresh": 1, 1555 | "regex": "", 1556 | "skipUrlSync": false, 1557 | "type": "datasource" 1558 | }, 1559 | { 1560 | "current": {}, 1561 | "datasource": { 1562 | "type": "prometheus", 1563 | "uid": "${DS_PROMETHEUS}" 1564 | }, 1565 | "definition": "label_values(traefik_entrypoint_open_connections, entrypoint)", 1566 | "hide": 0, 1567 | "includeAll": true, 1568 | "multi": false, 1569 | "name": "entrypoint", 1570 | "options": [], 1571 | "query": { 1572 | "query": "label_values(traefik_entrypoint_open_connections, entrypoint)", 1573 | "refId": "StandardVariableQuery" 1574 | }, 1575 | "refresh": 1, 1576 | "regex": "", 1577 | "skipUrlSync": false, 1578 | "sort": 0, 1579 | "type": "query" 1580 | }, 1581 | { 1582 | "current": {}, 1583 | "datasource": { 1584 | "type": "prometheus", 1585 | "uid": "${DS_PROMETHEUS}" 1586 | }, 1587 | "definition": "label_values(traefik_service_open_connections, service)", 1588 | "hide": 0, 1589 | "includeAll": true, 1590 | "multi": false, 1591 | "name": "service", 1592 | "options": [], 1593 | "query": { 1594 | "query": "label_values(traefik_service_open_connections, service)", 1595 | "refId": "StandardVariableQuery" 1596 | }, 1597 | "refresh": 2, 1598 | "regex": "/([^-]+-[^-]+.*)@.*/", 1599 | "skipUrlSync": false, 1600 | "sort": 1, 1601 | "type": "query" 1602 | } 1603 | ] 1604 | }, 1605 | "time": { 1606 | "from": "now-6h", 1607 | "to": "now" 1608 | }, 1609 | "timepicker": {}, 1610 | "timezone": "", 1611 | "title": "Traefik Official Kubernetes Dashboard", 1612 | "uid": "n5bu_kv4k", 1613 | "version": 6, 1614 | "weekStart": "" 1615 | } 1616 | --------------------------------------------------------------------------------