Skip to content

Commit 50322df

Browse files
indiebrainwtarreau
authored andcommitted
MEDIUM: server: add init-state
Allow the user to set the "initial state" of a server. Context: Servers are always set in an UP status by default. In some cases, further checks are required to determine if the server is ready to receive client traffic. This introduces the "init-state {up|down}" configuration parameter to the server. - when set to 'fully-up', the server is considered immediately available and can turn to the DOWN sate when ALL health checks fail. - when set to 'up' (the default), the server is considered immediately available and will initiate a health check that can turn it to the DOWN state immediately if it fails. - when set to 'down', the server initially is considered unavailable and will initiate a health check that can turn it to the UP state immediately if it succeeds. - when set to 'fully-down', the server is initially considered unavailable and can turn to the UP state when ALL health checks succeed. The server's init-state is considered when the HAProxy instance is (re)started, a new server is detected (for example via service discovery / DNS resolution), a server exits maintenance, etc. Link: haproxy/haproxy#51
1 parent e8b1ad4 commit 50322df

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

doc/configuration.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17551,6 +17551,51 @@ downinter <delay>
1755117551
"inter" setting will have a very limited effect as it will not be able to
1755217552
reduce the time spent in the queue.
1755317553

17554+
init-state { fully-up | up | down | fully-down }
17555+
May be used in the following contexts: tcp, http
17556+
17557+
May be used in sections : defaults | frontend | listen | backend
17558+
no | no | yes | yes
17559+
17560+
The "init-state" option sets the initial state of the server:
17561+
- when set to 'fully-up', the server is considered immediately available
17562+
and can turn to the DOWN sate when ALL health checks fail.
17563+
- when set to 'up' (the default), the server is considered immediately
17564+
available and will initiate a health check that can turn it to the DOWN
17565+
state immediately if it fails.
17566+
- when set to 'down', the server initially is considered unavailable and
17567+
will initiate a health check that can turn it to the UP state immediately
17568+
if it succeeds.
17569+
- when set to 'fully-down', the server is initially considered unavailable
17570+
and can turn to the UP state when ALL health checks succeed.
17571+
17572+
The server's init-state is considered when the HAProxy instance is
17573+
(re)started, a new server is detected (for example via service discovery /
17574+
DNS resolution), a server exits maintenance, etc.
17575+
17576+
Examples:
17577+
# pass client traffic ONLY to Redis "master" node
17578+
backend redis-master
17579+
mode tcp
17580+
balance first
17581+
option tcp-check
17582+
tcp-check send role\r\n
17583+
tcp-check expect string master
17584+
server-template redis 3 _redis._tcp.redis-headless-service.sandbox.svc.cluster.local:6379 check ... init-state down
17585+
17586+
# pass traffic to the server only after 3 successful health checks
17587+
backend google-backend
17588+
mode http
17589+
server srv1 google.com:80 check init-state down rise 3
17590+
server srv2 google.com:80 check init-state down rise 3
17591+
17592+
# or
17593+
listen
17594+
mode http
17595+
server-template srv 2 google.com:80 check init-state down rise 3
17596+
17597+
See also: "option tcp-check", "option httpchk"
17598+
1755417599
log-bufsize <bufsize>
1755517600
May be used in the following contexts: log
1755617601

include/haproxy/server-t.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ enum srv_initaddr {
101101
SRV_IADDR_IP = 4, /* we set an arbitrary IP address to the server */
102102
} __attribute__((packed));
103103

104+
/* options for servers' "init-state" parameter this parameter may be
105+
* used to drive HAProxy's behavior when determining a server's status
106+
* at start up time.
107+
*/
108+
enum srv_init_state {
109+
SRV_INIT_STATE_FULLY_DOWN = 0, /* the server should initially be considered DOWN until it passes all health checks. Please keep set to zero. */
110+
SRV_INIT_STATE_DOWN, /* the server should initially be considered DOWN until it passes one health check. */
111+
SRV_INIT_STATE_UP, /* the server should initially be considered UP, but will go DOWN if it fails one health check. */
112+
SRV_INIT_STATE_FULLY_UP, /* the server should initially be considered UP, but will go DOWN if it fails all health checks. */
113+
} __attribute__((packed));
114+
104115
/* server-state-file version */
105116
#define SRV_STATE_FILE_VERSION 1
106117
#define SRV_STATE_FILE_VERSION_MIN 1
@@ -279,6 +290,7 @@ struct proxy;
279290
struct server {
280291
/* mostly config or admin stuff, doesn't change often */
281292
enum obj_type obj_type; /* object type == OBJ_TYPE_SERVER */
293+
enum srv_init_state init_state; /* server's initial state among SRV_INIT_STATE */
282294
enum srv_state next_state, cur_state; /* server state among SRV_ST_* */
283295
enum srv_admin next_admin, cur_admin; /* server maintenance status : SRV_ADMF_* */
284296
signed char use_ssl; /* ssl enabled (1: on, 0: disabled, -1 forced off) */

src/server.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,27 @@ static int srv_parse_init_addr(char **args, int *cur_arg,
10541054
return 0;
10551055
}
10561056

1057+
/* Parse the "init-state" server keyword */
1058+
static int srv_parse_init_state(char **args, int *cur_arg,
1059+
struct proxy *curproxy, struct server *newsrv, char **err)
1060+
{
1061+
if (strcmp(args[*cur_arg + 1], "fully-up") == 0)
1062+
newsrv->init_state= SRV_INIT_STATE_FULLY_UP;
1063+
else if (strcmp(args[*cur_arg + 1], "up") == 0)
1064+
newsrv->init_state = SRV_INIT_STATE_UP;
1065+
else if (strcmp(args[*cur_arg + 1], "down") == 0)
1066+
newsrv->init_state= SRV_INIT_STATE_DOWN;
1067+
else if (strcmp(args[*cur_arg + 1], "fully-down") == 0)
1068+
newsrv->init_state= SRV_INIT_STATE_FULLY_DOWN;
1069+
else {
1070+
memprintf(err, "'%s' expects one of 'fully-up', 'up', 'down', or 'fully-down' but got '%s'",
1071+
args[*cur_arg], args[*cur_arg + 1]);
1072+
return ERR_ALERT | ERR_FATAL;
1073+
}
1074+
1075+
return 0;
1076+
}
1077+
10571078
/* Parse the "log-bufsize" server keyword */
10581079
static int srv_parse_log_bufsize(char **args, int *cur_arg,
10591080
struct proxy *curproxy, struct server *newsrv, char **err)
@@ -2302,6 +2323,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, {
23022323
{ "hash-key", srv_parse_hash_key, 1, 1, 1 }, /* Configure how chash keys are computed */
23032324
{ "id", srv_parse_id, 1, 0, 1 }, /* set id# of server */
23042325
{ "init-addr", srv_parse_init_addr, 1, 1, 0 }, /* */
2326+
{ "init-state", srv_parse_init_state, 1, 1, 0 }, /* Set the initial state of the server */
23052327
{ "log-bufsize", srv_parse_log_bufsize, 1, 1, 0 }, /* Set the ring bufsize for log server (only for log backends) */
23062328
{ "log-proto", srv_parse_log_proto, 1, 1, 0 }, /* Set the protocol for event messages, only relevant in a log or ring section */
23072329
{ "maxconn", srv_parse_maxconn, 1, 1, 1 }, /* Set the max number of concurrent connection */
@@ -2713,6 +2735,8 @@ void srv_settings_init(struct server *srv)
27132735
srv->agent.fall = DEF_AGENT_FALLTIME;
27142736
srv->agent.port = 0;
27152737

2738+
srv->init_state = SRV_INIT_STATE_UP;
2739+
27162740
srv->maxqueue = 0;
27172741
srv->minconn = 0;
27182742
srv->maxconn = 0;
@@ -2842,6 +2866,8 @@ void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl
28422866

28432867
srv->init_addr_methods = src->init_addr_methods;
28442868
srv->init_addr = src->init_addr;
2869+
2870+
srv->init_state = src->init_state;
28452871
#if defined(USE_OPENSSL)
28462872
srv_ssl_settings_cpy(srv, src);
28472873
#endif
@@ -6504,7 +6530,17 @@ static int _srv_update_status_adm(struct server *s, enum srv_adm_st_chg_cause ca
65046530
*/
65056531
if (s->check.state & CHK_ST_ENABLED) {
65066532
s->check.state &= ~CHK_ST_PAUSED;
6507-
s->check.health = s->check.rise; /* start OK but check immediately */
6533+
if(s->init_state == SRV_INIT_STATE_FULLY_UP) {
6534+
s->check.health = s->check.rise + s->check.fall - 1; /* initially UP, when all checks fail to bring server DOWN */
6535+
}
6536+
else if(s->init_state == SRV_INIT_STATE_DOWN) {
6537+
s->check.health = s->check.rise - 1; /* initially DOWN, when one check is successful bring server UP */
6538+
}
6539+
else if(s->init_state == SRV_INIT_STATE_FULLY_DOWN) {
6540+
s->check.health = 0; /* initially DOWN, when all checks are successful bring server UP */
6541+
} else {
6542+
s->check.health = s->check.rise; /* initially UP, when one check fails check brings server DOWN */
6543+
}
65086544
}
65096545

65106546
if ((!s->track || s->track->next_state != SRV_ST_STOPPED) &&

0 commit comments

Comments
 (0)