Skip to content

Instantly share code, notes, and snippets.

@leepa
Created December 3, 2019 20:23
Show Gist options
  • Select an option

  • Save leepa/515bfabc1beca3b9b717c6dcbc2686c4 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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