From 570ca85cd8ea27139226fe279b9c82309cad59ea Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Wed, 17 Feb 2021 15:23:19 +1100 Subject: [PATCH] gerrit: add mariadb_container option This adds a local mariadb container to the gerrit host to hold the accountPatchReviewDb database. This is inspired by a few things - since migration to NoteDB, there is only one table left where Gerrit records what files have been reviewed for a change. This logically scales with the number of reviews users are doing. Pulling the stats on this, we can see since the NoteDB upgrade this went from a very busy database (~300 queries/70 commits per second) to barely registering one hit per second : https://imgur.com/a/QGJV7Fw Thus separating the db to an external host for performance reasons is not a large concern any more. - emperically we've done a bad job in keeping the existing hosted db up-to-date; it's still running mysql 5.1 and we have been hit by bugs such as the one referenced in-line which silently drops backups. - The other gerrit option is to use an on-disk H2 database. This is certainly an option, however you need special tools to interact with it for migration, etc. and it's not safe to backup from files on disk (as opposed to mysqldump). Upstream advice is unclear, and varies between H2 being a performance bottleneck to this being ephemeral data that users don't care about. We know how to admin mariadb/mysql and this allows us to migrate and backup data, so seems like the best choice. - we have a pressing need to update the server to a new operating system. Running the db alongside the gerrit instance minimises fiddling we have to do manging connections to and migrating the hosted db systems. - related to that, we are tending towards more provider independence for control-plane servers. A hosted database product is not always provided, so this gives us more flexibility in moving things around. - the main concern here is memory usage. "docker stats" reports a quiescent container, freshly started on a 8GB host: gerrit-compose_mariadb_1 67.32MiB After loading a copy of the production table, and then dumping it back to a file the same container reports: gerrit-compose_mariadb_1 462.6MiB The existing remote mysql configuration path remains mostly the same. We move the gerrit startup into a script rather than a CMD so we can call it after a "wait for db" script in the mariadb_container case (this is the reccommeded way to enforce ordering [1]). Backups of the local container need different dump commands; backups are relocated to a new file and updated. Testing is converted to use this rather than a local H2 database. [1] https://docs.docker.com/compose/startup-order/ Change-Id: Iec981ef3c2e38889f91e9759e66295dbfb499c2e --- docker/gerrit/base/Dockerfile | 12 +- .../host_vars/review01.openstack.org.yaml | 1 + .../host_vars/review02.opendev.org.yaml | 7 +- playbooks/roles/gerrit/README.rst | 31 +++ playbooks/roles/gerrit/defaults/main.yaml | 4 +- playbooks/roles/gerrit/tasks/backup.yaml | 43 ++++ playbooks/roles/gerrit/tasks/main.yaml | 52 ++--- .../gerrit/templates/docker-compose.yaml.j2 | 25 +++ .../root.my.cnf.mariadb_container.j2 | 7 + .../{root.my.cnf.j2 => root.my.cnf.mysql.j2} | 0 .../roles/gerrit/templates/secure.config.j2 | 6 +- playbooks/zuul/gerrit/base.yaml | 11 + playbooks/zuul/gerrit/files/run-gerrit.sh | 4 + playbooks/zuul/gerrit/files/wait-for-it.sh | 212 ++++++++++++++++++ .../zuul/templates/group_vars/review.yaml.j2 | 9 +- zuul.d/docker-images/gerrit.yaml | 3 + 16 files changed, 387 insertions(+), 40 deletions(-) create mode 100644 playbooks/roles/gerrit/tasks/backup.yaml create mode 100644 playbooks/roles/gerrit/templates/root.my.cnf.mariadb_container.j2 rename playbooks/roles/gerrit/templates/{root.my.cnf.j2 => root.my.cnf.mysql.j2} (100%) create mode 100644 playbooks/zuul/gerrit/base.yaml create mode 100755 playbooks/zuul/gerrit/files/run-gerrit.sh create mode 100755 playbooks/zuul/gerrit/files/wait-for-it.sh diff --git a/docker/gerrit/base/Dockerfile b/docker/gerrit/base/Dockerfile index a2df44ffd5..349da2e814 100644 --- a/docker/gerrit/base/Dockerfile +++ b/docker/gerrit/base/Dockerfile @@ -47,6 +47,12 @@ RUN addgroup gerrit --gid 3000 --system \ --ingroup gerrit \ gerrit +# Startup scripts +COPY wait-for-it.sh /wait-for-it.sh +RUN chmod +x /wait-for-it.sh +COPY run-gerrit.sh /run-gerrit.sh +RUN chmod +x /run-gerrit.sh + USER gerrit RUN mkdir /var/gerrit/bin \ && mkdir /var/gerrit/hooks \ @@ -54,7 +60,8 @@ RUN mkdir /var/gerrit/bin \ # Download mysql-connector so that gerrit doens't download it during init. RUN mkdir /var/gerrit/lib && \ - wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.43/mysql-connector-java-5.1.43.jar -O /var/gerrit/lib/mysql-connector-java.jar + wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.43/mysql-connector-java-5.1.43.jar -O /var/gerrit/lib/mysql-connector-java.jar && \ + wget https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.7.2/mariadb-java-client-2.7.2.jar -O /var/gerrit/lib/mariadb-java-client.jar # Allow incoming traffic # OpenDev Gerrit listens on 8081 not default of 8080 @@ -70,5 +77,4 @@ ENV JAVA_OPTIONS "" # Ulimits should be set on command line or in docker-compose.yaml ENTRYPOINT ["/usr/bin/dumb-init", "--"] -# The /dev/./urandom is not a typo. https://stackoverflow.com/questions/58991966/what-java-security-egd-option-is-for -CMD /usr/local/openjdk-11/bin/java -Djava.security.egd=file:/dev/./urandom ${JAVA_OPTIONS} -jar /var/gerrit/bin/gerrit.war daemon -d /var/gerrit +CMD "/run-gerrit.sh" diff --git a/inventory/service/host_vars/review01.openstack.org.yaml b/inventory/service/host_vars/review01.openstack.org.yaml index cec2216945..67bf6be7dd 100644 --- a/inventory/service/host_vars/review01.openstack.org.yaml +++ b/inventory/service/host_vars/review01.openstack.org.yaml @@ -60,6 +60,7 @@ gerrit_vhost_name: review.opendev.org gerrit_serverid: 4a232e18-c5a9-48ee-94c0-e04e7cca6543 gerrit_redirect_vhost: review.openstack.org gerrit_heap_limit: 48g +gerrit_reviewdb_database_type: "{{ gerrit_reviewdb_database_override | default('mysql') }}" letsencrypt_certs: review01-opendev-org-main: - review.opendev.org diff --git a/inventory/service/host_vars/review02.opendev.org.yaml b/inventory/service/host_vars/review02.opendev.org.yaml index f73c9158d8..8871e2aea6 100644 --- a/inventory/service/host_vars/review02.opendev.org.yaml +++ b/inventory/service/host_vars/review02.opendev.org.yaml @@ -4,7 +4,7 @@ gerrit_vhost_name: review.opendev.org gerrit_serverid: 4a232e18-c5a9-48ee-94c0-e04e7cca6543 gerrit_redirect_vhost: review.openstack.org gerrit_heap_limit: 48g -gerrit_database_type: h2 +gerrit_reviewdb_database_type: h2 letsencrypt_certs: review02-opendev-org-main: - review.opendev.org @@ -20,5 +20,6 @@ borg_backup_excludes_extra: - /home/gerrit2/review_site/cache/* - /home/gerrit2/review_site/tmp/* - /home/gerrit2/review_site/index/* - # dump directly via stream - - /home/gerrit2/mysql_backups/* + # live db when used with mariadb_container; dumped by separate job + # using mysqldump + - /home/gerrit2/reviewdb/* diff --git a/playbooks/roles/gerrit/README.rst b/playbooks/roles/gerrit/README.rst index 984e3c5c95..a415076d2d 100644 --- a/playbooks/roles/gerrit/README.rst +++ b/playbooks/roles/gerrit/README.rst @@ -1 +1,32 @@ Run Gerrit. + +**Role Variables** + +.. zuul:rolevar:: gerrit_reviewdb_database_type + :default: h2 + + Database to use for the reviewdb + + One of + + * h2 : use local h2 database, not for production + * mysql : connect to existing mysql instance + * mariadb_container : run a sibling mariadb container + +.. zuul:rolevar:: gerrit_reviewdb_mariadb_dbname + :default: gerrit + + When ``gerrit_reviewdb_database_type`` is ``mariadb_container``; the default + database to make and connect to. + +.. zuul:rolevar:: gerrit_reviewdb_mariadb_username + :default: gerrit + + When ``gerrit_reviewdb_database_type`` is ``mariadb_container``; the default + user to make and connect with. + +.. zuul:rolevar:: gerrit_reviewdb_mariadb_password + :default: + + When ``gerrit_reviewdb_database_type`` is ``mariadb_container``; the default + password to set for ``gerrit_reviewdb_mariadb_username`` diff --git a/playbooks/roles/gerrit/defaults/main.yaml b/playbooks/roles/gerrit/defaults/main.yaml index c1cfa1f840..ad8d166380 100644 --- a/playbooks/roles/gerrit/defaults/main.yaml +++ b/playbooks/roles/gerrit/defaults/main.yaml @@ -21,7 +21,9 @@ gerrit_container_volumes: - /home/gerrit2/review_site/tmp:/var/gerrit/tmp - /opt/project-config/gerrit/projects.yaml:/var/gerrit/etc/projects.yaml - /opt/project-config/gerrit/projects.ini:/var/gerrit/etc/projects.ini -gerrit_database_type: MYSQL gerrit_project_creator_user: openstack-project-creator gerrit_manage_projects_args: "-v" gerrit_track_upstream: true +gerrit_reviewdb_database_type: h2 +gerrit_reviewdb_mariadb_username: gerrit +gerrit_reviewdb_mariadb_dbname: accountPatchReviewDb diff --git a/playbooks/roles/gerrit/tasks/backup.yaml b/playbooks/roles/gerrit/tasks/backup.yaml new file mode 100644 index 0000000000..db74b9441c --- /dev/null +++ b/playbooks/roles/gerrit/tasks/backup.yaml @@ -0,0 +1,43 @@ +- name: Create backup streaming config dir + file: + path: /etc/borg-streams + state: directory + +- name: Setup remote mysql backup jobs + when: gerrit_reviewdb_database_type == 'mysql' + block: + # NOTE(ianw) 2021-02-19 We are explicitly backing up just + # accountPatchReviewDb because "--all-databases" doesn't work with + # our trove instance + # https://bugs.launchpad.net/ubuntu/+source/mysql-5.7/+bug/1914695 + - name: Create accountPatchReviewDb streaming file + copy: + content: >- + /usr/bin/mysqldump --defaults-file=/root/.gerrit_db.cnf --skip-extended-insert --ignore-table mysql.event --single-transaction --databases accountPatchReviewDb + dest: /etc/borg-streams/mysql-accountPatchReviewDb + + - name: Set up cron job to back up gerrit db to disk + cron: + name: gerrit-backup + user: root + hour: 0 + minute: 0 + job: '/usr/bin/mysqldump --defaults-file=/root/.gerrit_db.cnf --opt --ignore-table mysql.event --single-transaction --databases accountPatchReviewDb | gzip -9 > /home/gerrit2/mysql_backups/gerrit.sql.gz' + +# NOTE(ianw) 2021-06-09 : we don't also keep an on-disk backup as we +# did for the old mysql instance above because it's easy to restore +# from borg now (in the past with bup it was a real pain to extract +# data so it was worth managing on-disk copies to possibly avoid that). +# +# # borg-mount +# the dump file will be under +# /opt/backups/review02-mariadb-T