Skip to content

Commit 9e46532

Browse files
Elad Ben-Israelmergify[bot]
authored andcommitted
feat(eks): output update-kubeconfig command (#3669)
* feat(eks): output update-kubeconfig command Synthesize a CloudFormation output that shows the `aws eks update-kubeconfig` that needs to be executed in order to connect to the cluster. This command will include the IAM masters role ARN if applicable. Disable all other outputs by default, but added `outputXxx` options to enable. Fixes #3664 BREAKING CHANGE: cluster name output will not be synthesized by default. instead we synthesize an output that includes the full `aws eks update-kubeconfig` command. You can enable synthesis of the cluster name output using the `outputClusterName: true` options. * update expectations * update readme
1 parent 15f01d0 commit 9e46532

8 files changed

+268
-47
lines changed

packages/@aws-cdk/aws-eks/README.md

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ new eks.Cluster(this, 'cluster', {
6969
defaultCapacityInstance: new ec2.InstanceType('m2.xlarge')
7070
});
7171
```
72-
To disable the default capacity, simply set `defaultCapacity` to `0`:
7372

73+
To disable the default capacity, simply set `defaultCapacity` to `0`:
7474

7575
```ts
7676
new eks.Cluster(this, 'cluster-with-no-capacity', { defaultCapacity: 0 });
@@ -121,13 +121,56 @@ new eks.Cluster(this, 'Cluster', {
121121
});
122122
```
123123

124-
Now, given AWS credentials for a user that is trusted by the masters role, you
125-
will be able to interact with your cluster like this:
124+
When you `cdk deploy` this CDK app, you will notice that an output will be printed
125+
with the `update-kubeconfig` command.
126+
127+
Something like this:
128+
129+
```
130+
Outputs:
131+
eks-integ-defaults.ClusterConfigCommand43AAE40F = aws eks update-kubeconfig --name cluster-ba7c166b-c4f3-421c-bf8a-6812e4036a33 --role-arn arn:aws:iam::112233445566:role/eks-integ-defaults-Role1ABCC5F0-1EFK2W5ZJD98Y
132+
```
133+
134+
Copy & paste the "`aws eks update-kubeconfig ...`" command to your shell in
135+
order to connect to your EKS cluster with the "masters" role.
136+
137+
Now, given [AWS CLI](https://aws.amazon.com/cli/) is configured to use AWS
138+
credentials for a user that is trusted by the masters role, you should be able
139+
to interact with your cluster through `kubectl` (the above example will trust
140+
all users in the account).
141+
142+
For example:
126143

127144
```console
128-
$ aws eks update-kubeconfig --name CLUSTER-NAME
145+
$ aws eks update-kubeconfig --name cluster-ba7c166b-c4f3-421c-bf8a-6812e4036a33 --role-arn arn:aws:iam::112233445566:role/eks-integ-defaults-Role1ABCC5F0-1EFK2W5ZJD98Y
146+
Added new context arn:aws:eks:eu-west-2:112233445566:cluster/cluster-ba7c166b-c4f3-421c-bf8a-6812e4036a33 to /Users/boom/.kube/config
147+
148+
$ kubectl get nodes # list all nodes
149+
NAME STATUS ROLES AGE VERSION
150+
ip-10-0-147-66.eu-west-2.compute.internal Ready <none> 21m v1.13.7-eks-c57ff8
151+
ip-10-0-169-151.eu-west-2.compute.internal Ready <none> 21m v1.13.7-eks-c57ff8
152+
129153
$ kubectl get all -n kube-system
130-
...
154+
NAME READY STATUS RESTARTS AGE
155+
pod/aws-node-fpmwv 1/1 Running 0 21m
156+
pod/aws-node-m9htf 1/1 Running 0 21m
157+
pod/coredns-5cb4fb54c7-q222j 1/1 Running 0 23m
158+
pod/coredns-5cb4fb54c7-v9nxx 1/1 Running 0 23m
159+
pod/kube-proxy-d4jrh 1/1 Running 0 21m
160+
pod/kube-proxy-q7hh7 1/1 Running 0 21m
161+
162+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
163+
service/kube-dns ClusterIP 172.20.0.10 <none> 53/UDP,53/TCP 23m
164+
165+
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
166+
daemonset.apps/aws-node 2 2 2 2 2 <none> 23m
167+
daemonset.apps/kube-proxy 2 2 2 2 2 <none> 23m
168+
169+
NAME READY UP-TO-DATE AVAILABLE AGE
170+
deployment.apps/coredns 2/2 2 2 23m
171+
172+
NAME DESIRED CURRENT READY AGE
173+
replicaset.apps/coredns-5cb4fb54c7 2 2 2 23m
131174
```
132175

133176
For your convenience, an AWS CloudFormation output will automatically be
@@ -274,7 +317,7 @@ not have administrative privileges on the EKS cluster.
274317
if you wish to be able to manually interact with your cluster, you will need
275318
to map an IAM role or user to the `system:masters` group. This can be either
276319
done by specifying a `mastersRole` when the cluster is defined, calling
277-
`cluster.addMastersRole` or explicitly mapping an IAM role or IAM user to the
320+
`cluster.awsAuth.addMastersRole` or explicitly mapping an IAM role or IAM user to the
278321
relevant Kubernetes RBAC groups using `cluster.addRoleMapping` and/or
279322
`cluster.addUserMapping`.
280323

@@ -293,12 +336,13 @@ and a new cluster to be created.
293336

294337
When kubectl is disabled, you should be aware of the following:
295338

296-
1. When you log-in to your cluster, you don't need to specify `--role-arn` as long as you are using the same user that created
297-
the cluster.
339+
1. When you log-in to your cluster, you don't need to specify `--role-arn` as
340+
long as you are using the same user that created the cluster.
298341
2. As described in the Amazon EKS User Guide, you will need to manually
299-
edit the [aws-auth ConfigMap](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html) when you add capacity in order to map
300-
the IAM instance role to RBAC to allow nodes to join the cluster.
301-
3. Any `eks.Cluster` APIs that depend on programmatic kubectl support will fail with an error: `cluster.addResource`, `cluster.awsAuth`, `props.mastersRole`.
342+
edit the [aws-auth ConfigMap](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html)
343+
when you add capacity in order to map the IAM instance role to RBAC to allow nodes to join the cluster.
344+
3. Any `eks.Cluster` APIs that depend on programmatic kubectl support will fail
345+
with an error: `cluster.addResource`, `cluster.awsAuth`, `props.mastersRole`.
302346

303347
### Roadmap
304348

packages/@aws-cdk/aws-eks/lib/cluster.ts

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,31 @@ export interface ClusterProps {
196196
* @default m5.large
197197
*/
198198
readonly defaultCapacityInstance?: ec2.InstanceType;
199+
200+
/**
201+
* Determines whether a CloudFormation output with the name of the cluster
202+
* will be synthesized.
203+
*
204+
* @default false
205+
*/
206+
readonly outputClusterName?: boolean;
207+
208+
/**
209+
* Determines whether a CloudFormation output with the ARN of the "masters"
210+
* IAM role will be synthesized (if `mastersRole` is specified).
211+
*
212+
* @default false
213+
*/
214+
readonly outputMastersRoleArn?: boolean;
215+
216+
/**
217+
* Determines whether a CloudFormation output with the `aws eks
218+
* update-kubeconfig` command will be synthesized. This command will include
219+
* the cluster name and, if applicable, the ARN of the masters IAM role.
220+
*
221+
* @default true
222+
*/
223+
readonly outputConfigCommand?: boolean;
199224
}
200225

201226
/**
@@ -362,7 +387,11 @@ export class Cluster extends Resource implements ICluster {
362387
this.clusterEndpoint = resource.attrEndpoint;
363388
this.clusterCertificateAuthorityData = resource.attrCertificateAuthorityData;
364389

365-
new CfnOutput(this, 'ClusterName', { value: this.clusterName });
390+
let configCommand = `aws eks update-kubeconfig --name ${this.clusterName}`;
391+
392+
if (props.outputClusterName) {
393+
new CfnOutput(this, 'ClusterName', { value: this.clusterName });
394+
}
366395

367396
// we maintain a single manifest custom resource handler per cluster since
368397
// permissions and role are scoped. This will return `undefined` if kubectl
@@ -376,6 +405,12 @@ export class Cluster extends Resource implements ICluster {
376405
}
377406

378407
this.awsAuth.addMastersRole(props.mastersRole);
408+
409+
if (props.outputMastersRoleArn) {
410+
new CfnOutput(this, 'MastersRoleArn', { value: props.mastersRole.roleArn });
411+
}
412+
413+
configCommand += ` --role-arn ${props.mastersRole.roleArn}`;
379414
}
380415

381416
// allocate default capacity if non-zero (or default).
@@ -384,6 +419,11 @@ export class Cluster extends Resource implements ICluster {
384419
const instanceType = props.defaultCapacityInstance || DEFAULT_CAPACITY_TYPE;
385420
this.defaultCapacity = this.addCapacity('DefaultCapacity', { instanceType, desiredCapacity });
386421
}
422+
423+
const outputConfigCommand = props.outputConfigCommand === undefined ? true : props.outputConfigCommand;
424+
if (outputConfigCommand) {
425+
new CfnOutput(this, 'ConfigCommand', { value: configCommand });
426+
}
387427
}
388428

389429
/**
@@ -456,11 +496,6 @@ export class Cluster extends Resource implements ICluster {
456496
// EKS Required Tags
457497
autoScalingGroup.node.applyAspect(new Tag(`kubernetes.io/cluster/${this.clusterName}`, 'owned', { applyToLaunchedInstances: true }));
458498

459-
// Create an CfnOutput for the Instance Role ARN (need to paste it into aws-auth-cm.yaml)
460-
new CfnOutput(autoScalingGroup, 'InstanceRoleARN', {
461-
value: autoScalingGroup.role.roleArn
462-
});
463-
464499
if (options.mapRole === true && !this.kubectlEnabled) {
465500
throw new Error(`Cannot map instance IAM role to RBAC if kubectl is disabled for the cluster`);
466501
}
@@ -477,6 +512,12 @@ export class Cluster extends Resource implements ICluster {
477512
'system:nodes'
478513
]
479514
});
515+
} else {
516+
// since we are not mapping the instance role to RBAC, synthesize an
517+
// output so it can be pasted into `aws-auth-cm.yaml`
518+
new CfnOutput(autoScalingGroup, 'InstanceRoleARN', {
519+
value: autoScalingGroup.role.roleArn
520+
});
480521
}
481522
}
482523

packages/@aws-cdk/aws-eks/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,10 @@
8888
"engines": {
8989
"node": ">= 8.10.0"
9090
},
91+
"awslint": {
92+
"exclude": [
93+
"props-no-arn-refs:@aws-cdk/aws-eks.ClusterProps.outputMastersRoleArn"
94+
]
95+
},
9196
"stability": "experimental"
92-
}
97+
}

packages/@aws-cdk/aws-eks/test/integ.eks-cluster.defaults.expected.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,16 +1192,16 @@
11921192
}
11931193
},
11941194
"Outputs": {
1195-
"ClusterClusterNameEB26049E": {
1195+
"ClusterConfigCommand43AAE40F": {
11961196
"Value": {
1197-
"Ref": "Cluster9EE0221C"
1198-
}
1199-
},
1200-
"ClusterDefaultCapacityInstanceRoleARN7DADF219": {
1201-
"Value": {
1202-
"Fn::GetAtt": [
1203-
"ClusterDefaultCapacityInstanceRole3E209969",
1204-
"Arn"
1197+
"Fn::Join": [
1198+
"",
1199+
[
1200+
"aws eks update-kubeconfig --name ",
1201+
{
1202+
"Ref": "Cluster9EE0221C"
1203+
}
1204+
]
12051205
]
12061206
}
12071207
}

packages/@aws-cdk/aws-eks/test/integ.eks-cluster.kubectl-disabled.expected.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,9 +912,17 @@
912912
}
913913
},
914914
"Outputs": {
915-
"EKSClusterClusterName2B056109": {
915+
"EKSClusterConfigCommand3809C9C9": {
916916
"Value": {
917-
"Ref": "EKSClusterBA6ECF8F"
917+
"Fn::Join": [
918+
"",
919+
[
920+
"aws eks update-kubeconfig --name ",
921+
{
922+
"Ref": "EKSClusterBA6ECF8F"
923+
}
924+
]
925+
]
918926
}
919927
},
920928
"EKSClusterNodesInstanceRoleARN10992C84": {

packages/@aws-cdk/aws-eks/test/integ.eks-cluster.lit.expected.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,16 +1192,16 @@
11921192
}
11931193
},
11941194
"Outputs": {
1195-
"EKSClusterClusterName2B056109": {
1195+
"EKSClusterConfigCommand3809C9C9": {
11961196
"Value": {
1197-
"Ref": "EKSClusterE11008B6"
1198-
}
1199-
},
1200-
"EKSClusterNodesInstanceRoleARN10992C84": {
1201-
"Value": {
1202-
"Fn::GetAtt": [
1203-
"EKSClusterNodesInstanceRoleEE5595D6",
1204-
"Arn"
1197+
"Fn::Join": [
1198+
"",
1199+
[
1200+
"aws eks update-kubeconfig --name ",
1201+
{
1202+
"Ref": "EKSClusterE11008B6"
1203+
}
1204+
]
12051205
]
12061206
}
12071207
}

packages/@aws-cdk/aws-eks/test/integ.eks-kubectl.lit.expected.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,16 +1118,16 @@
11181118
}
11191119
},
11201120
"Outputs": {
1121-
"cluster22ClusterNameC4896469": {
1121+
"cluster22ConfigCommand96B20279": {
11221122
"Value": {
1123-
"Ref": "cluster227BD1CB20"
1124-
}
1125-
},
1126-
"cluster22NodesInstanceRoleARNEE60B01D": {
1127-
"Value": {
1128-
"Fn::GetAtt": [
1129-
"cluster22NodesInstanceRole51CD052F",
1130-
"Arn"
1123+
"Fn::Join": [
1124+
"",
1125+
[
1126+
"aws eks update-kubeconfig --name ",
1127+
{
1128+
"Ref": "cluster227BD1CB20"
1129+
}
1130+
]
11311131
]
11321132
}
11331133
}

0 commit comments

Comments
 (0)