Documentation
¶
Overview ¶
Package observability manages a realm's monitoring stack: Grafana Alloy, which collects the Slurm metrics, the container resource use and the journals of the monitored clusters' nodes, Prometheus and Loki, which store them, and Grafana, which shows them. The stack runs as four containers on the realm's mesh network. The package generates their configuration from the nodes it is given; pkg/cluster decides which nodes those are and when the stack is created, synced and removed.
It is not called monitor: pkg/monitor is the Docker and systemd event watcher of the readiness probes.
Index ¶
- Constants
- Variables
- func CgroupPath(driver string, id docker.ContainerID) string
- func ContainerName(realm string, s Service) docker.ContainerName
- func DNSName(realm string, s Service) string
- func Dashboards() map[string][]byte
- func GenerateAlloyConfig(realm, cgroupDriver string, targets []Target) string
- func GrafanaProvisioning(realm string) map[string][]byte
- func Images() []string
- func JournalSubpath(cluster, node string) string
- func JournalVolume(realm string) docker.VolumeName
- func VolumeName(realm string, s Service) docker.VolumeName
- type Check
- type Collection
- type Manager
- func (m *Manager) EnsureStack(ctx context.Context, dnsIP, alloyConfig string) (changed bool, err error)
- func (m *Manager) Fingerprint() string
- func (m *Manager) Remove(ctx context.Context) error
- func (m *Manager) RemoveJournals(ctx context.Context, cluster string, nodes ...string) error
- func (m *Manager) RemoveVolumes(ctx context.Context) error
- func (m *Manager) ResetJournals(ctx context.Context, cluster string, nodes ...string) error
- func (m *Manager) ServiceReady(ctx context.Context, s Service) error
- func (m *Manager) Start(ctx context.Context) (found bool, err error)
- func (m *Manager) Status(ctx context.Context) ([]ServiceStatus, bool, error)
- func (m *Manager) Sync(ctx context.Context, alloyConfig string) error
- func (m *Manager) URL(s Service, p string) string
- func (m *Manager) WaitReady(ctx context.Context) error
- type Service
- type ServiceStatus
- type Target
Constants ¶
const ( // DashboardsDir is where the sind dashboards are provisioned from. DashboardsDir = grafanaProvisioning + "/dashboards/sind" // PrometheusUID and LokiUID are the fixed UIDs of the datasources, // which the dashboards refer to. PrometheusUID = "sind-prometheus" LokiUID = "sind-loki" )
Grafana's provisioning.
const ( AlloyImage = "grafana/alloy:v1.20.1" PrometheusImage = "prom/prometheus:v3.15.0" LokiImage = "grafana/loki:3.7.8" GrafanaImage = "grafana/grafana:13.2.3" )
The stack's images, each pinned and bumped on its own. Grafana must be the standard image: its Prometheus and Loki datasources ship only in the standard image's bundled plugins, and the -slim image would fetch them at start. The standard image is also the only one of the four with curl, which sind runs there to reach the others.
const ( GrafanaPort = "3000" PrometheusPort = "9090" LokiPort = "3100" AlloyPort = "12345" )
Ports the services listen on, on the mesh network.
const AlloyConfigPath = "/etc/alloy/sind.alloy"
AlloyConfigPath is the configuration file sind writes into the Alloy container, before its first start and at every sync.
const DefaultReadyTimeout = 2 * time.Minute
DefaultReadyTimeout is how long EnsureStack waits for the stack to be ready, when the context has no earlier deadline: Loki reports ready only some seconds after it starts.
const JournalDir = "/var/log/sind"
JournalDir is where Alloy mounts the journal volume.
const LabelVersion = "sind.observability.version"
LabelVersion is the label of the stack's containers that records the fingerprint of the stack sind created them with (see Fingerprint): its images, configuration and dashboards. A create that finds another fingerprint recreates the containers, keeping their volumes.
const NodeJournalDir = "/var/log/journal"
NodeJournalDir is where a monitored node mounts its directory of the journal volume: journald writes a persistent journal there.
Variables ¶
var Services = []Service{ServiceGrafana, ServicePrometheus, ServiceLoki, ServiceAlloy}
Services lists the stack's services in the order sind get monitoring shows them.
Functions ¶
func CgroupPath ¶
func CgroupPath(driver string, id docker.ContainerID) string
CgroupPath returns the cgroup of a container under a cgroup driver: /system.slice/docker-<id>.scope with systemd, /docker/<id> with cgroupfs.
func ContainerName ¶
func ContainerName(realm string, s Service) docker.ContainerName
ContainerName returns the container of a service in a realm: <realm>-<service>. Two-part names never equal a cluster's <realm>-<cluster>-<type> resources.
func Dashboards ¶
Dashboards returns the sind dashboards' JSON models by file name.
func GenerateAlloyConfig ¶
GenerateAlloyConfig returns Alloy's configuration for a realm's monitored nodes, under the daemon's cgroup driver (see CgroupPath):
- prometheus.scrape of slurmctld's metrics endpoints on every managed controller, by container name on the mesh network, without following redirects: a standby controller answers 303, so up is 1 only on the controller in control;
- prometheus.exporter.blackbox with the Slurm daemon probes of Collect;
- prometheus.exporter.cadvisor on the nodes' cgroups, read from the host's cgroup tree, and a relabeling of its series to the cluster, node and role, and the cgroup below the node, from which the job_id and unit labels come;
- a loki.source.journal per node, on its directory of the journal volume, with the unit and level of each entry, the level parsed from the message for the Slurm daemons and MariaDB, which log all their lines at priority info;
- remote writes to Prometheus and Loki by container name.
Every series and log line carries realm, cluster and node, so a dashboard can link a panel to the matching logs.
func GrafanaProvisioning ¶
GrafanaProvisioning returns the files sind copies into /etc/grafana/provisioning before Grafana's first start, by path below it: the datasources, the dashboard provider and the dashboards.
func Images ¶
func Images() []string
Images returns the stack's images, in the order of its services.
func JournalSubpath ¶
JournalSubpath returns a node's directory in the journal volume.
func JournalVolume ¶
func JournalVolume(realm string) docker.VolumeName
JournalVolume returns the realm's journal volume, where each monitored node writes its journal into a directory of its own, <cluster>/<node>, and Alloy reads them.
func VolumeName ¶
func VolumeName(realm string, s Service) docker.VolumeName
VolumeName returns the data volume of a service in a realm.
Types ¶
type Check ¶
type Check struct {
Service string // slurmctld, slurmd or slurmdbd
Check string // live, ready or tcp
Module string // the blackbox module: http or tcp
Port string
Path string // the HTTP path, empty for tcp
}
Check is a health probe of a Slurm daemon on a node.
type Collection ¶
type Collection struct {
// Journal and Cgroups are collected from every monitored node: its
// journal and its container's and units' resource use.
Journal, Cgroups bool
// SlurmMetrics scrapes slurmctld's /metrics endpoints.
SlurmMetrics bool
// Checks are the node's Slurm daemon probes.
Checks []Check
}
Collection is what the stack collects from a node.
func Collect ¶
func Collect(role config.Role, managed bool) Collection
Collect returns what the stack collects from a node of a role, managed or not: the journal and the cgroups of every node, slurmctld's metrics and probes on managed controllers, slurmd's on managed workers and slurmdbd's on a managed db node. Unmanaged nodes run no Slurm of sind's, so there are no Slurm probes that would only show sind's daemons as down. slurmdbd serves no HTTP, so its probe is a TCP connect; sackd and slurmrestd get none.
type Manager ¶
type Manager struct {
Docker *docker.Client
Realm string
Pull bool // pull the stack's images afresh (--pull always)
// Interval is the delay between readiness probe rounds, zero for
// probe.DefaultInterval; ReadyTimeout bounds the wait, zero for
// DefaultReadyTimeout.
Interval time.Duration
ReadyTimeout time.Duration
}
Manager creates, configures and removes a realm's monitoring stack.
func NewManager ¶
NewManager returns a Manager of a realm's stack.
func (*Manager) EnsureStack ¶
func (m *Manager) EnsureStack(ctx context.Context, dnsIP, alloyConfig string) (changed bool, err error)
EnsureStack brings up the realm's stack on the mesh network: it creates the data volumes and containers that do not exist yet, with alloyConfig as Alloy's first configuration, recreates those of another fingerprint (another sind version's) and keeps their volumes, starts those that are stopped, and waits until all four are ready. dnsIP is the mesh DNS container's pinned address, from which Grafana, Prometheus and Loki take theirs (see mesh.ServiceIP); empty for a mesh without one, whose stack gets dynamic addresses. It reports whether it created or started a container.
func (*Manager) Fingerprint ¶
Fingerprint returns the fingerprint of the stack a realm gets from this sind: of its services' container arguments and of the files sind provisions them with, except Alloy's configuration, which each sync rewrites, and of --pull. A stack created by another sind version, with other images, arguments, configuration or dashboards, has another one.
func (*Manager) Remove ¶
Remove removes the stack's containers, keeping their volumes. It finds them by their labels first, so that a realm without a stack costs one docker call.
func (*Manager) RemoveJournals ¶
RemoveJournals removes the journal directories of nodes of a cluster, or the cluster's whole directory when no node is given.
func (*Manager) RemoveVolumes ¶
RemoveVolumes removes the stack's data volumes and the journal volume, once nothing mounts them. It finds them by their Compose project first.
func (*Manager) ResetJournals ¶
ResetJournals empties the journal directories of nodes of a cluster, creating them, so that a node's container can mount its directory and shows no journal of an earlier node of its name.
func (*Manager) ServiceReady ¶
ServiceReady checks that a service's container runs and that its readiness endpoint answers with success, through Grafana's curl. A stopped or dead container is a probe.TerminalError.
func (*Manager) Start ¶
Start starts the stack's containers that are stopped, as after a host reboot, and waits until the stack is ready. It creates nothing: a realm without any of the containers has no stack, and found is false then. A stack that lacks some of its containers is an error, as it cannot get ready; EnsureStack creates them again.
func (*Manager) Status ¶
Status returns the state of each of the stack's services, in the order of Services, and whether any of their containers exists. A running service is ready when ServiceReady passes; that check runs in Grafana, so without Grafana running none is checked. Like Remove, it lists the stack's containers first, so that a realm without a stack costs one docker call, and inspects those that exist in one more.
type Service ¶
type Service string
Service is one of the stack's containers.
type ServiceStatus ¶
type ServiceStatus struct {
Service Service `json:"service"`
Container docker.ContainerName `json:"container"`
State docker.ContainerState `json:"status"` // empty when the container does not exist
Image string `json:"image"`
IP string `json:"ip"`
DNSName string `json:"dns_name,omitempty"` // empty for Alloy, which has none
Port string `json:"port"`
Ready bool `json:"ready"`
Checked bool `json:"checked"` // whether Ready was checked, which needs Grafana running
}
ServiceStatus is the state of one of the stack's services.
type Target ¶
type Target struct {
Cluster string
Node string // the node's hostname, e.g. worker-0
Role config.Role
Managed bool // sind manages Slurm on the node (the sind.managed label)
Container docker.ContainerName
ContainerID docker.ContainerID // the full ID, which names the node's cgroup
}
Target is a monitored node: a node container of a monitored cluster, which mounts its directory of the realm's journal volume.