Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Hallo zusammen! Im Rahmen meiner Studienarbeit habe ich die Möglichkeiten einer solchen inländischen Cloud-Plattform untersucht Yandex.Cloud. Die Plattform bietet verschiedene Dienste zur Lösung praktischer Probleme. Manchmal ist es jedoch notwendig, Ihre Cloud-Anwendung mit einer ziemlich umfangreichen Infrastruktur zu konfigurieren, die auf diesen Diensten basiert. In diesem Artikel möchte ich die Erfahrungen mit der Bereitstellung einer solchen Anwendung teilen.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Was möchten Sie erhalten?

Grafana - ein leistungsstarkes Werkzeug zur Lösung analytischer Probleme oder zur Überwachung von Problemen beliebiger Systeme. In der Grundkonfiguration handelt es sich dabei um eine virtuelle Maschine mit dem Grafana-Webserver sowie einer Datenbank (ClickHouse, InfluxDB usw.) mit einem Datensatz, der zur Erstellung von Analysen verwendet wird.

Nachdem Sie eine virtuelle Maschine mit einem Webserver gestartet haben, können Sie zu ihrem Host gehen und eine schöne Benutzeroberfläche erhalten, Datenbanken als Quellen für die weitere Arbeit angeben, Dashboards und Diagramme erstellen.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Die Basisversion hat einen wesentlichen Nachteil: Sie ist überhaupt nicht fehlertolerant. Das heißt, die gesamte Leistung der Anwendung hängt von der Funktionsfähigkeit einer virtuellen Maschine ab. Weigert sie sich oder öffnen 10 Personen gleichzeitig die Benutzeroberfläche, kommt es zu Problemen.

Sie lassen sich einfach lösen: Sie müssen lediglich viele identische virtuelle Maschinen mit einem Webserver bereitstellen und sie unter einen L3-Balancer stellen. Aber hier ist nicht alles so eindeutig. Grafana speichert Benutzereinstellungen (Pfade zu Datenbanken, Dashboards, Grafiken usw.) direkt auf der Festplatte seiner virtuellen Maschine. Wenn Sie also einige Einstellungen in der Benutzeroberfläche ändern, werden diese Änderungen nur auf der virtuellen Maschine angezeigt, an die uns der Balancer gesendet hat. Dies führt zu inkonsistenten Einstellungen unserer Anwendung sowie zu Problemen beim Start und bei der Verwendung.

Hier hilft eine andere Datenbank, zum Beispiel MySQL oder eine gleichwertige Datenbank. Wir teilen Grafana mit, dass sie Benutzereinstellungen in dieser „Ersatzdatenbank“ speichern soll. Danach reicht es aus, den Pfad zu dieser Datenbank auf jeder Maschine einmal anzugeben und alle anderen Benutzereinstellungen auf einer der virtuellen Maschinen zu bearbeiten, sie werden auf den übrigen Maschinen wachsen.

Hier ist ein Diagramm der endgültigen Anwendungsinfrastruktur:

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Lernen Sie, mit den Händen zu heben

MySQL und ClickHouse

Bevor eine solche Anwendung per Knopfdruck bereitgestellt werden konnte, musste man lernen, wie man die einzelnen Komponenten mit Griffen anhebt und ineinander integriert.

Hier hilft uns Yandex.Cloud, das L3-Balancer, ClickHouse und MySQL als Managed Services bereitstellt. Der Benutzer muss lediglich die Parameter angeben und warten, bis die Plattform alles in einen funktionsfähigen Zustand versetzt.

Ich habe mich registriert, eine Cloud und ein Rechnungskonto für mich erstellt. Danach bin ich in die Cloud gegangen und habe MySQL- und ClickHouse-Cluster mit minimalen Einstellungen erstellt. Warten Sie, bis sie aktiv werden.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von GrafanaBereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Sie müssen auch daran denken, in jedem Cluster eine Datenbank zu erstellen und den Zugriff darauf per Login und Passwort zu konfigurieren. Ich werde hier nicht auf Details eingehen – in der Benutzeroberfläche ist alles ziemlich offensichtlich.

Das nicht offensichtliche Detail war, dass diese Datenbanken viele Hosts haben, die ihre Fehlertoleranz bereitstellen. Allerdings benötigt Grafana für jede Datenbank, mit der es arbeitet, genau einen Host. Lange Lektüre Dokumentation Die Wolken führten mich zu einer Entscheidung. Es stellt sich heraus, dass ein Host der Form c-<cluster_id>.rw.mdb.yandexcloud.net Wird dem aktuell aktiven Cluster-Master-Host mit der entsprechenden ID zugeordnet. Das ist es, was wir Grafana geben werden.

Webserver

Jetzt liegt es am Webserver. Lassen Sie uns eine normale virtuelle Maschine mit Linux erstellen und Grafana mit unseren Händen darauf einrichten.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Stellen wir eine Verbindung über SSH her und installieren die erforderlichen Pakete.

sudo apt-get install -y apt-transport-https software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo add-apt-repository "deb https://packages.grafana.com/enterprise/deb stable main"
sudo apt-get update
sudo apt-get install -y grafana-enterprise 

Danach starten wir Grafana unter systemctl und installieren das Plugin für die Arbeit mit ClickHouse (ja, es ist nicht im Basispaket enthalten).

sudo systemctl start grafana-server
sudo systemctl enable grafana-server
sudo grafana-cli plugins install vertamedia-clickhouse-datasource

Alles danach mit einem einfachen Befehl

sudo service grafana-server start

Wir starten den Webserver. Jetzt ist es möglich, die externe IP-Adresse der virtuellen Maschine im Browser einzugeben, Port 3000 anzugeben und die schöne Grafana-Benutzeroberfläche anzuzeigen.
Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Aber keine Eile, vor der Einrichtung von Grafana dürfen Sie nicht vergessen, den Pfad zu MySQL anzugeben, damit es die Einstellungen dort speichert.

Die gesamte Konfiguration des Grafana-Webservers befindet sich in der Datei /etc/grafana/grafana.ini. Die erforderliche Zeile sieht so aus:

;url =

Wir stellen den Host dem MySQL-Cluster zur Verfügung. Dieselbe Datei enthält den Benutzernamen und das Passwort für den Zugriff auf Grafana im Bild oben, die standardmäßig beide gleich sind admin.

Sie können sed-Befehle verwenden:

sudo sed -i "s#.*;url =.*#url = mysql://${MYSQL_USERNAME}:${MYSQL_PASSWORD}@${MYSQL_CLUSTER_URI}#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_user =.*#admin_user = ${GRAFANA_USERNAME}#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_password =.*#admin_password = ${GRAFANA_PASSWORD}#" /etc/grafana/grafana.ini

Es ist Zeit, den Webserver neu zu starten!

sudo service grafana-server restart

Jetzt geben wir in der Grafana-Benutzeroberfläche ClickHouse als DataSource an.

Ich habe es geschafft, eine funktionierende Konfiguration mit den folgenden Einstellungen zu erreichen:

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Ich habe als URL angegeben https://c-<cluster_id>.rw.mdb.yandexcloud.net:8443

Alle! Wir haben eine funktionierende virtuelle Maschine mit einem Webserver, der mit CH und MySQL verbunden ist. Sie können den Datensatz bereits auf ClickHouse hochladen und Dashboards erstellen. Allerdings haben wir unser Ziel noch nicht erreicht und keine vollwertige Infrastruktur aufgebaut.

Packer

Mit Yandex.Cloud können Sie ein Disk-Image einer vorhandenen virtuellen Maschine erstellen und darauf basierend beliebig viele identische Maschinen erstellen. Genau das werden wir nutzen. Um das Bild bequem zusammenzusetzen, nehmen Sie das Werkzeug Packer von HashiCorp. Als Eingabe wird eine JSON-Datei mit Anweisungen zum Erstellen des Bildes benötigt.

Unsere JSON-Datei besteht aus zwei Blöcken: Buildern und Provisionern. Der erste Block beschreibt die Parameter des Bildes selbst als Ganzes und der zweite beschreibt die Anweisungen zum Füllen des Bildes mit dem erforderlichen Inhalt.

Builders

{
"builders": [
    {
      "type": "yandex",
      "endpoint": "{{user `endpoint`}}",
      "folder_id": "<folder_id>",
      "subnet_id": "{{user `subnet_id`}}",
      "zone": "{{user `zone`}}",
      "labels": {},
      "use_ipv4_nat": true,
      "use_internal_ip": false,
      "service_account_key_file": "<service_account_key_file>",
      "image_name": "grafana-{{timestamp}}",
      "image_family": "grafana",
      "image_labels": {},
      "image_description": "GRAFANA",
      "source_image_family": "ubuntu-1804-lts",
      "disk_size_gb": 3,
      "disk_type": "network-hdd",
      "ssh_username": "ubuntu"
    }
  ],
...
}

In dieser Vorlage müssen Sie die Kennung des Abschnitts in der Cloud festlegen, in dem Sie ein Bild erstellen möchten, sowie den Pfad zur Datei mit den Schlüsseln des zuvor in diesem Abschnitt erstellten Dienstkontos. Weitere Informationen zum Erstellen von Dienstkonten und Schlüsseln in Form einer Datei finden Sie im entsprechenden Abschnitt. Dokumentation.

Diese Konfiguration besagt, dass das Disk-Image basierend auf der Plattform erstellt wird ubuntu-1804-lts, platziert im entsprechenden Benutzerabschnitt in der Bildfamilie GRAFANA unter dem Namen grafana-{{timestamp}}.

Versorger

Nun zum interessanteren Teil der Konfiguration. Es beschreibt die Abfolge von Aktionen, die auf einer virtuellen Maschine ausgeführt werden müssen, bevor ihr Zustand in einem Disk-Image eingefroren wird.

{
...,
"provisioners": [
    {
            "type": "shell",
            "pause_before": "5s",
            "scripts": [
                "prepare-ctg.sh"
            ]
        },
    {
            "type": "file",
            "source": "setup.sh",
            "destination": "/opt/grafana/setup.sh"
        },
        {
            "type": "shell",
        "execute_command": "sudo {{ .Vars }} bash '{{ .Path }}'",
            "pause_before": "5s",
            "scripts": [
                "install-packages.sh",
                "grafana-setup.sh",
                "run-setup-at-reboot.sh"
        ]
        }
  ]
}

Dabei sind alle Aktionen in 3 Phasen unterteilt. Im ersten Schritt wird ein einfaches Skript ausgeführt, das ein Hilfsverzeichnis erstellt.

Prepare-ctg.sh:

#!/bin/bash
sudo mkdir -p /opt/grafana
sudo chown -R ubuntu:ubuntu /opt/grafana

Im nächsten Schritt platzieren wir in diesem Verzeichnis ein Skript, das unmittelbar nach dem Start der virtuellen Maschine ausgeführt werden muss. Dieses Skript fügt die festzulegenden Benutzervariablen in die Konfiguration von Grafana ein und startet den Webserver neu.

setup.sh:

#!/bin/bash
CLUSTER_ID="<cluster_id>"
USERNAME="<username>"
PASSWORD="<password>"
sudo sed -i "s#.*;url =.*#url = mysql://${USERNAME}:${PASSWORD}@c-${CLUSTER_ID}.rw.mdb.yandexcloud.net#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_user =.*#admin_user = ${USERNAME}#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_password =.*#admin_password = ${PASSWORD}#" /etc/grafana/grafana.ini
sudo service grafana-server restart

Danach gibt es drei Dinge zu tun:
1) Pakete installieren
2) Starten Sie Grafana unter systemctl und installieren Sie das ClickHouse-Plugin
3) Stellen Sie das Skript setup.sh in die Warteschlange, damit es sofort nach dem Einschalten der virtuellen Maschine ausgeführt wird.

install-packages.sh:

#!/bin/bash
sudo systemd-run --property='After=apt-daily.service apt-daily-upgrade.service' --wait /bin/true
sudo apt-get install -y apt-transport-https
sudo apt-get install -y software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo add-apt-repository "deb https://packages.grafana.com/enterprise/deb stable main"
sudo apt-get update
sudo apt-get install -y grafana-enterprise 

grafana-setup.sh:

#!/bin/bash
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
sudo grafana-cli plugins install vertamedia-clickhouse-datasource

run-setup-at-reboot.sh:

#!/bin/bash
chmod +x /opt/grafana/setup.sh
cat > /etc/cron.d/first-boot <<EOF
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
@reboot root /bin/bash /opt/grafana/setup.sh > /var/log/yc-setup.log 2>&1
EOF
chmod +x /etc/cron.d/first-boot;

Jetzt muss noch Packer ausgeführt werden und das Ausgabebild in der angegebenen Partition abgelegt werden. Beim Erstellen einer virtuellen Maschine können Sie diese als Bootdiskette auswählen und erhalten nach dem Start einen fertigen Grafana-Webserver.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana
Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Instanzgruppe und Balancer

Sobald es ein Disk-Image gibt, mit dem Sie viele identische Grafana-Webserver erstellen können, können wir eine Instanzgruppe erstellen. Auf der Yandex.Cloud-Plattform bezeichnet dieser Begriff die Vereinigung virtueller Maschinen mit gleichen Eigenschaften. Beim Erstellen einer Instanzgruppe wird der Prototyp aller Maschinen dieser Gruppe konfiguriert und anschließend die Eigenschaften der Gruppe selbst (z. B. die minimale und maximale Anzahl aktiver Maschinen). Wenn die aktuelle Anzahl dieses Kriterium nicht erfüllt, entfernt die Instanzgruppe selbst unnötige Maschinen oder erstellt neue im Bild und Abbild.

Im Rahmen unserer Aufgabe erstellen wir eine Instanzgruppe von Webservern, die aus dem zuvor erstellten Disk-Image erzeugt werden.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Die letzte Instanzgruppeneinstellung ist wirklich bemerkenswert. Die Zielgruppe in der Integration mit Load Balancer hilft Ihnen durch Drücken einiger Tasten beim Einrichten eines L3-Balancers auf den virtuellen Maschinen dieser Gruppe.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Beim Aufbau des Balancers habe ich zwei wichtige Punkte umgesetzt:

  1. Ich habe es so gemacht, dass der Balancer Benutzerverkehr auf Port 80 akzeptiert und ihn auf Port 3000 der virtuellen Maschinen umleitet, genau dort, wo Grafana lebt.
  2. Richten Sie Maschinenzustandsprüfungen ein, indem Sie sie an Port 3000 pingen.

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Mini-Gesamtsumme

Schließlich konnten wir die gewünschte Anwendungsinfrastruktur manuell bereitstellen und verfügen nun über einen äußerst belastbaren Grafana-Dienst. Es ist lediglich erforderlich, die IP-Adresse des Balancers als Einstiegspunkt zur Anwendung und den Host des ClickHouse-Clusters zu kennen, um den Datensatz in diesen zu laden.

Es scheint ein Sieg zu sein? Ja, Sieg. Aber irgendetwas stört mich immer noch. Der gesamte obige Prozess erfordert viele manuelle Aktionen und lässt sich überhaupt nicht skalieren. Ich möchte ihn nach Möglichkeit automatisieren. Dies wird der Schwerpunkt des nächsten Abschnitts sein.

Integration mit Terraform

Wir werden wieder ein Tool von HashiCorp namens verwenden Terraform. Es hilft dabei, die gesamte Anwendungsinfrastruktur auf Knopfdruck bereitzustellen, basierend auf einigen vom Benutzer übergebenen Variablen. Schreiben wir ein Rezept, das in verschiedenen Abschnitten verschiedener Benutzer mehrmals ausgeführt werden kann.

Die gesamte Arbeit mit Terraform läuft darauf hinaus, eine Konfigurationsdatei zu schreiben (*.tf) und die Schaffung einer darauf basierenden Infrastruktur.

Variablen

Ganz am Anfang der Datei werden wir die Variablen herausnehmen, die bestimmen, wo und wie die zukünftige Infrastruktur bereitgestellt wird.

variable "oauth_token" {
    type = string
    default = "<oauth-token>"
}
variable "cloud_id" {
    type = string
    default = "<cloud-id>"
}
variable "folder_id" {
    type = string
    default = "<folder_id>"
}
variable "service_account_id" {
    type = string
    default = "<service_account_id>"
}
variable "image_id" {
    type = string
    default = "<image_id>"
}
variable "username" {
    type = string
    default = "<username>"
}
variable "password" {
    type = string
    default = "<password>"
}
variable "dbname" {
    type = string
    default = "<dbname>"
}
variable "public_key_path" {
    type = string
    default = "<path to ssh public key>"
}

Der gesamte Prozess der Bereitstellung einer Anwendung besteht darin, ein Disk-Image zu erstellen und diese Variablen festzulegen. Lassen Sie mich erklären, wofür sie verantwortlich sind:

oauth_token — ein Token für den Zugriff auf die Cloud. Erhältlich bei Link.
cloud_id - Kennung der Cloud, in der wir die Anwendung bereitstellen
Ordner-ID — Kennung des Abschnitts, in dem wir die Anwendung bereitstellen
service_account_id — Kennung des Dienstkontos im entsprechenden Abschnitt der Cloud.
image_id - Kennung des mit Packer erhaltenen Disk-Images
Benutzername и Passwort - Benutzername und Passwort für den Zugriff auf beide Datenbanken und den Grafana-Webserver
Datenbankname - Datenbankname innerhalb von CH- und MySQL-Clustern
public_key_path - den Pfad zur Datei mit Ihrem öffentlichen SSH-Schlüssel, mit dem Sie unter diesem Namen eine Verbindung herstellen können ubuntu zu virtuellen Maschinen mit Webservern

Anbietereinstellung

Jetzt müssen Sie den Terraform-Anbieter konfigurieren – in unserem Fall Yandex:

provider "yandex" {
  token     = var.oauth_token
  cloud_id  = var.cloud_id
  folder_id = var.folder_id
  zone      = "ru-central1-a"
}

Sie sehen, dass wir hier die oben definierten Variablen verwenden.

Netzwerk und Cluster

Lassen Sie uns nun ein Netzwerk erstellen, in dem Elemente unserer Infrastruktur kommunizieren, drei Subnetze (eines in jeder Region) und die CH- und MySQL-Cluster aufbauen.


resource "yandex_vpc_network" "grafana_network" {}

resource "yandex_vpc_subnet" "subnet_a" {
  zone           = "ru-central1-a"
  network_id     = yandex_vpc_network.grafana_network.id
  v4_cidr_blocks = ["10.1.0.0/24"]
}

resource "yandex_vpc_subnet" "subnet_b" {
  zone           = "ru-central1-b"
  network_id     = yandex_vpc_network.grafana_network.id
  v4_cidr_blocks = ["10.2.0.0/24"]
}

resource "yandex_vpc_subnet" "subnet_c" {
  zone           = "ru-central1-c"
  network_id     = yandex_vpc_network.grafana_network.id
  v4_cidr_blocks = ["10.3.0.0/24"]
}

resource "yandex_mdb_clickhouse_cluster" "ch_cluster" {
  name        = "grafana-clickhouse"
  environment = "PRODUCTION"
  network_id  = yandex_vpc_network.grafana_network.id

  clickhouse {
    resources {
      resource_preset_id = "s2.micro"
      disk_type_id       = "network-ssd"
      disk_size          = 16
    }
  }

  zookeeper {
    resources {
      resource_preset_id = "s2.micro"
      disk_type_id       = "network-ssd"
      disk_size          = 10
    }
  }

  database {
    name = var.dbname
  }

  user {
    name     = var.username
    password = var.password
    permission {
      database_name = var.dbname
    }
  }

  host {
    type      = "CLICKHOUSE"
    zone      = "ru-central1-a"
    subnet_id = yandex_vpc_subnet.subnet_a.id
  }

  host {
    type      = "CLICKHOUSE"
    zone      = "ru-central1-b"
    subnet_id = yandex_vpc_subnet.subnet_b.id
  }

  host {
    type      = "CLICKHOUSE"
    zone      = "ru-central1-c"
    subnet_id = yandex_vpc_subnet.subnet_c.id
  }

  host {
    type      = "ZOOKEEPER"
    zone      = "ru-central1-a"
    subnet_id = yandex_vpc_subnet.subnet_a.id
  }

  host {
    type      = "ZOOKEEPER"
    zone      = "ru-central1-b"
    subnet_id = yandex_vpc_subnet.subnet_b.id
  }

  host {
    type      = "ZOOKEEPER"
    zone      = "ru-central1-c"
    subnet_id = yandex_vpc_subnet.subnet_c.id
  }
}

resource "yandex_mdb_mysql_cluster" "mysql_cluster" {
  name        = "grafana_mysql"
  environment = "PRODUCTION"
  network_id  = yandex_vpc_network.grafana_network.id
  version     = "8.0"

  resources {
    resource_preset_id = "s2.micro"
    disk_type_id       = "network-ssd"
    disk_size          = 16
  }

  database {
    name = var.dbname
  }

  user {
    name     = var.username
    password = var.password
    permission {
      database_name = var.dbname
      roles         = ["ALL"]
    }
  }

  host {
    zone      = "ru-central1-a"
    subnet_id = yandex_vpc_subnet.subnet_a.id
  }
  host {
    zone      = "ru-central1-b"
    subnet_id = yandex_vpc_subnet.subnet_b.id
  }
  host {
    zone      = "ru-central1-c"
    subnet_id = yandex_vpc_subnet.subnet_c.id
  }
}

Wie Sie sehen können, ist jeder der beiden Cluster ziemlich fehlertolerant, da er in drei Availability Zones platziert ist.

Webserver

Es scheint, dass man im gleichen Sinne weitermachen kann, aber ich bin auf Schwierigkeiten gestoßen. Zuvor habe ich zuerst den MySQL-Cluster erstellt und erst danach, da ich seine ID kannte, ein Disk-Image mit der gewünschten Konfiguration erstellt, in dem ich den Host für den Cluster angegeben habe. Aber jetzt kennen wir die Cluster-ID nicht vor dem Start von Terraform, auch nicht zum Zeitpunkt der Image-Erstellung. Also musste ich auf Folgendes zurückgreifen Trick.

Mithilfe des Metadatendienstes von Amazon übergeben wir einige Parameter an die virtuelle Maschine, die diese akzeptiert und verarbeitet. Wir benötigen die Maschine, um zu den Metadaten für den MySQL-Host des Clusters und zum Benutzernamen-Passwort zu gelangen, das der Benutzer nach dem Start in der Terraform-Datei angegeben hat. Ändern Sie den Inhalt der Datei geringfügig setup.sh, das ausgeführt wird, wenn die virtuelle Maschine eingeschaltet ist.

setup.sh:

#!/bin/bash
CLUSTER_URI="$(curl -H 'Metadata-Flavor:Google' http://169.254.169.254/computeMetadata/v1/instance/attributes/mysql_cluster_uri)"
USERNAME="$(curl -H 'Metadata-Flavor:Google' http://169.254.169.254/computeMetadata/v1/instance/attributes/username)"
PASSWORD="$(curl -H 'Metadata-Flavor:Google' http://169.254.169.254/computeMetadata/v1/instance/attributes/password)"
sudo sed -i "s#.*;url =.*#url = mysql://${USERNAME}:${PASSWORD}@${CLUSTER_URI}#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_user =.*#admin_user = ${USERNAME}#" /etc/grafana/grafana.ini
sudo sed -i "s#.*;admin_password =.*#admin_password = ${PASSWORD}#" /etc/grafana/grafana.ini
sudo service grafana-server restart

Instanzgruppe und Balancer

Nachdem wir das neue Disk-Image neu erstellt haben, können wir endlich unsere Datei für Terraform hinzufügen.

Wir geben an, dass wir ein vorhandenes Disk-Image verwenden möchten:

data "yandex_compute_image" "grafana_image" {
  image_id = var.image_id
}

Jetzt erstellen wir eine Instanzgruppe:

resource "yandex_compute_instance_group" "grafana_group" {
  name               = "grafana-group"
  folder_id          = var.folder_id
  service_account_id = var.service_account_id
  instance_template {
    platform_id = "standard-v1"
    resources {
      memory = 1
      cores  = 1
    }
    boot_disk {
      mode = "READ_WRITE"
      initialize_params {
        image_id = data.yandex_compute_image.grafana_image.id
        size     = 4
      }
    }
    network_interface {
      network_id = yandex_vpc_network.grafana_network.id
      subnet_ids = [yandex_vpc_subnet.subnet_a.id, yandex_vpc_subnet.subnet_b.id, yandex_vpc_subnet.subnet_c.id]
      nat = "true"
    }
    metadata = {
      mysql_cluster_uri = "c-${yandex_mdb_mysql_cluster.mysql_cluster.id}.rw.mdb.yandexcloud.net:3306/${var.dbname}"
      username = var.username
      password = var.password
      ssh-keys = "ubuntu:${file("${var.public_key_path}")}"
    }
    network_settings {
      type = "STANDARD"
    }
  }

  scale_policy {
    fixed_scale {
      size = 6
    }
  }

  allocation_policy {
    zones = ["ru-central1-a", "ru-central1-b", "ru-central1-c"]
  }

  deploy_policy {
    max_unavailable = 2
    max_creating    = 2
    max_expansion   = 2
    max_deleting    = 2
  }

  load_balancer {
    target_group_name = "grafana-target-group"
  }
}

Es lohnt sich, darauf zu achten, wie wir die Metadaten übergeben haben cluster_uri, username и password. Es ist ihre virtuelle Maschine, die es beim Start erhält und in die Grafana-Konfiguration einfügt.

Es geht um den Balancer.

resource "yandex_lb_network_load_balancer" "grafana_balancer" {
  name = "grafana-balancer"

  listener {
    name = "grafana-listener"
    port = 80
    target_port = 3000
    external_address_spec {
      ip_version = "ipv4"
    }
  }

  attached_target_group {
    target_group_id = yandex_compute_instance_group.grafana_group.load_balancer.0.target_group_id

    healthcheck {
      name = "healthcheck"
      tcp_options {
        port = 3000
      }
    }
  }
}

Ein bisschen Zucker

Es war sehr wenig übrig. Nachdem die Infrastruktur bereitgestellt wurde, müssen Sie zur Grafana-Benutzeroberfläche gehen und den CH-Cluster (dessen ID Sie noch benötigen) manuell als Datenquelle hinzufügen. Aber Terraform kennt die Cluster-ID. Bringen wir ihn dazu, den Job zu Ende zu bringen.

Fügen wir einen neuen Anbieter hinzu – Grafana – und geben Sie die Balancer-IP als Host ein. Alle Änderungen, die Terraform auf der Maschine vornimmt, die sein Balancer bestimmt, werden in MySQL und damit auf allen anderen Maschinen wachsen.

provider "grafana" {
  url  = "http://${[for s in yandex_lb_network_load_balancer.grafana_balancer.listener: s.external_address_spec.0.address].0}"
  auth = "${var.username}:${var.password}"
}

resource "grafana_data_source" "ch_data_source" {
  type          = "vertamedia-clickhouse-datasource"
  name          = "grafana"
  url           = "https://c-${yandex_mdb_clickhouse_cluster.ch_cluster.id}.rw.mdb.yandexcloud.net:8443"
  basic_auth_enabled = "true"
  basic_auth_username = var.username
  basic_auth_password = var.password
  is_default = "true"
  access_mode = "proxy"
}

Lass uns kämmen

Balancer-IP und ClickHouse-Cluster-Host anzeigen

output "grafana_balancer_ip_address" {
  value = [for s in yandex_lb_network_load_balancer.grafana_balancer.listener: s.external_address_spec.0.address].0
}

output "clickhouse_cluster_host" {
  value = "https://c-${yandex_mdb_clickhouse_cluster.ch_cluster.id}.rw.mdb.yandexcloud.net:8443"
}

Kann laufen

Alle! Unsere Konfigurationsdatei ist fertig und wir können Terraform durch das Setzen von Variablen anweisen, alles auszulösen, was wir oben beschrieben haben. Der gesamte Vorgang hat bei mir etwa 15 Minuten gedauert.
Am Ende sehen Sie eine schöne Nachricht:

Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
Outputs:

clickhouse_cluster_host = https://c-c9q14ipa2ngadqsbp2iq.rw.mdb.yandexcloud.net:8443
grafana_balancer_ip_address = 130.193.50.25

Und in der Cloud werden Elemente der erhöhten Infrastruktur sichtbar sein:

Bereitstellung verteilter Dienste in Yandex.Cloud am Beispiel von Grafana

Summieren

Am Beispiel von Grafana kann nun jeder von Ihnen Anwendungen mit weitläufiger Cloud-Architektur auf der Yandex.Cloud-Plattform bereitstellen. Nützliche Tools von HashiCorp wie Packer und Terraform können Ihnen dabei helfen. Ich hoffe, dass jemand diesen Artikel nützlich findet 🙂

PS: Unten füge ich einen Link zum Repository hinzu, in dem Sie vorgefertigte Rezepte für Packer und Terraform finden, von denen ich Fragmente in diesem Artikel zitiert habe.

Repository

Source: habr.com

Kommentar hinzufügen