-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(aws-rds): support Aurora Serverless v2 cluster and instances #22446
feat(aws-rds): support Aurora Serverless v2 cluster and instances #22446
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pull request linter has failed. See the aws-cdk-automation comment below for failure reasons. If you believe this pull request should receive an exemption, please comment and provide a justification.
* | ||
* @default - TBC | ||
*/ | ||
readonly scalingV2?: ServerlessV2ScalingOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That V2
suffix is a bit of an eye sore.
Is there no better way?
Can we perhaps set an enum on the ServerlessCluster
class that specifies which version it is, and it then type narrows the interface? Or will it confuse JSII?
enum ServerlessClusterVersion {
V1,
V2,
}
interface ServerlessClusterNewProps {
version: ServerlessClusterVersion
}
interface ServerlessClusterNewPropsV1 {
version: ServerlessClusterVersion.V1
scaling: V1Scaling
}
interface ServerlessClusterNewPropsV2 {
version: ServerlessClusterVersion.V2
scaling: V2Scaling
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @moltar
Let's make it a little bit clear.
What I am trying to propose is to reuse the ServerlessCluster
to create either v1 or v2 clusters. As v1 and v2 have different scaling configuration logic and can't be shared, we would have both scaling interfaces for v1 and v2 in the ServerlessClusterProps
if we have to reuse the ServerlessCluster
construct for both scenarios. Your sample seems to create ServerlessClusterV2
just for v2 in addition to the existing ServerlessCluster
just for v1. I am fine with that as this is opinionated. Is this something you prefer in the API design?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my example, I am following your proposal to reuse the same class too. I guess my point about that was not very clear.
I was proposing to use discriminating unions to type narrow the interface based on the version
prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Union types don't work with jsii.
Also, from the docs: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html#aurora-serverless-v2.how-it-works.cluster_topology
Has this mixed-configuration cluster type been tested? I see only |
Co-authored-by: Roman <491247+moltar@users.noreply.github.com>
Co-authored-by: Roman <491247+moltar@users.noreply.github.com>
Co-authored-by: Roman <491247+moltar@users.noreply.github.com>
|
Yeah, we've used v1 extensively. I am familiar with this limitation that's why I was asking. It feels like maybe trying to fit a round peg in a square hole.
Meanwhile, we are trying to make ServerlessCluster class represent what it was not intended to do. Wouldn't it make more sense to make the original cluster work with the v2 instances, and then have some convenience interface, perhaps, over it? But I might be totally off base here, as I feel like I am still not fully understanding the problem space. So I am sorry, if what I am saying is noise. |
Hi @moltar please check out this sample in which I created 1 x v1 cluster and 2 x v2 clusters mixed with "serverless" and "provisioned" instances. In aurora serverless v2 cluster, the cluster itself is actually a "regional cluster" and you can add "serverless" or "provisioned" instances into the serverless v2 cluster. We could make all instances serverless, partially serverless or completely provisioned. 😄 It is interesting you literally can add all "provisioned" writer/readers instances in an "aurora serverless v2 cluster". I believe it's the primary feature v2 differentiates itself from v1 as v1 is 100% serverless. check out my cdk code used to provision the 3 clusters here |
Looking at the doc again, I think I was wrong. There is literally no "Aurora Serververless v2 cluster", only the old aurora cluster. We should be able to add any new "serverless v2 DB instances" or provisioned instances to any new or existing aurora clusters. I will update my PR shortly. |
I don't think there was even a v1 Serverless Cluster technically. It was always just an I think with V1 the design limitation was that you were not able to add any instances to the cluster (even the first one), as it was created for you. So maybe that's why a separate class was created for it. |
@moltar thanks for clearing it up. As the
Maybe we should extend the
wdyt? |
✅ Updated pull request passes all PRLinter validations. Dissmissing previous PRLinter review.
I don't know all of the permutations of cluster & instances. But I think overall it sounds good to me what you are suggesting. I think standardizing on the |
IMO, the entire In ideal world, what I would like to see is (and this is definitely outside of this PR scope):
IMO, we don't need the And the convenience method shall not also care about what type of instance is being added. It should just accept an cluster.addInstance(new ProvisionedInstance())
// OR
cluster.addInstance(new SeverlessInstance()) I have not studied all of the typings, so I am not sure if this is possible. But this feels like the CDK approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may want to think a little bit more about the user experience here. Previously DatabaseCluster
created only provisioned instances and now it can create a mix of provisioned or serverlessV2. In your proposed API there are too many things that the user needs to keep track of.
- If I start with a provisioned cluster and want to add a serverlessv2 instance can I just do
addServerlessInstance
? or do I also have to go back and addserverlessV2Scaling
to the cluster props? - What is
instanceProps
used for if I setinstances=0
? - It is not straight forward to figure out if my writer is a serverlessv2 instance or not.
- What happens if I change my writer from a
provisioned
to aserverlessV2
(or vice versa)
I think instead of starting from the existing DatabaseCluster
construct, we should start from the ideal customer experience and work backwards from there. If it allows us to continue using the DatabaseCluster
construct then great, but if we need to create a new construct DatabaseClusterV2
then that is ok too.
}); | ||
|
||
// adding a serverless writer | ||
cluster.addServerlessInstance('instance1', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this adding a serverless v1 or v2 instance? I think we need to update all references to include V2
if it is referring to v2
(docs & API), otherwise I am not sure if it is referring to v1
or v2
. You might know that I can't add a serverless v1 instance, but others might not.
Is it adding a writer because it is the first instance that we are adding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it's a little bit confusing but the core concept is:
- You are not allowed to add any instances for Aurora Serverless v1 cluster.
- You can't add serverless v2 instances into a general cluster until it is serverless v2 enabled.
- there is no
serverless v1 instance
. In Aurora Serverless v1, instances are not required.
We could add a check in this method to check the eligibility. Only clusters with v2 enabled are allowed to addServerlessInstance
. More details discussed in the comment below.
minCapacity: 0.5, | ||
}, | ||
// do not create any provisioned instance in the cluster | ||
instances: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to create this cluster with a serverless v2 writer we have to set instances=0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes 😄
Yes I was struggling if we should use the existing Current API design is based on using the existing The user experience could be like:
For case To answer your questions above:
If you create a cluster without
For serverlessv2 writer(discussed in case a. b. and f. above) we have to set
This is interesting. From CFN's perspective I believe this will trigger the update replacement described in this doc. CFN will create a new one before it "replaces" the old one, however, terminating the writer for replacement should result in a "failover" so your writer might immediately failover to the existing reader. I am not sure how CFN deals with that. Will give it a try and update here. I hope this helps to make it a little bit clear. I agree we should consider the user experience and work backwards from it. I am totally fine with a new |
Co-authored-by: Cory Hall <43035978+corymhall@users.noreply.github.com>
Hi @corymhall Last night I implemented a new /**
* Aurora serverless v2 cluster for MySQL with the mix of serverless and provisioned instances.
*/
// Aurora Serverless v2 cluster for MySQL
new rds.ServerlessV2DatabaseCluster(stack, 'cluster2', {
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }),
serverlessV2Scaling: {
maxCapacity: 4,
minCapacity: 0.5,
},
// 1 writer(serverless)
writer: { engine: rds.DatabaseInstanceEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }) },
// 2 readers: 1 serverless and 1 provisioned.
reader: [
{ engine: rds.DatabaseInstanceEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }) },
{
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE),
engine: rds.DatabaseInstanceEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }),
},
],
vpc,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
removalPolicy: cdk.RemovalPolicy.DESTROY,
}); Should we opt in a new construct like this for this PR? |
IMO, the solution I have proposed is more idiomatic: new DatabaseCluster(scope, 'Cluster', {
// ...
instances: [
new ProvisionedInstance(),
new SeverlessInstance(),
]
// ...
}) If you want to have a specific reader writer instance, you can create classes for that: new DatabaseCluster(scope, 'Cluster', {
// ...
instances: [
new ReaderInstance(),
new WriterInstance(),
]
// ...
}) |
@moltar Yeah we can discuss more details about the design if we decide to opt in a new construct. |
If this is the case then I definitely think that we should go with a new construct. This means that there are 3 different types of clusters that you can create, ServerlessV1 cluster, traditional provisioned cluster, serverless v2 enabled cluster. But based on what I can see in the docs it looks like it is possible to add serverless v2 instances to an existing cluster.
I think instead of I have some outstanding questions that I think we need to answer before we can design the experience.
From the docs
Do I even need to create more than 1 serverless v2 instance (I think the answer is yes)?
I wonder how this works?
It looks like you can convert an existing cluster to serverless v2?
Some of this is covered in scaling (i.e. promotion tiers). |
One typical reason will be cost. Aurora Serverless V2 is significantly more expensive than Provisioned On-Demand instances. In many scenarios a provisioned (and reserved) base capacity will be more economical. |
@corymhall Love the discussion! Appreciated! Let's dive a little bit deeper and get things sorted.
From CFN's perspective, there's only one AWS::RDS::DBCluster resource and we can create 3 types of clusters from it:
From my experiment with CDK, you can't just add a
I'm probably not the best one to answer this question but AFAIK
As aurora serverless v2 is single-AZ based instance. Customers may opt in multi-AZ serverless readers, in which case they might need 2 or more serverless readers across multi-AZ. One of the advantages is the AZ-tolerance, another one is that when the primary serverless reader instance fails(everything fails 😄 ), it could immediate fail over to another serverless reader, instead of the writer.
I probably need to look into that as it seems not possible from console.
yes, as discussed above, the
With a serverlessV2 writer and one provisioned reader:
However, customers with very critical, steady and intensive read queries might consider multiple provisioned readers across multi-AZ for fault tolerance, which will not impact the writer when any single reader fails. Nice discussion. Thanks for bringing this up.
|
Yep! I think my point in bringing this up was that I think our design should take these specific scenarios into consideration. For example, If I really want to (or even have to) have a provisioned instance as my writer, then I also need a provisioned instance as a reader in the 0 promotion tier and any serverlessv2 instances should be in lower promotion tiers. If we make this hard for the user to do then we could make it easy for users to shoot themselves in the foot (e.g. Only a provisioned writer can handle the production load and they failover to a serverless v2 instance and prod goes down :( ). Previously you could only create a cluster with a single type of instance so these types of considerations didn't really matter. Also, what if I want to create different endpoints? It seems like the API needs to account for users needing more control over the individual instances they create in the cluster.
My point in bringing this up is that we should take the upgrade experience into consideration. If it is possible to upgrade an existing cluster, then maybe we don't want to require the user to use a new construct since that would prevent them from upgrading their cluster. If it is not possible then they have to create a new cluster anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this feature might be a good candidate for an RFC.
Some important findings today:
// create a ordinary provisioned cluster
new rds.DatabaseCluster(stack, 'general-cluster', {
// make sure you use serverless v2 compatible DatabaseClusterEngine
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_02_1 }),
instanceProps: {
vpc,
vpcSubnets,
},
subnetGroup,
});
// OK now you are allowed to add a serverless v2 reader into this cluster from console. This indicates that you are not literally convert the original cluster into a In this case,
If we consider the existing clusters created with the
Apart from above, we should allow them to create a new cluster with both serverless v2 writer and reader(s). Sounds like we should extend the existing DatabaseCluster construct instead? |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
I'm going to go ahead and close this for now since we are going the RFC route. |
@corymhall, @pahud, What's happening with the support for Aurora Serverless v2 construct? |
where could we check the progress of this RFC route @corymhall? I would really prefer to not have to go with the DbCluster workaround, instead of proper serverless v2 resource. |
About this PR
Aurora Serverless v2 now supports AWS CloudFormation and CDK has included the L1 support. The cluster with serverless v2 support is created from (AWS::RDS::DBCluster) with some conditions and limitations:
serverless
instances orprovisioned
instances, which means whenDBCluster
is provisioned with v2 support, we should be able to add an arbitrary number of instances in it, eitherserverless
orprovisioned
. The first one added would be the writer while others the readers.This PR extends the
DatabaseCluster
construct so we can enable its serverless v2 support by specifying the newserverlessV2Scaling
property. After the cluster is created, we canaddServerlessInstance
to add a serverless v2 instance oraddInstance
to add a provisioned instance into the serverless v2 enabled DBCluster.This PR has tested a few scenarios in the
integ.serverlessv2-cluster.ts
including:call out
I am not sure if this would make breaking changes:
instances
from ofDatabaseClusterBaseProps
can be0
now. This allows the DBCluster to be provisioned as a cluster with serverless instances only.Fixes: #20197
All Submissions:
Adding new Unconventional Dependencies:
New Features
yarn integ
to deploy the infrastructure and generate the snapshot (i.e.yarn integ
without--dry-run
)?By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license