reloadCommand returns an entrypoint that convinces PostgreSQL to reload certificate files when they change. The process will appear as name in `ps` and `top`.
( name string, pgdataAutoGrowVolumeSpec *v1beta1.VolumeClaimSpecWithAutoGrow, pgwalAutoGrowVolumeSpec *v1beta1.VolumeClaimSpecWithAutoGrow, )
| 278 | // certificate files when they change. The process will appear as name in `ps` |
| 279 | // and `top`. |
| 280 | func reloadCommand( |
| 281 | name string, |
| 282 | pgdataAutoGrowVolumeSpec *v1beta1.VolumeClaimSpecWithAutoGrow, |
| 283 | pgwalAutoGrowVolumeSpec *v1beta1.VolumeClaimSpecWithAutoGrow, |
| 284 | ) []string { |
| 285 | |
| 286 | pgdataTrigger, pgdataMaxGrow := util.GetAutoGrowFromSpec(pgdataAutoGrowVolumeSpec) |
| 287 | pgwalTrigger, pgwalMaxGrow := util.GetAutoGrowFromSpec(pgwalAutoGrowVolumeSpec) |
| 288 | |
| 289 | // Use a Bash loop to periodically check the mtime of the mounted |
| 290 | // certificate volume. When it changes, copy the replication certificate, |
| 291 | // signal PostgreSQL, and print the observed timestamp. |
| 292 | // |
| 293 | // PostgreSQL v10 reads its server certificate files during reload (SIGHUP). |
| 294 | // - https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-SERVER-FILES |
| 295 | // - https://www.postgresql.org/docs/current/app-postgres.html |
| 296 | // |
| 297 | // PostgreSQL reads its replication credentials every time it opens a |
| 298 | // replication connection. It does not need to be signaled when the |
| 299 | // certificate contents change. |
| 300 | // |
| 301 | // The copy is necessary because Kubernetes sets g+r when fsGroup is enabled, |
| 302 | // but PostgreSQL requires client keys to not be readable by other users. |
| 303 | // - https://www.postgresql.org/docs/current/libpq-ssl.html |
| 304 | // - https://issue.k8s.io/57923 |
| 305 | // |
| 306 | // Coreutils `sleep` uses a lot of memory, so the following opens a file |
| 307 | // descriptor and uses the timeout of the builtin `read` to wait. That same |
| 308 | // descriptor gets closed and reopened to use the builtin `[ -nt` to check |
| 309 | // mtimes. |
| 310 | // - https://unix.stackexchange.com/a/407383 |
| 311 | // |
| 312 | // In the manageAutogrowAnnotation function below, df is used to return the |
| 313 | // relevant volume size in Mebibytes. The 'read' variable gets the value from |
| 314 | // the '1M-blocks' output (second column) and the 'use' variable gets the value |
| 315 | // from the 'Use%' column (fifth column). This value is grabbed after stripping |
| 316 | // out the column headers (before the '\n') and then getting the respective |
| 317 | // value delimited by the white spaces by using the 'read -r' command. |
| 318 | // The underscores (_) discard fields and the variables store them. This allows |
| 319 | // for selective parsing of the provided lines. The percent value is stripped of |
| 320 | // the '%' and then used to determine if a expansion should be triggered by |
| 321 | // setting the calculated volume size using the 'size' variable. |
| 322 | script := fmt.Sprintf(` |
| 323 | # Parameters for curl when managing autogrow annotation. |
| 324 | APISERVER="https://kubernetes.default.svc" |
| 325 | SERVICEACCOUNT="/var/run/secrets/kubernetes.io/serviceaccount" |
| 326 | NAMESPACE=$(cat "${SERVICEACCOUNT}/namespace") |
| 327 | TOKEN=$(cat "${SERVICEACCOUNT}/token") |
| 328 | CACERT="${SERVICEACCOUNT}/ca.crt" |
| 329 | |
| 330 | # Manage autogrow annotation. |
| 331 | # Return size in Mebibytes. |
| 332 | manageAutogrowAnnotation() { |
| 333 | local volume=$1 |
| 334 | local trigger=$2 |
| 335 | local maxGrow=$3 |
| 336 | |
| 337 | size=$(df --block-size=M /"${volume}") |