Repository navigation
Expand file tree
/
Copy pathupdate.sh
More file actions
executable file
·169 lines (142 loc) · 7.42 KB
/
Copy pathupdate.sh
File metadata and controls
executable file
·169 lines (142 loc) · 7.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/utils/utils.sh" "$@"
# Ahead of the timescaledb check: on a node left on its old IP (see
# utils/ensure_node_ip.sh) that check cannot read the volume and stops
# update.sh, and this is the repair. It only annotates the Node.
ensure_node_ip
# First, while the cluster is untouched: a PostgreSQL major upgrade that cannot
# go ahead (no disk, no answer) has to stop update.sh before anything changes.
if ! plan_timescaledb_major_upgrade; then
exit 1
fi
# Nothing terminates TLS in the cluster in this mode, so any Certificate left
# over from a previous https install keeps retrying HTTP-01 against a server
# that no longer answers the challenge -- silently accumulating failed orders
# against Let's Encrypt's rate limit. watch_ssl_status is skipped below, so
# there is nothing to report it either.
if [ "$REVERSE_PROXY" = true ]; then
for CERT in 5stack-ssl 5stack-mediamtx-ssl; do
kubectl --kubeconfig=$KUBECONFIG delete certificate "$CERT" -n 5stack 2>/dev/null
done
# Behind a proxy that already terminated TLS, this would loop forever.
kubectl --kubeconfig=$KUBECONFIG delete httproute https-redirect -n 5stack 2>/dev/null
else
# A REVERSE_PROXY install's answer on 443; this install's own listeners serve
# those hosts there now.
kubectl --kubeconfig=$KUBECONFIG delete gateway 5stack-tls -n 5stack 2>/dev/null
kubectl --kubeconfig=$KUBECONFIG delete secret 5stack-reverse-proxy-tls -n 5stack 2>/dev/null
fi
if [ "$REVERSE_PROXY" != true ]; then
step "Installing cert-manager"
apply_overlay overlays/cert-manager-crds || die "failed to install cert-manager"
for CRD in certificates.cert-manager.io issuers.cert-manager.io clusterissuers.cert-manager.io; do
if ! output_redirect kubectl --kubeconfig=$KUBECONFIG wait --for=condition=Established "crd/$CRD" --timeout=120s; then
die "cert-manager CRD $CRD never became established"
fi
done
ok "cert-manager CRDs ready"
# The CRDs are Established within a second of the apply, long before any
# cert-manager pod is running -- which is exactly why this wait exists. The
# overlay below carries the Certificate and the Issuer, and cert-manager's
# admission webhook rejects both outright while it is still starting.
step "Waiting for cert-manager"
wait_for_cert_manager || die "cert-manager did not become ready; re-run ./update.sh once it settles"
ok "cert-manager is ready"
fi
# Before the overlay: its Gateway, routes and Middlewares need the CRDs, and
# on an upgrade from ingress-nginx Traefik has to be serving before it is
# handed ports 80/443.
step "Installing Traefik"
install_traefik || die "failed to install Traefik"
ok "Traefik is ready"
step "Building overlay manifests"
# Whether an operator has asked for a TURN relay at all. Read straight from
# coturn's own env file rather than the environment: this is the same file the
# generated ConfigMap is built from, so the two can never disagree.
TURN_DOMAIN="$(grep -s '^TURN_DOMAIN=' "$PANEL_DIR/overlays/coturn/coturn.env" | tail -1 | cut -d= -f2- | tr -d '\r')"
TURN_DOMAIN="${TURN_DOMAIN%\"}"
TURN_DOMAIN="${TURN_DOMAIN#\"}"
write_overlays || die "failed to generate the overlays"
ok "overlays generated"
step "Applying kustomize overlay"
if [ "$VAULT_MANAGER" = true ]; then
OVERLAY_BASE="vault"
else
OVERLAY_BASE="local-secrets"
fi
if [ "$REVERSE_PROXY" = true ]; then
OVERLAY="overlays/${OVERLAY_BASE}-http"
else
OVERLAY="overlays/${OVERLAY_BASE}-https"
fi
# RustFS replaces MinIO on the *same* volume -- it reads a MinIO data directory
# in place, buckets, objects and IAM users included. That only holds while one
# of them is running: minio-pvc is ReadWriteOnce, but both pods land on the same
# node, and Kubernetes happily lets two pods on one node mount the same RWO
# claim. Two object stores writing one directory corrupts it, so the old
# StatefulSet has to be gone before the apply below creates the new one.
if s3_storage_is_builtin && kubectl --kubeconfig=$KUBECONFIG get statefulset minio -n 5stack >/dev/null 2>&1; then
step "Migrating MinIO to RustFS"
kubectl --kubeconfig=$KUBECONFIG delete statefulset minio -n 5stack >/dev/null 2>&1
kubectl --kubeconfig=$KUBECONFIG wait --for=delete pod -l app=minio -n 5stack --timeout=120s >/dev/null 2>&1
# Asserted against the live state rather than the wait's exit code: `wait`
# also fails when the selector matches nothing, which is the case where
# there is nothing left to wait for.
if [ -n "$(kubectl --kubeconfig=$KUBECONFIG get pods -l app=minio -n 5stack -o name 2>/dev/null)" ]; then
die "minio is still running; refusing to start rustfs on the same volume"
fi
ok "minio stopped; its volume is now served by rustfs"
fi
if ! upgrade_timescaledb_major; then
exit 1
fi
apply_overlay "$OVERLAY" || die "failed to apply $OVERLAY"
ok "overlay applied"
# Strictly after the apply: it is the apply that removes the cert-manager.io/issuer
# annotation from the ingresses, and until that lands ingress-shim recreates an
# Ingress-owned Certificate as fast as we can let go of one.
if [ "$REVERSE_PROXY" != true ]; then
disown_shim_owned_certificates
fi
retire_ingress_nginx || die "Traefik did not take over ports 80/443"
if [ "$VAULT_MANAGER" = true ]; then
step "Syncing Vault secrets"
if ! resync_vault_secrets; then
exit 1
fi
fi
step "Recycling stateful workloads"
kubectl --kubeconfig=$KUBECONFIG delete deployment rustfs -n 5stack 2>/dev/null
kubectl --kubeconfig=$KUBECONFIG delete deployment timescaledb -n 5stack 2>/dev/null
kubectl --kubeconfig=$KUBECONFIG delete deployment typesense -n 5stack 2>/dev/null
kubectl --kubeconfig=$KUBECONFIG delete deployment redis -n 5stack 2>/dev/null
step "Updating the TimescaleDB extension"
update_timescaledb_extension
finish_timescaledb_major_upgrade
GIT_SHA="${FIVESTACK_RELEASE:-$(git rev-parse HEAD)}"
kubectl --kubeconfig=$KUBECONFIG label node $(kubectl --kubeconfig=$KUBECONFIG get nodes --selector='node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}') 5stack-panel-version=$GIT_SHA --overwrite
# Must track the mediamtx overlay above: the deployment's node affinity is
# requiredDuringScheduling, so without this label the pod never schedules.
kubectl --kubeconfig=$KUBECONFIG label node $(kubectl --kubeconfig=$KUBECONFIG get nodes --selector='node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}') 5stack-mediamtx=true --overwrite
if [ -n "$TURN_DOMAIN" ]; then
kubectl --kubeconfig=$KUBECONFIG label node $(kubectl --kubeconfig=$KUBECONFIG get nodes --selector='node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}') 5stack-coturn=true --overwrite
fi
SSL_OK=true
if [ "$REVERSE_PROXY" != true ]; then
watch_ssl_status || SSL_OK=false
fi
if [ "$SSL_OK" != true ]; then
banner "5Stack : Updated (SSL incomplete)"
# install.sh and game-node-server-setup.sh source this file, and an `exit`
# here would take them down with it -- suppressing the install banner and,
# on a game node, the Tailscale IP the operator needs to finish joining it.
# The cluster work all succeeded; only issuance is outstanding. So report a
# non-zero status when update.sh is what was run, and let a caller finish
# its own output otherwise.
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
exit 1
fi
return 1
fi
banner "5Stack : Updated"