Chartreuse: Automated Alembic migrations within kubernetes

Overview

Chartreuse: Automated Alembic SQL schema migrations within kubernetes

"How to automate management of Alembic database schema migration at scale using CI/CD and Kubernetes"

Chartreuse is a wrapper around Alembic to ease, detect and automate migrations on deployed Python applications.

Chartreuse leverages Helm Hooks, the Hooks are defined in Chartreuse Helm Chart.

Usage

Requirements

  • Python >= 3.7
  • Using Helm to deploy you application
  • This Python package requires the expecteddeploymentscales.wiremind.io Kubernetes Custom Resource Definition from wiremind-kubernetes repository:
kubectl apply -f https://raw.githubusercontent.com/wiremind/wiremind-kubernetes/main/CustomResourceDefinition-expecteddeploymentscales.yaml
  • Please make sure Chartreuse Python Package version and Chartreuse Helm Chart version, you use, share major.minor otherwise Chartreuse won't start.

Configuration

Using Helm

Chartreuse comes with a Helm Chart ready to be used as a Helm Subchart in your own Helm Chart.

All you have to do is build your own container image containing:

  • Chartreuse Python package
  • Your Alembic migrations in an alembic directory
  • All required dependencies to run your alembic migrations.

Usually, it will be the same container image for your project with your code as usual, with Chartreuse added as dependency in your setup.py.

and state in the Chartreuse Helm Chart values.yaml:

  • the image repository and tag
  • URL to connect to your PostgreSQL

During install and/or upgrade of your Helm Release, Chartreuse will run as Kubernetes Job and automatically migrate PostgreSQL shchema to HEAD if needed.

If required, it will also scale down Deployments that should NOT run during a Deployment using ExpectedDeploymentScale CRD.

Please refer to the example directory for example.

Diagram

The state diagram of your application while upgrading using Helm and using Chartreuse for your migrations is as follows:

alt text

Notes

  1. PG clusters managed by postgres-operator (Patroni PG):
    • When Chartreuse starts running against a PG cluster managed by postgres-operator (Patroni PG), it may run the migrations before that the cluster is configured, and by configured we mean:
      • the Roles, especially wiremind_owner_user and wiremind_owner used by Chartreuse and Alembic, are created.
      • The default privileges are set, so the other Roles, like wiremind_writer_user used by the application, can interact with the created objects. To ensure that, Chartreuse will not start until postgres-operator has performed the above two actions. To make Chartreuse wait, the environment variable CHARTREUSE_PATRONI_POSTGRESQL should be set:
      # in the appropriate Helm values file
      chartreuse-for-a-patroni-pg:
        additionalEnvironmentVariables:
          CHARTREUSE_PATRONI_POSTGRESQL: "anything"
          CHARTREUSE_ALEMBIC_POSTGRES_WAIT_CONFIGURED_TIMEOUT: 100 # It's set to 60s by default
    • The default privileges above-mentioned are set for the NOLOGIN owner wiremind_owner, e.g. tables should be created by wiremind_owner so wiremind_writer[_user] can insert to them. This is why we need to SET ROLE wiremind_owner in the beginning of the transaction before running the migrations, Chartreuse does set -x patroni_postgresql=yes to alembic upgrade head when the environment variable PATRONI_POSTGRESQL is set, you can then retrieve the argument and set the role in your env.py:
      ...
      patroni_postgresql: bool = "patroni_postgresql" in context.get_x_argument(as_dictionary=True)
        ...
        with connectable.connect() as connection:
          ...
          with context.begin_transaction():
            if patroni_postgresql:
              context.execute("SET ROLE wiremind_owner")
            context.run_migrations()
       ...
  2. Chartreuse in pre-upgrade mode:
    • When running Chartreuse in pre-upgrade mode (upgradeBeforeDeployment: true), it will not start running (The Chartreuse Pod will hang in Init state) until one PG Pod (and ES Pod if ES is used) is running, so make sure these Pods are available to Chartreuse. To fix that:
      • You will need to delete the Chartreuse Job so the upgrade can resume and fix you PG and ES pods (or create them if they don't exist), then you can redeploy so your migrations can run.
      • You can also try the upgradeBeforeDeployment: false mode (maybe temporarily).

Development

Test

There are three kind of tests:

  • Unit tests
  • Integration tests: allows to run in a real environment, but still control chartreuse from the inside
  • blackbox test: deploy a real Helm Release and test if databases are migrated.

Documentation

  • The diagram has been drawn using the free online software https://draw.io, the source code is located at doc/chartreuse_sd.xml, feel free to correct it or make it more understandable.
Comments
  • chore(deps): bump oauthlib from 3.1.1 to 3.2.1

    chore(deps): bump oauthlib from 3.1.1 to 3.2.1

    Bumps oauthlib from 3.1.1 to 3.2.1.

    Release notes

    Sourced from oauthlib's releases.

    3.2.1

    In short

    OAuth2.0 Provider:

    • #803 : Metadata endpoint support of non-HTTPS
    • CVE-2022-36087

    OAuth1.0:

    • #818 : Allow IPv6 being parsed by signature

    General:

    • Improved and fixed documentation warnings.
    • Cosmetic changes based on isort

    What's Changed

    New Contributors

    Full Changelog: https://github.com/oauthlib/oauthlib/compare/v3.2.0...v3.2.1

    3.2.0

    Changelog

    OAuth2.0 Client:

    • #795: Add Device Authorization Flow for Web Application
    • #786: Add PKCE support for Client
    • #783: Fallback to none in case of wrong expires_at format.

    OAuth2.0 Provider:

    • #790: Add support for CORS to metadata endpoint.
    • #791: Add support for CORS to token endpoint.
    • #787: Remove comma after Bearer in WWW-Authenticate

    OAuth2.0 Provider - OIDC:

    • #755: Call save_token in Hybrid code flow
    • #751: OIDC add support of refreshing ID Tokens with refresh_id_token
    • #751: The RefreshTokenGrant modifiers now take the same arguments as the AuthorizationCodeGrant modifiers (token, token_handler, request).

    ... (truncated)

    Changelog

    Sourced from oauthlib's changelog.

    3.2.1 (2022-09-09)

    OAuth2.0 Provider:

    • #803: Metadata endpoint support of non-HTTPS
    • CVE-2022-36087

    OAuth1.0:

    • #818: Allow IPv6 being parsed by signature

    General:

    • Improved and fixed documentation warnings.
    • Cosmetic changes based on isort

    3.2.0 (2022-01-29)

    OAuth2.0 Client:

    • #795: Add Device Authorization Flow for Web Application
    • #786: Add PKCE support for Client
    • #783: Fallback to none in case of wrong expires_at format.

    OAuth2.0 Provider:

    • #790: Add support for CORS to metadata endpoint.
    • #791: Add support for CORS to token endpoint.
    • #787: Remove comma after Bearer in WWW-Authenticate

    OAuth2.0 Provider - OIDC:

    • #755: Call save_token in Hybrid code flow
    • #751: OIDC add support of refreshing ID Tokens with refresh_id_token
    • #751: The RefreshTokenGrant modifiers now take the same arguments as the AuthorizationCodeGrant modifiers (token, token_handler, request).

    General:

    • Added Python 3.9, 3.10, 3.11
    • Improve Travis & Coverage
    Commits
    • 88bb156 Updated date and authors
    • 1a45d97 Prepare 3.2.1 release
    • 0adbbe1 docs: fix typos
    • 6569ec3 docs: Fix a few typos
    • bdc486e Fixed isort imports
    • 7db45bd Fix typo in server.rst
    • b14ad85 chore: s/bode_code_verifier/body_code_verifier/g
    • b123283 Allow non-HTTPS issuer when OAUTHLIB_INSECURE_TRANSPORT. (#803)
    • 2f887b5 Docs: fix Sphinx warnings for better ReadTheDocs generation (#807)
    • d4bafd9 Merge pull request #797 from cclauss/patch-2
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • chore(deps): bump mako from 1.1.5 to 1.2.2

    chore(deps): bump mako from 1.1.5 to 1.2.2

    Bumps mako from 1.1.5 to 1.2.2.

    Release notes

    Sourced from mako's releases.

    1.2.2

    Released: Mon Aug 29 2022

    bug

    • [bug] [lexer] Fixed issue in lexer where the regexp used to match tags would not correctly interpret quoted sections individually. While this parsing issue still produced the same expected tag structure later on, the mis-handling of quoted sections was also subject to a regexp crash if a tag had a large number of quotes within its quoted sections.

      References: #366

    1.2.1

    Released: Thu Jun 30 2022

    bug

    • [bug] [tests] Various fixes to the test suite in the area of exception message rendering to accommodate for variability in Python versions as well as Pygments.

      References: #360

    misc

    • [performance] Optimized some codepaths within the lexer/Python code generation process, improving performance for generation of templates prior to their being cached. Pull request courtesy Takuto Ikuta.

      References: #361

    1.2.0

    Released: Thu Mar 10 2022

    changed

    • [changed] [py3k] Corrected "universal wheel" directive in setup.cfg so that building a wheel does not target Python 2.

      References: #351

    • [changed] [py3k] The bytestring_passthrough template argument is removed, as this flag only applied to Python 2.

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • chore(deps): bump certifi from 2022.9.24 to 2022.12.7

    chore(deps): bump certifi from 2022.9.24 to 2022.12.7

    Bumps certifi from 2022.9.24 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Resources without -ephemeral are created even when we don't need them.

    Resources without -ephemeral are created even when we don't need them.

    confimap.yaml (which is always created) is only needed to be created when "Upgrade BEFORE deployment" mode INITIAL deployment of version N but not when "Upgrade BEFORE deployment" mode UPGRADE existing deployment N-1 to version N, in this case we can rely on hooks and confimap-ephemeral.yaml is used.

    those resources will continue to live in the namespace. (the goal of ephemeral resources was to avoid keeping a Role/RoleBinding in the cluster).

    opened by desaintmartin 0
  • Possible mess when upgradeBeforeDeployment: true on an install with multiple chartreuses

    Possible mess when upgradeBeforeDeployment: true on an install with multiple chartreuses

    during the upgrade we do control the order (helm hooks order)

    2 chartreuses = 2 jobs on install (first time), the first one (may be the least important one, may finish first and start-pods while the import chartreuse is still running) => error logs

    maybe upgradeBeforeDeployment: true on install should run as upgradeBeforeDeployment: false

    opened by desaintmartin 0
Releases(v4.3.1)
  • v4.3.1(Nov 22, 2022)

    What's Changed

    • fix(setup): do not pin major versions of alembic/psycopg2 dependencies. by @desaintmartin in https://github.com/wiremind/chartreuse/pull/19

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.3.0...v4.3.1

    Source code(tar.gz)
    Source code(zip)
  • v4.3.0(Oct 6, 2022)

    What's Changed

    • Support Kube HPAScaleToZero feature gate, see here for more details.

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.2.0...v4.3.0

    Source code(tar.gz)
    Source code(zip)
  • v4.2.0(Aug 2, 2022)

    What's Changed

    • added an environment variable CHARTREUSE_ALEMBIC_CONFIG_FILE_PATH to set a custom alembic configuration path

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.1.0...v4.2.0

    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Aug 1, 2022)

    What's Changed

    • correctly added mypy support for src/ and example/alembic
    • added an environment variable CHARTREUSE_ALEMBIC_DIRECTORY_PATH to set a custom alembic folder
    • setup.py: added long_description and platforms

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.0.5...v4.1.0

    Source code(tar.gz)
    Source code(zip)
  • v4.0.5(Nov 24, 2021)

    What's Changed

    • Revert "fix(setup): setup.py: require psycopg2-binary instead of psycopg2" by @desaintmartin in https://github.com/wiremind/chartreuse/pull/10

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.0.4...v4.0.5

    Source code(tar.gz)
    Source code(zip)
  • v4.0.4(Nov 18, 2021)

    What's Changed

    • fix(setup): setup.py: require psycopg2-binary instead of psycopg2. by @desaintmartin in https://github.com/wiremind/chartreuse/pull/9

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.0.3...v4.0.4

    Source code(tar.gz)
    Source code(zip)
  • v4.0.3(Oct 9, 2021)

    What's Changed

    • ci: add 3.10 support by @desaintmartin in https://github.com/wiremind/chartreuse/pull/8

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.0.2...v4.0.3

    Source code(tar.gz)
    Source code(zip)
  • v4.0.2(Oct 9, 2021)

    What's Changed

    • fix: upgrade wiremind-kubernetes to ignore failed (like Evicted) Pods when stop-pods by @desaintmartin in https://github.com/wiremind/chartreuse/pull/7

    Full Changelog: https://github.com/wiremind/chartreuse/compare/v4.0.1...v4.0.2

    Source code(tar.gz)
    Source code(zip)
  • v4.0.1(Oct 4, 2021)

  • v4.0.0(Oct 4, 2021)

    4.0.0 (2021-10-01)

    Breaking Changes

    • Drop eslembic support
    • drop wiremind.fr CRD

    Fix

    • Avoid logging the PG password when seding alembic.ini.

    Chore

    • Open source
    Source code(tar.gz)
    Source code(zip)
Owner
Wiremind
Wiremind
Chef-like functionality for Fabric

/ / ___ ___ ___ ___ | | )| |___ | | )|___) |__ |__/ | __/ | | / |__ -- Chef-like functionality for Fabric About Fabric i

Sébastien Pierre 1.3k Dec 21, 2022
Project 4 Cloud DevOps Nanodegree

Project Overview In this project, you will apply the skills you have acquired in this course to operationalize a Machine Learning Microservice API. Yo

1 Nov 21, 2021
Coding For Entrepreneurs 100 Jan 01, 2023
Rundeck / Grafana / Prometheus / Rundeck Exporter integration demo

Rundeck / Prometheus / Grafana integration demo via Rundeck Exporter This is a demo environment that shows how to monitor a Rundeck instance using Run

Reiner 4 Oct 14, 2022
Utilitaire de contrôle de Kubernetes

Utilitaire de contrôle de Kubernetes ** What is this ??? ** Every time we use a word in English our manager tells us to use the French translation of

Théophane Vié 9 Dec 03, 2022
MLops tools review for execution on multiple cluster types: slurm, kubernetes, dask...

MLops tools review focused on execution using multiple cluster types: slurm, kubernetes, dask...

4 Nov 30, 2022
A simple python application for running a CI pipeline locally This app currently supports GitLab CI scripts

🏃 Simple Local CI Runner 🏃 A simple python application for running a CI pipeline locally This app currently supports GitLab CI scripts ⚙️ Setup Inst

Tom Stowe 0 Jan 11, 2022
Play Wordle from any Kubernetes cluster.

wordle-operator 🟩 ⬛ 🟩 🟨 ⬛ Play Wordle from any Kubernetes cluster. Using the power of CustomResourceDefinitions and Kubernetes Operators, now you c

Lucas Melin 1 Jan 15, 2022
Wubes is like Qubes but for Windows.

Qubes containerization on Windows. The idea is to leverage the Windows Sandbox technology to spawn applications in isolation.

NCC Group Plc 124 Dec 16, 2022
Push Container Image To Docker Registry In Python

push-container-image-to-docker-registry 概要 push-container-image-to-docker-registry は、エッジコンピューティング環境において、特定のエッジ端末上の Private Docker Registry に特定のコンテナイメー

Latona, Inc. 3 Nov 04, 2021
A little script and trick to make your heroku app run forever without being concerned about dyno hours.

A little script and trick to make your heroku app run forever without being concerned about dyno hours.

Tiararose Biezetta 152 Dec 25, 2022
A Kubernetes operator that creates UptimeRobot monitors for your ingresses

This operator automatically creates uptime monitors at UptimeRobot for your Kubernetes Ingress resources. This allows you to easily integrate uptime monitoring of your services into your Kubernetes d

Max 49 Dec 14, 2022
ZeroMQ bindings for Twisted

Twisted bindings for 0MQ Introduction txZMQ allows to integrate easily ØMQ sockets into Twisted event loop (reactor). txZMQ supports both CPython and

Andrey Smirnov 149 Dec 08, 2022
Flexible and scalable monitoring framework

Presentation of the Shinken project Welcome to the Shinken project. Shinken is a modern, Nagios compatible monitoring framework, written in Python. It

Gabès Jean 1.1k Dec 18, 2022
The leading native Python SSHv2 protocol library.

Paramiko Paramiko: Python SSH module Copyright: Copyright (c) 2009 Robey Pointer 8.1k Jan 04, 2023

Bugbane - Application security tools for CI/CD pipeline

BugBane Набор утилит для аудита безопасности приложений. Основные принципы и осо

GardaTech 20 Dec 09, 2022
Dockerized iCloud drive

iCloud-drive-docker is a simple iCloud drive client in Docker environment. It uses pyiCloud python library to interact with iCloud

Mandar Patil 376 Jan 01, 2023
Hatch plugin for Docker containers

hatch-containers CI/CD Package Meta This provides a plugin for Hatch that allows

Ofek Lev 11 Dec 30, 2022
sysctl/sysfs settings on a fly for Kubernetes Cluster. No restarts are required for clusters and nodes.

SysBindings Daemon Little toolkit for control the sysctl/sysfs bindings on Kubernetes Cluster on the fly and without unnecessary restarts of cluster o

Wallarm 19 May 06, 2022