Created
December 3, 2019 20:23
-
-
Save leepa/515bfabc1beca3b9b717c6dcbc2686c4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cdk = require('@aws-cdk/core'); | |
import autoscaling = require('@aws-cdk/aws-autoscaling'); | |
import ec2 = require('@aws-cdk/aws-ec2'); | |
import eks = require('@aws-cdk/aws-eks'); | |
import iam = require('@aws-cdk/aws-iam'); | |
import fs = require('fs'); | |
import path = require('path'); | |
import { safeLoadAll, safeLoad } from 'js-yaml'; | |
export class ProductionCluster extends eks.Cluster { | |
protected autoscalingGroups: autoscaling.AutoScalingGroup[] = []; | |
constructor(scope: cdk.Construct, id: string, props: eks.ClusterProps) { | |
super(scope, id, props); | |
} | |
/** | |
* Wrap addCapacity from eks.Cluster to provide a tracking of the capacity | |
* we have added. | |
* | |
* @param id | |
* @param options | |
*/ | |
public addCapacity(id: string, options: eks.CapacityOptions): autoscaling.AutoScalingGroup { | |
const asg = super.addCapacity(id, options); | |
this.autoscalingGroups.push(asg); | |
return asg; | |
} | |
/** | |
* Wrap addAutoScalingGroup to provide a tracking of ASGs added. | |
* | |
* @param autoScalingGroup | |
* @param options | |
*/ | |
public addAutoScalingGroup(autoScalingGroup: autoscaling.AutoScalingGroup, options: eks.AutoScalingGroupOptions) { | |
this.autoscalingGroups.push(autoScalingGroup); | |
super.addAutoScalingGroup(autoScalingGroup, options); | |
} | |
public addDashboard() { | |
const f = fs.readFileSync(path.resolve(__dirname, 'k8s', 'kubernetes-dashboard.yaml')); | |
const resources = safeLoadAll(f.toString()); | |
this.addResource('Dashboard', ...resources); | |
} | |
public addAlbIngressController(): eks.KubernetesResource { | |
const rbac_file = fs.readFileSync(path.resolve(__dirname, 'k8s', 'alb-rbac-role.yaml')); | |
const rbac = safeLoadAll(rbac_file.toString()); | |
const f = fs.readFileSync(path.resolve(__dirname, 'k8s', 'alb-ingress-controller.yaml')); | |
let resources = safeLoadAll(f.toString()); | |
const role = this.addResource('AlbRbacRole', ...rbac); | |
resources[0]['spec']['template']['spec']['containers'][0]['args'].push('--cluster-name=' + this.clusterName); | |
const alb = this.addResource('AlbIngressController', ...resources) | |
alb.node.addDependency(role); | |
return alb; | |
} | |
public deploy2048(): eks.KubernetesResource { | |
const ns = this.addResource('TwentyFortyEightNS', | |
{ | |
"apiVersion": "v1", | |
"kind": "Namespace", | |
"metadata": { | |
"name": "2048-game" | |
} | |
} | |
); | |
const files = [ | |
'2048-deployment.yaml', | |
'2048-service.yaml', | |
'2048-ingress.yaml', | |
] | |
const resources = files.map(rf => { | |
const f = fs.readFileSync(path.resolve(__dirname, 'k8s', '2048', rf)); | |
return safeLoad(f.toString()); | |
}); | |
const r = this.addResource('TwentyFortyEight', ...resources); | |
r.node.addDependency(ns); | |
return r; | |
} | |
public addAlbPermissionsToAllCapacity() { | |
this.autoscalingGroups.forEach(asg => { | |
const role = asg.role; | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"acm:DescribeCertificate", | |
"acm:ListCertificates", | |
"acm:GetCertificate" | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"ec2:AuthorizeSecurityGroupIngress", | |
"ec2:CreateSecurityGroup", | |
"ec2:CreateTags", | |
"ec2:DeleteTags", | |
"ec2:DeleteSecurityGroup", | |
"ec2:DescribeAccountAttributes", | |
"ec2:DescribeAddresses", | |
"ec2:DescribeInstances", | |
"ec2:DescribeInstanceStatus", | |
"ec2:DescribeInternetGateways", | |
"ec2:DescribeNetworkInterfaces", | |
"ec2:DescribeSecurityGroups", | |
"ec2:DescribeSubnets", | |
"ec2:DescribeTags", | |
"ec2:DescribeVpcs", | |
"ec2:ModifyInstanceAttribute", | |
"ec2:ModifyNetworkInterfaceAttribute", | |
"ec2:RevokeSecurityGroupIngress", | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"elasticloadbalancing:AddListenerCertificates", | |
"elasticloadbalancing:AddTags", | |
"elasticloadbalancing:CreateListener", | |
"elasticloadbalancing:CreateLoadBalancer", | |
"elasticloadbalancing:CreateRule", | |
"elasticloadbalancing:CreateTargetGroup", | |
"elasticloadbalancing:DeleteListener", | |
"elasticloadbalancing:DeleteLoadBalancer", | |
"elasticloadbalancing:DeleteRule", | |
"elasticloadbalancing:DeleteTargetGroup", | |
"elasticloadbalancing:DeregisterTargets", | |
"elasticloadbalancing:DescribeListenerCertificates", | |
"elasticloadbalancing:DescribeListeners", | |
"elasticloadbalancing:DescribeLoadBalancers", | |
"elasticloadbalancing:DescribeLoadBalancerAttributes", | |
"elasticloadbalancing:DescribeRules", | |
"elasticloadbalancing:DescribeSSLPolicies", | |
"elasticloadbalancing:DescribeTags", | |
"elasticloadbalancing:DescribeTargetGroups", | |
"elasticloadbalancing:DescribeTargetGroupAttributes", | |
"elasticloadbalancing:DescribeTargetHealth", | |
"elasticloadbalancing:ModifyListener", | |
"elasticloadbalancing:ModifyLoadBalancerAttributes", | |
"elasticloadbalancing:ModifyRule", | |
"elasticloadbalancing:ModifyTargetGroup", | |
"elasticloadbalancing:ModifyTargetGroupAttributes", | |
"elasticloadbalancing:RegisterTargets", | |
"elasticloadbalancing:RemoveListenerCertificates", | |
"elasticloadbalancing:RemoveTags", | |
"elasticloadbalancing:SetIpAddressType", | |
"elasticloadbalancing:SetSecurityGroups", | |
"elasticloadbalancing:SetSubnets", | |
"elasticloadbalancing:SetWebACL" | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"iam:CreateServiceLinkedRole", | |
"iam:GetServerCertificate", | |
"iam:ListServerCertificates" | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"waf-regional:GetWebACLForResource", | |
"waf-regional:GetWebACL", | |
"waf-regional:AssociateWebACL", | |
"waf-regional:DisassociateWebACL" | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"tag:GetResources", | |
"tag:TagResources" | |
] | |
})); | |
role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"waf:GetWebACL" | |
] | |
})); | |
}); | |
} | |
public addCAToScalingGroup(asg: autoscaling.AutoScalingGroup) { | |
asg.role.addToPolicy(new iam.PolicyStatement({ | |
resources: ['*'], | |
actions: [ | |
"autoscaling:DescribeAutoScalingGroups", | |
"autoscaling:DescribeAutoScalingInstances", | |
"autoscaling:SetDesiredCapacity", | |
"autoscaling:TerminateInstanceInAutoScalingGroup", | |
"autoscaling:DescribeTags" | |
] | |
})); | |
this.addResource("ClusterAutoScaler", { | |
"apiVersion": "v1", | |
"kind": "ServiceAccount", | |
"metadata": { | |
"labels": { | |
"k8s-addon": "cluster-autoscaler.addons.k8s.io", | |
"k8s-app": "cluster-autoscaler" | |
}, | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system" | |
} | |
}, | |
{ | |
"apiVersion": "rbac.authorization.k8s.io/v1beta1", | |
"kind": "ClusterRole", | |
"metadata": { | |
"name": "cluster-autoscaler", | |
"labels": { | |
"k8s-addon": "cluster-autoscaler.addons.k8s.io", | |
"k8s-app": "cluster-autoscaler" | |
} | |
}, | |
"rules": [ | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"events", | |
"endpoints" | |
], | |
"verbs": [ | |
"create", | |
"patch" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"pods/eviction" | |
], | |
"verbs": [ | |
"create" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"pods/status" | |
], | |
"verbs": [ | |
"update" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"endpoints" | |
], | |
"resourceNames": [ | |
"cluster-autoscaler" | |
], | |
"verbs": [ | |
"get", | |
"update" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"nodes" | |
], | |
"verbs": [ | |
"watch", | |
"list", | |
"get", | |
"update" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"pods", | |
"services", | |
"replicationcontrollers", | |
"persistentvolumeclaims", | |
"persistentvolumes" | |
], | |
"verbs": [ | |
"watch", | |
"list", | |
"get" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"extensions" | |
], | |
"resources": [ | |
"replicasets", | |
"daemonsets" | |
], | |
"verbs": [ | |
"watch", | |
"list", | |
"get" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"policy" | |
], | |
"resources": [ | |
"poddisruptionbudgets" | |
], | |
"verbs": [ | |
"watch", | |
"list" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"apps" | |
], | |
"resources": [ | |
"statefulsets", | |
"replicasets" | |
], | |
"verbs": [ | |
"watch", | |
"list", | |
"get" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"storage.k8s.io" | |
], | |
"resources": [ | |
"storageclasses" | |
], | |
"verbs": [ | |
"watch", | |
"list", | |
"get" | |
] | |
} | |
] | |
}, | |
{ | |
"apiVersion": "rbac.authorization.k8s.io/v1beta1", | |
"kind": "Role", | |
"metadata": { | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system", | |
"labels": { | |
"k8s-addon": "cluster-autoscaler.addons.k8s.io", | |
"k8s-app": "cluster-autoscaler" | |
} | |
}, | |
"rules": [ | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"configmaps" | |
], | |
"verbs": [ | |
"create" | |
] | |
}, | |
{ | |
"apiGroups": [ | |
"" | |
], | |
"resources": [ | |
"configmaps" | |
], | |
"resourceNames": [ | |
"cluster-autoscaler-status" | |
], | |
"verbs": [ | |
"delete", | |
"get", | |
"update" | |
] | |
} | |
] | |
}, | |
{ | |
"apiVersion": "rbac.authorization.k8s.io/v1beta1", | |
"kind": "ClusterRoleBinding", | |
"metadata": { | |
"name": "cluster-autoscaler", | |
"labels": { | |
"k8s-addon": "cluster-autoscaler.addons.k8s.io", | |
"k8s-app": "cluster-autoscaler" | |
} | |
}, | |
"roleRef": { | |
"apiGroup": "rbac.authorization.k8s.io", | |
"kind": "ClusterRole", | |
"name": "cluster-autoscaler" | |
}, | |
"subjects": [ | |
{ | |
"kind": "ServiceAccount", | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system" | |
} | |
] | |
}, | |
{ | |
"apiVersion": "rbac.authorization.k8s.io/v1beta1", | |
"kind": "RoleBinding", | |
"metadata": { | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system", | |
"labels": { | |
"k8s-addon": "cluster-autoscaler.addons.k8s.io", | |
"k8s-app": "cluster-autoscaler" | |
} | |
}, | |
"roleRef": { | |
"apiGroup": "rbac.authorization.k8s.io", | |
"kind": "Role", | |
"name": "cluster-autoscaler" | |
}, | |
"subjects": [ | |
{ | |
"kind": "ServiceAccount", | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system" | |
} | |
] | |
}, | |
{ | |
"apiVersion": "apps/v1", | |
"kind": "Deployment", | |
"metadata": { | |
"name": "cluster-autoscaler", | |
"namespace": "kube-system", | |
"labels": { | |
"app": "cluster-autoscaler" | |
} | |
}, | |
"spec": { | |
"replicas": 1, | |
"selector": { | |
"matchLabels": { | |
"app": "cluster-autoscaler" | |
} | |
}, | |
"template": { | |
"metadata": { | |
"labels": { | |
"app": "cluster-autoscaler" | |
} | |
}, | |
"spec": { | |
"serviceAccountName": "cluster-autoscaler", | |
"containers": [ | |
{ | |
"image": "k8s.gcr.io/cluster-autoscaler:v1.12.3", | |
"name": "cluster-autoscaler", | |
"resources": { | |
"limits": { | |
"cpu": "100m", | |
"memory": "300Mi" | |
}, | |
"requests": { | |
"cpu": "100m", | |
"memory": "300Mi" | |
} | |
}, | |
"command": [ | |
"./cluster-autoscaler", | |
"--v=4", | |
"--stderrthreshold=info", | |
"--cloud-provider=aws", | |
"--skip-nodes-with-local-storage=false", | |
"--nodes=3:8:" + asg.autoScalingGroupName | |
], | |
"env": [ | |
{ | |
"name": "AWS_REGION", | |
"value": cdk.Aws.REGION, | |
} | |
], | |
"volumeMounts": [ | |
{ | |
"name": "ssl-certs", | |
"mountPath": "/etc/ssl/certs/ca-certificates.crt", | |
"readOnly": true | |
} | |
], | |
"imagePullPolicy": "Always" | |
} | |
], | |
"volumes": [ | |
{ | |
"name": "ssl-certs", | |
"hostPath": { | |
"path": "/etc/ssl/certs/ca-bundle.crt" | |
} | |
} | |
] | |
} | |
} | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you also post the app stack code?