Better handling of tags update in consul

This commit is contained in:
Daniel Berteaud 2024-03-07 22:26:26 +01:00
parent 80da801ea6
commit 0534991545
4 changed files with 96 additions and 36 deletions

View File

@ -95,15 +95,11 @@ job "postgres" {
# This check will ensure the current role is published in Consul tags (if the callback during a role change failed for example)
check {
name = "tags"
type = "script"
command = "/bin/sh"
args = [
"-c",
"ROLE=$(curl -k https://localhost:${NOMAD_PORT_patroni}/health | jq -r .role) && /local/update_tags.sh ensure_tags ${ROLE}"
]
name = "tags"
type = "script"
command = "/local/update_tags.sh"
task = "postgres"
interval = "60s"
interval = "20s"
timeout = "10s"
}
@ -200,7 +196,7 @@ def create_svc_txn:
# Select our own instance
select(.ServiceTags[] | contains($mytag))
# Add needed tags
# Add needed tags, remove unwanted ones
| .ServiceTags -= ["master"]
| .ServiceTags -= ["replica"]
| .ServiceTags -= ["uninitialized"]
@ -209,12 +205,28 @@ def create_svc_txn:
| .ServiceTags += [$role]
| if $role == "master" then .ServiceTags += ["traefik.enable=true"] else .ServiceTags += ["traefik.enable=false"] end
# Rewrite keys to remove the Service prefix
# Rename 'ServiceName' to 'ServiceService'
# Will be transformed to 'Service.Service later'
| . + {ServiceService: .ServiceName}
| del(.ServiceName)
| nest_service_params as $nested_params
| $nested_params
# Create transaction to update services using check-and-set option.
# If service has been modified since our last read, or no longer exists, the
# transaction will fail.
| {
Service: {
Verb: "cas",
Node: .Node,
# Nest service-related parameters under 'Service' key
# Add ModfyIndex key
Service: ($nested_params + {ModifyIndex: .ModifyIndex})
}
}
;
. | map(create_svc_txn) | .[]
. | map(create_svc_txn)
_EOT
destination = "local/serviceformat.jq"
@ -231,6 +243,12 @@ set -eo pipefail
EVENT=$1
NEW_ROLE=$2
if [ -z "${NEW_ROLE}" ]; then
# If new role is not given as argument, fetch it from patroni
NEW_ROLE=$(curl --silent --insecure https://localhost:${NOMAD_PORT_patroni}/health | jq -r .role)
fi
# Source env file to get our consul token
source /secrets/pg.env
# translate promoted = master and demoted = recplica
@ -240,17 +258,29 @@ elif [ "${NEW_ROLE}" = "demoted" ]; then
NEW_ROLE="replica"
fi
CURL_OPTS="--connect-timeout 5 --max-time 10 --retry 5 --retry-delay 1 --retry-max-time 40 --retry-connrefused"
CURL_OPTS="--connect-timeout 5 --max-time 10 --retry 5 --retry-delay 1 --retry-max-time 40 --retry-connrefused --silent"
# Update tags on the main service
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/postgres |\
jq --from-file /local/serviceformat.jq --arg role ${NEW_ROLE} --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CORL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/agent/service/register
SERVICE=$(curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/postgres)
if [ "$(echo ${SERVICE} | jq ".[] | .ServiceTags | any(.==\"${NEW_ROLE}\")")" = "false" ]; then
echo "Updating tags for the main service"
echo "${SERVICE}" |\
jq --from-file /local/serviceformat.jq --arg role "${NEW_ROLE}" --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CORL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/txn > /dev/null
else
echo "Main service already has th expected ${NEW_ROLE} tag"
fi
# Update tags on the sidecar service (connect-proxy)
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/postgres-sidecar-proxy |\
jq --from-file /local/serviceformat.jq --arg role ${NEW_ROLE} --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/agent/service/register
SIDECAR=$(curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/postgres-sidecar-proxy)
if [ "$(echo ${SIDECAR} | jq ".[] | .ServiceTags | any(.==\"${NEW_ROLE}\")")" = "false" ]; then
echo "Updating tags for the sidecar"
echo "${SIDECAR}" |\
jq --from-file /local/serviceformat.jq --arg role "${NEW_ROLE}" --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/txn > /dev/null
else
echo "Sidecar service already has the expected ${NEW_ROLE} tag"
fi
_EOT
destination = "local/update_tags.sh"

View File

@ -73,13 +73,9 @@ job "[[ .instance ]]" {
check {
name = "tags"
type = "script"
command = "/bin/sh"
args = [
"-c",
"ROLE=$(curl -k https://localhost:${NOMAD_PORT_patroni}/health | jq -r .role) && /local/update_tags.sh ensure_tags ${ROLE}"
]
command = "/local/update_tags.sh"
task = "postgres"
interval = "60s"
interval = "20s"
timeout = "10s"
}

View File

@ -8,7 +8,7 @@ def create_svc_txn:
# Select our own instance
select(.ServiceTags[] | contains($mytag))
# Add needed tags
# Add needed tags, remove unwanted ones
| .ServiceTags -= ["master"]
| .ServiceTags -= ["replica"]
| .ServiceTags -= ["uninitialized"]
@ -19,9 +19,25 @@ def create_svc_txn:
| if $role == "master" then .ServiceTags += ["[[ .traefik.instance ]].enable=true"] else .ServiceTags += ["[[ .traefik.instance ]].enable=false"] end
[[- end ]]
# Rewrite keys to remove the Service prefix
# Rename 'ServiceName' to 'ServiceService'
# Will be transformed to 'Service.Service later'
| . + {ServiceService: .ServiceName}
| del(.ServiceName)
| nest_service_params as $nested_params
| $nested_params
# Create transaction to update services using check-and-set option.
# If service has been modified since our last read, or no longer exists, the
# transaction will fail.
| {
Service: {
Verb: "cas",
Node: .Node,
# Nest service-related parameters under 'Service' key
# Add ModfyIndex key
Service: ($nested_params + {ModifyIndex: .ModifyIndex})
}
}
;
. | map(create_svc_txn) | .[]
. | map(create_svc_txn)

View File

@ -6,6 +6,12 @@ set -eo pipefail
EVENT=$1
NEW_ROLE=$2
if [ -z "${NEW_ROLE}" ]; then
# If new role is not given as argument, fetch it from patroni
NEW_ROLE=$(curl --silent --insecure https://localhost:${NOMAD_PORT_patroni}/health | jq -r .role)
fi
# Source env file to get our consul token
source /secrets/pg.env
# translate promoted = master and demoted = recplica
@ -15,14 +21,26 @@ elif [ "${NEW_ROLE}" = "demoted" ]; then
NEW_ROLE="replica"
fi
CURL_OPTS="--connect-timeout 5 --max-time 10 --retry 5 --retry-delay 1 --retry-max-time 40 --retry-connrefused"
CURL_OPTS="--connect-timeout 5 --max-time 10 --retry 5 --retry-delay 1 --retry-max-time 40 --retry-connrefused --silent"
# Update tags on the main service
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/[[ .instance ]] |\
jq --from-file /local/serviceformat.jq --arg role ${NEW_ROLE} --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CORL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/agent/service/register
SERVICE=$(curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/[[ .instance ]])
if [ "$(echo ${SERVICE} | jq ".[] | .ServiceTags | any(.==\"${NEW_ROLE}\")")" = "false" ]; then
echo "Updating tags for the main service"
echo "${SERVICE}" |\
jq --from-file /local/serviceformat.jq --arg role "${NEW_ROLE}" --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CORL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/txn > /dev/null
else
echo "Main service already has th expected ${NEW_ROLE} tag"
fi
# Update tags on the sidecar service (connect-proxy)
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/[[ .instance ]]-sidecar-proxy |\
jq --from-file /local/serviceformat.jq --arg role ${NEW_ROLE} --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/agent/service/register
SIDECAR=$(curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/catalog/service/[[ .instance ]]-sidecar-proxy)
if [ "$(echo ${SIDECAR} | jq ".[] | .ServiceTags | any(.==\"${NEW_ROLE}\")")" = "false" ]; then
echo "Updating tags for the sidecar"
echo "${SIDECAR}" |\
jq --from-file /local/serviceformat.jq --arg role "${NEW_ROLE}" --arg mytag postgres-{{ env "NOMAD_ALLOC_INDEX" }} |\
curl ${CURL_OPTS} -H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}" -X PUT -d @- http://{{ sockaddr "GetInterfaceIP \"nomad\"" }}:8500/v1/txn > /dev/null
else
echo "Sidecar service already has the expected ${NEW_ROLE} tag"
fi