Skip to content

root: configuration reloading#5415

Closed
rissson wants to merge 7 commits intomainfrom
server-handle-sighup
Closed

root: configuration reloading#5415
rissson wants to merge 7 commits intomainfrom
server-handle-sighup

Conversation

@rissson
Copy link
Member

@rissson rissson commented Apr 28, 2023

EDIT: Configuration watching is now implemented. This PR is best reviewed commit by commit, I'll update this description later.

Details

This is the first step to handle configuration reloading. With those changes, it is already possible to do so, by sending a SIGUSR2 signal to the Go server process. The next step would be to watch for changes to configuration files and call the Restart function of the GoUnicorn instance.

SIGHUP is catched by the go server and forwarded as-is to gunicorn, which causes it to restart its workers. However, that does not trigger a reload of the Django settings, probably because they are already loaded in the master, before creating any of the worker instances.

SIGUSR2, however, can be used to spawn a new gunicorn master process, but handling it is a bit trickier. Please refer to Gunicorn's documentation[0] for details, especially the "Upgrading to a new binary on the fly" section.

As we are now effectively killing the gunicorn processed launched by the server, we need to handle some sort of check to make sure it is still running. That's done by using the already existing healthchecks, making them useful not only for the application start, but also for its lifetime. If a check is failed too many times in a given time period, the gunicorn processed is killed (if necessary) and then restarted.

[0] https://docs.gunicorn.org/en/20.1.0/signals.html

Other relevant links and documentation:

Python library handling the processing swaping upon a SIGUSR2: https://github.com/flupke/rainbow-saddle/

Golang cannot easily check if a process exists on Unix systems: golang/go#34396

Changes

New Features

  • Support file configuration reloading by sending a SIGUSR2 signal to the server process.
  • The golang server now automatically restarts (gracefully) the underlying gunicorn process if it fails healthchecks.

Breaking Changes

Not that I'm aware of.

Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make website)

This is the first step to handle configuration reloading. With those
changes, it is already possible to do so, by sending a SIGUSR2 signal to
the Go server process. The next step would be to watch for changes to
configuration files and call the Restart function of the GoUnicorn
instance.

SIGHUP is catched by the go server and forwarded as-is to gunicorn,
which causes it to restart its workers. However, that does not trigger
a reload of the Django settings, probably because they are already
loaded in the master, before creating any of the worker instances.

SIGUSR2, however, can be used to spawn a new gunicorn master process,
but handling it is a bit trickier. Please refer to Gunicorn's
documentation[0] for details, especially the "Upgrading to a new binary
on the fly" section.

As we are now effectively killing the gunicorn processed launched by the
server, we need to handle some sort of check to make sure it is still
running. That's done by using the already existing healthchecks, making
them useful not only for the application start, but also for its
lifetime. If a check is failed too many times in a given time period,
the gunicorn processed is killed (if necessary) and then restarted.

[0] https://docs.gunicorn.org/en/20.1.0/signals.html

Other relevant links and documentation:

Python library handling the processing swaping upon a SIGUSR2:
https://github.com/flupke/rainbow-saddle/

Golang cannot easily check if a process exists on Unix systems:
golang/go#34396

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
@rissson rissson requested a review from BeryJu April 28, 2023 22:07
@codecov
Copy link

codecov bot commented Apr 28, 2023

Codecov Report

Patch coverage has no change and project coverage change: +2.25 🎉

Comparison is base (5830781) 90.37% compared to head (241059f) 92.61%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5415      +/-   ##
==========================================
+ Coverage   90.37%   92.61%   +2.25%     
==========================================
  Files         506      550      +44     
  Lines       25944    26487     +543     
==========================================
+ Hits        23443    24528    +1085     
+ Misses       2501     1959     -542     
Flag Coverage Δ
e2e 51.66% <ø> (+3.33%) ⬆️
integration 26.42% <ø> (?)
unit 89.50% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

see 179 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@rissson
Copy link
Member Author

rissson commented Apr 28, 2023

I've started working on automatic configuration reloading, but currently the configuration discovery doesn't match between the go and python code, so I'm updating that first.
EDIT: second commit of this PR, which is standalone and can be moved to another PR if deemed necessary.

return
}

newPidB, err := ioutil.ReadFile(newPidFile)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anyone that knows go, knows how to do this without writing 1k lines, I'd be happy to know it too!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.ReadFile

rissson added 4 commits April 29, 2023 00:39
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
@rissson rissson force-pushed the server-handle-sighup branch from f347c36 to d3ef158 Compare April 28, 2023 23:32
@rissson rissson added enhancement New feature or request go labels Apr 28, 2023
@rissson rissson changed the title root: handle SIGHUP and SIGUSR2 root: configuration reloading Apr 28, 2023
Comment on lines 38 to 39
started: false,
killed: false,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would an enum be better here?

@BeryJu BeryJu mentioned this pull request Jun 14, 2023
7 tasks
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@BeryJu BeryJu requested a review from a team as a code owner June 23, 2023 16:44
@netlify
Copy link

netlify bot commented Jun 23, 2023

Deploy Preview for authentik-storybook failed.

Name Link
🔨 Latest commit 241059f
🔍 Latest deploy log https://app.netlify.com/sites/authentik-storybook/deploys/6495cc3246353c00087d03ac

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@netlify
Copy link

netlify bot commented Jun 23, 2023

Deploy Preview for authentik ready!

Name Link
🔨 Latest commit 18db59a
🔍 Latest deploy log https://app.netlify.com/sites/authentik/deploys/6495cbf3c4343500098caff8
😎 Deploy Preview https://deploy-preview-5415--authentik.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@github-actions
Copy link
Contributor

authentik PR Installation instructions

Instructions for docker-compose

Add the following block to your .env file:

AUTHENTIK_IMAGE=ghcr.io/goauthentik/dev-server
AUTHENTIK_TAG=gh-server-handle-sighup-1687539399-241059f
AUTHENTIK_OUTPOSTS__CONTAINER_IMAGE_BASE=ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s

For arm64, use these values:

AUTHENTIK_IMAGE=ghcr.io/goauthentik/dev-server
AUTHENTIK_TAG=gh-server-handle-sighup-1687539399-241059f-arm64
AUTHENTIK_OUTPOSTS__CONTAINER_IMAGE_BASE=ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s

Afterwards, run the upgrade commands from the latest release notes.

Instructions for Kubernetes

Add the following block to your values.yml file:

authentik:
    outposts:
        container_image_base: ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s
image:
    repository: ghcr.io/goauthentik/dev-server
    tag: gh-server-handle-sighup-1687539399-241059f

For arm64, use these values:

authentik:
    outposts:
        container_image_base: ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s
image:
    repository: ghcr.io/goauthentik/dev-server
    tag: gh-server-handle-sighup-1687539399-241059f-arm64

Afterwards, run the upgrade commands from the latest release notes.

Copy link
Member

@BeryJu BeryJu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Configuration changes are good to keep all the defaults in one place
  • Gunicorn health checking and reloading is great
  • Configuration watching isn't really needed anymore since we can do that natively now
  • In a future PR maybe generalise the process manager to be re-usable for Guacamole

@rissson
Copy link
Member Author

rissson commented Sep 21, 2023

Closing as it's been split up into #6629 and #6630

@rissson rissson closed this Sep 21, 2023
@rissson rissson deleted the server-handle-sighup branch June 6, 2024 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants