Skip to content

Commit 4f4b9fb

Browse files
authored
Reporting workloads that are marked with the Prometheus scraping annotation to support automatically create network policies to allow Prometheus scraping in Otterize cloud (#278)
1 parent 65b5240 commit 4f4b9fb

12 files changed

+560
-27
lines changed

src/mapper/cmd/main.go

+18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/otterize/network-mapper/src/mapper/pkg/gcpintentsholder"
2323
"github.com/otterize/network-mapper/src/mapper/pkg/incomingtrafficholder"
2424
"github.com/otterize/network-mapper/src/mapper/pkg/labelreporter"
25+
"github.com/otterize/network-mapper/src/mapper/pkg/metrics_collection_traffic"
2526
"github.com/otterize/network-mapper/src/mapper/pkg/resourcevisibility"
2627
"github.com/otterize/network-mapper/src/shared/echologrus"
2728
"golang.org/x/sync/errgroup"
@@ -242,6 +243,23 @@ func main() {
242243
if err := namespaceReconciler.SetupWithManager(mgr); err != nil {
243244
logrus.WithError(err).Panic("unable to create namespace reconciler")
244245
}
246+
247+
metricsCollectionTrafficHandler := metrics_collection_traffic.NewMetricsCollectionTrafficHandler(mgr.GetClient(), serviceidresolver.NewResolver(mgr.GetClient()), cloudClient)
248+
249+
metricsCollectorPodReconciler := metrics_collection_traffic.NewPodReconciler(metricsCollectionTrafficHandler)
250+
if err = metricsCollectorPodReconciler.SetupWithManager(mgr); err != nil {
251+
logrus.WithError(err).Panic("unable to create pod reconciler")
252+
}
253+
254+
metricsCollectorServiceReconciler := metrics_collection_traffic.NewServiceReconciler(metricsCollectionTrafficHandler)
255+
if err = metricsCollectorServiceReconciler.SetupWithManager(mgr); err != nil {
256+
logrus.WithError(err).Panic("unable to create service reconciler")
257+
}
258+
259+
metricsCollectorEndpointsReconciler := metrics_collection_traffic.NewEndpointsReconciler(metricsCollectionTrafficHandler)
260+
if err = metricsCollectorEndpointsReconciler.SetupWithManager(mgr); err != nil {
261+
logrus.WithError(err).Panic("unable to create endpoints reconciler")
262+
}
245263
}
246264

247265
if viper.GetBool(config.OTelEnabledKey) {

src/mapper/pkg/cloudclient/cloud_client.go

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type CloudClient interface {
1818
ReportTrafficLevels(ctx context.Context, trafficLevels []TrafficLevelInput) error
1919
ReportNamespaceLabels(ctx context.Context, namespace string, labels []LabelInput) error
2020
ReportWorkloadsLabels(ctx context.Context, workloadsLabels []ReportServiceMetadataInput) error
21+
ReportK8sResourceEligibleForMetricsCollection(ctx context.Context, namespace string, reason EligibleForMetricsCollectionReason, resources []K8sResourceEligibleForMetricsCollectionInput) error
2122
}
2223

2324
type CloudClientImpl struct {
@@ -100,6 +101,17 @@ func (c *CloudClientImpl) ReportK8sIngresses(ctx context.Context, namespace stri
100101
return nil
101102
}
102103

104+
func (c *CloudClientImpl) ReportK8sResourceEligibleForMetricsCollection(ctx context.Context, namespace string, reason EligibleForMetricsCollectionReason, resources []K8sResourceEligibleForMetricsCollectionInput) error {
105+
logrus.Debug("Uploading k8s metrics collector resource to cloud, count: ", len(resources))
106+
107+
_, err := ReportK8sResourceEligibleForMetricsCollection(ctx, c.client, namespace, reason, resources)
108+
if err != nil {
109+
return errors.Wrap(err)
110+
}
111+
112+
return nil
113+
}
114+
103115
func (c *CloudClientImpl) ReportTrafficLevels(
104116
ctx context.Context,
105117
trafficLevels []TrafficLevelInput,

src/mapper/pkg/cloudclient/generated.go

+91
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/mapper/pkg/cloudclient/genqlient.graphql

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ mutation ReportK8sIngresses($namespace: String!, $ingresses: [K8sIngressInput!]!
2323
reportK8sIngresses(namespace: $namespace, ingresses: $ingresses)
2424
}
2525

26+
mutation ReportK8sResourceEligibleForMetricsCollection($namespace: String!, $reason: EligibleForMetricsCollectionReason!, $resources: [K8sResourceEligibleForMetricsCollectionInput!]!) {
27+
reportK8sResourceEligibleForMetricsCollection(namespace: $namespace, reason: $reason, resources: $resources)
28+
}
29+
2630
mutation ReportTrafficLevels(
2731
$trafficLevels: [TrafficLevelInput!]!
2832
) {

src/mapper/pkg/cloudclient/mocks/mocks.go

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/mapper/pkg/cloudclient/schema.graphql

+17
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,11 @@ type EdgeAccessStatuses {
743743
linkerdPolicies: EdgeAccessStatus!
744744
}
745745

746+
enum EligibleForMetricsCollectionReason {
747+
POD_ANNOTATIONS
748+
SERVICE_ANNOTATIONS
749+
}
750+
746751
type Environment {
747752
id: ID!
748753
name: String!
@@ -1468,6 +1473,7 @@ input IntentsOperatorConfigurationInput {
14681473
awsALBLoadBalancerExemptionEnabled: Boolean
14691474
allowExternalTrafficPolicy: AllowExternalTrafficPolicy
14701475
externallyManagedPolicyWorkloads: [ExternallyManagedPolicyWorkloadInput!]
1476+
automateThirdPartyNetworkPolicies: AllowExternalTrafficPolicy
14711477
}
14721478

14731479
type IntentsOperatorState {
@@ -1567,6 +1573,12 @@ enum K8sPortProtocol {
15671573
SCTP
15681574
}
15691575

1576+
input K8sResourceEligibleForMetricsCollectionInput {
1577+
namespace: String!
1578+
name: String!
1579+
kind: String!
1580+
}
1581+
15701582
input K8sResourceIngressInput {
15711583
spec: K8sResourceIngressSpecInput!
15721584
status: K8sResourceIngressStatusInput
@@ -2031,6 +2043,11 @@ type Mutation {
20312043
namespace: String!
20322044
ingresses: [K8sIngressInput!]!
20332045
): Boolean!
2046+
reportK8sResourceEligibleForMetricsCollection(
2047+
namespace: String!
2048+
reason: EligibleForMetricsCollectionReason!
2049+
resources: [K8sResourceEligibleForMetricsCollectionInput!]!
2050+
): Boolean!
20342051
reportKafkaServerConfigs(
20352052
namespace: String!
20362053
serverConfigs: [KafkaServerConfigInput!]!

src/mapper/pkg/config/config.go

+30-27
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,35 @@ import (
99
)
1010

1111
const (
12-
ClusterDomainKey = "cluster-domain"
13-
ClusterDomainDefault = kubeutils.DefaultClusterDomain
14-
CloudApiAddrKey = "api-address"
15-
CloudApiAddrDefault = "https://app.otterize.com/api"
16-
UploadIntervalSecondsKey = "upload-interval-seconds"
17-
UploadIntervalSecondsDefault = 60
18-
UploadBatchSizeKey = "upload-batch-size"
19-
UploadBatchSizeDefault = 500
20-
ExcludedNamespacesKey = "exclude-namespaces"
21-
OTelEnabledKey = "enable-otel-export"
22-
OTelEnabledDefault = false
23-
OTelMetricKey = "otel-metric-name"
24-
OTelMetricDefault = "traces_service_graph_request_total" // same as expected in otel-collector-contrib's servicegraphprocessor
25-
ExternalTrafficCaptureEnabledKey = "capture-external-traffic-enabled"
26-
ExternalTrafficCaptureEnabledDefault = true
27-
CreateWebhookCertificateKey = "create-webhook-certificate"
28-
CreateWebhookCertificateDefault = true
29-
DNSCacheItemsMaxCapacityKey = "dns-cache-items-max-capacity"
30-
DNSCacheItemsMaxCapacityDefault = 100000
31-
DNSClientIntentsUpdateIntervalKey = "dns-client-intents-update-interval"
32-
DNSClientIntentsUpdateIntervalDefault = 100 * time.Millisecond
33-
DNSClientIntentsUpdateEnabledKey = "dns-client-intents-update-enabled"
34-
DNSClientIntentsUpdateEnabledDefault = true
35-
ServiceCacheTTLDurationKey = "service-cache-ttl-duration"
36-
ServiceCacheTTLDurationDefault = 1 * time.Minute
37-
ServiceCacheSizeKey = "service-cache-size"
38-
ServiceCacheSizeDefault = 10000
12+
ClusterDomainKey = "cluster-domain"
13+
ClusterDomainDefault = kubeutils.DefaultClusterDomain
14+
CloudApiAddrKey = "api-address"
15+
CloudApiAddrDefault = "https://app.otterize.com/api"
16+
UploadIntervalSecondsKey = "upload-interval-seconds"
17+
UploadIntervalSecondsDefault = 60
18+
UploadBatchSizeKey = "upload-batch-size"
19+
UploadBatchSizeDefault = 500
20+
ExcludedNamespacesKey = "exclude-namespaces"
21+
OTelEnabledKey = "enable-otel-export"
22+
OTelEnabledDefault = false
23+
OTelMetricKey = "otel-metric-name"
24+
OTelMetricDefault = "traces_service_graph_request_total" // same as expected in otel-collector-contrib's servicegraphprocessor
25+
ExternalTrafficCaptureEnabledKey = "capture-external-traffic-enabled"
26+
ExternalTrafficCaptureEnabledDefault = true
27+
CreateWebhookCertificateKey = "create-webhook-certificate"
28+
CreateWebhookCertificateDefault = true
29+
DNSCacheItemsMaxCapacityKey = "dns-cache-items-max-capacity"
30+
DNSCacheItemsMaxCapacityDefault = 100000
31+
DNSClientIntentsUpdateIntervalKey = "dns-client-intents-update-interval"
32+
DNSClientIntentsUpdateIntervalDefault = 100 * time.Millisecond
33+
DNSClientIntentsUpdateEnabledKey = "dns-client-intents-update-enabled"
34+
DNSClientIntentsUpdateEnabledDefault = true
35+
ServiceCacheTTLDurationKey = "service-cache-ttl-duration"
36+
ServiceCacheTTLDurationDefault = 1 * time.Minute
37+
ServiceCacheSizeKey = "service-cache-size"
38+
ServiceCacheSizeDefault = 10000
39+
MetricsCollectionTrafficCacheSizeKey = "metrics-collection-traffic-cache-size"
40+
MetricsCollectionTrafficCacheSizeDefault = 10000
3941

4042
EnableIstioCollectionKey = "enable-istio-collection"
4143
EnableIstioCollectionDefault = false
@@ -79,6 +81,7 @@ func init() {
7981
viper.SetDefault(EnableIstioCollectionKey, EnableIstioCollectionDefault)
8082
viper.SetDefault(ServiceCacheTTLDurationKey, ServiceCacheTTLDurationDefault)
8183
viper.SetDefault(ServiceCacheSizeKey, ServiceCacheSizeDefault)
84+
viper.SetDefault(MetricsCollectionTrafficCacheSizeKey, MetricsCollectionTrafficCacheSizeDefault)
8285
viper.SetDefault(TimeServerHasToLiveBeforeWeTrustItKey, TimeServerHasToLiveBeforeWeTrustItDefault)
8386
viper.SetDefault(ControlPlaneIPv4CidrPrefixLength, ControlPlaneIPv4CidrPrefixLengthDefault)
8487

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package metrics_collection_traffic
2+
3+
import (
4+
"context"
5+
"github.com/otterize/intents-operator/src/shared/errors"
6+
"github.com/otterize/intents-operator/src/shared/injectablerecorder"
7+
"github.com/samber/lo"
8+
corev1 "k8s.io/api/core/v1"
9+
"k8s.io/client-go/tools/record"
10+
ctrl "sigs.k8s.io/controller-runtime"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
"sigs.k8s.io/controller-runtime/pkg/controller"
13+
)
14+
15+
type EndpointsReconciler struct {
16+
client.Client
17+
injectablerecorder.InjectableRecorder
18+
metricsCollectionTrafficHandler *MetricsCollectionTrafficHandler
19+
}
20+
21+
func NewEndpointsReconciler(metricsCollectionTrafficHandler *MetricsCollectionTrafficHandler) *EndpointsReconciler {
22+
return &EndpointsReconciler{
23+
metricsCollectionTrafficHandler: metricsCollectionTrafficHandler,
24+
}
25+
}
26+
27+
func (r *EndpointsReconciler) SetupWithManager(mgr ctrl.Manager) error {
28+
recorder := mgr.GetEventRecorderFor("intents-operator")
29+
r.InjectRecorder(recorder)
30+
31+
return ctrl.NewControllerManagedBy(mgr).
32+
For(&corev1.Endpoints{}).
33+
WithOptions(controller.Options{RecoverPanic: lo.ToPtr(true)}).
34+
Complete(r)
35+
}
36+
37+
func (r *EndpointsReconciler) InjectRecorder(recorder record.EventRecorder) {
38+
r.Recorder = recorder
39+
}
40+
41+
func (r *EndpointsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
42+
err := r.metricsCollectionTrafficHandler.HandleAllServicesInNamespace(ctx, req)
43+
if err != nil {
44+
return ctrl.Result{}, errors.Wrap(err)
45+
}
46+
47+
return ctrl.Result{}, nil
48+
}

0 commit comments

Comments
 (0)