Skip to content

Instantly share code, notes, and snippets.

@leepa
Created December 3, 2019 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leepa/515bfabc1beca3b9b717c6dcbc2686c4 to your computer and use it in GitHub Desktop.
Save leepa/515bfabc1beca3b9b717c6dcbc2686c4 to your computer and use it in GitHub Desktop.
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"
}
}
]
}
}
}
});
}
}
@blakegreendev
Copy link

Can you also post the app stack code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment