...
1syntax = "proto3";
2
3package io.linkerd.proxy.outbound;
4
5option go_package = "github.com/linkerd/linkerd2-proxy-api/go/outbound";
6
7import "net.proto";
8import "destination.proto";
9import "meta.proto";
10import "grpc_route.proto";
11import "http_route.proto";
12import "google/protobuf/duration.proto";
13
14service OutboundPolicies {
15 rpc Get(TrafficSpec) returns (OutboundPolicy) {}
16
17 rpc Watch(TrafficSpec) returns (stream OutboundPolicy) {}
18}
19
20message TrafficSpec {
21 // Uniquely identifies the source proxy workload (e.g., pod name) to the
22 // control plane.
23 string source_workload = 1;
24
25 // Describes a target address, as observed by the proxy.
26 oneof target {
27 // Indicates the proxy is connecting to a specific IP:port.
28 io.linkerd.proxy.net.TcpAddress addr = 2;
29
30 // Indicates the proxy is connecting to a named address (like an HTTP
31 // authority).
32 string authority = 3;
33 }
34}
35
36// Outbound policy for a given traffic spec.
37message OutboundPolicy {
38 // Indicates the protocol to use for this target. This will be set to Opaque
39 // if the target has been marked as opaque and will be Discover otherwise.
40 ProxyProtocol protocol = 1;
41
42 // Describes the resource for which outbound policy has been discovered.
43 io.linkerd.proxy.meta.Metadata metadata = 2;
44}
45
46message ProxyProtocol {
47 oneof kind {
48 Detect detect = 1;
49
50 Opaque opaque = 2;
51
52 // HTTP/1 policy configuration.
53 Http1 http1 = 3;
54
55 // HTTP/2 policy configuration.
56 Http2 http2 = 4;
57
58 // gRPC policy configuration.
59 Grpc grpc = 5;
60 }
61
62 message Detect {
63 // Protocol detection timeout.
64 google.protobuf.Duration timeout = 1;
65
66 Opaque opaque = 2;
67
68 // HTTP/1 policy configuration.
69 Http1 http1 = 3;
70
71 // HTTP/2 policy configuration.
72 Http2 http2 = 4;
73 }
74
75 message Opaque {
76 repeated OpaqueRoute routes = 1;
77 }
78
79 message Http1 {
80 repeated HttpRoute routes = 1;
81 // If empty, circuit breaking is not performed.
82 FailureAccrual failure_accrual = 2;
83 }
84
85 message Http2 {
86 repeated HttpRoute routes = 1;
87 // If empty, circuit breaking is not performed.
88 FailureAccrual failure_accrual = 2;
89 }
90
91 message Grpc {
92 repeated GrpcRoute routes = 1;
93 // If empty, circuit breaking is not performed.
94 FailureAccrual failure_accrual = 2;
95 }
96}
97
98// Outbound-specific HTTP route configuration (based on the
99// [Gateway API](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute)).
100message HttpRoute {
101 io.linkerd.proxy.meta.Metadata metadata = 1;
102
103 // If empty, the host value is ignored.
104 repeated io.linkerd.proxy.http_route.HostMatch hosts = 2;
105
106 // Must have at least one rule.
107 repeated Rule rules = 3;
108 message Rule {
109 repeated io.linkerd.proxy.http_route.HttpRouteMatch matches = 1;
110 repeated Filter filters = 2;
111 Distribution backends = 3;
112
113 // After this time has elapsed since receiving the initial request, any
114 // outstanding request will be cancelled if no response has been received.
115 // If the request is cancelled, a timeout error response will be returned,
116 // and no more retries will be attempted
117 //
118 // If this field is empty, no request timeout is applied.
119 google.protobuf.Duration requestTimeout = 4;
120 }
121
122 message Filter {
123 oneof kind {
124 io.linkerd.proxy.http_route.HttpFailureInjector failure_injector = 1;
125 io.linkerd.proxy.http_route.RequestHeaderModifier request_header_modifier = 2;
126 io.linkerd.proxy.http_route.RequestRedirect redirect = 3;
127 io.linkerd.proxy.http_route.ResponseHeaderModifier response_header_modifier = 4;
128 }
129 }
130
131 message Distribution {
132 oneof kind {
133 Empty empty = 1;
134 // Use the first available backend in the list.
135 FirstAvailable first_available = 2;
136 RandomAvailable random_available = 3;
137 }
138
139 message Empty {}
140 message FirstAvailable {
141 repeated RouteBackend backends = 1;
142 }
143 message RandomAvailable {
144 repeated WeightedRouteBackend backends = 1;
145 }
146 }
147
148 message RouteBackend {
149 Backend backend = 1;
150 repeated Filter filters = 3;
151
152 // After this time has elapsed since a request is dispatched to this
153 // backend, any request will be cancelled if no response has been received.
154 // If the request is not retried, a timeout error response is returned.
155 //
156 // If this field is empty, no request timeout is applied.
157 google.protobuf.Duration requestTimeout = 4;
158 }
159
160 message WeightedRouteBackend {
161 RouteBackend backend = 1;
162 uint32 weight = 2;
163 }
164}
165
166message GrpcRoute {
167 io.linkerd.proxy.meta.Metadata metadata = 1;
168
169 // If empty, the host value is ignored.
170 repeated io.linkerd.proxy.http_route.HostMatch hosts = 2;
171
172 // Must have at least one rule.
173 repeated Rule rules = 3;
174 message Rule {
175 repeated io.linkerd.proxy.grpc_route.GrpcRouteMatch matches = 1;
176 repeated Filter filters = 2;
177 Distribution backends = 3;
178
179 // After this time has elapsed since receiving the initial request, any
180 // outstanding request will be cancelled if no response has been received.
181 // If the request is cancelled, a timeout error response will be returned,
182 // and no more retries will be attempted
183 //
184 // If this field is empty, no request timeout is applied.
185 google.protobuf.Duration requestTimeout = 4;
186 }
187
188 message Filter {
189 oneof kind {
190 io.linkerd.proxy.grpc_route.GrpcFailureInjector failure_injector = 1;
191 io.linkerd.proxy.http_route.RequestHeaderModifier request_header_modifier = 2;
192 }
193 }
194
195 message Distribution {
196 oneof kind {
197 Empty empty = 1;
198 // Use the first available backend in the list.
199 FirstAvailable first_available = 2;
200 RandomAvailable random_available = 3;
201 }
202
203 message Empty {}
204 message FirstAvailable {
205 repeated RouteBackend backends = 1;
206 }
207 message RandomAvailable {
208 repeated WeightedRouteBackend backends = 1;
209 }
210 }
211
212 message RouteBackend {
213 Backend backend = 1;
214 repeated Filter filters = 3;
215
216 // After this time has elapsed since a request is dispatched to this
217 // backend, any request will be cancelled if no response has been received.
218 // If the request is not retried, a timeout error response is returned.
219 //
220 // If this field is empty, no request timeout is applied.
221 google.protobuf.Duration requestTimeout = 4;
222 }
223
224 message WeightedRouteBackend {
225 RouteBackend backend = 1;
226 uint32 weight = 2;
227 }
228}
229
230message OpaqueRoute {
231 io.linkerd.proxy.meta.Metadata metadata = 1;
232
233 // Must have at least one rule.
234 repeated Rule rules = 3;
235 message Rule {
236 Distribution backends = 1;
237 }
238
239 message Distribution {
240 oneof kind {
241 Empty empty = 1;
242 // Use the first available backend in the list.
243 FirstAvailable first_available = 2;
244 RandomAvailable random_available = 3;
245 }
246
247 message Empty {}
248 message FirstAvailable {
249 repeated RouteBackend backends = 1;
250 }
251 message RandomAvailable {
252 repeated WeightedRouteBackend backends = 1;
253 }
254 }
255
256 message RouteBackend {
257 Backend backend = 1;
258 }
259
260 message WeightedRouteBackend {
261 RouteBackend backend = 1;
262 uint32 weight = 2;
263 }
264}
265
266message Backend {
267 io.linkerd.proxy.meta.Metadata metadata = 1;
268
269 oneof kind {
270 // A backend that consists of a single endpoint.
271 io.linkerd.proxy.destination.WeightedAddr forward = 2;
272
273 // A backend that comprises a load balanced service.
274 BalanceP2c balancer = 3;
275 }
276
277 // Describes queue configuration for a backend.
278 Queue queue = 4;
279
280 // A strategy for discovering endpoints for a service.
281 message EndpointDiscovery {
282 oneof kind {
283 // Use the `Destination` service to discover endpoints for this service.
284 DestinationGet dst = 1;
285 }
286
287 message DestinationGet {
288 string path = 1;
289 }
290 }
291
292 // Describes a power-of-two-choices (P2C) load balancer configuration for a
293 // backend.
294 message BalanceP2c {
295 EndpointDiscovery discovery = 1;
296
297 // The load estimation strategy used by this load balancer.
298 oneof load {
299 // This load balancer uses peak EWMA (exponentially weighted moving
300 // average) load estimates.
301 PeakEwma peak_ewma = 2;
302 }
303
304 // Parameters configuring peak EWMA load estimation.
305 message PeakEwma {
306 // Initial latency value used when no latencies have been
307 // recorded for an endpoint.
308 google.protobuf.Duration default_rtt = 1;
309
310 // The duration of the moving window over which latency is observed.
311 google.protobuf.Duration decay = 2;
312 }
313 }
314}
315
316message Queue {
317 // The number of requests that may be held in a queue before backpressure is
318 // exerted.
319 uint32 capacity = 1;
320
321 // A timeout that limits how long a backend may remain unready before any
322 // requests in its queue are failed.
323 google.protobuf.Duration failfast_timeout = 2;
324}
325
326message FailureAccrual {
327 message ConsecutiveFailures {
328 uint32 max_failures = 1;
329 ExponentialBackoff backoff = 2;
330 }
331
332 oneof kind {
333 ConsecutiveFailures consecutive_failures = 1;
334 }
335}
336
337message ExponentialBackoff {
338 // The minimum amount of time to wait before resuming an operation.
339 google.protobuf.Duration min_backoff = 1;
340 // The maximum amount of time to wait before resuming an operation.
341 // Must be greater than or equal to min_backoff.
342 google.protobuf.Duration max_backoff = 2;
343 // The ratio of the base timeout that may be randomly added to a backoff.
344 // Must be greater than or equal to 0.0.
345 float jitter_ratio = 3;
346}
View as plain text