Skip to content

Commit

Permalink
Add ASOv1 -> ASOv2 migration guide
Browse files Browse the repository at this point in the history
Fixes #3006
  • Loading branch information
matthchr committed Apr 3, 2024
1 parent 3bbaa54 commit 6e384fe
Show file tree
Hide file tree
Showing 11 changed files with 615 additions and 2 deletions.
338 changes: 338 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/_index.md

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/azuresql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: Azure SQL
---
## Secrets

ASOv1 `AzureSqlServer` creates a Kubernetes secret associated with the SQL server:

```
kubectl get secrets -n ns1
azuresqlserver-azuresql-migration-sample-1 Opaque 5 22h
```

This secret has the following 5 keys:

| Key | Source | ASOv2 equivalent |
|--------------------------|-----------------|---------------------------------------------------------------------|
| azureSqlServerName | User | None (see `.spec.operatorSpec.configMaps.fullyQualifiedDomainName`) |
| fullyQualifiedServerName | Azure | `.spec.operatorSpec.configMaps.fullyQualifiedDomainName` |
| fullyQualifiedUsername | ASOv1 generated | None |
| password | ASOv1 generated | `.spec.administratorPassword` |
| username | ASOv1 generated | `.spec.administratorLogin` |

Unlike ASOv1, ASOv2 does not automatically generate any usernames or passwords. It is up to you to manage and generate
usernames and passwords. You can continue using the ASOv1 generated username and password when you switch from ASOv1 to ASOv2,
as shown below.

Example ASOv2 YAML snippet for exporting FQDN to configmap:
```yaml
spec:
operatorSpec:
configMaps:
fullyQualifiedDomainName:
name: azuresqlserver-azuresql-migration-sample-1-asov2
key: fullyQualifiedServerName
```
Example ASOv2 YAML snippet for configuring the server username and password:
ASOv2 doesn't classify the administrator account name as a secret, so it will be automatically
included in the YAML after running `asoctl`.

We recommend making a _new_ secret containing just the server password. You can produce this secret by copying
the value from the ASOv1 secret `password` key into a new secret. In this example we'd create a new secret named
`azuresqlserver-azuresql-migration-sample-admin-pw` containing the `password` key with value from the ASOv1 secret
`azuresqlserver-azuresql-migration-sample-1` `password` key.
```yaml
spec:
administratorLogin: myusername # This value will be automatically populated by asoctl
administratorLoginPassword:
name: azuresqlserver-azuresql-migration-sample-admin-pw
key: password
```

Once you've applied the above, make sure to update your applications to depend on the new configmap
written by ASOv2 (`azuresqlserver-azuresql-migration-sample-1-asov2`), and the new secret written by you
(`azuresqlserver-azuresql-migration-sample-admin-pw`).
39 changes: 39 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/databaseusers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: Database Users
---

ASOv1 supports 3 types of database user:
- Azure SQL
- MySQL
- PostgreSQL

Unlike other resources, these users do not exist as first class entities in the Azure API. This means
that `asoctl` will not import them.

To migrate database users from ASOv1 to ASOv2, you must manually transform the ASOv1 DatabaseUser shape
into the ASOv2 shape.

## Azure SQL

ASOv1 `AzureSQLUser` [example](https://github.com/Azure/azure-service-operator/blob/main/config/samples/azure_v1alpha1_azuresqluser.yaml).

ASOv2 `sql.azure.com/User` [example](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/sql/v1api/v1api/v1_user.yaml).

## MySQL

ASOv1 `MySQLUser` [example](https://github.com/Azure/azure-service-operator/blob/main/config/samples/azure_v1alpha2_mysqluser.yaml).

ASOv1 `MySQLAADUser` [example](https://github.com/Azure/azure-service-operator/blob/main/config/samples/azure_v1alpha2_mysqlaaduser.yaml).

ASOv2 `dbformysql.azure.com/User` [example](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/dbformysql/v1api/v1_user.yaml).

ASOv2 `dbformysql.azure.com/User` in AAD configuration [example](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/dbformysql/v1api/v1_user_aad.yaml).
- Note that MySQL Flexible server has certain requirements for how it is set up to work with AAD [here](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/dbformysql/v1api/v1_user_aad.yaml#L3).
So not only do you need to create the user in ASOv2 you must also ensure that the FlexibleServer has the right
[FlexibleServerAdministrator](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/dbformysql/v1api/v1api20220101_flexibleserversadministrator.yaml) configured, with the right permissions.

## PostgreSQL

ASOv1 `PostgreSQLUser` [example](https://github.com/Azure/azure-service-operator/blob/main/config/samples/azure_v1alpha1_postgresqluser.yaml).

ASOv2 `dbforpostgresql.azure.com/User` [example](https://github.com/Azure/azure-service-operator/blob/main/v2/samples/dbforpostgresql/v1api/v1_user.yaml).
24 changes: 24 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/eventhub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: EventHub
---
## Secrets

ASOv1 `EventHubs` save a Kubernetes secret:

```
kubectl get secrets -n ns1
eventhub-eventhub-sample-1 Opaque 7 22h
```

This secret has the following 7 keys:

| Key | Source | ASOv2 equivalent |
|---------------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| eventhubName | User | None |
| eventhubNamespace | User | None |
| primaryConnectionString | Azure | `.spec.operatorSpec.secrets.primaryConnectionString` (added in ASO v2.7.0) |
| primaryKey | Azure | `.spec.operatorSpec.secrets.primaryKey` (added in ASO v2.7.0) |
| secondaryConnectionString | Azure | `.spec.operatorSpec.secrets.secondaryConnectionString` (added in ASO v2.7.0) |
| secondaryKey | Azure | `.spec.operatorSpec.secrets.secondaryKey` (added in ASO v2.7.0) |
| sharedaccessKey | Azure | None, see ASOv2 [NamespacesAuthorizationRules](https://azure.github.io/azure-service-operator/reference/eventhub/v1api20211101/#eventhub.azure.com/v1api20211101.NamespacesAuthorizationRule) for exporting keys for any authorization rule except the default `RootManageSharedAccessKey` |
40 changes: 40 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/mysql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: MySQL
---

ASOv1 supports MySQL single server, which is
[being deprecated](https://learn.microsoft.com/azure/mysql/single-server/whats-happening-to-mysql-single-server).

ASOv2 does _not_ support MySQL single server, but it does support MySQL Flexible Server (the single server replacement).

Migration from ASOv1 to ASOv2 for these resources is a two-step process:
1. Migrate from Single Server to Flexible Server.
2. Import the Flexible Server into ASOv2.

### Migrate from Single Server to Flexible Server

Annotate your ASOv1 MySQL single servers in Kubernetes with the `skipreconcile=true` annotation, and then
follow the [migration guide](https://learn.microsoft.com/azure/mysql/single-server/whats-happening-to-mysql-single-server#migrate-from-single-server-to-flexible-server).

Once the migration has been complete, use [asoctl](../../../tools/asoctl/) to import the new Flexible Server resource from
Azure following the standard process defined in the [ASOv1 to ASOv2 migration guide](../)

## Secrets

ASOv1 `MySQLServer` saves a Kubernetes secret:

```
kubectl get secrets -n ns1
mysqlserver-mysqlserver-migration Opaque 5 17h
```

This secret has the following 5 keys:

| Key | Source | ASOv2 equivalent |
|---------------------------|-----------------|--------------------------------------------------------------------------|
| fullyQualifiedServerName | User | `.spec.operatorSpec.secrets.fullyQualifiedDomainName` |
| fullyQualifiedUsername | User | None |
| mySqlServerName | User | None (see `.spec.operatorSpec.secrets.fullyQualifiedDomainName`) |
| password | ASOv1 generated | `.spec.administratorLoginPassword` |
| username | ASOv1 generated | `.spec.operatorSpec.configMaps.administratorLogin` (added in ASO v2.7.0) |
23 changes: 23 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/postgresql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: PostgreSQL
---

ASOv1 supports PostgreSQL single server, which is
[being deprecated](https://azure.microsoft.com/updates/azure-database-for-postgresql-single-server-will-be-retired-migrate-to-flexible-server-by-28-march-2025/).

ASOv2 does _not_ support PostgreSQL single server, but it does support PostgreSQL Flexible Server
(the single server replacement).

Migration from ASOv1 to ASOv2 for these resources is a two-step process:
1. Migrate from Single Server to Flexible Server.
2. Import the Flexible Server into ASOv2.

### Migrate from Single Server to Flexible Server

Annotate your ASOv1 PostgreSQL single servers in Kubernetes with the `skipreconcile=true` annotation,
and then follow the
[migration guide](https://learn.microsoft.com/azure/postgresql/migrate/migration-service/concepts-migration-service-postgresql).

Once the migration has been complete, use [asoctl](../../../tools/asoctl/) to import the new Flexible Server resource from
Azure following the standard process defined in the [ASOv1 to ASOv2 migration guide](../)

35 changes: 35 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/redis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: Redis
---
## Secrets

ASOv1 `RedisCaches` save a Kubernetes secret:

```
kubectl get secrets -n ns1
rediscache-rediscache-sample-1 Opaque 2 9s
```

This secret has the following 2 keys:

| Key | Source | ASOv2 equivalent |
|-------------------|--------|-------------------------------------------|
| primaryKey | Azure | `.spec.operatorSpec.secrets.primaryKey` |
| secondaryKey | Azure | `.spec.operatorSpec.secrets.secondaryKey` |

Example ASOv2 YAML snippet:
```yaml
spec:
operatorSpec:
secrets:
primaryKey:
name: rediscache-rediscache-sample-1-asov2
key: primarykey
key1:
name: rediscache-rediscache-sample-1-asov2
key: secondaryKey
```
Once you've applied the above, make sure to update your applications to depend on the new secret
written by ASOv2.
46 changes: 46 additions & 0 deletions docs/hugo/content/guide/asov1-asov2-migration/storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: Storage Account
---
## Secrets

ASOv1 `StorageAccounts` save a Kubernetes secret:

```
kubectl get secrets -n ns1
storageaccount-cutoverteststorage1 Opaque 5 17h
```

This secret has the following 5 keys:

| Key | Source | ASOv2 equivalent |
|--------------------|--------|-----------------------------------------------|
| StorageAccountName | User | None |
| connectionString0 | Azure | None (see `.spec.operatorSpec.secrets.key1`) |
| key0 | Azure | `.spec.operatorSpec.secrets.key1` |
| connectionString1 | Azure | None (see `.spec.operatorSpec.secrets.key2`) |
| key1 | Azure | `.spec.operatorSpec.secrets.key2` |

Instead of full connection strings, ASOv2 exposes individual endpoints such as `blobEndpoint`, which you can use to
craft a connection string.

Example ASOv2 YAML snippet:
```yaml
spec:
operatorSpec:
secrets:
blobEndpoint:
name: storageaccount-cutoverteststorage1-asov2
key: blobEndpoint
key1:
name: storageaccount-cutoverteststorage1-asov2
key: key0 # Matches the name the ASOv1 generated secret used
```
Once you've applied the above, make sure to update your applications to depend on the new secret
written by ASOv2.
TODO: How to work around connection string issues?
1. init container? https://stackoverflow.com/questions/77748779/how-to-prepare-environment-variables-with-init-containers-in-a-kubernetes-deploy
2. Support https://github.com/Azure/azure-service-operator/issues/3446?
3. Modify the command of the container itself to run a script first?
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Storage Container
---

No additional handling is needed above what `asoctl` automatically imports. Just apply the imported resource!
1 change: 1 addition & 0 deletions docs/hugo/content/guide/uninstalling.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "Uninstalling"
weight: 10
---

## Before you uninstall
Expand Down
9 changes: 7 additions & 2 deletions docs/hugo/content/tools/asoctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,15 @@ Usage:
asoctl import azure-resource <ARM/ID/of/resource> [flags]
Flags:
-h, --help help for azure-resource
-o, --output string Write ARM resource CRD to a file
-a, --annotations strings Add the specified annotations to the imported resources. Multiple comma-separated annotations can be specified (example.com/myannotation=foo,example.com/myannotation2=bar) or the --annotations (-a) argument can be used multiple times (-a example.com/myannotation=foo -a example.com/myannotation2=bar)
-h, --help help for azure-resource
-l, --labels strings Add the specified labels to the imported resources. Multiple comma-separated labels can be specified (example.com/mylabel=foo,example.com/mylabel2=bar) or the --labels (-l) argument can be used multiple times (-l example.com/mylabel=foo -l example.com/mylabel2=bar)
-n, --namespace string Write the imported resources to the specified namespace
-o, --output string Write ARM resource CRDs to a single file
-f, --output-folder string Write ARM resource CRDs to individual files in a folder
Global Flags:
--quiet Silence most logging
--verbose Enable verbose logging
```
Expand Down

0 comments on commit 6e384fe

Please sign in to comment.