How to Deploy Apicurio v3 Alongside v2
This guide shows you how to prepare the Apicurio Registry v3 values, deploy v3 next to your running v2 on a temporary hostname, and check that v3 is up and empty.
Type |
How-to guide |
Goal |
Run an empty Apicurio Registry v3 next to v2 on a temporary hostname, with no change for clients. |
Audience |
Platform Operator with Helm access to the Axual Streaming release in the |
When to use |
Use this guide as the first stage of Upgrade Apicurio Registry from v2 to v3, once Axual Streaming runs |
Prerequisites
Confirm the following before you begin.
Access and permissions required
You need the following access and permissions:
-
Helm access to the Axual Streaming release in the
kafkanamespace. -
The client secret of the platform’s
apicurio-apiKeycloak client, for the verification step.
Tools and versions required
You need the following tools and versions:
-
helmandkubectl -
curlandjq -
Axual Streaming Charts
2.0.0
Resources that must exist before starting
The following resources must already exist before you start:
-
Axual Streaming upgraded to
2.0.0, with your existing Apicurio v2 still running unchanged under itsapicurio-registrykey. See Upgrade Axual Streaming to 2.0.0.
Replace every <VALUE> placeholder and every example.com hostname with your actual value before running a command. [same as configured for your apicurio-registry] means copy the value from the matching key of your existing apicurio-registry block.
|
Step 1: Prepare the Apicurio v3 values
Your Apicurio v2 keeps running unchanged under its apicurio-registry: block. Add a new apicurio-registry-v3: block alongside it by working through the sections below.
Don’t pin image.tag in any of the blocks below. The chart already pins the correct Apicurio version.
|
1.1 Enable Apicurio v3 and disable the bundled Keycloak
Enable Apicurio v3 in the global block. Disable the bundled Keycloak instances, because v3 reuses the existing v2 Keycloak throughout the upgrade.
global:
apicurio:
enabled: true # your existing Apicurio v2, still running
apicurio-registry-v3:
enabled: true # enable Apicurio v3 alongside v2
axual-streaming:
apicurio-registry-v3:
imagePullSecrets:
- name: [same as configured for your apicurio-registry]
apicurioKeycloak:
enabled: false # reuse the v2 Keycloak, don't deploy a new one
apicurioKeycloakMysql:
enabled: false
1.2 Set the UI URL
Set the public HTTPS URL the browser uses to reach the v3 API. Use a temporary hostname for now; you switch to the production hostname in Step 6: Switch ingress to v3.
axual-streaming:
apicurio-registry-v3:
ui:
config:
registryApiUrl: "https://apicurio-v3.example.com/apis/registry/v3"
registryApiUrl must be publicly reachable from the browser. Don’t use localhost.
|
1.3 Configure the Kafka connection and topics
Set the bootstrap servers and the three v3 topic names. Replace <tenant> and <instance> with the values for your environment.
axual-streaming:
apicurio-registry-v3:
kafka:
bootstrapServers: [same as configured for your apicurio-registry]
journalTopic: "_<tenant>-<instance>-kafkasql-journal"
snapshotsTopic: "_<tenant>-<instance>-kafkasql-snapshots"
eventsTopic: "_<tenant>-<instance>-registry-events"
1.4 Configure TLS
Reuse the same TLS secret names as your existing Apicurio v2 deployment.
axual-streaming:
apicurio-registry-v3:
tls:
clientKeypairSecretName: [same as configured for your apicurio-registry]
serverKeypairSecretName: [same as configured for your apicurio-registry]
truststoreCaSecretName: [same as configured for your apicurio-registry]
1.5 Configure the Kafka init container
The init container creates the three Kafka topics and the ACLs (Access Control Lists) for the Apicurio principal. Reuse the same broker TLS secret names as your Apicurio v2 deployment.
axual-streaming:
apicurio-registry-v3:
kafkaInitContainer:
apicurioPrincipal: [same as configured for your apicurio-registry]
replicationFactor: [same as configured for your apicurio-registry]
minIsr: [same as configured for your apicurio-registry]
tls:
keypairSecretName: [same as configured for your apicurio-registry]
keypairSecretKeyName: [same as configured for your apicurio-registry]
keypairSecretCertName: [same as configured for your apicurio-registry]
truststoreCaSecretName: [same as configured for your apicurio-registry]
truststoreCaSecretCertName: [same as configured for your apicurio-registry]
1.6 Configure security
Copy the security block from your v2 values as-is. The only value that must differ is webRedirectUrl: point it to the temporary v3 hostname for now, and update it to the production hostname in Step 6: Switch ingress to v3.
axual-streaming:
apicurio-registry-v3:
security:
authentication:
enabled: true
basicAuthEnabled: true
keycloak:
authUrl: [same as configured for your apicurio-registry]
realm: [same as configured for your apicurio-registry]
webClientId: [same as configured for your apicurio-registry]
webRedirectUrl: "https://apicurio-v3.example.com" # point to v3, not v2
1.7 Configure the backend and UI ingresses
Where v2 had a single ingress block with a hosts array, v3 splits it into ingress.backend (the API) and ingress.ui (the web console). Both blocks accept the same className, annotations and tls fields you already have on the v2 ingress, and both route to the same Apicurio Service, typically <release-name>-apicurio-registry-v3, on different ports and paths:
| Ingress (values key) | Service name | Service port | Path |
|---|---|---|---|
|
|
|
|
|
|
|
|
If you front Apicurio with an external ingress or gateway rather than the chart’s ingress resources, see the Ingress routing reference for the full service, port and path mapping, including the Auth Proxy.
Use a temporary hostname here; you cut over to the production hostname in Step 6: Switch ingress to v3.
axual-streaming:
apicurio-registry-v3:
ingress:
backend:
enabled: true
className: [same as configured for your apicurio-registry]
annotations: [same as configured for your apicurio-registry]
host: "apicurio-v3.example.com"
tls:
- secretName: [same as configured for your apicurio-registry]
hosts:
- "apicurio-v3.example.com"
ui:
enabled: true
className: [same as configured for your apicurio-registry]
annotations: [same as configured for your apicurio-registry]
host: "apicurio-v3.example.com"
tls:
- secretName: [same as configured for your apicurio-registry]
hosts:
- "apicurio-v3.example.com"
Put the external-dns annotations on backend only. Backend and UI share the same hostname, so a single DNS registration is enough.
|
1.8 Configure the Auth Proxy (optional)
Skip this section if you don’t use the Auth Proxy sidecar. The Auth Proxy is disabled by default (authProxy.enabled: false); when enabled, it runs as a sidecar and validates JWT tokens before forwarding requests to the Apicurio backend.
If you’re adapting your v2 authProxy values, update these three fields. The v3 backend listens on 8081, the port the v2 proxy used, so the proxy moves to 8082:
| Value | v2 | v3 |
|---|---|---|
|
|
|
|
|
|
|
|
The Auth Proxy ingress can’t share a hostname and path with |
axual-streaming:
apicurio-registry-v3:
authProxy:
enabled: true
secrets:
auth-proxy:
client-secret-salt: <CLIENT_SECRET_SALT>
clientSecretAlgorithm: HmacSHA256
config:
auth-proxy:
valid-issuer-uri: [same as configured for your apicurio-registry]
jwks-endpoint-uri: [same as configured for your apicurio-registry]
client-id: [same as configured for your apicurio-registry]
check-audience: [same as configured for your apicurio-registry]
ingress:
enabled: true
className: [same as configured for your apicurio-registry]
annotations: [same as configured for your apicurio-registry]
hosts:
- host: "apicurio-auth-proxy.example.com"
paths:
- path: "/apis"
pathType: "Prefix"
tls:
- secretName: "<same TLS secret as your other ingresses>"
hosts:
- "apicurio-auth-proxy.example.com"
Step 2: Deploy Apicurio v3
Apply the updated values with a Helm upgrade of your existing Streaming release:
helm upgrade --install streaming oci://registry.axual.io/axual-charts/axual-streaming --version=2.0.0 -n kafka -f values.yaml
Only the v3 resources are added. The v2 registry keeps serving clients on its current hostname.
Step 3: Verify Apicurio v3 is running
Check that the v3 pods are ready, then confirm the v3 API answers on the temporary hostname and holds no artifacts yet.
-
List the v3 pods:
kubectl get pods -n kafka | grep apicurio-registry-v3Every pod shows
Running, and itsREADYcolumn shows all containers ready. -
Get a token for the platform’s
apicurio-apiclient from the existing v2 Keycloak, and count the artifacts in v3:TOKEN=$(curl -skS --fail-with-body -X POST \ "https://<APICURIO_KEYCLOAK_HOST>/auth/realms/<APICURIO_REALM>/protocol/openid-connect/token" \ -d "grant_type=client_credentials&client_id=apicurio-api&client_secret=<APICURIO_API_CLIENT_SECRET>" \ | jq -r '.access_token') curl -skS --fail-with-body \ "https://apicurio-v3.example.com/apis/registry/v3/search/artifacts?limit=1" \ -H "Authorization: Bearer $TOKEN" | jq '.count'The command prints
0. If it prints a higher number, a previous attempt left data behind; empty v3 with Restore the Apicurio v3 topics before you continue. -
Open
https://apicurio-v3.example.comin a browser and log in with ansr-adminuser. The v3 web console loads with an empty artifact list.
Next steps
Continue with How to Migrate Schemas to Apicurio v3.