Skip to content

Commit aa417b2

Browse files
authored
feat(apisix-standalone): support upstream healthcheck and service discovery (#333)
1 parent abec7bc commit aa417b2

File tree

5 files changed

+86
-27
lines changed

5 files changed

+86
-27
lines changed

libs/backend-apisix-standalone/README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,3 @@ The ADC will ignore the resource-type level `conf_version` and resource level `m
3939
They will not be exported to a YAML file. Updates to conf_version and modifiedIndex will only occur during synchronization.
4040

4141
Their values will be reset to that moment's timestamp when they are created or updated.
42-
43-
### Differences in upstream
44-
45-
This backend's upstream converter will not support the configuration of the APISIX health checker or service discovery.
46-
47-
The reason for this is that this backend will primarily be used in an Ingress Controller scenario. In this scenario, the Kubernetes Endpoints mechanism and probes will implement these two capabilities.

libs/backend-apisix-standalone/src/operator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ export class Operator extends ADCSDK.backend.BackendEventSource {
448448
keepalive_pool: res.keepalive_pool,
449449
pass_host: res.pass_host,
450450
upstream_host: res.upstream_host,
451+
checks: res.checks,
452+
discovery_type: res.discovery_type,
453+
service_name: res.service_name,
454+
discovery_args: res.discovery_args,
451455
} satisfies typing.Upstream as typing.Upstream;
452456
if (parentId)
453457
upstream.labels = {

libs/backend-apisix-standalone/src/transformer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export const toADC = (input: typing.APISIXStandalone) => {
3131
// Empty Lua tables will be encoded as "{}" rather than "[]" by cjson,
3232
// so this must be handled separately to prevent unexpected diff results.
3333
nodes: !isEmpty(upstream.nodes) ? upstream.nodes : [],
34+
35+
checks: upstream.checks,
36+
discovery_type: upstream.discovery_type,
37+
service_name: upstream.service_name,
38+
discovery_args: upstream.discovery_args,
3439
});
3540
return {
3641
services:

libs/backend-apisix-standalone/src/typing.ts

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,27 @@ const RouteSchema = z.strictObject({
4141
});
4242
export type Route = z.infer<typeof RouteSchema>;
4343

44+
const upstreamHealthCheckPassiveHealthy = z.strictObject({
45+
http_statuses: z
46+
.array(z.coerce.number().int().min(200).max(599))
47+
.min(1)
48+
.default([200, 302])
49+
.optional(),
50+
successes: z.coerce.number().int().min(1).max(254).default(2).optional(),
51+
});
52+
const upstreamHealthCheckPassiveUnhealthy = z.strictObject({
53+
http_statuses: z
54+
.array(z.coerce.number().int().min(200).max(599))
55+
.min(1)
56+
.default([429, 404, 500, 501, 502, 503, 504, 505])
57+
.optional(),
58+
http_failures: z.coerce.number().int().min(1).max(254).default(5).optional(),
59+
tcp_failures: z.coerce.number().int().min(1).max(254).default(2).optional(),
60+
timeouts: z.coerce.number().int().min(1).max(254).default(3).optional(),
61+
});
62+
const upstreamHealthCheckType = z
63+
.union([z.literal('http'), z.literal('https'), z.literal('tcp')])
64+
.default('http');
4465
const UpstreamSchema = z.strictObject({
4566
...ModifiedIndex,
4667
...Metadata,
@@ -99,9 +120,44 @@ const UpstreamSchema = z.strictObject({
99120
})
100121
.optional(),
101122

102-
// Will not include health checks and service discovery configurations,
103-
// which are implemented by other components on the target ecosystem,
104-
// such as Kubernetes and Ingress Controller.
123+
checks: z
124+
.strictObject({
125+
active: z
126+
.strictObject({
127+
type: upstreamHealthCheckType.optional(),
128+
timeout: z.coerce.number().default(1).optional(),
129+
concurrency: z.coerce.number().default(10).optional(),
130+
host: z.string().min(1).optional(),
131+
port: z.coerce.number().int().min(1).max(65535).optional(),
132+
http_path: z.string().default('/').optional(),
133+
https_verify_cert: z.boolean().default(true).optional(),
134+
http_request_headers: z.array(z.string()).min(1).optional(),
135+
healthy: z
136+
.strictObject({
137+
...upstreamHealthCheckPassiveHealthy.shape,
138+
interval: z.coerce.number().int().min(1).default(1),
139+
})
140+
.optional(),
141+
unhealthy: z
142+
.strictObject({
143+
...upstreamHealthCheckPassiveUnhealthy.shape,
144+
interval: z.coerce.number().int().min(1).default(1),
145+
})
146+
.optional(),
147+
})
148+
.optional(),
149+
passive: z
150+
.strictObject({
151+
type: upstreamHealthCheckType.optional(),
152+
healthy: upstreamHealthCheckPassiveHealthy.optional(),
153+
unhealthy: upstreamHealthCheckPassiveUnhealthy.optional(),
154+
})
155+
.optional(),
156+
})
157+
.optional(),
158+
discovery_type: z.string().optional(),
159+
service_name: z.string().optional(),
160+
discovery_args: z.record(z.string(), z.any()).optional(),
105161
});
106162
export type Upstream = z.infer<typeof UpstreamSchema>;
107163

libs/sdk/src/core/index.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,35 +83,35 @@ export interface UpstreamKeepalivePool {
8383
requests: number;
8484
}
8585
export interface UpstreamHealthCheck {
86-
active: UpstreamHealthCheckActive;
87-
passive: UpstreamHealthCheckPassive;
86+
active?: UpstreamHealthCheckActive;
87+
passive?: UpstreamHealthCheckPassive;
8888
}
8989
export interface UpstreamHealthCheckActive {
9090
type?: 'http' | 'https' | 'tcp';
9191
timeout?: number;
9292
concurrency?: number;
93-
host: string;
94-
port: number;
95-
http_path: string;
96-
https_verify_cert: boolean;
97-
http_request_headers: Array<string>;
98-
healthy: UpstreamHealthCheckActiveHealthy;
99-
unhealthy: UpstreamHealthCheckActiveUnhealthy;
93+
host?: string;
94+
port?: number;
95+
http_path?: string;
96+
https_verify_cert?: boolean;
97+
http_request_headers?: Array<string>;
98+
healthy?: UpstreamHealthCheckActiveHealthy;
99+
unhealthy?: UpstreamHealthCheckActiveUnhealthy;
100100
}
101101
export interface UpstreamHealthCheckPassive {
102-
type: string;
103-
healthy: UpstreamHealthCheckPassiveHealthy;
104-
unhealthy: UpstreamHealthCheckPassiveUnhealthy;
102+
type?: 'http' | 'https' | 'tcp';
103+
healthy?: UpstreamHealthCheckPassiveHealthy;
104+
unhealthy?: UpstreamHealthCheckPassiveUnhealthy;
105105
}
106106
export interface UpstreamHealthCheckPassiveHealthy {
107-
http_statuses: Array<number>;
108-
successes: number;
107+
http_statuses?: Array<number>;
108+
successes?: number;
109109
}
110110
export interface UpstreamHealthCheckPassiveUnhealthy {
111-
http_statuses: Array<number>;
112-
http_failures: number;
113-
tcp_failures: number;
114-
timeouts: number;
111+
http_statuses?: Array<number>;
112+
http_failures?: number;
113+
tcp_failures?: number;
114+
timeouts?: number;
115115
}
116116

117117
export type UpstreamHealthCheckActiveHealthy = {

0 commit comments

Comments
 (0)