How to upgrade Mesh H2 database inside Bitbucket Kubernetes pod
Platform Notice: Data Center - This article applies to Atlassian products on the Data Center platform.
Note that this knowledge base article was created for the Data Center version of the product. Data Center knowledge base articles for non-Data Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
There are manual tasks needed to upgrade Bitbucket Mesh due to the H2 database usage. On bare-metal or physical servers, you can follow the steps in the Migrate H2 database guide. However, with Bitbucket Remote Mesh installations using Kubernetes, we will need to orchestrate the steps as explained in this article.
- The H2 database is only used for Bitbucket Mirror and Bitbucket Mesh.
- This is not an as-is steps article - you might not be able to run the same exact commands and achieve the same result.
- The content in this article is to showcase a concept and should be adapted into the upgrade process for Bitbucket Mesh.
If the Mesh H2 database manual migration isn't completed and an attempt is made to upgrade the Mesh nodes to a newer version without performing the manual upgrade, you will encounter the below errors in the logs after the upgrade. Additionally, the Mesh pods will enter a
CrashLoopBackOff
status.
2024-11-29 10:07:42,607 WARN [main] - o.s.c.a.AnnotationConfigApplicationContext Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'databaseValidator' defined in com.atlassian.bitbucket.mesh.MeshDatabaseWiring: Invocation of init method failed; nested exception is com.atlassian.bitbucket.mesh.UnsupportedH2StoreException: The storage format for the internal database that you are using has changed and requires manual migration.
2024-11-29 10:07:42,608 INFO [main] - c.a.b.mesh.boot.StandaloneRunner Shutting down
2024-11-29 10:07:42,681 ERROR [main] - o.s.b.d.LoggingFailureAnalysisReporter
***************************
APPLICATION FAILED TO START
***************************
Description:
The storage format for the internal database that you are using has changed and requires manual migration.
Action:
Please perform the manual migration of the database. See https://confluence.atlassian.com/bitbucketserver088/migrate-h2-database-1216583295.html.
The purpose of this KB is to resolve the above errors.
Environment
- Please refer to the Migrate H2 database guide for the exact steps to be orchestrated.
- For this article, we are performing Bitbucket Mesh upgrade from 2.0.1 to 2.5.7.
Kubernetes Environment details
We're using the below values through this document, you will need to tweak the commands in this document to match your environment.
- Kubernetes namespace:
bitbucket-mesh
- Helm chart name:
bitbucket-mesh
- Helm values file:
values-bitbucket-mesh.yaml
- Mesh Home is stored in a Kubernetes PVC (persistent volume claim)
Solution
- Make sure you have all the required backups before performing any changes.
- Test the steps in a non-production environment.
Step 1: Bring down Bitbucket Mesh pods
Update the
values.yaml
and make the replicaCount of the Mesh Nodes to 0 so the Mesh Nodes are not being attempted to be started# Mesh configuration mesh: # -- Enable Bitbucket Mesh. See: https://confluence.atlassian.com/bitbucketserver/bitbucket-mesh-1128304351.html # enabled: true nodeAutoRegistration: false setByDefault: false image: repository: atlassian/bitbucket-mesh pullPolicy: IfNotPresent tag: "2.0.1" # -- Number of Bitbucket Mesh nodes. Do not change it. Currently, only the quorum of 3 mesh nodes is supported. # Reducing the number of replicas will result in mesh degradation while increasing the number of Mesh nodes # will result in new nodes being unused by the Bitbucket server. # replicaCount: 3
Edit the
replicaCount: 3
toreplicaCount: 0
.Bring down the Mesh pods:
helm upgrade --install bitbucket-mesh atlassian-data-center/bitbucket --namespace bitbucket-mesh --values values-bitbucket-mesh.yaml
Step 2: Deploy the Mesh H2 upgrade pods
Deploy an H2 upgrade pod for each Mesh node. Since there are three Mesh nodes, three new pods need to be created, with each pod attached to the PVC of its corresponding Mesh node.
We are spinning up three new Mesh pods and mounting the local PVC of each production Mesh pod to one of the new pods. This configuration ensures that the upgrade is performed on each pod individually. Each new pod must have the PVC of its respective production Mesh pod attached, as illustrated in the examples provided.
Locate the Mesh
PVCs
(already created when 3 Mesh Pods were created)in thebitbucket-mesh
namespace using the below command:kubectl get pvc --namespace bitbucket-mesh
Example result:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mesh-home-bitbucket-mesh-0 Bound pvc-056074c8-d704-411e-a4a6-4c46264864fb 1Gi RWO nfs-client 20h mesh-home-bitbucket-mesh-1 Bound pvc-ee0433c0-4458-4fd0-b83e-426776f5631a 1Gi RWO nfs-client 20h mesh-home-bitbucket-mesh-2 Bound pvc-6e981422-eefb-4926-bfca-a8178086688e 1Gi RWO nfs-client 20h
Set up a new YAML file called
values-bitbucket-mesh-h2-upgrade.yaml
:apiVersion: v1 kind: Pod metadata: namespace: bitbucket name: bitbucket-mesh-h2-upgrade0 spec: restartPolicy: Never containers: - image: atlassian/bitbucket-mesh:2.5.7 name: bitbucket-mesh-h2-upgrade0 command: ["tail"] args: ["-f", "/dev/null"] volumeMounts: - mountPath: /var/atlassian/application-data/mesh name: pvc-mount volumes: - name: pvc-mount persistentVolumeClaim: claimName: mesh-home-bitbucket-mesh-0 --- apiVersion: v1 kind: Pod metadata: namespace: bitbucket name: bitbucket-mesh-h2-upgrade1 spec: restartPolicy: Never containers: - image: atlassian/bitbucket-mesh:2.5.7 name: bitbucket-mesh-h2-upgrade1 command: ["tail"] args: ["-f", "/dev/null"] volumeMounts: - mountPath: /var/atlassian/application-data/mesh name: pvc-mount volumes: - name: pvc-mount persistentVolumeClaim: claimName: mesh-home-bitbucket-mesh-1 --- apiVersion: v1 kind: Pod metadata: namespace: bitbucket name: bitbucket-mesh-h2-upgrade2 spec: restartPolicy: Never containers: - image: atlassian/bitbucket-mesh:2.5.7 name: bitbucket-mesh-h2-upgrade2 command: ["tail"] args: ["-f", "/dev/null"] volumeMounts: - mountPath: /var/atlassian/application-data/mesh name: pvc-mount volumes: - name: pvc-mount persistentVolumeClaim: claimName: mesh-home-bitbucket-mesh-2
Deploy the Mesh H2 Upgrade Pods
kubectl create -f values-bitbucket-mesh-h2-upgrade.yaml
You should see 3 new Mesh H2 upgrade pods:
kubectl get pods -n bitbucket-mesh NAME READY STATUS RESTARTS AGE bitbucket-mesh-h2-upgrade0 1/1 Running 0 19s bitbucket-mesh-h2-upgrade1 1/1 Running 0 19s bitbucket-mesh-h2-upgrade2 1/1 Running 0 19s
Step 3: Perform the H2 upgrade
Log in to the Mesh H2 upgrade pod
bitbucket-mesh-h2-upgrade0
.kubectl exec -it bitbucket-mesh-h2-upgrade0 -n bitbucket-mesh bash
Info
The same steps must be repeated for the other two Mesh upgrade pods as well.
Obtain the H2 JAR file to do the migration inside the pod by running the below commands:
cd /var/atlassian/application-data/mesh #####Source H2 Jar##### wget https://repo1.maven.org/maven2/com/h2database/h2/2.1.214/h2-2.1.214.jar #####Target H2 Jar##### wget https://repo1.maven.org/maven2/com/h2database/h2/2.2.220/h2-2.2.220.jar
To identify the exact source and target H2 version JAR, refer to the document How do I check the H2 database version used by Mesh?
Create a new file named
h2-migrate-db-file.sh
inside the Pod on/var/atlassian/application-data/mesh
directory and copy paste the below code:#!/usr/bin/env bash if [ -z "$SOURCE_H2_JAR_PATH" ]; then echo "Please provide the location of the <source H2> JAR in the 'SOURCE_H2_JAR_PATH' environment variable" exit 1 fi # BIN_DIR & INST_DIR will be absolute paths, not relative pushd $(dirname $0) > /dev/null BIN_DIR=$(pwd) popd > /dev/null INST_DIR=$(dirname "$BIN_DIR") source "$BIN_DIR"/set-jre-home.sh && source "$BIN_DIR"/set-mesh-home.sh && source "$BIN_DIR"/set-mesh-user.sh DB_FILE_WITHOUT_EXT="$MESH_HOME/mesh" DB_FILE="$DB_FILE_WITHOUT_EXT.mv.db" DB_LOCK_FILE="$DB_FILE_WITHOUT_EXT.lock.db" if [ -f "$DB_LOCK_FILE" ]; then echo "The file $DB_LOCK_FILE is present which means the database may be in use. Please stop Mesh or any other clients using the $DB_FILE file and try again. If the database is not in use, manually delete the file $DB_LOCK_FILE and try again." exit 1 fi if [ ! -f "$DB_FILE" ]; then echo "Cannot run migration; $DB_FILE doesn't exist" exit 1 fi if [ -z "$H2_JAR_PATH" ]; then H2_JAR_PATH="$BIN_DIR/h2.jar" fi JDBC_URL="jdbc:h2:$DB_FILE_WITHOUT_EXT" SCRIPT_FILE="h2_script.sql" SCRIPT_JAVA_OPTS="-cp $SOURCE_H2_JAR_PATH org.h2.tools.Script -user sa -url $JDBC_URL -script $SCRIPT_FILE" RUN_SCRIPT_JAVA_OPTS="-cp $H2_JAR_PATH org.h2.tools.RunScript -user sa -url $JDBC_URL -script $SCRIPT_FILE -showResults -options FROM_1X" BACKUP_FILE="$MESH_HOME/backup_mesh.mv.db" echo "Creating script file..." $JAVA_BINARY $SCRIPT_JAVA_OPTS if [ $? -eq 0 ]; then echo "Script file created successfully" mv "$DB_FILE" "${BACKUP_FILE}" else echo "Script generation failed" exit 1 fi echo "Running script..." $JAVA_BINARY $RUN_SCRIPT_JAVA_OPTS if [[ $? -eq 0 && -f "$DB_FILE" ]]; then echo "Run script finished, DB file generated successfully at $DB_FILE" rm -rf "$SCRIPT_FILE" chmod u=rw,go=r $DB_FILE else echo "Run script failed" rm -rf ${DB_FILE_WITHOUT_EXT}.*.db mv "${BACKUP_FILE}" "$DB_FILE" exit 1 fi
Grant execute permissions to the script.
chmod +x h2-migrate-db-file.sh
Run the Mesh H2 Upgrade Script
MESH_HOME=/var/atlassian/application-data/mesh SOURCE_H2_JAR_PATH=/var/atlassian/application-data/mesh/h2-2.1.214.jar H2_JAR_PATH=/var/atlassian/application-data/mesh/h2-2.2.220.jar ./h2-migrate-db-file.sh
When the H2 DB Migration script is successfully executed, it will generate output that looks similar to the following:
Creating script file... Script file created successfully Running script... Run script finished, DB file generated successfully at /var/opt/atlassian-bitbucket/home/mesh.mv.db
Fix the permissions for the file
mesh.mv.db
chown bitbucket:bitbucket /var/atlassian/application-data/mesh/mesh.mv.db
Repeat the same steps for the bitbucket-mesh-h2-upgrade1 and bitbucket-mesh-h2-upgrade2 pods following the above steps
Step 4: Delete the H2 upgrade pod
Once we have a successful H2 upgrade, we can delete the Mesh H2 upgrade pods:
kubectl delete pod bitbucket-mesh-h2-upgrade0 bitbucket-mesh-h2-upgrade1 bitbucket-mesh-h2-upgrade2 -n bitbucket-mesh
Step 5: Upgrade and Start the Bitbucket Mesh Nodes
Update the Bitbucket Mesh YAML file:
mesh: enabled: true replicaCount: 3 image: tag: "2.5.7"
Bring up the Bitbucket Mesh Nodes and perform the upgrade:
helm upgrade --install bitbucket-mesh atlassian-data-center/bitbucket --namespace bitbucket-mesh --values values-bitbucket-mesh.yaml