@@ -56,12 +56,19 @@ import (
56
56
const (
57
57
postgresExporterServiceName string = "postgres-exporter"
58
58
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"
59
64
postgresExporterServiceTenantAnnotationName string = pg .TenantLabelName
60
65
postgresExporterServiceProjectIDAnnotationName string = pg .ProjectIDLabelName
61
66
storageEncryptionKeyName string = "storage-encryption-key"
62
67
storageEncryptionKeyFinalizerName string = "postgres.database.fits.cloud/secret-finalizer"
63
68
walGEncryptionSecretNamePostfix string = "-walg-encryption"
64
69
walGEncryptionSecretKeyName string = "key"
70
+ podMonitorName string = "patroni"
71
+ podMonitorPort string = "8008"
65
72
initDBName string = "postgres-initdb"
66
73
initDBSQLDummy string = `SELECT 'NOOP';`
67
74
debugLogLevel int = 1
@@ -102,6 +109,7 @@ type PostgresReconciler struct {
102
109
EnableCustomTLSCert bool
103
110
TLSClusterIssuer string
104
111
TLSSubDomain string
112
+ EnableWalGExporter bool
105
113
}
106
114
107
115
type PatroniStandbyCluster struct {
@@ -300,6 +308,12 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
300
308
return ctrl.Result {}, fmt .Errorf ("error while creating sidecars servicemonitor %v: %w" , namespace , err )
301
309
}
302
310
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
+
303
317
// Make sure the storage secret exist, if necessary
304
318
if err := r .ensureStorageEncryptionSecret (log , ctx , instance ); err != nil {
305
319
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
1473
1487
1474
1488
// createOrUpdateExporterSidecarServices ensures the necessary services to access the sidecars exist
1475
1489
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 )
1477
1503
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
1480
1506
}
1481
1507
1482
- exporterServiceTargetPort , error := strconv .ParseInt (c .Data ["postgres-exporter-service-target-port" ], 10 , 32 )
1508
+ wgesTargetPort , error := strconv .ParseInt (c .Data [walGExporterServiceTargetPortKeyName ], 10 , 32 )
1483
1509
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
1486
1512
}
1487
1513
1488
1514
labels := map [string ]string {
@@ -1506,11 +1532,20 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServices(log logr.Logg
1506
1532
pes .Spec .Ports = []corev1.ServicePort {
1507
1533
{
1508
1534
Name : postgresExporterServicePortName ,
1509
- Port : int32 (exporterServicePort ), //nolint
1535
+ Port : int32 (pesPort ), //nolint
1510
1536
Protocol : corev1 .ProtocolTCP ,
1511
- TargetPort : intstr .FromInt (int (exporterServiceTargetPort )),
1537
+ TargetPort : intstr .FromInt (int (pesTargetPort )),
1512
1538
},
1513
1539
}
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
+ }
1514
1549
selector := map [string ]string {
1515
1550
pg .ApplicationLabelName : pg .ApplicationLabelValue ,
1516
1551
}
@@ -1586,6 +1621,12 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
1586
1621
Port : postgresExporterServicePortName ,
1587
1622
},
1588
1623
}
1624
+ if r .EnableWalGExporter {
1625
+ wgesme := coreosv1.Endpoint {
1626
+ Port : walGExporterServicePortName ,
1627
+ }
1628
+ pesm .Spec .Endpoints = append (pesm .Spec .Endpoints , wgesme )
1629
+ }
1589
1630
pesm .Spec .NamespaceSelector = coreosv1.NamespaceSelector {
1590
1631
MatchNames : []string {namespace },
1591
1632
}
@@ -1596,6 +1637,10 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
1596
1637
pesm .Spec .Selector = metav1.LabelSelector {
1597
1638
MatchLabels : matchLabels ,
1598
1639
}
1640
+ pesm .Spec .TargetLabels = []string {
1641
+ "postgres_partition_id=" + in .Spec .PartitionID ,
1642
+ "is_primary=" + strconv .FormatBool (in .IsReplicationPrimaryOrStandalone ()),
1643
+ }
1599
1644
1600
1645
// try to fetch any existing postgres-exporter service
1601
1646
ns := types.NamespacedName {
@@ -1623,6 +1668,69 @@ func (r *PostgresReconciler) createOrUpdateExporterSidecarServiceMonitor(log log
1623
1668
return nil
1624
1669
}
1625
1670
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
+
1626
1734
func (r * PostgresReconciler ) deleteExporterSidecarService (log logr.Logger , ctx context.Context , namespace string ) error {
1627
1735
s := & corev1.Service {
1628
1736
ObjectMeta : metav1.ObjectMeta {
0 commit comments