Skip to main content

Grafana Installation with Ansible, Add VictoriaMetrics Datasource

419 words·
Grafana Ansible Kubernetes Helm VictoriaMetrics
Table of Contents

Grafana Installation
#

Ansible Playbook
#

  • helm_grafana.yml
---
- name: Grafana Helm Chart Installation
  hosts: localhost
  connection: local
  gather_facts: false
  become: false
  vars:
    # Vault Secrets
    credentials: "{{ lookup('community.hashi_vault.vault_kv2_get', 'services/grafana', engine_mount_point='homelab_prod').secret }}"
    postgres: "{{ lookup('community.hashi_vault.vault_kv2_get', 'services/postgres/grafana', engine_mount_point='homelab_prod').secret }}"
    # Postgres Server
    postgres_db: "{{ postgres.grafana_db }}"
    postgres_user: "{{ postgres.grafana_user }}"
    postgres_pw: "{{ postgres.grafana_pw }}"
    postgres_ip: "192.168.70.87"
    # Grafana Configuration
    grafana_admin_user: "admin"
    grafana_admin_pw: "{{ credentials.admin_pw }}"
    # Helm Configuration
    helm_chart: "grafana/grafana"
    helm_chart_version: "10.3.0"
    helm_release_name: "grafana"
    kubernetes_namespace: "grafana"
    # Storage Confiugration
    kubernetes_storage_class: "csi-nfs-1-prod"
    kubernetes_storage_size: "4Gi"
    # Ingress Configuration
    kubernetes_ingress_class: "nginx-metallb"
    kubernetes_cluster_issuer: "cluster-issuer-dns01"
    kubernetes_ingress_url: "grafana.jklug.work"


  roles:
    - helm_grafana
# Run Ansible playbook:
ansible-playbook playbooks/helm_grafana.yml -i inventory



Ansible Role
#

Tasks
#

  • tasks/main.yml
# Grafana Setup

---
- name: Add Helm repository
  kubernetes.core.helm_repository:
    name: "grafana"
    repo_url: "https://grafana.github.io/helm-charts"
    force_update: true

- name: Create namespace
  kubernetes.core.k8s:
    api_version: v1
    kind: Namespace
    name: "{{ kubernetes_namespace }}"
    state: present

- name: Create Grafana Postgres Credentials Secret
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Secret
      metadata:
        name: grafana-db-credentials
        namespace: "{{ kubernetes_namespace }}"
      type: Opaque
      data:
        # must be base64-encoded
        GRAFANA_DB_PASSWORD: "{{ postgres_pw | b64encode }}"

- name: Install Helm Chart
  kubernetes.core.helm:
    name: "{{ helm_release_name }}"
    chart_ref: "{{ helm_chart }}"
    chart_version: "{{ helm_chart_version }}"
    release_namespace: "{{ kubernetes_namespace }}"
    create_namespace: false
    wait: true  # Ansible waits till all resources are ready
    atomic: true  # Auto-rollback on failure
    values: "{{ lookup('template', 'grafana-values.yml.j2') | from_yaml }}"

Templates
#

  • templates/grafana-values.yml.j2
replicas: 1

autoscaling:
  enabled: false

deploymentStrategy:
  type: RollingUpdate

readinessProbe:
  httpGet:
    path: /api/health
    port: 3000

livenessProbe:
  httpGet:
    path: /api/health
    port: 3000
  initialDelaySeconds: 60
  timeoutSeconds: 30
  failureThreshold: 10

service:
  enabled: true
  type: ClusterIP

ingress:
  enabled: true
  ingressClassName: "{{ kubernetes_ingress_class }}"
  annotations:
    cert-manager.io/cluster-issuer: "{{ kubernetes_cluster_issuer }}"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
  labels: {}
  path: /
  pathType: Prefix
  hosts:
    - {{ kubernetes_ingress_url }}
  extraPaths: []
  tls:
    - secretName: grafana-tls
      hosts:
        - {{ kubernetes_ingress_url }}

resources: {}
#  limits:
#    cpu: 100m
#    memory: 128Mi
#  requests:
#    cpu: 100m
#    memory: 128Mi

persistence:
  type: pvc
  enabled: true
  storageClassName: {{ kubernetes_storage_class }}
  ## (Optional) Use this to bind the claim to an existing PersistentVolume (PV) by name.
  volumeName: ""
  accessModes:
    - ReadWriteOnce
  size: {{ kubernetes_storage_size }}


adminUser: {{ grafana_admin_user }}
adminPassword: {{ grafana_admin_pw }}

assertNoLeakedSecrets: false

# Grafana SSO Configuration
grafana.ini:
  auth.azuread:
    enabled: false

  database:
    type: postgres
    host: "{{ postgres_ip }}:5432"
    name: {{ postgres_db }}
    user: "{{ postgres_user }}"
    password: $__env{GRAFANA_DB_PASSWORD}   # use env var instead of plain text
    ssl_mode: disable 

envFromSecrets:
  - name: grafana-db-credentials

plugins:
  - victoriametrics-metrics-datasource
  - victoriametrics-logs-datasource


datasources:
  datasources.yaml:
    apiVersion: 1
    datasources:
    - name: VictoriaMetrics
      type: prometheus
      url: http://vmsingle-vm-vmks.victoria-metrics.svc.cluster.local:8428
      access: proxy
      isDefault: true

    #deleteDatasources:
    #  - name: datasource-name