Skip to content

Commit f06beaa

Browse files
committed
Merge branch 'master' into remove_spot
2 parents 79e4ac0 + 836eec5 commit f06beaa

File tree

11 files changed

+350
-93
lines changed

11 files changed

+350
-93
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ can be sent to a Kafka topic. There's a few prerequisites to develop with this e
8989
#### Update and compile Protobuf definition
9090

9191
Whenever the Protobuf definition is updated you can update using `make proto`. It will download the definitions, compile
92-
and place them in the correct packages.
92+
and place them in the correct packages.
9393

9494
### Code generation
9595

charts/naiserator/Feature.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ values:
169169
naiserator.observability.otel.enabled:
170170
computed:
171171
template: '{{ne .Kind "onprem"}}'
172+
naiserator.observability.otel.auto-instrumentation.enabled:
173+
config:
174+
type: bool
175+
ignoreKind:
176+
- onprem
172177
naiserator.observability.logging.destinations:
173178
computed:
174179
# Find all logging_*_default_flow environment variables and use for configuration of available log destinations

charts/naiserator/values.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ naiserator:
5959
observability:
6060
otel:
6161
enabled: false
62+
auto-instrumentation:
63+
enabled: false
64+
app-config: "nais-system/apps"
6265
collector:
6366
labels:
6467
- "app.kubernetes.io/name=opentelemetry-collector"

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/magiconair/properties v1.8.7
1414
github.com/mitchellh/hashstructure v1.1.0
1515
github.com/mitchellh/mapstructure v1.5.0
16-
github.com/nais/liberator v0.0.0-20240220103506-4507fc2aaa3c
16+
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d
1717
github.com/novln/docker-parser v1.0.0
1818
github.com/prometheus/client_golang v1.17.0
1919
github.com/sirupsen/logrus v1.9.3

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
244244
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
245245
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
246246
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
247-
github.com/nais/liberator v0.0.0-20240220103506-4507fc2aaa3c h1:heFDGaSKO/ZIVNwGfybuqTXUOfaT0NXJ64Yety4B+qg=
248-
github.com/nais/liberator v0.0.0-20240220103506-4507fc2aaa3c/go.mod h1:cWThp1WBBbkRFhMI2DQMvBTTEN+6GPzmmh+Xjv8vffE=
247+
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d h1:NA//xj14122osF306Q19oARHyg9JW7g4qJReFO1O3Ds=
248+
github.com/nais/liberator v0.0.0-20240223134957-13b72a76ba9d/go.mod h1:cWThp1WBBbkRFhMI2DQMvBTTEN+6GPzmmh+Xjv8vffE=
249249
github.com/novln/docker-parser v1.0.0 h1:PjEBd9QnKixcWczNGyEdfUrP6GR0YUilAqG7Wksg3uc=
250250
github.com/novln/docker-parser v1.0.0/go.mod h1:oCeM32fsoUwkwByB5wVjsrsVQySzPWkl3JdlTn1txpE=
251251
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=

pkg/naiserator/config/config.go

+73-63
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,14 @@ type Observability struct {
7070
}
7171

7272
type Otel struct {
73-
Enabled bool `json:"enabled"`
74-
Collector OtelCollector `json:"collector"`
73+
Enabled bool `json:"enabled"`
74+
Collector OtelCollector `json:"collector"`
75+
AutoInstrumentation AutoInstrumentation `json:"auto-instrumentation"`
76+
}
77+
78+
type AutoInstrumentation struct {
79+
Enabled bool `json:"enabled"`
80+
AppConfig string `json:"app-config"`
7581
}
7682

7783
type OtelCollector struct {
@@ -173,67 +179,69 @@ type Config struct {
173179
}
174180

175181
const (
176-
AivenProject = "aiven-project"
177-
AivenRange = "aiven-range"
178-
ApiServerIp = "api-server-ip"
179-
Bind = "bind"
180-
HealthProbeBindAddress = "health-probe-bind-address"
181-
ClusterName = "cluster-name"
182-
DryRun = "dry-run"
183-
NaisNamespace = "nais-namespace"
184-
FeaturesAccessPolicyNotAllowedCIDRs = "features.access-policy-not-allowed-cidrs"
185-
FeaturesAzurerator = "features.azurerator"
186-
FeaturesGCP = "features.gcp"
187-
FeaturesIDPorten = "features.idporten"
188-
FeaturesJwker = "features.jwker"
189-
FeaturesCNRM = "features.cnrm"
190-
FeaturesKafkarator = "features.kafkarator"
191-
FeaturesLinkerd = "features.linkerd"
192-
FeaturesMaskinporten = "features.maskinporten"
193-
FeaturesNetworkPolicy = "features.network-policy"
194-
FeaturesPrometheusOperator = "features.prometheus-operator"
195-
FeaturesVault = "features.vault"
196-
FeaturesWebhook = "features.webhook"
197-
FeaturesWonderwall = "features.wonderwall"
198-
FeaturesLegacyGCP = "features.legacy-gcp"
199-
FQDNPolicyEnabled = "fqdn-policy.enabled"
200-
GoogleCloudSQLProxyContainerImage = "google-cloud-sql-proxy-container-image"
201-
GoogleProjectId = "google-project-id"
202-
InformerFullSynchronizationInterval = "informer.full-sync-interval"
203-
KafkaBrokers = "kafka.brokers"
204-
KafkaEnabled = "kafka.enabled"
205-
KafkaLogVerbosity = "kafka.log-verbosity"
206-
KafkaTLSCAPath = "kafka.tls.ca-path"
207-
KafkaTLSCertificatePath = "kafka.tls.certificate-path"
208-
KafkaTLSEnabled = "kafka.tls.enabled"
209-
KafkaTLSInsecure = "kafka.tls.insecure"
210-
KafkaTLSPrivateKeyPath = "kafka.tls.private-key-path"
211-
KafkaTopic = "kafka.topic"
212-
KubeConfig = "kubeconfig"
213-
LeaderElectionImage = "leader-election.image"
214-
MaxConcurrentReconciles = "max-concurrent-reconciles"
215-
ObservabilityLoggingDestinations = "observability.logging.destinations"
216-
ObservabilityOtelCollectorLabels = "observability.otel.collector.labels"
217-
ObservabilityOtelCollectorNamespace = "observability.otel.collector.namespace"
218-
ObservabilityOtelCollectorPort = "observability.otel.collector.port"
219-
ObservabilityOtelCollectorProtocol = "observability.otel.collector.protocol"
220-
ObservabilityOtelCollectorService = "observability.otel.collector.service"
221-
ObservabilityOtelCollectorTLS = "observability.otel.collector.tls"
222-
ObservabilityOtelEnabled = "observability.otel.enabled"
223-
ProxyAddress = "proxy.address"
224-
ProxyExclude = "proxy.exclude"
225-
RateLimitBurst = "ratelimit.burst"
226-
RateLimitQPS = "ratelimit.qps"
227-
SecurelogsConfigMapReloadImage = "securelogs.configmap-reload-image"
228-
SecurelogsFluentdImage = "securelogs.fluentd-image"
229-
SynchronizerRolloutCheckInterval = "synchronizer.rollout-check-interval"
230-
SynchronizerRolloutTimeout = "synchronizer.rollout-timeout"
231-
SynchronizerSynchronizationTimeout = "synchronizer.synchronization-timeout"
232-
VaultAddress = "vault.address"
233-
VaultAuthPath = "vault.auth-path"
234-
VaultInitContainerImage = "vault.init-container-image"
235-
VaultKvPath = "vault.kv-path"
236-
WonderwallImage = "wonderwall.image"
182+
AivenProject = "aiven-project"
183+
AivenRange = "aiven-range"
184+
ApiServerIp = "api-server-ip"
185+
Bind = "bind"
186+
HealthProbeBindAddress = "health-probe-bind-address"
187+
ClusterName = "cluster-name"
188+
DryRun = "dry-run"
189+
NaisNamespace = "nais-namespace"
190+
FeaturesAccessPolicyNotAllowedCIDRs = "features.access-policy-not-allowed-cidrs"
191+
FeaturesAzurerator = "features.azurerator"
192+
FeaturesGCP = "features.gcp"
193+
FeaturesIDPorten = "features.idporten"
194+
FeaturesJwker = "features.jwker"
195+
FeaturesCNRM = "features.cnrm"
196+
FeaturesKafkarator = "features.kafkarator"
197+
FeaturesLinkerd = "features.linkerd"
198+
FeaturesMaskinporten = "features.maskinporten"
199+
FeaturesNetworkPolicy = "features.network-policy"
200+
FeaturesPrometheusOperator = "features.prometheus-operator"
201+
FeaturesVault = "features.vault"
202+
FeaturesWebhook = "features.webhook"
203+
FeaturesWonderwall = "features.wonderwall"
204+
FeaturesLegacyGCP = "features.legacy-gcp"
205+
FQDNPolicyEnabled = "fqdn-policy.enabled"
206+
GoogleCloudSQLProxyContainerImage = "google-cloud-sql-proxy-container-image"
207+
GoogleProjectId = "google-project-id"
208+
InformerFullSynchronizationInterval = "informer.full-sync-interval"
209+
KafkaBrokers = "kafka.brokers"
210+
KafkaEnabled = "kafka.enabled"
211+
KafkaLogVerbosity = "kafka.log-verbosity"
212+
KafkaTLSCAPath = "kafka.tls.ca-path"
213+
KafkaTLSCertificatePath = "kafka.tls.certificate-path"
214+
KafkaTLSEnabled = "kafka.tls.enabled"
215+
KafkaTLSInsecure = "kafka.tls.insecure"
216+
KafkaTLSPrivateKeyPath = "kafka.tls.private-key-path"
217+
KafkaTopic = "kafka.topic"
218+
KubeConfig = "kubeconfig"
219+
LeaderElectionImage = "leader-election.image"
220+
MaxConcurrentReconciles = "max-concurrent-reconciles"
221+
ObservabilityLoggingDestinations = "observability.logging.destinations"
222+
ObservabilityOtelCollectorLabels = "observability.otel.collector.labels"
223+
ObservabilityOtelCollectorNamespace = "observability.otel.collector.namespace"
224+
ObservabilityOtelCollectorPort = "observability.otel.collector.port"
225+
ObservabilityOtelCollectorProtocol = "observability.otel.collector.protocol"
226+
ObservabilityOtelCollectorService = "observability.otel.collector.service"
227+
ObservabilityOtelCollectorTLS = "observability.otel.collector.tls"
228+
ObservabilityOtelEnabled = "observability.otel.enabled"
229+
ObservabilityOtelAutoInstrumentationAppConfig = "observability.otel.auto-instrumentation.app-config"
230+
ObservabilityOtelAutoInstrumentationEnabled = "observability.otel.auto-instrumentation.enabled"
231+
ProxyAddress = "proxy.address"
232+
ProxyExclude = "proxy.exclude"
233+
RateLimitBurst = "ratelimit.burst"
234+
RateLimitQPS = "ratelimit.qps"
235+
SecurelogsConfigMapReloadImage = "securelogs.configmap-reload-image"
236+
SecurelogsFluentdImage = "securelogs.fluentd-image"
237+
SynchronizerRolloutCheckInterval = "synchronizer.rollout-check-interval"
238+
SynchronizerRolloutTimeout = "synchronizer.rollout-timeout"
239+
SynchronizerSynchronizationTimeout = "synchronizer.synchronization-timeout"
240+
VaultAddress = "vault.address"
241+
VaultAuthPath = "vault.auth-path"
242+
VaultInitContainerImage = "vault.init-container-image"
243+
VaultKvPath = "vault.kv-path"
244+
WonderwallImage = "wonderwall.image"
237245
)
238246

239247
func bindNAIS() {
@@ -302,6 +310,8 @@ func init() {
302310
flag.String(ObservabilityOtelCollectorNamespace, "nais-system", "namespace of the OpenTelemetry collector")
303311
flag.String(ObservabilityOtelCollectorService, "opentelmetry-collector", "service name of the OpenTelemetry collector")
304312
flag.String(ObservabilityOtelCollectorProtocol, "grpc", "protocol used by the OpenTelemetry collector")
313+
flag.Bool(ObservabilityOtelAutoInstrumentationEnabled, false, "enable OpenTelemetry auto-instrumentation")
314+
flag.String(ObservabilityOtelAutoInstrumentationAppConfig, "nais-system/apps", "path to OpenTelemetry auto-instrumentation config")
305315
flag.Int(ObservabilityOtelCollectorPort, 4317, "port used by the OpenTelemetry collector")
306316
flag.Bool(ObservabilityOtelCollectorTLS, false, "use TLS for the OpenTelemetry collector")
307317
flag.StringArray(ObservabilityOtelCollectorLabels, []string{}, "list of labels to be used by the OpenTelemetry collector")

pkg/resourcecreator/observability/observability.go

+60-19
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const otelExporterInsecure = "OTEL_EXPORTER_OTLP_INSECURE"
3737
const logLabelDefault = "logs.nais.io/flow-default"
3838
const logLabelPrefix = "logs.nais.io/flow-"
3939

40+
const autoInstrumentationInjectAnnotationPrefix = "instrumentation.opentelemetry.io/inject-"
41+
const autoInstrumentationContainerNamesAnnotation = "instrumentation.opentelemetry.io/container-names"
42+
4043
func otelEndpointFromConfig(collector config.OtelCollector) string {
4144
schema := "http"
4245
if collector.Tls {
@@ -73,7 +76,17 @@ func otelEnvVars(source Source, otel config.Otel) []corev1.EnvVar {
7376
}
7477
}
7578

76-
func labelsFromCollectorConfig(collector config.OtelCollector) map[string]string {
79+
func otelAutoInstrumentAnnotations(source Source, otel config.Otel) map[string]string {
80+
runtime := source.GetObservability().AutoInstrumentation.Runtime
81+
autoInstrumentationInjectAnnotation := autoInstrumentationInjectAnnotationPrefix + runtime
82+
83+
return map[string]string{
84+
autoInstrumentationInjectAnnotation: otel.AutoInstrumentation.AppConfig,
85+
autoInstrumentationContainerNamesAnnotation: source.GetName(),
86+
}
87+
}
88+
89+
func netpolLabelsFromCollectorConfig(collector config.OtelCollector) map[string]string {
7790
labels := collector.Labels
7891
labelMap := make(map[string]string, len(labels))
7992
for _, label := range labels {
@@ -86,7 +99,29 @@ func labelsFromCollectorConfig(collector config.OtelCollector) map[string]string
8699
return labelMap
87100
}
88101

89-
func tracingNetpol(source Source, otel config.Otel) (*networkingv1.NetworkPolicy, error) {
102+
func logLabels(obs *nais_io_v1.Observability, cfg config.Logging) (map[string]string, error) {
103+
if !obs.Logging.Enabled {
104+
return map[string]string{logLabelDefault: "false"}, nil
105+
}
106+
107+
labels := map[string]string{}
108+
109+
if len(obs.Logging.Destinations) > 0 {
110+
labels[logLabelDefault] = "false"
111+
112+
for _, destination := range obs.Logging.Destinations {
113+
if !slices.Contains(cfg.Destinations, destination.ID) {
114+
return nil, fmt.Errorf("logging destination %q does not exist in cluster", destination.ID)
115+
}
116+
117+
labels[logLabelPrefix+destination.ID] = "true"
118+
}
119+
}
120+
121+
return labels, nil
122+
}
123+
124+
func otelNetpol(source Source, otel config.Otel) (*networkingv1.NetworkPolicy, error) {
90125
name, err := namegen.ShortName(source.GetName()+"-"+"tracing", validation.DNS1035LabelMaxLength)
91126
if err != nil {
92127
return nil, err
@@ -96,7 +131,7 @@ func tracingNetpol(source Source, otel config.Otel) (*networkingv1.NetworkPolicy
96131
objectMeta.Name = name
97132

98133
protocolTCP := corev1.ProtocolTCP
99-
collectorLabels := labelsFromCollectorConfig(otel.Collector)
134+
collectorLabels := netpolLabelsFromCollectorConfig(otel.Collector)
100135

101136
return &networkingv1.NetworkPolicy{
102137
ObjectMeta: objectMeta,
@@ -147,36 +182,42 @@ func Create(source Source, ast *resource.Ast, config Config) error {
147182
return nil
148183
}
149184

150-
if obs.Tracing != nil && obs.Tracing.Enabled {
185+
if obs.AutoInstrumentation != nil && obs.AutoInstrumentation.Enabled && obs.Tracing != nil && obs.Tracing.Enabled {
186+
return fmt.Errorf("auto-instrumentation and tracing cannot be enabled at the same time")
187+
}
188+
189+
if (obs.Tracing != nil && obs.Tracing.Enabled) || (obs.AutoInstrumentation != nil && obs.AutoInstrumentation.Enabled) {
151190
if !cfg.Otel.Enabled {
152-
return fmt.Errorf("tracing is not supported in this cluster configuration")
191+
return fmt.Errorf("opentelemetry is not supported for this cluster")
153192
}
154193

155-
netpol, err := tracingNetpol(source, cfg.Otel)
194+
if !cfg.Otel.AutoInstrumentation.Enabled && obs.AutoInstrumentation != nil && obs.AutoInstrumentation.Enabled {
195+
return fmt.Errorf("auto-instrumentation is not supported for this cluster")
196+
}
197+
198+
netpol, err := otelNetpol(source, cfg.Otel)
156199
if err != nil {
157200
return err
158201
}
159202

203+
if obs.AutoInstrumentation != nil && obs.AutoInstrumentation.Enabled {
204+
for k, v := range otelAutoInstrumentAnnotations(source, cfg.Otel) {
205+
ast.Annotations[k] = v
206+
}
207+
}
208+
160209
ast.Env = append(ast.Env, otelEnvVars(source, cfg.Otel)...)
161210
ast.AppendOperation(resource.OperationCreateOrUpdate, netpol)
162211
}
163212

164213
if obs.Logging != nil {
165-
if !obs.Logging.Enabled {
166-
ast.Labels[logLabelDefault] = "false"
167-
return nil
214+
logLabels, err := logLabels(obs, cfg.Logging)
215+
if err != nil {
216+
return err
168217
}
169218

170-
if len(obs.Logging.Destinations) > 0 {
171-
ast.Labels[logLabelDefault] = "false"
172-
173-
for _, destination := range obs.Logging.Destinations {
174-
if !slices.Contains(cfg.Logging.Destinations, destination.ID) {
175-
return fmt.Errorf("logging destination %q does not exist in cluster", destination.ID)
176-
}
177-
178-
ast.Labels[logLabelPrefix+destination.ID] = "true"
179-
}
219+
for k, v := range logLabels {
220+
ast.Labels[k] = v
180221
}
181222
}
182223

0 commit comments

Comments
 (0)