diff --git a/api/v1alpha1/envoyproxy_accesslogging_types.go b/api/v1alpha1/envoyproxy_accesslogging_types.go
index 9aec175bf26..f09cad2e227 100644
--- a/api/v1alpha1/envoyproxy_accesslogging_types.go
+++ b/api/v1alpha1/envoyproxy_accesslogging_types.go
@@ -5,7 +5,10 @@
package v1alpha1
-import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+import (
+ "k8s.io/apimachinery/pkg/api/resource"
+ gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+)
type ProxyAccessLog struct {
// Disable disables access logging for managed proxies if set to true.
@@ -134,6 +137,36 @@ type ProxyAccessLogSink struct {
OpenTelemetry *OpenTelemetryEnvoyProxyAccessLog `json:"openTelemetry,omitempty"`
}
+// GRPCAccessLogBufferSettings configures how Envoy buffers access log entries before
+// flushing them to a gRPC access log sink.
+//
+// Entries accumulate until FlushInterval elapses or SizeBytes worth have been buffered,
+// whichever comes first, at which point Envoy flushes. Entries are discarded, and counted
+// by the sink's `logs_dropped` stat, only when a flush cannot drain the buffer. How much
+// of a sink outage the buffer absorbs therefore depends on both settings, since only
+// entries still buffered when the sink returns are delivered.
+type GRPCAccessLogBufferSettings struct {
+ // FlushInterval defines how often buffered access log entries are flushed to the sink.
+ // Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ // been buffered, whichever comes first.
+ // Must be greater than 0. Defaults to 1s.
+ //
+ // +kubebuilder:validation:XValidation:rule="duration(self) > duration('0s')",message="flushInterval must be greater than 0"
+ // +optional
+ FlushInterval *gwapiv1.Duration `json:"flushInterval,omitempty"`
+ // SizeBytes defines the soft size limit of the access log entry buffer.
+ // For example, 20Mi, 1Gi, 256Ki etc.
+ // Note that when the suffix is not provided, the value is interpreted as bytes.
+ // Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ // rejected when the EnvoyProxy is translated rather than at admission.
+ // Defaults to 16384 bytes.
+ //
+ // +kubebuilder:validation:XIntOrString
+ // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$"
+ // +optional
+ SizeBytes *resource.Quantity `json:"sizeBytes,omitempty"`
+}
+
type ALSEnvoyProxyAccessLogType string
const (
@@ -169,6 +202,10 @@ type ALSEnvoyProxyAccessLog struct {
// HTTP defines additional configuration specific to HTTP access logs.
// +optional
HTTP *ALSEnvoyProxyHTTPAccessLogConfig `json:"http,omitempty"`
+ // Buffer defines how access log entries are buffered before being flushed to the
+ // access log service.
+ // +optional
+ Buffer *GRPCAccessLogBufferSettings `json:"buffer,omitempty"`
}
type ALSEnvoyProxyHTTPAccessLogConfig struct {
@@ -228,6 +265,10 @@ type OpenTelemetryEnvoyProxyAccessLog struct {
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=32
Headers []gwapiv1.HTTPHeader `json:"headers,omitempty"`
+ // Buffer defines how access log entries are buffered before being flushed to the
+ // OpenTelemetry collector.
+ // +optional
+ Buffer *GRPCAccessLogBufferSettings `json:"buffer,omitempty"`
// TODO: support more OpenTelemetry accesslog options(e.g. TLS, auth etc.) in the future.
}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 6af742f16fc..bc5191a6409 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -34,6 +34,11 @@ func (in *ALSEnvoyProxyAccessLog) DeepCopyInto(out *ALSEnvoyProxyAccessLog) {
*out = new(ALSEnvoyProxyHTTPAccessLogConfig)
(*in).DeepCopyInto(*out)
}
+ if in.Buffer != nil {
+ in, out := &in.Buffer, &out.Buffer
+ *out = new(GRPCAccessLogBufferSettings)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ALSEnvoyProxyAccessLog.
@@ -4014,6 +4019,31 @@ func (in *ForceLocalZone) DeepCopy() *ForceLocalZone {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GRPCAccessLogBufferSettings) DeepCopyInto(out *GRPCAccessLogBufferSettings) {
+ *out = *in
+ if in.FlushInterval != nil {
+ in, out := &in.FlushInterval, &out.FlushInterval
+ *out = new(v1.Duration)
+ **out = **in
+ }
+ if in.SizeBytes != nil {
+ in, out := &in.SizeBytes, &out.SizeBytes
+ x := (*in).DeepCopy()
+ *out = &x
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCAccessLogBufferSettings.
+func (in *GRPCAccessLogBufferSettings) DeepCopy() *GRPCAccessLogBufferSettings {
+ if in == nil {
+ return nil
+ }
+ out := new(GRPCAccessLogBufferSettings)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GRPCActiveHealthChecker) DeepCopyInto(out *GRPCActiveHealthChecker) {
*out = *in
@@ -6530,6 +6560,11 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopyInto(out *OpenTelemetryEnvoy
*out = make([]v1.HTTPHeader, len(*in))
copy(*out, *in)
}
+ if in.Buffer != nil {
+ in, out := &in.Buffer, &out.Buffer
+ *out = new(GRPCAccessLogBufferSettings)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryEnvoyProxyAccessLog.
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 9a75b630c86..868464cbd27 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -13153,6 +13153,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ access log service.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
http:
description: HTTP defines additional configuration
specific to HTTP access logs.
@@ -14847,6 +14880,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ OpenTelemetry collector.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
headers:
description: |-
Headers is a list of additional headers to send with OTLP export requests.
diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 76a65310e7c..19fd277e078 100644
--- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -13152,6 +13152,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ access log service.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
http:
description: HTTP defines additional configuration
specific to HTTP access logs.
@@ -14846,6 +14879,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ OpenTelemetry collector.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
headers:
description: |-
Headers is a list of additional headers to send with OTLP export requests.
diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go
index 3d8376553ad..afa323747c0 100644
--- a/internal/gatewayapi/listener.go
+++ b/internal/gatewayapi/listener.go
@@ -13,6 +13,7 @@ import (
"net/netip"
"strconv"
"strings"
+ "time"
"github.com/google/cel-go/cel"
corev1 "k8s.io/api/core/v1"
@@ -767,7 +768,7 @@ func (t *Translator) processProxyObservability(gwCtx *GatewayContext, xdsIR *ir.
xdsIR.AccessLog, err = t.processAccessLog(gwCtx, envoyProxy, resources)
if err != nil {
status.UpdateGatewayStatusNotAccepted(gwCtx.Gateway, gwapiv1.GatewayReasonInvalidParameters,
- fmt.Sprintf("Invalid access log backendRefs in the referenced EnvoyProxy: %v", err))
+ fmt.Sprintf("Invalid access log configuration in the referenced EnvoyProxy: %v", err))
return
}
@@ -965,6 +966,11 @@ func (t *Translator) processAccessLog(gwCtx *GatewayContext, envoyproxy *egv1a1.
setting.Protocol = ir.GRPC
}
+ buffer, err := buildAccessLogBuffer(sink.ALS.Buffer)
+ if err != nil {
+ return nil, err
+ }
+
al := &ir.ALSAccessLog{
LogName: logName,
Destination: ir.RouteDestination{
@@ -976,6 +982,7 @@ func (t *Translator) processAccessLog(gwCtx *GatewayContext, envoyproxy *egv1a1.
Type: sink.ALS.Type,
CELMatches: validExprs,
LogType: accessLogType,
+ Buffer: buffer,
}
if al.Type == egv1a1.ALSEnvoyProxyAccessLogTypeHTTP && sink.ALS.HTTP != nil {
@@ -1010,6 +1017,11 @@ func (t *Translator) processAccessLog(gwCtx *GatewayContext, envoyproxy *egv1a1.
d.Protocol = ir.GRPC
}
+ buffer, err := buildAccessLogBuffer(sink.OpenTelemetry.Buffer)
+ if err != nil {
+ return nil, err
+ }
+
al := &ir.OpenTelemetryAccessLog{
CELMatches: validExprs,
ResourceAttributes: ir.MapToSlice(sink.OpenTelemetry.GetResourceAttributes()),
@@ -1022,6 +1034,7 @@ func (t *Translator) processAccessLog(gwCtx *GatewayContext, envoyproxy *egv1a1.
},
Traffic: traffic,
LogType: accessLogType,
+ Buffer: buffer,
}
if len(ds) == 0 {
@@ -1051,6 +1064,40 @@ func (t *Translator) processAccessLog(gwCtx *GatewayContext, envoyproxy *egv1a1.
return irAccessLog, nil
}
+// buildAccessLogBuffer translates the buffering settings of a gRPC access log sink to the IR.
+// A nil result leaves Envoy's defaults in place.
+func buildAccessLogBuffer(buffer *egv1a1.GRPCAccessLogBufferSettings) (*ir.AccessLogBuffer, error) {
+ if buffer == nil {
+ return nil, nil
+ }
+
+ irBuffer := &ir.AccessLogBuffer{}
+
+ if buffer.FlushInterval != nil {
+ d, err := time.ParseDuration(string(*buffer.FlushInterval))
+ if err != nil {
+ return nil, fmt.Errorf("invalid access log buffer flushInterval value %s", *buffer.FlushInterval)
+ }
+ irBuffer.FlushInterval = ir.MetaV1DurationPtr(d)
+ }
+
+ if buffer.SizeBytes != nil {
+ size, ok := buffer.SizeBytes.AsInt64()
+ if !ok {
+ return nil, fmt.Errorf("invalid access log buffer sizeBytes value %s", buffer.SizeBytes.String())
+ }
+ // The CRD pattern constrains only the string branch of this int-or-string field,
+ // so a bare YAML number reaches here unchecked. Reject zero and negatives to match
+ // what the pattern accepts.
+ if size <= 0 || size > math.MaxUint32 {
+ return nil, fmt.Errorf("access log buffer sizeBytes value %s is out of range", buffer.SizeBytes.String())
+ }
+ irBuffer.SizeBytes = new(uint32(size))
+ }
+
+ return irBuffer, nil
+}
+
func (t *Translator) processTracing(gwCtx *GatewayContext, envoyproxy *egv1a1.EnvoyProxy,
mergeGateways bool, resources *resource.Resources,
) (*ir.Tracing, error) {
diff --git a/internal/gatewayapi/listener_test.go b/internal/gatewayapi/listener_test.go
index 0ca43b8b362..e8ca2c052d7 100644
--- a/internal/gatewayapi/listener_test.go
+++ b/internal/gatewayapi/listener_test.go
@@ -8,11 +8,13 @@ package gatewayapi
import (
"strings"
"testing"
+ "time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
+ apiresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
@@ -1318,6 +1320,102 @@ func TestProcessAccessLog(t *testing.T) {
}
}
+func TestBuildAccessLogBuffer(t *testing.T) {
+ tests := []struct {
+ name string
+ buffer *egv1a1.GRPCAccessLogBufferSettings
+ expected *ir.AccessLogBuffer
+ wantErr string
+ }{
+ {
+ name: "unset leaves envoy defaults in place",
+ buffer: nil,
+ expected: nil,
+ },
+ {
+ name: "flush interval only",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ FlushInterval: new(gwapiv1.Duration("5s")),
+ },
+ expected: &ir.AccessLogBuffer{
+ FlushInterval: ir.MetaV1DurationPtr(5 * time.Second),
+ },
+ },
+ {
+ name: "size only, suffixed quantity is resolved to bytes",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ SizeBytes: new(apiresource.MustParse("4Mi")),
+ },
+ expected: &ir.AccessLogBuffer{
+ SizeBytes: new(uint32(4194304)),
+ },
+ },
+ {
+ name: "both fields",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ FlushInterval: new(gwapiv1.Duration("1m30s")),
+ SizeBytes: new(apiresource.MustParse("32768")),
+ },
+ expected: &ir.AccessLogBuffer{
+ FlushInterval: ir.MetaV1DurationPtr(90 * time.Second),
+ SizeBytes: new(uint32(32768)),
+ },
+ },
+ {
+ name: "unparsable flush interval",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ FlushInterval: new(gwapiv1.Duration("5 seconds")),
+ },
+ wantErr: "invalid access log buffer flushInterval value 5 seconds",
+ },
+ {
+ name: "size beyond uint32",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ SizeBytes: new(apiresource.MustParse("5Gi")),
+ },
+ wantErr: "access log buffer sizeBytes value 5Gi is out of range",
+ },
+ {
+ name: "size beyond int64",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ SizeBytes: new(apiresource.MustParse("1e30")),
+ },
+ wantErr: "invalid access log buffer sizeBytes value 1e30",
+ },
+ {
+ // The pattern accepts only values of 1 and above, but it constrains just the
+ // string branch, so a bare YAML 0 would otherwise slip through.
+ name: "zero size",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ SizeBytes: new(apiresource.MustParse("0")),
+ },
+ wantErr: "access log buffer sizeBytes value 0 is out of range",
+ },
+ {
+ // A raw manifest can write sizeBytes as a bare YAML number, which the CRD
+ // pattern does not constrain (JSON Schema applies it to strings only), so a
+ // negative value reaches the translator.
+ name: "negative size",
+ buffer: &egv1a1.GRPCAccessLogBufferSettings{
+ SizeBytes: new(apiresource.MustParse("-5")),
+ },
+ wantErr: "access log buffer sizeBytes value -5 is out of range",
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ actual, err := buildAccessLogBuffer(tc.buffer)
+ if tc.wantErr != "" {
+ require.EqualError(t, err, tc.wantErr)
+ return
+ }
+ require.NoError(t, err)
+ require.Equal(t, tc.expected, actual)
+ })
+ }
+}
+
func TestGetAuthorityFromDestination(t *testing.T) {
tests := []struct {
name string
diff --git a/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.in.yaml b/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.in.yaml
new file mode 100644
index 00000000000..a655eb5cce7
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.in.yaml
@@ -0,0 +1,49 @@
+envoyProxyForGatewayClass:
+ apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyProxy
+ metadata:
+ namespace: envoy-gateway-system
+ name: test
+ spec:
+ telemetry:
+ accessLog:
+ settings:
+ - sinks:
+ - type: OpenTelemetry
+ openTelemetry:
+ backendRefs:
+ - Name: backend-otel
+ Namespace: envoy-gateway
+ Kind: Backend
+ Group: gateway.envoyproxy.io
+ port: 4317
+ buffer:
+ # Above the 32-bit unsigned integer Envoy carries buffer_size_bytes in,
+ # so this is rejected at translation rather than at admission.
+ sizeBytes: 5Gi
+backends:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-otel
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 2.2.2.2
+ port: 4317
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ namespace: envoy-gateway
+ name: gateway-1
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: Same
diff --git a/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.out.yaml b/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.out.yaml
new file mode 100644
index 00000000000..6c6cfc242ec
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-grpc-buffer-invalid.out.yaml
@@ -0,0 +1,150 @@
+backends:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-otel
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 2.2.2.2
+ port: 4317
+ status:
+ conditions:
+ - lastTransitionTime: null
+ message: The Backend was accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ name: gateway-1
+ namespace: envoy-gateway
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - allowedRoutes:
+ namespaces:
+ from: Same
+ name: http
+ port: 80
+ protocol: HTTP
+ status:
+ conditions:
+ - lastTransitionTime: null
+ message: 'Invalid access log configuration in the referenced EnvoyProxy: access
+ log buffer sizeBytes value 5Gi is out of range'
+ reason: InvalidParameters
+ status: "False"
+ type: Accepted
+ listeners:
+ - attachedRoutes: 0
+ conditions:
+ - lastTransitionTime: null
+ message: Sending translated listener configuration to the data plane
+ reason: Programmed
+ status: "True"
+ type: Programmed
+ - lastTransitionTime: null
+ message: Listener has been successfully translated
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Listener references have been resolved
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ name: http
+ supportedKinds:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ - group: gateway.networking.k8s.io
+ kind: GRPCRoute
+infraIR:
+ envoy-gateway/gateway-1:
+ proxy:
+ config:
+ apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyProxy
+ metadata:
+ name: test
+ namespace: envoy-gateway-system
+ spec:
+ logging: {}
+ telemetry:
+ accessLog:
+ settings:
+ - sinks:
+ - openTelemetry:
+ backendRefs:
+ - group: gateway.envoyproxy.io
+ kind: Backend
+ name: backend-otel
+ namespace: envoy-gateway
+ port: 4317
+ buffer:
+ sizeBytes: 5Gi
+ type: OpenTelemetry
+ status: {}
+ listeners:
+ - name: envoy-gateway/gateway-1/http
+ ports:
+ - containerPort: 10080
+ name: http-80
+ protocol: HTTP
+ servicePort: 80
+ metadata:
+ labels:
+ gateway.envoyproxy.io/owning-gateway-name: gateway-1
+ gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+ ownerReference:
+ kind: GatewayClass
+ name: envoy-gateway-class
+ name: envoy-gateway/gateway-1
+ namespace: envoy-gateway-system
+xdsIR:
+ envoy-gateway/gateway-1:
+ globalResources:
+ proxyServiceCluster:
+ metadata:
+ kind: Service
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.6.5.4
+ port: 8080
+ zone: zone1
+ metadata:
+ kind: Service
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ protocol: TCP
+ http:
+ - address: 0.0.0.0
+ externalPort: 80
+ hostnames:
+ - '*'
+ metadata:
+ kind: Gateway
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ name: envoy-gateway/gateway-1/http
+ path:
+ escapedSlashesAction: UnescapeAndRedirect
+ mergeSlashes: true
+ port: 10080
+ readyListener:
+ address: 0.0.0.0
+ ipFamily: IPv4
+ path: /ready
+ port: 19003
diff --git a/internal/gatewayapi/testdata/accesslog-grpc-buffer.in.yaml b/internal/gatewayapi/testdata/accesslog-grpc-buffer.in.yaml
new file mode 100644
index 00000000000..65aa62aa59f
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-grpc-buffer.in.yaml
@@ -0,0 +1,71 @@
+envoyProxyForGatewayClass:
+ apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyProxy
+ metadata:
+ namespace: envoy-gateway-system
+ name: grpc-buffer
+ spec:
+ telemetry:
+ accessLog:
+ settings:
+ - sinks:
+ - type: ALS
+ als:
+ logName: accesslog
+ backendRefs:
+ - Name: backend-als
+ Namespace: envoy-gateway
+ Kind: Backend
+ Group: gateway.envoyproxy.io
+ port: 9000
+ type: HTTP
+ buffer:
+ flushInterval: 5s
+ sizeBytes: 4Mi
+ - sinks:
+ - type: OpenTelemetry
+ openTelemetry:
+ backendRefs:
+ - Name: backend-otel
+ Namespace: envoy-gateway
+ Kind: Backend
+ Group: gateway.envoyproxy.io
+ port: 4317
+ buffer:
+ sizeBytes: 1Mi
+gateways:
+ - apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ namespace: envoy-gateway
+ name: gateway-1
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: Same
+backends:
+ - apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-als
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 1.1.1.1
+ port: 9000
+ - apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-otel
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 2.2.2.2
+ port: 4317
diff --git a/internal/gatewayapi/testdata/accesslog-grpc-buffer.out.yaml b/internal/gatewayapi/testdata/accesslog-grpc-buffer.out.yaml
new file mode 100644
index 00000000000..61be84ee924
--- /dev/null
+++ b/internal/gatewayapi/testdata/accesslog-grpc-buffer.out.yaml
@@ -0,0 +1,219 @@
+backends:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-als
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 1.1.1.1
+ port: 9000
+ status:
+ conditions:
+ - lastTransitionTime: null
+ message: The Backend was accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: Backend
+ metadata:
+ name: backend-otel
+ namespace: envoy-gateway
+ spec:
+ endpoints:
+ - ip:
+ address: 2.2.2.2
+ port: 4317
+ status:
+ conditions:
+ - lastTransitionTime: null
+ message: The Backend was accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ name: gateway-1
+ namespace: envoy-gateway
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - allowedRoutes:
+ namespaces:
+ from: Same
+ name: http
+ port: 80
+ protocol: HTTP
+ status:
+ listeners:
+ - attachedRoutes: 0
+ conditions:
+ - lastTransitionTime: null
+ message: Sending translated listener configuration to the data plane
+ reason: Programmed
+ status: "True"
+ type: Programmed
+ - lastTransitionTime: null
+ message: Listener has been successfully translated
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Listener references have been resolved
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ name: http
+ supportedKinds:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ - group: gateway.networking.k8s.io
+ kind: GRPCRoute
+infraIR:
+ envoy-gateway/gateway-1:
+ proxy:
+ config:
+ apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyProxy
+ metadata:
+ name: grpc-buffer
+ namespace: envoy-gateway-system
+ spec:
+ logging: {}
+ telemetry:
+ accessLog:
+ settings:
+ - sinks:
+ - als:
+ backendRefs:
+ - group: gateway.envoyproxy.io
+ kind: Backend
+ name: backend-als
+ namespace: envoy-gateway
+ port: 9000
+ buffer:
+ flushInterval: 5s
+ sizeBytes: 4Mi
+ logName: accesslog
+ type: HTTP
+ type: ALS
+ - sinks:
+ - openTelemetry:
+ backendRefs:
+ - group: gateway.envoyproxy.io
+ kind: Backend
+ name: backend-otel
+ namespace: envoy-gateway
+ port: 4317
+ buffer:
+ sizeBytes: 1Mi
+ type: OpenTelemetry
+ status: {}
+ listeners:
+ - name: envoy-gateway/gateway-1/http
+ ports:
+ - containerPort: 10080
+ name: http-80
+ protocol: HTTP
+ servicePort: 80
+ metadata:
+ labels:
+ gateway.envoyproxy.io/owning-gateway-name: gateway-1
+ gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+ ownerReference:
+ kind: GatewayClass
+ name: envoy-gateway-class
+ name: envoy-gateway/gateway-1
+ namespace: envoy-gateway-system
+xdsIR:
+ envoy-gateway/gateway-1:
+ accessLog:
+ als:
+ - buffer:
+ flushInterval: 5s
+ sizeBytes: 4194304
+ destination:
+ metadata:
+ kind: EnvoyProxy
+ name: grpc-buffer
+ namespace: envoy-gateway-system
+ name: accesslog_als_0_0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 1.1.1.1
+ port: 9000
+ metadata:
+ kind: Backend
+ name: backend-als
+ namespace: envoy-gateway
+ name: accesslog_als_0_0/backend/-1
+ protocol: GRPC
+ name: accesslog
+ type: HTTP
+ openTelemetry:
+ - authority: backend-otel.envoy-gateway
+ buffer:
+ sizeBytes: 1048576
+ destination:
+ metadata:
+ kind: EnvoyProxy
+ name: grpc-buffer
+ namespace: envoy-gateway-system
+ name: accesslog_otel_1_0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 2.2.2.2
+ port: 4317
+ metadata:
+ kind: Backend
+ name: backend-otel
+ namespace: envoy-gateway
+ name: accesslog_otel_1_0/backend/-1
+ protocol: GRPC
+ globalResources:
+ proxyServiceCluster:
+ metadata:
+ kind: Service
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.6.5.4
+ port: 8080
+ zone: zone1
+ metadata:
+ kind: Service
+ name: envoy-envoy-gateway-gateway-1-196ae069
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: envoy-gateway/gateway-1
+ protocol: TCP
+ http:
+ - address: 0.0.0.0
+ externalPort: 80
+ hostnames:
+ - '*'
+ metadata:
+ kind: Gateway
+ name: gateway-1
+ namespace: envoy-gateway
+ sectionName: http
+ name: envoy-gateway/gateway-1/http
+ path:
+ escapedSlashesAction: UnescapeAndRedirect
+ mergeSlashes: true
+ port: 10080
+ readyListener:
+ address: 0.0.0.0
+ ipFamily: IPv4
+ path: /ready
+ port: 19003
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-backend-invalid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-backend-invalid.out.yaml
index a8c079dc663..43165e49c39 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-backend-invalid.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-backend-invalid.out.yaml
@@ -16,7 +16,7 @@ gateways:
status:
conditions:
- lastTransitionTime: null
- message: 'Invalid access log backendRefs in the referenced EnvoyProxy: service
+ message: 'Invalid access log configuration in the referenced EnvoyProxy: service
monitoring/service-not-found not found'
reason: InvalidParameters
status: "False"
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel-with-invalid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel-with-invalid.out.yaml
index 6b43f062643..79eb2116869 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel-with-invalid.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel-with-invalid.out.yaml
@@ -16,7 +16,7 @@ gateways:
status:
conditions:
- lastTransitionTime: null
- message: 'Invalid access log backendRefs in the referenced EnvoyProxy: invalid
+ message: 'Invalid access log configuration in the referenced EnvoyProxy: invalid
CEL expression: )++++'
reason: InvalidParameters
status: "False"
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 5c364eb6283..d91c5b4f9d8 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -3116,6 +3116,14 @@ type ALSAccessLog struct {
Attributes []MapEntry `json:"attributes,omitempty" yaml:"attributes,omitempty"`
HTTP *ALSAccessLogHTTP `json:"http,omitempty" yaml:"http,omitempty"`
LogType *ProxyAccessLogType `json:"logType,omitempty" yaml:"logType,omitempty"`
+ Buffer *AccessLogBuffer `json:"buffer,omitempty" yaml:"buffer,omitempty"`
+}
+
+// AccessLogBuffer holds the buffering configuration for the gRPC access log sinks.
+// +k8s:deepcopy-gen=true
+type AccessLogBuffer struct {
+ FlushInterval *metav1.Duration `json:"flushInterval,omitempty" yaml:"flushInterval,omitempty"`
+ SizeBytes *uint32 `json:"sizeBytes,omitempty" yaml:"sizeBytes,omitempty"`
}
// ALSAccessLogHTTP holds the configuration for HTTP ALS access logging.
@@ -3138,6 +3146,7 @@ type OpenTelemetryAccessLog struct {
Destination RouteDestination `json:"destination,omitempty" yaml:"destination,omitempty"`
Traffic *TrafficFeatures `json:"traffic,omitempty" yaml:"traffic,omitempty"`
LogType *ProxyAccessLogType `json:"logType,omitempty" yaml:"logType,omitempty"`
+ Buffer *AccessLogBuffer `json:"buffer,omitempty" yaml:"buffer,omitempty"`
}
// EnvoyPatchPolicy defines the intermediate representation of the EnvoyPatchPolicy resource.
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 141f3f81efc..c6552f22340 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -50,6 +50,11 @@ func (in *ALSAccessLog) DeepCopyInto(out *ALSAccessLog) {
*out = new(ProxyAccessLogType)
**out = **in
}
+ if in.Buffer != nil {
+ in, out := &in.Buffer, &out.Buffer
+ *out = new(AccessLogBuffer)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ALSAccessLog.
@@ -219,6 +224,31 @@ func (in *AccessLog) DeepCopy() *AccessLog {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AccessLogBuffer) DeepCopyInto(out *AccessLogBuffer) {
+ *out = *in
+ if in.FlushInterval != nil {
+ in, out := &in.FlushInterval, &out.FlushInterval
+ *out = new(metav1.Duration)
+ **out = **in
+ }
+ if in.SizeBytes != nil {
+ in, out := &in.SizeBytes, &out.SizeBytes
+ *out = new(uint32)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessLogBuffer.
+func (in *AccessLogBuffer) DeepCopy() *AccessLogBuffer {
+ if in == nil {
+ return nil
+ }
+ out := new(AccessLogBuffer)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) {
*out = *in
@@ -3668,6 +3698,11 @@ func (in *OpenTelemetryAccessLog) DeepCopyInto(out *OpenTelemetryAccessLog) {
*out = new(ProxyAccessLogType)
**out = **in
}
+ if in.Buffer != nil {
+ in, out := &in.Buffer, &out.Buffer
+ *out = new(AccessLogBuffer)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryAccessLog.
diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go
index c47c0b224cf..824bed76841 100644
--- a/internal/xds/translator/accesslog.go
+++ b/internal/xds/translator/accesslog.go
@@ -18,7 +18,9 @@ import (
reqwithoutqueryformatter "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/req_without_query/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
otlpcommonv1 "go.opentelemetry.io/proto/otlp/common/v1"
+ "google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/structpb"
+ "google.golang.org/protobuf/types/known/wrapperspb"
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/ir"
@@ -227,6 +229,7 @@ func buildXdsAccessLog(al *ir.AccessLog, accessLogType ir.ProxyAccessLogType) ([
},
TransportApiVersion: cfgcore.ApiVersion_V3,
}
+ applyAccessLogBuffer(cc, als.Buffer)
switch als.Type {
case egv1a1.ALSEnvoyProxyAccessLogTypeHTTP:
@@ -287,20 +290,23 @@ func buildXdsAccessLog(al *ir.AccessLog, accessLogType ir.ProxyAccessLogType) ([
// NR is only added to listener logs originating from a global log configuration
defaultLogTypeForListener := accessLogType == ir.ProxyAccessLogTypeListener && otel.LogType == nil
- al := &otelaccesslog.OpenTelemetryAccessLogConfig{
- CommonConfig: &grpcaccesslog.CommonGrpcAccessLogConfig{
- LogName: otelLogName,
- GrpcService: &cfgcore.GrpcService{
- TargetSpecifier: &cfgcore.GrpcService_EnvoyGrpc_{
- EnvoyGrpc: &cfgcore.GrpcService_EnvoyGrpc{
- ClusterName: otel.Destination.Name,
- Authority: otel.Authority,
- },
+ cc := &grpcaccesslog.CommonGrpcAccessLogConfig{
+ LogName: otelLogName,
+ GrpcService: &cfgcore.GrpcService{
+ TargetSpecifier: &cfgcore.GrpcService_EnvoyGrpc_{
+ EnvoyGrpc: &cfgcore.GrpcService_EnvoyGrpc{
+ ClusterName: otel.Destination.Name,
+ Authority: otel.Authority,
},
- InitialMetadata: buildGrpcInitialMetadata(otel.Headers),
},
- TransportApiVersion: cfgcore.ApiVersion_V3,
+ InitialMetadata: buildGrpcInitialMetadata(otel.Headers),
},
+ TransportApiVersion: cfgcore.ApiVersion_V3,
+ }
+ applyAccessLogBuffer(cc, otel.Buffer)
+
+ al := &otelaccesslog.OpenTelemetryAccessLogConfig{
+ CommonConfig: cc,
ResourceAttributes: convertToKeyValueList(otel.ResourceAttributes, false),
}
@@ -352,6 +358,21 @@ func buildXdsAccessLog(al *ir.AccessLog, accessLogType ir.ProxyAccessLogType) ([
return accessLogs, nil
}
+// applyAccessLogBuffer sets the buffering fields on a gRPC access log config, leaving
+// Envoy's defaults in place for anything the user did not set.
+func applyAccessLogBuffer(cc *grpcaccesslog.CommonGrpcAccessLogConfig, buffer *ir.AccessLogBuffer) {
+ if buffer == nil {
+ return
+ }
+
+ if buffer.FlushInterval != nil {
+ cc.BufferFlushInterval = durationpb.New(buffer.FlushInterval.Duration)
+ }
+ if buffer.SizeBytes != nil {
+ cc.BufferSizeBytes = wrapperspb.UInt32(*buffer.SizeBytes)
+ }
+}
+
// accessLogTypeMatch checks if the access log type from the IR matches the desired access log type for the proxy (listener, route or Upstream).
// nil ProxyAccessLogType doesn't match Upstream for compatibility.
func accessLogTypeMatch(left *ir.ProxyAccessLogType, right ir.ProxyAccessLogType) bool {
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-grpc-buffer.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-grpc-buffer.yaml
new file mode 100644
index 00000000000..53e6e25e17d
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-grpc-buffer.yaml
@@ -0,0 +1,66 @@
+accesslog:
+ als:
+ - name: als-http
+ buffer:
+ flushInterval: 5s
+ sizeBytes: 4194304
+ destination:
+ name: accesslog/monitoring/envoy-als/port/9000
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 1.1.1.1
+ port: 9000
+ protocol: GRPC
+ weight: 1
+ name: accesslog/monitoring/envoy-als/port/9000/backend/0
+ type: HTTP
+ - name: als-tcp
+ buffer:
+ sizeBytes: 1048576
+ destination:
+ name: accesslog/monitoring/envoy-als-tcp/port/9000
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 2.2.2.2
+ port: 9000
+ protocol: GRPC
+ weight: 1
+ name: accesslog/monitoring/envoy-als-tcp/port/9000/backend/0
+ type: TCP
+ openTelemetry:
+ - buffer:
+ flushInterval: 10s
+ attributes:
+ - key: "response_code"
+ value: "%RESPONSE_CODE%"
+ authority: "otel-collector.default.svc.cluster.local"
+ destination:
+ name: "accesslog-otel-0"
+ settings:
+ - endpoints:
+ - host: "otel-collector.default.svc.cluster.local"
+ port: 4317
+ protocol: "GRPC"
+ addressType: FQDN
+ name: "accesslog-otel-0/backend/0"
+http:
+- name: "first-listener"
+ address: "::"
+ port: 10080
+ hostnames:
+ - "*"
+ path:
+ mergeSlashes: true
+ escapedSlashesAction: UnescapeAndRedirect
+ routes:
+ - name: "direct-route"
+ hostname: "*"
+ destination:
+ name: "direct-route-dest"
+ settings:
+ - endpoints:
+ - host: "1.2.3.4"
+ port: 50000
+ name: "direct-route-dest/backend/0"
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.clusters.yaml
new file mode 100644
index 00000000000..ce76cd01ad2
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.clusters.yaml
@@ -0,0 +1,127 @@
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: direct-route-dest
+ ignoreHealthOnHostRemoval: true
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: direct-route-dest
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: accesslog/monitoring/envoy-als/port/9000
+ ignoreHealthOnHostRemoval: true
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: accesslog/monitoring/envoy-als/port/9000
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
+ typedExtensionProtocolOptions:
+ envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+ '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
+ explicitHttpConfig:
+ http2ProtocolOptions:
+ initialConnectionWindowSize: 1048576
+ initialStreamWindowSize: 65536
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ edsClusterConfig:
+ edsConfig:
+ ads: {}
+ resourceApiVersion: V3
+ serviceName: accesslog/monitoring/envoy-als-tcp/port/9000
+ ignoreHealthOnHostRemoval: true
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: accesslog/monitoring/envoy-als-tcp/port/9000
+ perConnectionBufferLimitBytes: 32768
+ type: EDS
+ typedExtensionProtocolOptions:
+ envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+ '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
+ explicitHttpConfig:
+ http2ProtocolOptions:
+ initialConnectionWindowSize: 1048576
+ initialStreamWindowSize: 65536
+- circuitBreakers:
+ thresholds:
+ - maxRetries: 1024
+ clusterType:
+ name: envoy.cluster.dns
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.clusters.dns.v3.DnsCluster
+ dnsLookupFamily: V4_PREFERRED
+ dnsRefreshRate: 30s
+ respectDnsTtl: true
+ commonLbConfig: {}
+ connectTimeout: 10s
+ dnsLookupFamily: V4_PREFERRED
+ ignoreHealthOnHostRemoval: true
+ loadAssignment:
+ clusterName: accesslog-otel-0
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: otel-collector.default.svc.cluster.local
+ portValue: 4317
+ loadBalancingWeight: 1
+ loadBalancingWeight: 1
+ locality:
+ region: accesslog-otel-0/backend/0
+ loadBalancingPolicy:
+ policies:
+ - typedExtensionConfig:
+ name: envoy.load_balancing_policies.least_request
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest
+ localityLbConfig:
+ localityWeightedLbConfig: {}
+ name: accesslog-otel-0
+ perConnectionBufferLimitBytes: 32768
+ typedExtensionProtocolOptions:
+ envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+ '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
+ explicitHttpConfig:
+ http2ProtocolOptions:
+ initialConnectionWindowSize: 1048576
+ initialStreamWindowSize: 65536
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.endpoints.yaml
new file mode 100644
index 00000000000..df5cda5c10c
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.endpoints.yaml
@@ -0,0 +1,36 @@
+- clusterName: direct-route-dest
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 1.2.3.4
+ portValue: 50000
+ loadBalancingWeight: 1
+ loadBalancingWeight: 1
+ locality:
+ region: direct-route-dest/backend/0
+- clusterName: accesslog/monitoring/envoy-als/port/9000
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 1.1.1.1
+ portValue: 9000
+ loadBalancingWeight: 1
+ loadBalancingWeight: 1
+ locality:
+ region: accesslog/monitoring/envoy-als/port/9000/backend/0
+- clusterName: accesslog/monitoring/envoy-als-tcp/port/9000
+ endpoints:
+ - lbEndpoints:
+ - endpoint:
+ address:
+ socketAddress:
+ address: 2.2.2.2
+ portValue: 9000
+ loadBalancingWeight: 1
+ loadBalancingWeight: 1
+ locality:
+ region: accesslog/monitoring/envoy-als-tcp/port/9000/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.listeners.yaml
new file mode 100644
index 00000000000..f2cdc85442a
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.listeners.yaml
@@ -0,0 +1,138 @@
+- accessLog:
+ - filter:
+ responseFlagFilter:
+ flags:
+ - NR
+ name: envoy.access_loggers.http_grpc
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig
+ commonConfig:
+ bufferFlushInterval: 5s
+ bufferSizeBytes: 4194304
+ grpcService:
+ envoyGrpc:
+ clusterName: accesslog/monitoring/envoy-als/port/9000
+ logName: als-http
+ transportApiVersion: V3
+ - filter:
+ responseFlagFilter:
+ flags:
+ - NR
+ name: envoy.access_loggers.tcp_grpc
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig
+ commonConfig:
+ bufferSizeBytes: 1048576
+ grpcService:
+ envoyGrpc:
+ clusterName: accesslog/monitoring/envoy-als-tcp/port/9000
+ logName: als-tcp
+ transportApiVersion: V3
+ - filter:
+ responseFlagFilter:
+ flags:
+ - NR
+ name: envoy.access_loggers.open_telemetry
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig
+ attributes:
+ values:
+ - key: k8s.namespace.name
+ value:
+ stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%'
+ - key: k8s.pod.name
+ value:
+ stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%'
+ - key: response_code
+ value:
+ stringValue: '%RESPONSE_CODE%'
+ commonConfig:
+ bufferFlushInterval: 10s
+ grpcService:
+ envoyGrpc:
+ authority: otel-collector.default.svc.cluster.local
+ clusterName: accesslog-otel-0
+ logName: otel_envoy_accesslog
+ transportApiVersion: V3
+ resourceAttributes: {}
+ address:
+ socketAddress:
+ address: '::'
+ portValue: 10080
+ defaultFilterChain:
+ filters:
+ - name: envoy.filters.network.http_connection_manager
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+ accessLog:
+ - name: envoy.access_loggers.http_grpc
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig
+ commonConfig:
+ bufferFlushInterval: 5s
+ bufferSizeBytes: 4194304
+ grpcService:
+ envoyGrpc:
+ clusterName: accesslog/monitoring/envoy-als/port/9000
+ logName: als-http
+ transportApiVersion: V3
+ - name: envoy.access_loggers.tcp_grpc
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.TcpGrpcAccessLogConfig
+ commonConfig:
+ bufferSizeBytes: 1048576
+ grpcService:
+ envoyGrpc:
+ clusterName: accesslog/monitoring/envoy-als-tcp/port/9000
+ logName: als-tcp
+ transportApiVersion: V3
+ - name: envoy.access_loggers.open_telemetry
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.access_loggers.open_telemetry.v3.OpenTelemetryAccessLogConfig
+ attributes:
+ values:
+ - key: k8s.namespace.name
+ value:
+ stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%'
+ - key: k8s.pod.name
+ value:
+ stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%'
+ - key: response_code
+ value:
+ stringValue: '%RESPONSE_CODE%'
+ commonConfig:
+ bufferFlushInterval: 10s
+ grpcService:
+ envoyGrpc:
+ authority: otel-collector.default.svc.cluster.local
+ clusterName: accesslog-otel-0
+ logName: otel_envoy_accesslog
+ transportApiVersion: V3
+ resourceAttributes: {}
+ commonHttpProtocolOptions:
+ headersWithUnderscoresAction: REJECT_REQUEST
+ http2ProtocolOptions:
+ initialConnectionWindowSize: 1048576
+ initialStreamWindowSize: 65536
+ maxConcurrentStreams: 100
+ httpFilters:
+ - name: envoy.filters.http.router
+ typedConfig:
+ '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+ suppressEnvoyHeaders: true
+ mergeSlashes: true
+ normalizePath: true
+ pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
+ rds:
+ configSource:
+ ads: {}
+ initialFetchTimeout: 0s
+ resourceApiVersion: V3
+ routeConfigName: first-listener
+ serverHeaderTransformation: PASS_THROUGH
+ statPrefix: http-10080
+ useRemoteAddress: true
+ name: first-listener
+ maxConnectionsToAcceptPerSocketEvent: 1
+ name: first-listener
+ perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.routes.yaml
new file mode 100644
index 00000000000..ea343799ac1
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-grpc-buffer.routes.yaml
@@ -0,0 +1,14 @@
+- ignorePortInHostMatching: true
+ name: first-listener
+ virtualHosts:
+ - domains:
+ - '*'
+ name: first-listener/*
+ routes:
+ - match:
+ prefix: /
+ name: direct-route
+ route:
+ cluster: direct-route-dest
+ upgradeConfigs:
+ - upgradeType: websocket
diff --git a/release-notes/current/new_features/9723-grpc-accesslog-buffer.md b/release-notes/current/new_features/9723-grpc-accesslog-buffer.md
new file mode 100644
index 00000000000..dd9714a13dc
--- /dev/null
+++ b/release-notes/current/new_features/9723-grpc-accesslog-buffer.md
@@ -0,0 +1 @@
+Added a `buffer` field with `flushInterval` and `sizeBytes` to the OpenTelemetry and ALS access log sinks in `EnvoyProxy`, so operators can tune Envoy's access log batching away from its 1s and 16384-byte defaults and trade proxy memory for fewer access logs lost while a sink is unavailable.
diff --git a/release-notes/current/other_changes/9723-accesslog-status-message.md b/release-notes/current/other_changes/9723-accesslog-status-message.md
new file mode 100644
index 00000000000..18feecde2b1
--- /dev/null
+++ b/release-notes/current/other_changes/9723-accesslog-status-message.md
@@ -0,0 +1 @@
+Reworded the Gateway status message for access log translation failures from "Invalid access log backendRefs in the referenced EnvoyProxy" to "Invalid access log configuration in the referenced EnvoyProxy", since the same message also reports invalid CEL match expressions and invalid buffer settings, neither of which involves backendRefs.
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index a7fdb75c863..fdebe647dbf 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -67,6 +67,7 @@ _Appears in:_
| `logName` | _string_ | false | | LogName defines the friendly name of the access log to be returned in
StreamAccessLogsMessage.Identifier. This allows the access log server
to differentiate between different access logs coming from the same Envoy. |
| `type` | _[ALSEnvoyProxyAccessLogType](#alsenvoyproxyaccesslogtype)_ | true | | Type defines the type of accesslog. Supported types are "HTTP" and "TCP". |
| `http` | _[ALSEnvoyProxyHTTPAccessLogConfig](#alsenvoyproxyhttpaccesslogconfig)_ | false | | HTTP defines additional configuration specific to HTTP access logs. |
+| `buffer` | _[GRPCAccessLogBufferSettings](#grpcaccesslogbuffersettings)_ | false | | Buffer defines how access log entries are buffered before being flushed to the
access log service. |
#### ALSEnvoyProxyAccessLogType
@@ -2737,6 +2738,29 @@ _Appears in:_
| `minEndpointsInZoneThreshold` | _integer_ | false | | MinEndpointsInZoneThreshold is the minimum number of upstream endpoints in the local zone required to honor the forceLocalZone
override. This is useful for protecting zones with fewer endpoints. |
+#### GRPCAccessLogBufferSettings
+
+
+
+GRPCAccessLogBufferSettings configures how Envoy buffers access log entries before
+flushing them to a gRPC access log sink.
+
+Entries accumulate until FlushInterval elapses or SizeBytes worth have been buffered,
+whichever comes first, at which point Envoy flushes. Entries are discarded, and counted
+by the sink's `logs_dropped` stat, only when a flush cannot drain the buffer. How much
+of a sink outage the buffer absorbs therefore depends on both settings, since only
+entries still buffered when the sink returns are delivered.
+
+_Appears in:_
+- [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog)
+- [OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog)
+
+| Field | Type | Required | Default | Description |
+| --- | --- | --- | --- | --- |
+| `flushInterval` | _[Duration](https://gateway-api.sigs.k8s.io/reference/api-spec/1.5/spec/#duration)_ | false | | FlushInterval defines how often buffered access log entries are flushed to the sink.
Entries are flushed when this interval elapses or when SizeBytes worth of entries have
been buffered, whichever comes first.
Must be greater than 0. Defaults to 1s. |
+| `sizeBytes` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#quantity-resource-api)_ | false | | SizeBytes defines the soft size limit of the access log entry buffer.
For example, 20Mi, 1Gi, 256Ki etc.
Note that when the suffix is not provided, the value is interpreted as bytes.
Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
rejected when the EnvoyProxy is translated rather than at admission.
Defaults to 16384 bytes. |
+
+
#### GRPCActiveHealthChecker
@@ -4608,6 +4632,7 @@ _Appears in:_
| `resources` | _object (keys:string, values:string)_ | false | | Resources is a set of labels that describe the source of a log entry, including envoy node info.
It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/).
Deprecated: Use ResourceAttributes instead. |
| `resourceAttributes` | _object (keys:string, values:string)_ | false | | ResourceAttributes is a set of labels that describe the source of a log entry, including envoy node info.
It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/). |
| `headers` | _[HTTPHeader](#httpheader) array_ | false | | Headers is a list of additional headers to send with OTLP export requests.
These headers are added as gRPC initial metadata for the OTLP gRPC service. |
+| `buffer` | _[GRPCAccessLogBufferSettings](#grpcaccesslogbuffersettings)_ | false | | Buffer defines how access log entries are buffered before being flushed to the
OpenTelemetry collector. |
#### OpenTelemetryTracingProvider
diff --git a/site/content/en/latest/tasks/observability/proxy-accesslog.md b/site/content/en/latest/tasks/observability/proxy-accesslog.md
index 1d93ab2c023..d3d5d8e75c6 100644
--- a/site/content/en/latest/tasks/observability/proxy-accesslog.md
+++ b/site/content/en/latest/tasks/observability/proxy-accesslog.md
@@ -187,6 +187,63 @@ Verify logs from envoy-als:
curl -s "http://$LOKI_IP:3100/loki/api/v1/query_range" --data-urlencode "query={exporter=\"OTLP\"}" | jq '.data.result[0].values'
```
+## Buffering for gRPC Sinks
+
+The OpenTelemetry and ALS sinks both stream over gRPC, and Envoy buffers log entries before flushing them. By default it flushes every `1s` or once `16384` bytes of entries have accumulated, whichever comes first.
+
+`sizeBytes` is a soft limit on the entry buffer: when buffered entries exceed it, Envoy flushes early instead of waiting for `flushInterval`. Entries are discarded — and counted by the sink's `logs_dropped` stat — only when that flush cannot drain the buffer, which is what happens while the sink is unavailable. Raising it trades proxy memory for a larger batch, so size it from your own measured entry size and request rate.
+
+The two settings together determine how much of a sink outage you can absorb, and they have to be tuned as a pair. Entries survive an outage only for as long as they stay buffered: a flush that fires while the sink is unreachable loses the batch it was carrying. So `flushInterval` has to be longer than the outage you want to ride out, and `sizeBytes` large enough to hold the entries that arrive during it — whichever limit is reached first ends the window. Leaving `flushInterval` at its 1s default means a flush is attempted every second, so raising `sizeBytes` on its own will not widen that window.
+
+Both settings are configured per sink under `buffer`:
+
+```shell
+kubectl apply -f - < duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
http:
description: HTTP defines additional configuration
specific to HTTP access logs.
@@ -48941,6 +48974,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ OpenTelemetry collector.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
headers:
description: |-
Headers is a list of additional headers to send with OTLP export requests.
diff --git a/test/helm/gateway-crds-helm/e2e.out.yaml b/test/helm/gateway-crds-helm/e2e.out.yaml
index 4820e230a85..1ad33911c46 100644
--- a/test/helm/gateway-crds-helm/e2e.out.yaml
+++ b/test/helm/gateway-crds-helm/e2e.out.yaml
@@ -23185,6 +23185,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ access log service.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
http:
description: HTTP defines additional configuration
specific to HTTP access logs.
@@ -24879,6 +24912,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ OpenTelemetry collector.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
headers:
description: |-
Headers is a list of additional headers to send with OTLP export requests.
diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
index 1a13a748173..d16254aa18d 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -23185,6 +23185,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ access log service.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
http:
description: HTTP defines additional configuration
specific to HTTP access logs.
@@ -24879,6 +24912,39 @@ spec:
&& !(has(self.loadBalancer) && has(self.loadBalancer.type)
&& self.loadBalancer.type in [''Random'',
''RoundRobin'']))'
+ buffer:
+ description: |-
+ Buffer defines how access log entries are buffered before being flushed to the
+ OpenTelemetry collector.
+ properties:
+ flushInterval:
+ description: |-
+ FlushInterval defines how often buffered access log entries are flushed to the sink.
+ Entries are flushed when this interval elapses or when SizeBytes worth of entries have
+ been buffered, whichever comes first.
+ Must be greater than 0. Defaults to 1s.
+ pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
+ type: string
+ x-kubernetes-validations:
+ - message: flushInterval must be greater
+ than 0
+ rule: duration(self) > duration('0s')
+ sizeBytes:
+ allOf:
+ - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ SizeBytes defines the soft size limit of the access log entry buffer.
+ For example, 20Mi, 1Gi, 256Ki etc.
+ Note that when the suffix is not provided, the value is interpreted as bytes.
+ Envoy carries this as a 32-bit unsigned integer, so values of 4Gi and above are
+ rejected when the EnvoyProxy is translated rather than at admission.
+ Defaults to 16384 bytes.
+ x-kubernetes-int-or-string: true
+ type: object
headers:
description: |-
Headers is a list of additional headers to send with OTLP export requests.