Skip to content

Commit bd2e6e2

Browse files
authored
Add PodMonitor + ServiceMonitor TargetLabels (#518)
* * Add PodMonitor * Add TargetLabels to ServiceMonitor * Include backup-exporter port in existing postgres-exporter service (and hence reuse the existing servicemonitor) * Also add walGExporter port to ServiceMonitor * Fix copy&paste error
1 parent abeaeed commit bd2e6e2

File tree

2 files changed

+123
-8
lines changed

2 files changed

+123
-8
lines changed

controllers/postgres_controller.go

Lines changed: 116 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,19 @@ import (
5656
const (
5757
postgresExporterServiceName string = "postgres-exporter"
5858
postgresExporterServicePortName string = "metrics"
59+
postgresExporterServicePortKeyName string = "postgres-exporter-service-port"
60+
postgresExporterServiceTargetPortKeyName string = "postgres-exporter-service-target-port"
61+
walGExporterServicePortName string = "backup-metrics"
62+
walGExporterServicePortKeyName string = "wal-g-exporter-service-port"
63+
walGExporterServiceTargetPortKeyName string = "wal-g-exporter-service-target-port"
5964
postgresExporterServiceTenantAnnotationName string = pg.TenantLabelName
6065
postgresExporterServiceProjectIDAnnotationName string = pg.ProjectIDLabelName
6166
storageEncryptionKeyName string = "storage-encryption-key"
6267
storageEncryptionKeyFinalizerName string = "postgres.database.fits.cloud/secret-finalizer"
6368
walGEncryptionSecretNamePostfix string = "-walg-encryption"
6469
walGEncryptionSecretKeyName string = "key"
70+
podMonitorName string = "patroni"
71+
podMonitorPort string = "8008"
6572
initDBName string = "postgres-initdb"
6673
initDBSQLDummy string = `SELECT 'NOOP';`
6774
debugLogLevel int = 1
@@ -102,6 +109,7 @@ type PostgresReconciler struct {
102109
EnableCustomTLSCert bool
103110
TLSClusterIssuer string
104111
TLSSubDomain string
112+
EnableWalGExporter bool
105113
}
106114

107115
type PatroniStandbyCluster struct {
@@ -300,6 +308,12 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
300308
return ctrl.Result{}, fmt.Errorf("error while creating sidecars servicemonitor %v: %w", namespace, err)
301309
}
302310

311+
// Add pod monitor
312+
if err := r.createOrUpdatePatroniPodMonitor(ctx, namespace, instance); err != nil {
313+
r.recorder.Eventf(instance, "Warning", "Error", "failed to create podmonitor: %v", err)
314+
return ctrl.Result{}, fmt.Errorf("error while creating podmonitor %v: %w", namespace, err)
315+
}
316+
303317
// Make sure the storage secret exist, if necessary
304318
if err := r.ensureStorageEncryptionSecret(log, ctx, instance); err != nil {
305319
r.recorder.Eventf(instance, "Warning", "Error", "failed to create storage secret: %v", err)
@@ -1473,16 +1487,28 @@ func (r *PostgresReconciler) createOrUpdateNetPol(ctx context.Context, instance
14731487

14741488
// createOrUpdateExporterSidecarServices ensures the necessary services to access the sidecars exist
14751489
func (r *PostgresReconciler) createOrUpdateExporterSidecarServices(log logr.Logger, ctx context.Context, namespace string, c *corev1.ConfigMap, in *pg.Postgres) error {
1476-
exporterServicePort, error := strconv.ParseInt(c.Data["postgres-exporter-service-port"], 10, 32)
1490+
pesPort, error := strconv.ParseInt(c.Data[postgresExporterServicePortKeyName], 10, 32)
1491+
if error != nil {
1492+
log.Error(error, "postgres-exporter-service-port could not be parsed to int32, falling back to default value")
1493+
pesPort = 9187
1494+
}
1495+
1496+
pesTargetPort, error := strconv.ParseInt(c.Data[postgresExporterServiceTargetPortKeyName], 10, 32)
1497+
if error != nil {
1498+
log.Error(error, "postgres-exporter-service-target-port could not be parsed to int32, falling back to default value")
1499+
pesTargetPort = pesPort
1500+
}
1501+
1502+
wgesPort, error := strconv.ParseInt(c.Data[walGExporterServicePortKeyName], 10, 32)
14771503
if error != nil {
1478-
// todo log error
1479-
exporterServicePort = 9187
1504+
log.Error(error, "wal-g-exporter-service-port could not be parsed to int32, falling back to default value")
1505+
pesPort = 9351
14801506
}
14811507

1482-
exporterServiceTargetPort, error := strconv.ParseInt(c.Data["postgres-exporter-service-target-port"], 10, 32)
1508+
wgesTargetPort, error := strconv.ParseInt(c.Data[walGExporterServiceTargetPortKeyName], 10, 32)
14831509
if error != nil {
1484-
// todo log error
1485-
exporterServiceTargetPort = exporterServicePort
1510+
log.Error(error, "wal-g-exporter-service-target-port could not be parsed to int32, falling back to default value")
1511+
pesTargetPort = pesPort
14861512
}
14871513

14881514
labels := map[string]string{
@@ -1506,11 +1532,20 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServices(log logr.Logg
15061532
pes.Spec.Ports = []corev1.ServicePort{
15071533
{
15081534
Name: postgresExporterServicePortName,
1509-
Port: int32(exporterServicePort), //nolint
1535+
Port: int32(pesPort), //nolint
15101536
Protocol: corev1.ProtocolTCP,
1511-
TargetPort: intstr.FromInt(int(exporterServiceTargetPort)),
1537+
TargetPort: intstr.FromInt(int(pesTargetPort)),
15121538
},
15131539
}
1540+
if r.EnableWalGExporter {
1541+
wgesp := corev1.ServicePort{
1542+
Name: walGExporterServicePortName,
1543+
Port: int32(wgesPort), //nolint
1544+
Protocol: corev1.ProtocolTCP,
1545+
TargetPort: intstr.FromInt(int(wgesTargetPort)),
1546+
}
1547+
pes.Spec.Ports = append(pes.Spec.Ports, wgesp)
1548+
}
15141549
selector := map[string]string{
15151550
pg.ApplicationLabelName: pg.ApplicationLabelValue,
15161551
}
@@ -1586,6 +1621,12 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
15861621
Port: postgresExporterServicePortName,
15871622
},
15881623
}
1624+
if r.EnableWalGExporter {
1625+
wgesme := coreosv1.Endpoint{
1626+
Port: walGExporterServicePortName,
1627+
}
1628+
pesm.Spec.Endpoints = append(pesm.Spec.Endpoints, wgesme)
1629+
}
15891630
pesm.Spec.NamespaceSelector = coreosv1.NamespaceSelector{
15901631
MatchNames: []string{namespace},
15911632
}
@@ -1596,6 +1637,10 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
15961637
pesm.Spec.Selector = metav1.LabelSelector{
15971638
MatchLabels: matchLabels,
15981639
}
1640+
pesm.Spec.TargetLabels = []string{
1641+
"postgres_partition_id=" + in.Spec.PartitionID,
1642+
"is_primary=" + strconv.FormatBool(in.IsReplicationPrimaryOrStandalone()),
1643+
}
15991644

16001645
// try to fetch any existing postgres-exporter service
16011646
ns := types.NamespacedName{
@@ -1623,6 +1668,69 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
16231668
return nil
16241669
}
16251670

1671+
// createOrUpdatePatroniPodMonitor ensures the servicemonitors for the sidecars exist
1672+
func (r *PostgresReconciler) createOrUpdatePatroniPodMonitor(ctx context.Context, namespace string, in *pg.Postgres) error {
1673+
log := r.Log.WithValues("namespace", namespace)
1674+
1675+
labels := map[string]string{
1676+
"app": "postgres-exporter",
1677+
"release": "prometheus",
1678+
}
1679+
1680+
annotations := map[string]string{
1681+
postgresExporterServiceTenantAnnotationName: in.Spec.Tenant,
1682+
postgresExporterServiceProjectIDAnnotationName: in.Spec.ProjectID,
1683+
}
1684+
1685+
pm := &coreosv1.PodMonitor{
1686+
ObjectMeta: metav1.ObjectMeta{
1687+
Name: podMonitorName,
1688+
Namespace: namespace,
1689+
Labels: labels,
1690+
Annotations: annotations,
1691+
},
1692+
}
1693+
1694+
pm.Spec.PodMetricsEndpoints = []coreosv1.PodMetricsEndpoint{
1695+
{
1696+
Port: podMonitorPort,
1697+
},
1698+
}
1699+
pm.Spec.NamespaceSelector = coreosv1.NamespaceSelector{
1700+
MatchNames: []string{namespace},
1701+
}
1702+
matchLabels := map[string]string{
1703+
"application": "spilo",
1704+
}
1705+
pm.Spec.Selector = metav1.LabelSelector{
1706+
MatchLabels: matchLabels,
1707+
}
1708+
1709+
// try to fetch any existing podmonitor
1710+
ns := types.NamespacedName{
1711+
Namespace: namespace,
1712+
Name: podMonitorName,
1713+
}
1714+
old := &coreosv1.PodMonitor{}
1715+
if err := r.SvcClient.Get(ctx, ns, old); err == nil {
1716+
// Copy the resource version
1717+
pm.ObjectMeta.ResourceVersion = old.ObjectMeta.ResourceVersion
1718+
if err := r.SvcClient.Update(ctx, pm); err != nil {
1719+
return fmt.Errorf("error while updating the podmonitor: %w", err)
1720+
}
1721+
log.Info("pod monitor updated")
1722+
return nil
1723+
}
1724+
1725+
// local podmonitor does not exist, creating it
1726+
if err := r.SvcClient.Create(ctx, pm); err != nil {
1727+
return fmt.Errorf("error while creating the podmonitor: %w", err)
1728+
}
1729+
log.Info("podmonitor created")
1730+
1731+
return nil
1732+
}
1733+
16261734
func (r *PostgresReconciler) deleteExporterSidecarService(log logr.Logger, ctx context.Context, namespace string) error {
16271735
s := &corev1.Service{
16281736
ObjectMeta: metav1.ObjectMeta{

main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const (
8989
tlsSubDomainFlg = "tls-sub-domain"
9090
enablePatroniFailsafeModeFlg = "enable-patroni-failsafe-mode"
9191
enableFsGroupChangePolicyWebhookFlg = "enable-fsgroup-change-policy-webhook"
92+
enableWalGExporterFlg = "enable-wal-g-exporter"
9293
)
9394

9495
var (
@@ -150,6 +151,7 @@ func main() {
150151
enableSuperUserForDBO bool
151152
enablePatroniFailsafeMode bool
152153
enableFsGroupChangePolicyWebhook bool
154+
enableWalGExporter bool
153155

154156
portRangeStart int32
155157
portRangeSize int32
@@ -315,6 +317,9 @@ func main() {
315317
viper.SetDefault(enableFsGroupChangePolicyWebhookFlg, true)
316318
enableFsGroupChangePolicyWebhook = viper.GetBool(enableFsGroupChangePolicyWebhookFlg)
317319

320+
viper.SetDefault(enableWalGExporterFlg, true)
321+
enableWalGExporter = viper.GetBool(enableWalGExporterFlg)
322+
318323
ctrl.Log.Info("flag",
319324
metricsAddrSvcMgrFlg, metricsAddrSvcMgr,
320325
metricsAddrCtrlMgrFlg, metricsAddrCtrlMgr,
@@ -360,6 +365,7 @@ func main() {
360365
tlsSubDomainFlg, tlsSubDomain,
361366
enablePatroniFailsafeModeFlg, enablePatroniFailsafeMode,
362367
enableFsGroupChangePolicyWebhookFlg, enableFsGroupChangePolicyWebhook,
368+
enableWalGExporterFlg, enableWalGExporter,
363369
)
364370

365371
svcClusterConf := ctrl.GetConfigOrDie()
@@ -478,6 +484,7 @@ func main() {
478484
EnableCustomTLSCert: enableCustomTLSCert,
479485
TLSClusterIssuer: tlsClusterIssuer,
480486
TLSSubDomain: tlsSubDomain,
487+
EnableWalGExporter: enableWalGExporter,
481488
}).SetupWithManager(ctrlPlaneClusterMgr); err != nil {
482489
setupLog.Error(err, "unable to create controller", "controller", "Postgres")
483490
os.Exit(1)

0 commit comments

Comments
 (0)