[aws-eks] Generalized build-order and/or simplified multi-dependencies #6299
Labels
@aws-cdk/aws-eks
Related to Amazon Elastic Kubernetes Service
closed-for-staleness
This issue was automatically closed because it hadn't received any attention in a while.
effort/medium
Medium work item – several days of effort
feature-request
A feature should be added or improved.
management/rfc
request for comments
p2
I'd like a way to more concisely flag dependencies between multiple resources, or specify a particular "build order" explicitly when necessary.
Use Case
CDK has always been pretty good about figuring out dependencies on its own, but my recent attempts to use it with
FargateCluster
,FargateProfile
,KubernetesResource
, andHelmChart
constructs proved that when CDK isn't able to figure out the deps on its own, it's really painful. I was ultimately successful, and I think the solution can be generalized to be integrated fairly cleanly into CDK core if desired.To avoid getting too deep into the weeds, I'll summarize the problem I was having:
Resources I needed to build:
FargateCluster
FargateProfile
KubernetesResource
"A" andKubernetesResource
"B" (k8sA
andk8sB
for brevity)HelmChart
"A",HelmChart
"B", and
HelmChart"C" (
HelmA,
HelmB, and
HelmC` for brevity)✅
FargateCluster
is an auto-detected dependency ofFargateProfile
,k8sA&B
andHelmA/B/C
. So far so good...❗️
k8sA&B
andHelmA/B/C
can technically be created withoutFargateProfile
being completed, but the resulting pods will be stuck in aPending
state forever until they are manually replaced because k8s tries to schedule them before there's anyFargateProfile
available to figure out where to put them. We can work around this by doingconst fargateProfile = cluster.node.findChild('fargate-profile-' + cluster.fargateProfileName)
and then explicitly calling<resource>.node.addDependency(fargateProfile)
(for each k8s & helm resource... and remembering to do that for every k8s-related resource that is added in the future).❗️
HelmB
andHelmC
can technically be created withoutHelmA
, but attempting to do so beforeHelmA
(which, in my case, was theMetricsServer
chart) has fully deployed will result in aError: could not get apiVersions from Kubernetes: unable to retrieve the complete list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to handle the request
. This can be worked around by using the--wait
flag on thehelm
invocation (see #6276 for relevant PR) and adding an explicit dependency onHelmA
toHelmB/C
(and remembering to add it for any charts that are added in the future).Proposed Solution
Eliminate the need to call
cluster.findChild(...)
to find theFargateProfile
(and find any other profiles) by automatically adding any of the cluster's associatedFargateProfile
resources as dependencies on any resources that depend on the cluster itself. This should easily be doable in conjunction with [aws-eks] Can't define a fargate cluster with more than one profile #6084.Create a simplified mechanism to add one resource as a dependency to several other resources without needing to bundle those resources into a separate construct.
Extend mechanism in (2) to perhaps define a more complex dependency hierarchy.
Assume that a dependency on a
HelmChart
resource implies that the--wait
flag needs to be used (sincehelm install
finishes pretty much immediately and has the actual install happen asynchronously in the background).This is what my CDK code would look like after #6276 is merged without any other CDK modifications:
For those unfamiliar, the
new class extends cdk.Construct { ...}(this, '...')
is an anonymous class and can be thought of along the same lines as you'd think of a self-executing anonymous function (e.g.(function (x) { console.log('Hello ' + x); })('world');
. I used this technique as a shortcut to avoid having to create a separate "wrapper"Construct
in a separate file and pass a bunch of parameters to it. This way, thecluster
,fargateProfile
,helmA
, etc., values are still in scope.Anyway, here's how I'd envision the above code looking if there was a generalized multi-dependency API available instead:
OK, what's going on there? How does CDK know what to do when? Here's how implementation of what I suggest above would allow us to get rid of a lot of the code needed earlier:
We can get rid of the
.findChild('fargate-profile')
call because bothKubernetesResource
andHelmChart
already depend oncluster
, and my proposed changes would automatically create a dependency on associatedFargateProfile
constructs for anything that depends on theFargateCluster
.The
.chainOrSometOtherMuchBetterName(...)
method (sorry, I'm terrible at naming things!) accepts an array of arrays such that all resources listed in element N (a) automatically have a dependency on all resources in element N-1, and (b) do not necessarily have dependencies on each other. In other words, aftercluster
and itsFargateProfile
is done building (since, remember, everything depending oncluster
now also implicitly depends onFargateProfile
),k8sA
andhelmA
start building concurrently. Once bothk8sA
andhelmA
are done building (i.e. all resources in element 0),k8sB
,helmB
, andhelmC
start building concurrently.Other
I'm not too sure if this capability would be widely useful outside of the EKS space, but implementing the solution should be easy to generalize, so we might as well unless someone thinks it would be particularly harmful to allow where not necessary.
This is a 🚀 Feature Request
The text was updated successfully, but these errors were encountered: