├── secrets └── .gitignore ├── vars ├── dynamic │ └── .gitignore └── static │ ├── custom_definitions.yaml.example │ └── definitions.yaml ├── cloudformation ├── .DS_Store ├── eks-external-dns-iam.template.yaml ├── eks-cluster-autoscaler-iam.template.yaml ├── eks-storage-provider-ebscsi-iam.template.yaml ├── eks-container-insights-iam.template.yaml ├── eks-storage-provider-efscsi-iam.template.yaml ├── eks-storage-provider-efscsi-storage.template.yaml ├── eks-bastion.template.yaml └── eks-loadbalancer-controller-iam-policy.template.yaml ├── .gitignore ├── docs ├── architecture │ ├── EksExampleArchitectureDiagram.png │ └── EksExampleArchitectureDiagram.drawio └── examples │ ├── k8s │ └── microservice-example │ │ ├── microservice-example-crystal-service.manifest.yaml │ │ ├── microservice-example-nodejs-service.manifest.yaml │ │ ├── microservice-example-frontend-service.manifest.yaml │ │ ├── microservice-example-hpa.manifest.yaml │ │ ├── microservice-example-nodejs-deployment.manifest.yaml │ │ ├── microservice-example-crystal-deployment.manifest.yaml │ │ ├── microservice-example-frontend-ingress.manifest.yaml │ │ └── microservice-example-frontend-deployment.manifest.yaml │ ├── deploy-examples.playbook.yaml │ ├── tasks │ └── microservice-example.task.yaml │ └── destroy-examples.playbook.yaml ├── CODE_OF_CONDUCT.md ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── tasks ├── eks-metrics-server.task.yaml ├── bastion.task.yaml ├── eks-external-dns.task.yaml ├── eks-cluster-autoscaler.task.yaml ├── eks-loadbalancer-controller.task.yaml ├── eks-xray.task.yaml ├── eks-cluster.task.yaml ├── eks-container-insights.task.yaml ├── acm.task.yaml ├── eks-storage-provider-ebscsi.task.yaml └── eks-storage-provider-efscsi.task.yaml ├── ansible.cfg ├── LICENSE.md ├── eks-deploy-cluster.playbook.yaml ├── CONTRIBUTING.MD ├── eks-destroy-cluster.playbook.yaml └── README.MD /secrets/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /vars/dynamic/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /cloudformation/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amazon-eks-ansible-example/HEAD/cloudformation/.DS_Store -------------------------------------------------------------------------------- /vars/static/custom_definitions.yaml.example: -------------------------------------------------------------------------------- 1 | eksexample_hostedzoneid: HOSTEDZONEID 2 | eksexample_hostedzonename: DOMAINNAME 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | secrets/* 2 | vars/eksexample_* 3 | vars/*/eksexample_* 4 | vars/static/custom_definitions.yaml 5 | ansible.log 6 | .vscode 7 | .DS_Store -------------------------------------------------------------------------------- /docs/architecture/EksExampleArchitectureDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amazon-eks-ansible-example/HEAD/docs/architecture/EksExampleArchitectureDiagram.png -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-crystal-service.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: eksdemo-crystal 5 | namespace: eksdemo 6 | spec: 7 | ports: 8 | - port: 80 9 | targetPort: 3000 10 | protocol: TCP 11 | selector: 12 | app: eksdemo-crystal -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-nodejs-service.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: eksdemo-nodejs 5 | namespace: eksdemo 6 | spec: 7 | ports: 8 | - port: 80 9 | targetPort: 3000 10 | protocol: TCP 11 | selector: 12 | app: eksdemo-nodejs -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-frontend-service.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: eksdemo-frontend 5 | namespace: eksdemo 6 | spec: 7 | type: NodePort 8 | ports: 9 | - port: 80 10 | targetPort: 3000 11 | protocol: TCP 12 | selector: 13 | app: eksdemo-frontend -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-hpa.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: {{ item }} 5 | namespace: eksdemo 6 | spec: 7 | maxReplicas: 10 8 | minReplicas: 2 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ item }} 13 | targetCPUUtilizationPercentage: 30 -------------------------------------------------------------------------------- /vars/static/definitions.yaml: -------------------------------------------------------------------------------- 1 | eksexample_region: eu-central-1 2 | eksexample_worker_desiredcount: 2 3 | eksexample_worker_maxcount: 10 4 | eksexample_worker_mincount: 2 5 | eksexample_worker_instancetype: t3a.medium 6 | eksexample_bastion_instancetype: t3a.small 7 | eksexample_clustername: ansible-eks-testcluster 8 | eksexample_clusterversion: 1.23 9 | eksexample_aws_profilename: ansible 10 | eksexample_aws_profilename: suredavi+ansible-admins -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-nodejs-deployment.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: eksdemo-nodejs 5 | labels: 6 | app: eksdemo-nodejs 7 | namespace: eksdemo 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: eksdemo-nodejs 13 | strategy: 14 | rollingUpdate: 15 | maxSurge: 25% 16 | maxUnavailable: 25% 17 | type: RollingUpdate 18 | template: 19 | metadata: 20 | labels: 21 | app: eksdemo-nodejs 22 | spec: 23 | containers: 24 | - image: brentley/ecsdemo-nodejs:latest 25 | imagePullPolicy: Always 26 | name: eksdemo-nodejs 27 | ports: 28 | - containerPort: 3000 29 | protocol: TCP 30 | resources: 31 | limits: 32 | cpu: 0.1 33 | requests: 34 | cpu: 0.1 -------------------------------------------------------------------------------- /tasks/eks-metrics-server.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | # Download and apply manifest 8 | - name: Download metrics-server manifest to the cluster. 9 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 10 | ansible.builtin.get_url: 11 | url: https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 12 | dest: ~/metrics-server.yaml 13 | mode: '0664' 14 | 15 | - name: Apply metrics-server manifest to the cluster. 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | kubernetes.core.k8s: 18 | state: present 19 | src: ~/metrics-server.yaml -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-crystal-deployment.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: eksdemo-crystal 5 | labels: 6 | app: eksdemo-crystal 7 | namespace: eksdemo 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: eksdemo-crystal 13 | strategy: 14 | rollingUpdate: 15 | maxSurge: 25% 16 | maxUnavailable: 25% 17 | type: RollingUpdate 18 | template: 19 | metadata: 20 | labels: 21 | app: eksdemo-crystal 22 | spec: 23 | containers: 24 | - image: brentley/ecsdemo-crystal:latest 25 | imagePullPolicy: Always 26 | name: eksdemo-crystal 27 | ports: 28 | - containerPort: 3000 29 | protocol: TCP 30 | resources: 31 | limits: 32 | cpu: 0.1 33 | requests: 34 | cpu: 0.1 -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | [defaults] 8 | host_key_checking = False 9 | fork = 5 10 | gathering = smart 11 | fact_caching = jsonfile 12 | fact_caching_connection = /tmp/cache 13 | fact_caching_timeout = 600 14 | nocows = 1 15 | timeout = 60 16 | retry_files_enabled = False 17 | callback_whitelist = profile_tasks 18 | stdout_callback = skippy 19 | log_path = ./ansible.log 20 | become = false 21 | interpreter_python = auto 22 | executable = /bin/bash 23 | 24 | [ssh_connection] 25 | ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ServerAliveInterval=10 -o IdentitiesOnly=yes 26 | control_path = ~/.ssh/ansible-%%r@%%h:%%p 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-frontend-ingress.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: eksdemo-frontend 5 | namespace: eksdemo 6 | annotations: 7 | kubernetes.io/ingress.class: alb 8 | alb.ingress.kubernetes.io/scheme: internet-facing 9 | alb.ingress.kubernetes.io/certificate-arn: "{{ eksexamplesslarn }}" 10 | external-dns.alpha.kubernetes.io/hostname: eksdemo."{{ eksexample_hostedzonename }}" 11 | alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]' 12 | alb.ingress.kubernetes.io/target-type: ip 13 | alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' 14 | spec: 15 | rules: 16 | - http: 17 | paths: 18 | - path: / 19 | pathType: Prefix 20 | backend: 21 | service: 22 | name: eksdemo-frontend 23 | port: 24 | number: 80 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /cloudformation/eks-external-dns-iam.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | Resources: 9 | 10 | EKSExternalDNSPolicy: 11 | Type: 'AWS::IAM::ManagedPolicy' 12 | Properties: 13 | ManagedPolicyName: EKSExternalDNSPolicy 14 | PolicyDocument: 15 | Version: 2012-10-17 16 | Statement: 17 | - Effect: Allow 18 | Action: 19 | - route53:ChangeResourceRecordSets 20 | Resource: 21 | - arn:aws:route53:::hostedzone/* 22 | - Effect: Allow 23 | Action: 24 | - route53:ListHostedZones 25 | - route53:ListResourceRecordSets 26 | Resource: 27 | - "*" -------------------------------------------------------------------------------- /docs/examples/k8s/microservice-example/microservice-example-frontend-deployment.manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: eksdemo-frontend 5 | labels: 6 | app: eksdemo-fronten 7 | namespace: eksdemo 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: eksdemo-frontend 12 | replicas: 2 13 | strategy: 14 | rollingUpdate: 15 | maxSurge: 25% 16 | maxUnavailable: 25% 17 | type: RollingUpdate 18 | template: 19 | metadata: 20 | labels: 21 | app: eksdemo-frontend 22 | spec: 23 | containers: 24 | - image: brentley/ecsdemo-frontend:latest 25 | imagePullPolicy: Always 26 | name: eksdemo-frontend 27 | ports: 28 | - containerPort: 3000 29 | protocol: TCP 30 | env: 31 | - name: CRYSTAL_URL 32 | value: "http://eksdemo-crystal.eksdemo.svc.cluster.local/crystal" 33 | - name: NODEJS_URL 34 | value: "http://eksdemo-nodejs.eksdemo.svc.cluster.local/" 35 | resources: 36 | limits: 37 | cpu: 0.2 38 | requests: 39 | cpu: 0.2 -------------------------------------------------------------------------------- /cloudformation/eks-cluster-autoscaler-iam.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | Resources: 9 | 10 | EKSClusterAutoscalerPolicy: 11 | Type: 'AWS::IAM::ManagedPolicy' 12 | Properties: 13 | ManagedPolicyName: EKSClusterAutoscalerPolicy 14 | PolicyDocument: 15 | Version: 2012-10-17 16 | Statement: 17 | - Effect: Allow 18 | Action: 19 | - autoscaling:DescribeAutoScalingGroups 20 | - autoscaling:DescribeAutoScalingInstances 21 | - autoscaling:DescribeLaunchConfigurations 22 | - autoscaling:DescribeTags 23 | - autoscaling:SetDesiredCapacity 24 | - autoscaling:TerminateInstanceInAutoScalingGroup 25 | - ec2:DescribeLaunchTemplateVersions 26 | Resource: '*' -------------------------------------------------------------------------------- /cloudformation/eks-storage-provider-ebscsi-iam.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | 9 | Resources: 10 | EKSStorageProviderEBSCsiPolicy: 11 | Type: 'AWS::IAM::ManagedPolicy' 12 | Properties: 13 | ManagedPolicyName: EKSStorageProviderEBSCsiPolicy 14 | PolicyDocument: 15 | Version: 2012-10-17 16 | Statement: 17 | - Effect: Allow 18 | Action: 19 | - ec2:AttachVolume 20 | - ec2:CreateSnapshot 21 | - ec2:CreateTags 22 | - ec2:CreateVolume 23 | - ec2:DeleteSnapshot 24 | - ec2:DeleteTags 25 | - ec2:DeleteVolume 26 | - ec2:DescribeInstances 27 | - ec2:DescribeSnapshots 28 | - ec2:DescribeTags 29 | - ec2:DescribeVolumes 30 | - ec2:DetachVolume 31 | Resource: '*' -------------------------------------------------------------------------------- /cloudformation/eks-container-insights-iam.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | Parameters: 9 | 10 | nodegroupRoleName: 11 | Type: String 12 | Default: "" 13 | 14 | Resources: 15 | 16 | nodegroupContainerInsightsPolicy: 17 | Type: 'AWS::IAM::ManagedPolicy' 18 | Properties: 19 | Path: / 20 | PolicyDocument: 21 | Version: 2012-10-17 22 | Statement: 23 | - Effect: Allow 24 | Action: 25 | - cloudwatch:PutMetricData 26 | - ec2:DescribeVolumes 27 | - ec2:DescribeTags 28 | - logs:PutLogEvents 29 | - logs:DescribeLogStreams 30 | - logs:DescribeLogGroups 31 | - logs:CreateLogStream 32 | - logs:CreateLogGroup 33 | Resource: "*" 34 | - Effect: Allow 35 | Action: 36 | - ssm:GetParameter 37 | Resource: "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*" 38 | Roles: 39 | - !Ref nodegroupRoleName -------------------------------------------------------------------------------- /cloudformation/eks-storage-provider-efscsi-iam.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | 9 | Resources: 10 | EKSStorageProviderEFSCsiPolicy: 11 | Type: 'AWS::IAM::ManagedPolicy' 12 | Properties: 13 | ManagedPolicyName: EKSStorageProviderEFSCsiPolicy 14 | PolicyDocument: 15 | Version: '2012-10-17' 16 | Statement: 17 | - Effect: Allow 18 | Action: 19 | - elasticfilesystem:DescribeAccessPoints 20 | - elasticfilesystem:DescribeFileSystems 21 | - elasticfilesystem:DescribeMountTargets 22 | - ec2:DescribeAvailabilityZones 23 | Resource: "*" 24 | - Effect: Allow 25 | Action: 26 | - elasticfilesystem:CreateAccessPoint 27 | Resource: "*" 28 | Condition: 29 | StringLike: 30 | aws:RequestTag/efs.csi.aws.com/cluster: 'true' 31 | - Effect: Allow 32 | Action: elasticfilesystem:DeleteAccessPoint 33 | Resource: "*" 34 | Condition: 35 | StringEquals: 36 | aws:ResourceTag/efs.csi.aws.com/cluster: 'true' -------------------------------------------------------------------------------- /tasks/bastion.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: Create EC2 KeyPair 8 | ec2_key: 9 | profile: "{{ eksexample_aws_profilename }}" 10 | name: "{{ eksexample_clustername }}-keypair" 11 | region: "{{ eksexample_region }}" 12 | register: ec2_key_result 13 | 14 | - name: Save Private Key for Bastion Access 15 | copy: content="{{ ec2_key_result.key.private_key }}" dest="./secrets/id_rsa_eks" mode=0600 16 | when: ec2_key_result.changed 17 | 18 | - name: create bastion Environment 19 | cloudformation: 20 | profile: "{{ eksexample_aws_profilename }}" 21 | stack_name: "{{ eksexample_clustername }}-bastion" 22 | state: "present" 23 | region: "{{ eksexample_region }}" 24 | disable_rollback: false 25 | template_parameters: 26 | EKSBastionInstanceType: "{{ eksexample_bastion_instancetype }}" 27 | EKSBastionKeyPairName: "{{ eksexample_clustername }}-keypair" 28 | template: "./cloudformation/eks-bastion.template.yaml" 29 | register: bastion_informations 30 | 31 | - name: save outputs to local file for ref 32 | copy: 33 | content: "{{ bastion_informations.stack_outputs | to_nice_yaml }}" 34 | dest: ./vars/dynamic/eksexample_bastion.yaml -------------------------------------------------------------------------------- /docs/examples/deploy-examples.playbook.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: Setup Kubernetes Example Deployments 8 | hosts: localhost 9 | gather_facts: no 10 | 11 | vars: 12 | ansible_ssh_private_key_file: "./secrets/id_rsa_eks" 13 | ansible_user: ec2-user 14 | 15 | tasks: 16 | - name: check ansible version 17 | when: (ansible_version.major == 2 and ansible_version.minor < 10 ) or (ansible_version.major < 2) 18 | run_once: yes 19 | fail: 20 | msg: Please use Ansible 2.10 or newer 21 | 22 | - name: import static var data 23 | include_vars: 24 | dir: ../../vars/static 25 | ignore_unknown_extensions: True 26 | extensions: 27 | - yaml 28 | 29 | - name: import dynamic var data 30 | include_vars: 31 | dir: ../../vars/dynamic 32 | ignore_unknown_extensions: True 33 | extensions: 34 | - yaml 35 | 36 | - name: Get AWS Account Information 37 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 38 | aws_caller_info: 39 | register: caller_info 40 | 41 | - name: setup kube services 42 | include_tasks: "{{ item }}" 43 | loop: 44 | - ./tasks/microservice-example.task.yaml -------------------------------------------------------------------------------- /docs/examples/tasks/microservice-example.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create eksdemo namespace 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | kubernetes.core.k8s: 10 | state: present 11 | definition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: eksdemo 16 | 17 | - name: create eksdemo deployment 18 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 19 | kubernetes.core.k8s: 20 | state: present 21 | apply: yes 22 | definition: "{{ lookup('template', './k8s/microservice-example/microservice-example-{{ item }}.manifest.yaml') | from_yaml }}" 23 | loop: 24 | - nodejs-deployment 25 | - crystal-deployment 26 | - frontend-deployment 27 | - nodejs-service 28 | - crystal-service 29 | - frontend-service 30 | - frontend-ingress 31 | 32 | - name: create eksdemo horizontal scaling 33 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 34 | kubernetes.core.k8s: 35 | state: present 36 | apply: yes 37 | definition: "{{ lookup('template', './k8s/microservice-example/microservice-example-hpa.manifest.yaml') | from_yaml }}" 38 | loop: 39 | - eksdemo-nodejs 40 | - eksdemo-crystal 41 | - eksdemo-frontend -------------------------------------------------------------------------------- /tasks/eks-external-dns.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create Roles and Policies for cluster-autoscaler 8 | cloudformation: 9 | profile: "{{ eksexample_aws_profilename }}" 10 | stack_name: "{{ eksexample_clustername }}-external-dns-policy" 11 | state: present 12 | region: "{{ eksexample_region }}" 13 | template: "./cloudformation/eks-external-dns-iam.template.yaml" 14 | 15 | - name: setup service account for external-dns 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | shell: > 18 | eksctl create iamserviceaccount \ 19 | --name external-dns \ 20 | --namespace kube-system \ 21 | --cluster "{{ eksexample_clustername }}" \ 22 | --attach-policy-arn "arn:aws:iam::{{ caller_info.account }}:policy/EKSExternalDNSPolicy" \ 23 | --approve \ 24 | --region {{ eksexample_region }} \ 25 | --override-existing-serviceaccounts 26 | 27 | - name: add the external-dns helm repo 28 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 29 | kubernetes.core.helm_repository: 30 | name: external-dns 31 | repo_url: "https://kubernetes-sigs.github.io/external-dns/" 32 | 33 | - name: Deploy latest version of the external-dns chart inside kube-system namespace 34 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 35 | kubernetes.core.helm: 36 | name: external-dns 37 | chart_ref: external-dns/external-dns 38 | release_namespace: kube-system 39 | values: 40 | serviceAccount: 41 | create: false 42 | name: external-dns -------------------------------------------------------------------------------- /tasks/eks-cluster-autoscaler.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create Policies for cluster-autoscaler 8 | cloudformation: 9 | profile: "{{ eksexample_aws_profilename }}" 10 | stack_name: "{{ eksexample_clustername }}-cluster-autoscaler-policy" 11 | state: present 12 | region: "{{ eksexample_region }}" 13 | template: "./cloudformation/eks-cluster-autoscaler-iam.template.yaml" 14 | 15 | - name: setup service account for cluster-autoscaler 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | shell: > 18 | eksctl create iamserviceaccount \ 19 | --name cluster-autoscaler \ 20 | --namespace kube-system \ 21 | --cluster "{{ eksexample_clustername }}" \ 22 | --attach-policy-arn "arn:aws:iam::{{ caller_info.account }}:policy/EKSClusterAutoscalerPolicy" \ 23 | --approve \ 24 | --region {{ eksexample_region }} \ 25 | --override-existing-serviceaccounts 26 | 27 | - name: add the cluster-autoscaler helm repo 28 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 29 | kubernetes.core.helm_repository: 30 | name: autoscaler 31 | repo_url: "https://kubernetes.github.io/autoscaler" 32 | 33 | - name: Deploy latest version of the cluster-autoscaler chart inside kube-system namespace 34 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 35 | kubernetes.core.helm: 36 | name: cluster-autoscaler 37 | chart_ref: autoscaler/cluster-autoscaler 38 | release_namespace: kube-system 39 | values: 40 | clusterName: "{{ eksexample_clustername }}" 41 | serviceAccount: 42 | create: false 43 | name: cluster-autoscaler -------------------------------------------------------------------------------- /docs/examples/destroy-examples.playbook.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: Destroy Amazon EKS example deployments 8 | hosts: localhost 9 | gather_facts: no 10 | 11 | vars: 12 | ansible_ssh_private_key_file: "./secrets/id_rsa_eks" 13 | ansible_user: ec2-user 14 | 15 | vars_prompt: 16 | - name: "security_check" 17 | prompt: "Do really want to DESTROY your example deployment (yes/no)?" 18 | private: no 19 | 20 | tasks: 21 | - name: check if we're gonna destroy 22 | when: not security_check | bool 23 | fail: 24 | msg: cancelled 25 | 26 | - name: check ansible version 27 | when: (ansible_version.major == 2 and ansible_version.minor < 10 ) or (ansible_version.major < 2) 28 | run_once: yes 29 | fail: 30 | msg: Please use Ansible 2.10 or newer 31 | 32 | - name: import static var data 33 | include_vars: 34 | dir: ../../vars/static 35 | ignore_unknown_extensions: True 36 | extensions: 37 | - yaml 38 | 39 | - name: import dynamic var data 40 | include_vars: 41 | dir: ../../vars/dynamic 42 | ignore_unknown_extensions: True 43 | extensions: 44 | - yaml 45 | 46 | - name: Get AWS Account Information 47 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 48 | aws_caller_info: 49 | register: caller_info 50 | 51 | - name: delete eksdemo namespace 52 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 53 | kubernetes.core.k8s: 54 | state: absent 55 | definition: 56 | apiVersion: v1 57 | kind: Namespace 58 | metadata: 59 | name: eksdemo -------------------------------------------------------------------------------- /tasks/eks-loadbalancer-controller.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create Policies for loadbalancer-controller 8 | cloudformation: 9 | profile: "{{ eksexample_aws_profilename }}" 10 | stack_name: "{{ eksexample_clustername }}-cluster-loadbalancercontroller-policy" 11 | state: present 12 | region: "{{ eksexample_region }}" 13 | template: "./cloudformation/eks-loadbalancer-controller-iam-policy.template.yaml" 14 | 15 | - name: setup service account for loadbalancer-controller 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | shell: > 18 | eksctl create iamserviceaccount \ 19 | --name aws-load-balancer-controller \ 20 | --namespace kube-system \ 21 | --cluster "{{ eksexample_clustername }}" \ 22 | --attach-policy-arn "arn:aws:iam::{{ caller_info.account }}:policy/EKSloadbalancerControllerPolicy" \ 23 | --approve \ 24 | --region {{ eksexample_region }} \ 25 | --override-existing-serviceaccounts 26 | 27 | - name: add the AWS Loadbalancer Controller helm repo 28 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 29 | kubernetes.core.helm_repository: 30 | name: aws-load-balancer-controller 31 | repo_url: "https://aws.github.io/eks-charts" 32 | 33 | - name: Deploy latest version of AWS Loadbalancer Controller chart inside kube-system namespace 34 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 35 | kubernetes.core.helm: 36 | name: aws-load-balancer-controller 37 | chart_ref: aws-load-balancer-controller/aws-load-balancer-controller 38 | release_namespace: kube-system 39 | values: 40 | clusterName: "{{ eksexample_clustername }}" 41 | serviceAccount: 42 | create: false 43 | name: aws-load-balancer-controller -------------------------------------------------------------------------------- /tasks/eks-xray.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: setup service account for x-ray 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | shell: > 10 | eksctl create iamserviceaccount \ 11 | --name xray-daemon \ 12 | --namespace kube-system \ 13 | --cluster "{{ eksexample_clustername }}" \ 14 | --attach-policy-arn arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess \ 15 | --approve \ 16 | --region {{ eksexample_region }} \ 17 | --override-existing-serviceaccounts 18 | 19 | - name: label the xray service-account 20 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 21 | shell: > 22 | kubectl label serviceaccount xray-daemon app=xray-daemon -n kube-system --overwrite 23 | 24 | - name: Download cloudwatch insights manifests to the cluster. 25 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 26 | ansible.builtin.get_url: 27 | url: https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/master/k8s-deployment-manifest-templates/deployment-mode/daemonset/cwagent-fluentd-xray/cwagent-fluentd-xray-quickstart.yaml 28 | dest: ~/cwagent-fluentd-xray-quickstart.yaml 29 | mode: '0664' 30 | 31 | 32 | - name: Replace variables with values 33 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 34 | ansible.builtin.replace: 35 | path: ~/cwagent-fluentd-xray-quickstart.yaml 36 | regexp: "{{ item.key }}" 37 | replace: "{{ item.value }}" 38 | loop: "{{ replace_data | dict2items }}" 39 | vars: 40 | replace_data: 41 | '\{\{cluster_name\}\}': "'{{ eksexample_clustername }}'" 42 | '\{\{region_name\}\}': "'{{ eksexample_region }}'" 43 | 44 | - name: Apply the container insights manifest to the cluster. 45 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 46 | kubernetes.core.k8s: 47 | state: present 48 | src: ~/cwagent-fluentd-xray-quickstart.yaml -------------------------------------------------------------------------------- /tasks/eks-cluster.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: check if eks cluster setup 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | shell: eksctl get cluster --region {{ eksexample_region }} --verbose 0 10 | register: eks_check_output 11 | retries: 20 12 | delay: 10 13 | until: "eks_check_output is not failed" 14 | 15 | - name: create the eks cluster 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | shell: > 18 | eksctl create cluster \ 19 | --name {{ eksexample_clustername }} \ 20 | --version {{ eksexample_clusterversion }} \ 21 | --region {{ eksexample_region }} \ 22 | --nodegroup-name {{ eksexample_clustername }}-linux-nodes \ 23 | --node-type {{ eksexample_worker_instancetype }} \ 24 | --nodes-min {{ eksexample_worker_mincount }} \ 25 | --nodes-max {{ eksexample_worker_maxcount }} \ 26 | --managed 27 | when: eks_check_output.stdout == "No clusters found" 28 | 29 | - name: write the kube config 30 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 31 | shell: > 32 | eksctl utils write-kubeconfig \ 33 | --cluster {{ eksexample_clustername }} \ 34 | --region {{ eksexample_region }} 35 | when: not eks_check_output.stdout == "No clusters found" 36 | 37 | - name: add the oidc provider for iam 38 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 39 | shell: > 40 | eksctl utils associate-iam-oidc-provider \ 41 | --cluster {{ eksexample_clustername }} \ 42 | --region {{ eksexample_region }} \ 43 | --approve 44 | when: eks_check_output.stdout == "No clusters found" 45 | 46 | - name: enable cloudwatch logging 47 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 48 | shell: > 49 | eksctl utils update-cluster-logging \ 50 | --cluster {{ eksexample_clustername }} \ 51 | --enable-types all \ 52 | --approve \ 53 | --region {{ eksexample_region }} 54 | when: eks_check_output.stdout == "No clusters found" 55 | -------------------------------------------------------------------------------- /cloudformation/eks-storage-provider-efscsi-storage.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | Parameters: 9 | 10 | Ekscidrblock: 11 | Type: String 12 | Default: "" 13 | Ekssubnetids: 14 | Type: CommaDelimitedList 15 | Default: "" 16 | Eksvpcid: 17 | Type: String 18 | Default: "" 19 | 20 | Resources: 21 | 22 | EksStorageProviderEfscsiSecurityGroup: 23 | Type: AWS::EC2::SecurityGroup 24 | Properties: 25 | VpcId: !Ref Eksvpcid 26 | GroupDescription: Security group for the Shared Storage 27 | 28 | EksStorageProviderEfscsiSecurityGroupApplicationPort: 29 | Type: AWS::EC2::SecurityGroupIngress 30 | Properties: 31 | CidrIp: !Ref Ekscidrblock 32 | IpProtocol: tcp 33 | FromPort: 2049 34 | ToPort: 2049 35 | GroupId: !Ref EksStorageProviderEfscsiSecurityGroup 36 | 37 | EksStorageProviderEfscsiFS: 38 | Type: AWS::EFS::FileSystem 39 | Properties: 40 | Encrypted: true 41 | 42 | EksStorageProviderEfscsiMountTarget1: 43 | Type: AWS::EFS::MountTarget 44 | Properties: 45 | FileSystemId: 46 | Ref: EksStorageProviderEfscsiFS 47 | SubnetId: !Select [0, !Ref Ekssubnetids] 48 | SecurityGroups: 49 | - !Ref EksStorageProviderEfscsiSecurityGroup 50 | 51 | EksStorageProviderEfscsiMountTarget2: 52 | Type: AWS::EFS::MountTarget 53 | Properties: 54 | FileSystemId: 55 | Ref: EksStorageProviderEfscsiFS 56 | SubnetId: !Select [1, !Ref Ekssubnetids] 57 | SecurityGroups: 58 | - !Ref EksStorageProviderEfscsiSecurityGroup 59 | 60 | EksStorageProviderEfscsiMountTarget3: 61 | Type: AWS::EFS::MountTarget 62 | Properties: 63 | FileSystemId: 64 | Ref: EksStorageProviderEfscsiFS 65 | SubnetId: !Select [2, !Ref Ekssubnetids] 66 | SecurityGroups: 67 | - !Ref EksStorageProviderEfscsiSecurityGroup 68 | Outputs: 69 | EksStorageProviderEfscsiFS: 70 | Value: !Ref EksStorageProviderEfscsiFS 71 | Description: Reference to the created Amazon EFS Volume -------------------------------------------------------------------------------- /eks-deploy-cluster.playbook.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: Setup and Customize Amazon EKS 8 | hosts: localhost 9 | gather_facts: no 10 | 11 | vars: 12 | ansible_ssh_private_key_file: "./secrets/id_rsa_eks" 13 | ansible_user: ec2-user 14 | 15 | tasks: 16 | - name: check ansible version 17 | when: (ansible_version.major == 2 and ansible_version.minor < 10 ) or (ansible_version.major < 2) 18 | run_once: yes 19 | fail: 20 | msg: Please use Ansible 2.10 or newer 21 | 22 | - name: import static var data 23 | include_vars: 24 | dir: vars/static 25 | ignore_unknown_extensions: True 26 | extensions: 27 | - yaml 28 | 29 | - name: setup bastion host 30 | include_tasks: ./tasks/bastion.task.yaml 31 | 32 | - name: import dynamic var data 33 | include_vars: 34 | dir: vars/dynamic 35 | ignore_unknown_extensions: True 36 | extensions: 37 | - yaml 38 | 39 | - name: wait for the bastion to be booted and bootstraped (first-start) 40 | wait_for: 41 | host: "{{ EKSBastionInstancePublicIP }}" 42 | port: 22 43 | timeout: 300 44 | delay: 120 45 | when: bastion_informations.changed 46 | 47 | - name: Get AWS Account Information 48 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 49 | aws_caller_info: 50 | register: caller_info 51 | retries: 20 52 | delay: 10 53 | until: "caller_info is not failed" 54 | 55 | - name: setup the EKS Cluster and additional extensions of the cluster infrastructure 56 | include_tasks: "{{ item }}" 57 | loop: 58 | - ./tasks/eks-cluster.task.yaml 59 | - ./tasks/eks-storage-provider-ebscsi.task.yaml 60 | - ./tasks/eks-storage-provider-efscsi.task.yaml 61 | - ./tasks/eks-container-insights.task.yaml 62 | - ./tasks/eks-cluster-autoscaler.task.yaml 63 | - ./tasks/eks-loadbalancer-controller.task.yaml 64 | - ./tasks/eks-external-dns.task.yaml 65 | - ./tasks/eks-metrics-server.task.yaml 66 | - ./tasks/eks-xray.task.yaml 67 | - ./tasks/acm.task.yaml -------------------------------------------------------------------------------- /tasks/eks-container-insights.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create amazon-cloudwatch namespace 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | kubernetes.core.k8s: 10 | state: present 11 | definition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: amazon-cloudwatch 16 | 17 | - name: get notegroups rolename 18 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 19 | shell: > 20 | aws cloudformation describe-stack-resources --region {{ eksexample_region }} --stack-name eksctl-{{ eksexample_clustername }}-nodegroup-{{ eksexample_clustername }}-linux-nodes \ 21 | | jq -r '.StackResources[] | select(.ResourceType=="AWS::IAM::Role") | .PhysicalResourceId' 22 | register: eks_nodegroup_role_name 23 | 24 | - name: create Roles and Policies for container insights 25 | cloudformation: 26 | profile: "{{ eksexample_aws_profilename }}" 27 | stack_name: "{{ eksexample_clustername }}-container-insights-policy" 28 | state: present 29 | region: "{{ eksexample_region }}" 30 | template: "./cloudformation/eks-container-insights-iam.template.yaml" 31 | template_parameters: 32 | nodegroupRoleName: "{{ eks_nodegroup_role_name.stdout }}" 33 | 34 | - name: Download cloudwatch insights manifests to the cluster. 35 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 36 | ansible.builtin.get_url: 37 | url: https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yaml 38 | dest: ~/cwagent-fluent-bit-quickstart.yaml 39 | mode: '0664' 40 | 41 | - name: Replace variables with values 42 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 43 | ansible.builtin.replace: 44 | path: ~/cwagent-fluent-bit-quickstart.yaml 45 | regexp: "{{ item.key }}" 46 | replace: "{{ item.value }}" 47 | loop: "{{ replace_data | dict2items }}" 48 | vars: 49 | replace_data: 50 | '\{\{cluster_name\}\}': "'{{ eksexample_clustername }}'" 51 | '\{\{region_name\}\}': "'{{ eksexample_region }}'" 52 | '\{\{http_server_toggle\}\}': "'On'" 53 | '\{\{read_from_tail\}\}': "'On'" 54 | '\{\{read_from_head\}\}': "'Off'" 55 | '\{\{http_server_port\}\}': "'2020'" 56 | 57 | - name: Apply the container insights manifest to the cluster. 58 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 59 | kubernetes.core.k8s: 60 | state: present 61 | src: ~/cwagent-fluent-bit-quickstart.yaml -------------------------------------------------------------------------------- /tasks/acm.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: check if cert already existing on ACM 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | shell: > 10 | aws acm list-certificates --region {{ eksexample_region }} \ 11 | | jq -r '.CertificateSummaryList | .[] | select (.DomainName == "{{ eksexample_hostedzonename }}").DomainName' 12 | register: cert_existing 13 | 14 | - name: request wildcard SSL Cert on ACM 15 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 16 | shell: > 17 | aws acm request-certificate --domain-name {{ eksexample_hostedzonename }} \ 18 | --subject-alternative-names *.{{ eksexample_hostedzonename }} --validation-method DNS \ 19 | --query CertificateArn --region {{ eksexample_region }} --output text 20 | when: cert_existing.stdout == "" 21 | 22 | - name: get cert arn on ACM 23 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 24 | shell: > 25 | aws acm list-certificates --region {{ eksexample_region }} \ 26 | | jq -r '.CertificateSummaryList | .[] | select (.DomainName == "{{ eksexample_hostedzonename }}").CertificateArn' 27 | register: cert_arn 28 | 29 | - name: waiting some seconds cause of AWS ACM latency 30 | pause: 31 | seconds: 20 32 | 33 | - name: read ssl cert name 34 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 35 | shell: > 36 | aws acm describe-certificate --region {{ eksexample_region }} \ 37 | --certificate-arn {{ cert_arn.stdout }} \ 38 | --query Certificate.DomainValidationOptions[0].ResourceRecord.Name \ 39 | --output text 40 | register: ssl_cert_name 41 | 42 | - name: read ssl cert value 43 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 44 | shell: > 45 | aws acm describe-certificate --region {{ eksexample_region }} \ 46 | --certificate-arn {{ cert_arn.stdout }} \ 47 | --query Certificate.DomainValidationOptions[0].ResourceRecord.Value \ 48 | --output text 49 | register: ssl_cert_value 50 | 51 | - name : create validation record set in route53 52 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 53 | route53: 54 | state: present 55 | zone: "{{ eksexample_hostedzonename }}" 56 | record: "{{ ssl_cert_name.stdout }}" 57 | type: CNAME 58 | ttl: 60 59 | value: "{{ ssl_cert_value.stdout }}" 60 | wait: yes 61 | overwrite: 'true' 62 | 63 | - name: wait for cert validation 64 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 65 | shell: > 66 | aws acm wait certificate-validated --region {{ eksexample_region }} --certificate-arn "{{ cert_arn.stdout }}" 67 | 68 | - name: save SSL creation outputs to local file for ref 69 | copy: 70 | content: "eksexamplesslarn: {{ cert_arn.stdout }}" 71 | dest: ./vars/dynamic/eksexample_ssl.yaml -------------------------------------------------------------------------------- /tasks/eks-storage-provider-ebscsi.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: create Roles and Policies for ebs csi 8 | cloudformation: 9 | profile: "{{ eksexample_aws_profilename }}" 10 | stack_name: "{{ eksexample_clustername }}-storage-provider-ebscsi-policy" 11 | state: present 12 | region: "{{ eksexample_region }}" 13 | template: "./cloudformation/eks-storage-provider-ebscsi-iam.template.yaml" 14 | 15 | - name: setup service account for ebs csi controller 16 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 17 | shell: > 18 | eksctl create iamserviceaccount \ 19 | --name ebs-csi-controller-sa \ 20 | --namespace kube-system \ 21 | --cluster "{{ eksexample_clustername }}" \ 22 | --attach-policy-arn "arn:aws:iam::{{ caller_info.account }}:policy/EKSStorageProviderEBSCsiPolicy" \ 23 | --approve \ 24 | --region {{ eksexample_region }} \ 25 | --override-existing-serviceaccounts 26 | 27 | - name: add the EBS CSI Driver helm repo 28 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 29 | kubernetes.core.helm_repository: 30 | name: aws-ebs-csi-driver 31 | repo_url: "https://kubernetes-sigs.github.io/aws-ebs-csi-driver" 32 | 33 | - name: Deploy latest version of EBS CSI Driver chart inside kube-system namespace 34 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 35 | kubernetes.core.helm: 36 | name: aws-ebs-csi-driver 37 | chart_ref: aws-ebs-csi-driver/aws-ebs-csi-driver 38 | release_namespace: kube-system 39 | values: 40 | controller: 41 | serviceAccount: 42 | create: false 43 | name: ebs-csi-controller-sa 44 | 45 | - name: create provisioned iops Storage Class 46 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 47 | kubernetes.core.k8s: 48 | state: present 49 | apply: yes 50 | definition: 51 | kind: StorageClass 52 | apiVersion: storage.k8s.io/v1 53 | metadata: 54 | name: ebs-io1 55 | provisioner: ebs.csi.aws.com 56 | volumeBindingMode: WaitForFirstConsumer 57 | parameters: 58 | csi.storage.k8s.io/fstype: ext4 59 | type: io1 60 | iopsPerGB: "50" 61 | encrypted: "true" 62 | 63 | - name: create additional Storage Classes 64 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 65 | kubernetes.core.k8s: 66 | state: present 67 | apply: yes 68 | definition: 69 | kind: StorageClass 70 | apiVersion: storage.k8s.io/v1 71 | metadata: 72 | name: "ebs-{{ item.name }}" 73 | provisioner: ebs.csi.aws.com 74 | volumeBindingMode: WaitForFirstConsumer 75 | parameters: 76 | csi.storage.k8s.io/fstype: ext4 77 | type: "{{ item.type }}" 78 | encrypted: "true" 79 | loop: 80 | - { name: gp2, type: gp2 } 81 | - { name: sc1, type: sc1 } 82 | - { name: st1, type: st1 } 83 | -------------------------------------------------------------------------------- /docs/architecture/EksExampleArchitectureDiagram.drawio: -------------------------------------------------------------------------------- 1 | 7V1Zk+I2EP41PDJl2fL1OFzZrUySqZpUNnmihC3AGWNRtpiB/PpItmywZI5ZzGXYmqpFbVkSUn/dn1oHLaM7W/4So/n0N+LjsKVr/rJl9Fq6DoBmsf+4ZCUkmmZkkkkc+EK2FrwF/+E8o5AuAh8npYyUkJAG87LQI1GEPVqSoTgmn+VsYxKWa52jCVYEbx4KVemPwKdTIbVMuH7wDQeTaV41sNzsyQzlucVXSabIJ58bIqPfMroxITT7NFt2cci7L++Y7L3BlqdFy2Ic0YNeCAe6+26/DP9Z9V/+SAbRL6bTFqPxgcKF+Mavi1EYeLy9i1GEqWg7XeU9MidBRNNeNTvsj9XZ1Vome9LlqSfdlARy2i4LgJriZZQFctouC4BcPJDqB3IDNwRKqlS8JtWvbTSQ/RkdsqBhEOFuoX8aE05i5AdsWLokJDGTRSRivdeZ0lnIUoB9/JwGFL/Nkcd79ZOBh8nGJKICAUDP06LjealMgeb882w54Wh7Qp8JfJrEZDFPq/zOMFD5dJhgbxEHdDVcZ36jMXkvCk4TeWNbuqFDxwGQNyEIww153x0YfYvJP3BMA4aS5zCY8Eop4cUikQrxmPJi2dcLoslLmuoZmvhKVfX4KJliXzRHqCSrAi+36jooEMSMDyYzTOMVy5K/kINO2B0divTnBogNIZtu4jcXImE4JkXZa2ixDwJdX0CariDtr9fuA123j66PuXcwhkRTa4LP83PH7jgngI9TRg9wTQU9hYfeRE/h62pHj7PPTyUt3UIz3o3RKJkX3fCA1i1D6/4cF5SgV0BxA3rQPKvjMh+Oq5noaqDjglCCj6bCx6zifZZ9KvgABT7PP96YoBuShf+A0e3DiH0cenwwhyiklYAy9AFXmBMCqqiidkBJTNCqmEdpsAJQjnYyf6QpqMH+BOdjSWI6JRMSobC/lnbYSEV+0THrPC+Ed3iqNP9iSldCQ9CCkrJKJRTF9JlHlJjAC1GSBF4uHgRhni1rGm/P7g5nzSeL2MM7vqcjYjOshgmmOzLqsHoIYxwiGnyUW1I1HOmr7Luh1UYGYYnWJb9ywVozbKusGgY0paHNSlwPdNG0I8ZetabFPODPGI3H/FOFcrygEQ7LA5pjzGMDg+MKKM4C3890ByfBf2hUWIqyje7tApoIS4qXW8X8qKQP25V8Kyy1J8Mt9X4eXvjamK8HNc9CxuNEBP0GNQ8dvA/YmuahsNUvAVtol2FrQXdztPfmN2zrDDB3VdLEhnbG+oV54WYAfIvRLgCuWRq8MYjnSx9Nh7iAzH6IWxeBuK2ZJcXJPfU2iBumuyv/aSCem5UNiDOWTxFj+zEr8HfiY/b0hUwmjPk2A/IZPLZCvs1mPjrQS0Nx9ZCHqqXu/8qntz9I/M5HUstG8jHNvfVpLvb0YRAxqxp5eMhyUZyOoDrd7TmWBYyTTneLKuoPv4IS/kxdne9CKBYjSuFXF25H5VHTXetOprsg395xct583HBUxPMaRk2t3XNP5qegbpZx0s4r/VlPJcrWy8XKBZzOj9n2A2VlJTAuiTJbXe9tGsoyjdsV4dEdaQJoXDsbBKpx7KAkGzPtG0nU3WSVzGdbcFtmROzZwHb6Gtx41gtiVlCQspiIQ1JdDO5pZhfYVdRlnP6TeUWuNqmKvZIkEMWPCGUquZfVFOq3oZr7WBpK5ll3jIMlb0c1bWNqm+I9I21ci6voGyNu9ZAjAK2ydbYshRzZFdwol9W/tHaRkGKd1lg/0BqDLSNzHmsM1C0Ab2/fmmGGwe44HCc70HGv3fBa5p3Ql0MBc1n6khvG8qJ/+/n1ezNAk6nbLtAAw5UWqKwj2Yso2yr7oLzUM3AbXRnTP+Y4RpSRh1pZjQiVSKSlyF4mLSLz1fGVVAtx3P/IokSZuajiMIskresE9ASooZvzspN7mVJat0Fi1Cnl+2LEtJa/yYtm3fGepMkmmGiwe3rJTLTm2nIQ5+ppzgNSNS8wHkdzVEg1a8FuX4jGtG5tvQ6ozLRe9vKIyRwUk3lP6iE9TpnzmGbF/ky3cr3qVLQnV6hTapgLzd5A/5qGmc+G1jHvRsOY16N4aBr1qJkhnac0DPuy5FqHDy27Ai1jfi5hzRuGBPnDEQpRxFfu69E5S5rqG9qFw836nWxv050D2efRG8+PG44dZ0K/c1hU3V7wiMwcHJkJRB/yYy01rSDJkK7YXXNWRMM72Vtz8IbVbHpw7IZVJWhrwvKOVANIh4OybyDeWg/qV3e+yvWY2u6dr8VJ2p/ML22eP81OWagS6t9QhCZ4VmHfbnKeDfcddrGdXIOvd2ZtqoukeMktKArbfpScwxNtmUTfvCfy8o3hQ1CPHzI1aRUpn07scUSmtl3hjtvvBBT9aKQjMg8NbF6WWtqqyW3c9rPdCOH7HgC4uTOGanQThaM2m5KyLk7a3I7EJAz5uYSHNb4aa2wBiVVd3Brfy1FV+0BrbB+7m+an2LwtnUtz97Bz+RyblP9E59hU2tc4V7HvqCrIrypYlSq8Yj9hK4PmhYuE9X2b4zLh938+fMQ1+QhbvzYfcSfBYPPQYLBdS+joqz7CkSKKrnwJrnzASLo3Q8p/Gh+R3+G26SPm85CBVRyNoHF64rEh7mL3MWfmLmzDuXoPoS4uLNtMMdo+wrMKx/7wDZfzDY5uX5dvsNTwQb0KwzfZGBA6X1yc7nSBYVqKRjV1cTq9lO0TUW9aj57JmyBgxWabsy5fWert7Q89u5CejUks5nwn0TU9X+2+lK45F4lQs96KV3+L99PEPzzBL9cQ6d5y82lv1cpvBj43UbYPva4PbuFH5wltO6pv4j930Rj26eyNa+uuI8W14XFsNC/aeCqvPoM8fYbrC87hCR7bevd5Am7AhkkGp5q2zMiOwHb1yzoC+ww7yGHPZg+/pmrsH+y4d6NqyzRKUYeGFXdkCw1zKu7MPi/VsC5BNa74gl/noovhjupb0Gb06hEJuZpIiBwlNw31h1vOGglx1G36Jd3RRsh7x5H/0KIr0iI5nnZCLWLJ9Q/gZWR4/UOCRv9/ -------------------------------------------------------------------------------- /CONTRIBUTING.MD: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *mainline* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /tasks/eks-storage-provider-efscsi.task.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: get eks cluster vpc 8 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 9 | shell: > 10 | aws eks describe-cluster --name {{ eksexample_clustername }} \ 11 | --query "cluster.resourcesVpcConfig.vpcId" --output text --region {{ eksexample_region }} 12 | register: eks_vpcinfo 13 | 14 | - name: get eks cluster vpc cidr 15 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 16 | shell: > 17 | aws ec2 describe-vpcs --vpc-ids {{ eks_vpcinfo.stdout }} \ 18 | --query "Vpcs[].CidrBlock" --output text --region {{ eksexample_region }} 19 | register: eks_vpccidr 20 | 21 | - name: get eks private subnet ids 22 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 23 | shell: > 24 | aws ec2 describe-subnets --region {{ eksexample_region }} --filter Name=vpc-id,Values={{ eks_vpcinfo.stdout }} \ 25 | | jq -r '.Subnets[] | select(.Tags[].Value | contains("SubnetPrivate")) | .SubnetId' | sort -u 26 | register: eks_subnetinfo 27 | 28 | - name: create Roles and Policies for efs csi 29 | cloudformation: 30 | profile: "{{ eksexample_aws_profilename }}" 31 | stack_name: "{{ eksexample_clustername }}-storage-provider-efscsi-policy" 32 | state: present 33 | region: "{{ eksexample_region }}" 34 | template: "./cloudformation/eks-storage-provider-efscsi-iam.template.yaml" 35 | 36 | - name: create efs storage for efs csi 37 | cloudformation: 38 | profile: "{{ eksexample_aws_profilename }}" 39 | stack_name: "{{ eksexample_clustername }}-storage-provider-efscsi-storage" 40 | state: present 41 | region: "{{ eksexample_region }}" 42 | template: "./cloudformation/eks-storage-provider-efscsi-storage.template.yaml" 43 | template_parameters: 44 | Ekscidrblock: "{{ eks_vpccidr.stdout }}" 45 | Ekssubnetids: "{{ eks_subnetinfo.stdout | replace('\n', ', ') }}" 46 | Eksvpcid: "{{ eks_vpcinfo.stdout }}" 47 | register: efs_filesystem 48 | 49 | - name: setup service account for efs csi controller 50 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 51 | shell: > 52 | . /home/ec2-user/.bashrc && \ 53 | eksctl create iamserviceaccount \ 54 | --name efs-csi-controller-sa \ 55 | --namespace kube-system \ 56 | --cluster "{{ eksexample_clustername }}" \ 57 | --attach-policy-arn "arn:aws:iam::{{ caller_info.account }}:policy/EKSStorageProviderEFSCsiPolicy" \ 58 | --approve \ 59 | --region {{ eksexample_region }} \ 60 | --override-existing-serviceaccounts 61 | 62 | - name: add the EFS CSI Driver helm repo 63 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 64 | kubernetes.core.helm_repository: 65 | name: aws-efs-csi-driver 66 | repo_url: "https://kubernetes-sigs.github.io/aws-efs-csi-driver/" 67 | 68 | - name: Deploy latest version of AWS EFS CSI Driver chart inside kube-system namespace 69 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 70 | kubernetes.core.helm: 71 | name: aws-efs-csi-driver 72 | chart_ref: aws-efs-csi-driver/aws-efs-csi-driver 73 | release_namespace: kube-system 74 | values: 75 | controller: 76 | serviceAccount: 77 | create: false 78 | name: efs-csi-controller-sa 79 | 80 | - name: create efs Storage Class 81 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 82 | kubernetes.core.k8s: 83 | state: present 84 | apply: yes 85 | definition: 86 | kind: StorageClass 87 | apiVersion: storage.k8s.io/v1 88 | metadata: 89 | name: efs-sc 90 | provisioner: efs.csi.aws.com -------------------------------------------------------------------------------- /cloudformation/eks-bastion.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: '2010-09-09' 8 | Description: Bastion using public subnet 9 | Parameters: 10 | EKSLatestAmazonLinuxAmiId: 11 | Description: AMI id that should be used for the EC2 instaces 12 | Type: 'AWS::SSM::Parameter::Value' 13 | Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' 14 | EKSBastionInstanceType: 15 | Description: InstanceType and Size for Bastion Host 16 | Type: String 17 | EKSBastionKeyPairName: 18 | Description: Keypair Name for SSH login 19 | Type: String 20 | 21 | Resources: 22 | EKSBastionRole: 23 | Type: AWS::IAM::Role 24 | Properties: 25 | AssumeRolePolicyDocument: 26 | Version: '2012-10-17' 27 | Statement: 28 | - Effect: Allow 29 | Principal: 30 | Service: 31 | - ec2.amazonaws.com 32 | Action: 33 | - sts:AssumeRole 34 | Policies: 35 | - PolicyName: EKSExample-service 36 | PolicyDocument: 37 | Version: '2012-10-17' 38 | Statement: 39 | - Effect: Allow 40 | Action: 41 | - cloudformation:* 42 | - eks:* 43 | - elasticfilesystem:* 44 | Resource: "*" 45 | ManagedPolicyArns: 46 | - arn:aws:iam::aws:policy/AmazonEC2FullAccess 47 | - arn:aws:iam::aws:policy/AmazonRoute53FullAccess 48 | - arn:aws:iam::aws:policy/IAMFullAccess 49 | - arn:aws:iam::aws:policy/AmazonVPCFullAccess 50 | - arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess 51 | - arn:aws:iam::aws:policy/AWSCertificateManagerFullAccess 52 | Path: "/" 53 | 54 | EKSBastionInstanceProfile: 55 | Type: AWS::IAM::InstanceProfile 56 | Properties: 57 | Path: "/" 58 | Roles: 59 | - Ref: EKSBastionRole 60 | 61 | EKSBastionInstanceSecurityGroup: 62 | Type: AWS::EC2::SecurityGroup 63 | Properties: 64 | GroupDescription: EKS Bastion ECS Instance Security Group 65 | 66 | EKSBastionInstanceSecurityGroupPorts: 67 | Type: AWS::EC2::SecurityGroupIngress 68 | Properties: 69 | GroupId: 70 | Fn::GetAtt: 71 | - EKSBastionInstanceSecurityGroup 72 | - GroupId 73 | IpProtocol: tcp 74 | FromPort: 22 75 | ToPort: 22 76 | CidrIp: 0.0.0.0/0 77 | 78 | EKSBastionInstance: 79 | Type: AWS::EC2::Instance 80 | Properties: 81 | ImageId: !Ref EKSLatestAmazonLinuxAmiId 82 | IamInstanceProfile: !Ref EKSBastionInstanceProfile 83 | InstanceType: !Ref EKSBastionInstanceType 84 | KeyName: !Ref EKSBastionKeyPairName 85 | SecurityGroups: 86 | - !Ref EKSBastionInstanceSecurityGroup 87 | UserData: 88 | Fn::Base64: !Sub | 89 | #!/bin/bash -xe 90 | 91 | yum update -y 92 | yum -y remove aws-cli 93 | yum -y install sqlite telnet jq strace tree gcc glibc-static gettext bash-completion 94 | 95 | pip3 install -U awscli ansible botocore boto boto3 openshift pyyaml 96 | update-alternatives --install /usr/bin/python python /usr/bin/python3 1 97 | 98 | # install helm on bastion 99 | curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash 100 | 101 | # install ansible kubernetes community collection 102 | /usr/local/bin/ansible-galaxy collection install kubernetes.core 103 | 104 | cd /tmp 105 | 106 | # eksctl install 107 | curl -sSL "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp 108 | chmod +x ./eksctl 109 | mv ./eksctl /usr/bin/eksctl 110 | 111 | # kubectl install 112 | curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl 113 | chmod +x ./kubectl 114 | mv ./kubectl /usr/bin/kubectl 115 | 116 | Outputs: 117 | EKSBastionInstanceDNSName: 118 | Description: The Bastion Host Public DNS Name 119 | Value: 120 | Fn::GetAtt: 121 | - EKSBastionInstance 122 | - PublicDnsName 123 | EKSBastionInstancePublicIP: 124 | Description: The Bastion Host Public DNS Name 125 | Value: 126 | Fn::GetAtt: 127 | - EKSBastionInstance 128 | - PublicIp -------------------------------------------------------------------------------- /eks-destroy-cluster.playbook.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2020 ## 5 | ############################################################# 6 | 7 | - name: example Kubernetes Workshop Workshop Destruction 8 | hosts: localhost 9 | gather_facts: no 10 | 11 | vars: 12 | ansible_ssh_private_key_file: "./secrets/id_rsa_eks" 13 | ansible_user: ec2-user 14 | 15 | vars_prompt: 16 | - name: "security_check" 17 | prompt: "Do really want to DESTROY your Amazon EKS cluster deployment (yes/no)?" 18 | private: no 19 | 20 | tasks: 21 | - name: check if we're gonna destroy 22 | when: not security_check | bool 23 | fail: 24 | msg: cancelled 25 | 26 | - name: check ansible version 27 | when: (ansible_version.major == 2 and ansible_version.minor < 10 ) or (ansible_version.major < 2) 28 | run_once: yes 29 | fail: 30 | msg: Please use Ansible 2.10 or newer 31 | 32 | - name: import static var data 33 | include_vars: 34 | dir: vars/static 35 | ignore_unknown_extensions: True 36 | extensions: 37 | - yaml 38 | 39 | - name: import dynamic var data 40 | include_vars: 41 | dir: vars/dynamic 42 | ignore_unknown_extensions: True 43 | extensions: 44 | - yaml 45 | 46 | - name: check if eks cluster setup 47 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 48 | shell: eksctl get cluster --region {{ eksexample_region }} --verbose 0 49 | register: eks_check_output 50 | 51 | - name: remove iamserviceaccounts via eksctl 52 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 53 | shell: > 54 | eksctl delete iamserviceaccount \ 55 | --name {{ item.name }} \ 56 | --namespace {{ item.namespace }} \ 57 | --cluster "{{ eksexample_clustername }}" \ 58 | --wait \ 59 | --region {{ eksexample_region }} 60 | loop: 61 | - { name: cluster-autoscaler, namespace: kube-system } 62 | - { name: external-dns, namespace: kube-system } 63 | - { name: aws-load-balancer-controller, namespace: kube-system } 64 | - { name: ebs-csi-controller-sa, namespace: kube-system } 65 | - { name: efs-csi-controller-sa, namespace: kube-system } 66 | - { name: xray-daemon, namespace: kube-system } 67 | when: not eks_check_output.stdout == "No clusters found" 68 | 69 | - name: destroy cloudformation stacks 70 | cloudformation: 71 | region: "{{ eksexample_region }}" 72 | profile: "{{ eksexample_aws_profilename }}" 73 | stack_name: "{{ item }}" 74 | state: "absent" 75 | loop: 76 | - "{{ eksexample_clustername }}-cluster-autoscaler-policy" 77 | - "{{ eksexample_clustername }}-container-insights-policy" 78 | - "{{ eksexample_clustername }}-external-dns-policy" 79 | - "{{ eksexample_clustername }}-cluster-loadbalancercontroller-policy" 80 | - "{{ eksexample_clustername }}-storage-provider-ebscsi-policy" 81 | - "{{ eksexample_clustername }}-storage-provider-efscsi-policy" 82 | - "{{ eksexample_clustername }}-storage-provider-efscsi-storage" 83 | 84 | - name: check if cert exists on ACM 85 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 86 | shell: > 87 | aws acm list-certificates --region {{ eksexample_region }} \ 88 | | jq -r ".CertificateSummaryList | .[] | select (.DomainName == \"{{ eksexample_hostedzonename }}\").CertificateArn" 89 | register: cert_existing 90 | 91 | - name: read ssl cert name 92 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 93 | shell: > 94 | aws acm describe-certificate --certificate-arn "{{ cert_existing.stdout }}" \ 95 | --query Certificate.DomainValidationOptions --region {{ eksexample_region }} | jq -r ".[] | select(.DomainName == \"{{ eksexample_hostedzonename }}\").ResourceRecord.Name" 96 | register: ssl_cert_name 97 | when: cert_existing.stdout 98 | 99 | - name: remove ACM Certfificate 100 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 101 | shell: > 102 | aws acm delete-certificate --region {{ eksexample_region }} --certificate-arn "{{ cert_existing.stdout }}" 103 | when: cert_existing.stdout 104 | 105 | - name : delete record set in route53 106 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 107 | route53: 108 | state: absent 109 | zone: "{{ eksexample_hostedzonename }}" 110 | record: "{{ ssl_cert_name.stdout }}" 111 | when: cert_existing.stdout == eksexample_hostedzonename 112 | 113 | - name: destroy amazon eks cluster 114 | delegate_to: "{{ EKSBastionInstancePublicIP }}" 115 | shell: > 116 | eksctl delete cluster \ 117 | --name {{ eksexample_clustername }} \ 118 | --region {{ eksexample_region }} \ 119 | --wait 120 | when: not eks_check_output.stdout == "No clusters found" 121 | 122 | - name: remove bastion host stack 123 | cloudformation: 124 | region: "{{ eksexample_region }}" 125 | profile: "{{ eksexample_aws_profilename }}" 126 | stack_name: "{{ eksexample_clustername }}-bastion" 127 | state: "absent" 128 | 129 | - name: remove ec2 secret key 130 | ec2_key: 131 | state: absent 132 | profile: "{{ eksexample_aws_profilename }}" 133 | name: "{{ eksexample_clustername }}-keypair" 134 | region: "{{ eksexample_region }}" 135 | 136 | - name: find dynamic var files 137 | find: 138 | paths: ./vars/dynamic/ 139 | patterns: "*" 140 | register: files_to_delete 141 | 142 | - name: remove dynamic var files 143 | file: 144 | path: "{{ item.path }}" 145 | state: absent 146 | with_items: "{{ files_to_delete.files }}" 147 | 148 | - name: delete local secret file 149 | file: 150 | path: ./secrets/id_rsa_eks 151 | state: absent 152 | -------------------------------------------------------------------------------- /cloudformation/eks-loadbalancer-controller-iam-policy.template.yaml: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | ## NOT FOR PRODUCTION USE. ## 3 | ## THE CONTENT OF THIS FILE IS FOR LEARNING PURPOSES ONLY ## 4 | ## created by David Surey, Amazon Web Services, 2021 ## 5 | ############################################################# 6 | 7 | AWSTemplateFormatVersion: "2010-09-09" 8 | Resources: 9 | 10 | EKSloadbalancerControllerPolicy: 11 | Type: 'AWS::IAM::ManagedPolicy' 12 | Properties: 13 | ManagedPolicyName: EKSloadbalancerControllerPolicy 14 | PolicyDocument: 15 | Version: '2012-10-17' 16 | Statement: 17 | - Effect: Allow 18 | Action: 19 | - iam:CreateServiceLinkedRole 20 | Resource: "*" 21 | Condition: 22 | StringEquals: 23 | iam:AWSServiceName: elasticloadbalancing.amazonaws.com 24 | - Effect: Allow 25 | Action: 26 | - ec2:DescribeAccountAttributes 27 | - ec2:DescribeAddresses 28 | - ec2:DescribeAvailabilityZones 29 | - ec2:DescribeInternetGateways 30 | - ec2:DescribeVpcs 31 | - ec2:DescribeVpcPeeringConnections 32 | - ec2:DescribeSubnets 33 | - ec2:DescribeSecurityGroups 34 | - ec2:DescribeInstances 35 | - ec2:DescribeNetworkInterfaces 36 | - ec2:DescribeTags 37 | - ec2:GetCoipPoolUsage 38 | - ec2:DescribeCoipPools 39 | - elasticloadbalancing:DescribeLoadBalancers 40 | - elasticloadbalancing:DescribeLoadBalancerAttributes 41 | - elasticloadbalancing:DescribeListeners 42 | - elasticloadbalancing:DescribeListenerCertificates 43 | - elasticloadbalancing:DescribeSSLPolicies 44 | - elasticloadbalancing:DescribeRules 45 | - elasticloadbalancing:DescribeTargetGroups 46 | - elasticloadbalancing:DescribeTargetGroupAttributes 47 | - elasticloadbalancing:DescribeTargetHealth 48 | - elasticloadbalancing:DescribeTags 49 | Resource: "*" 50 | - Effect: Allow 51 | Action: 52 | - cognito-idp:DescribeUserPoolClient 53 | - acm:ListCertificates 54 | - acm:DescribeCertificate 55 | - iam:ListServerCertificates 56 | - iam:GetServerCertificate 57 | - waf-regional:GetWebACL 58 | - waf-regional:GetWebACLForResource 59 | - waf-regional:AssociateWebACL 60 | - waf-regional:DisassociateWebACL 61 | - wafv2:GetWebACL 62 | - wafv2:GetWebACLForResource 63 | - wafv2:AssociateWebACL 64 | - wafv2:DisassociateWebACL 65 | - shield:GetSubscriptionState 66 | - shield:DescribeProtection 67 | - shield:CreateProtection 68 | - shield:DeleteProtection 69 | Resource: "*" 70 | - Effect: Allow 71 | Action: 72 | - ec2:AuthorizeSecurityGroupIngress 73 | - ec2:RevokeSecurityGroupIngress 74 | Resource: "*" 75 | - Effect: Allow 76 | Action: 77 | - ec2:CreateSecurityGroup 78 | Resource: "*" 79 | - Effect: Allow 80 | Action: 81 | - ec2:CreateTags 82 | Resource: arn:aws:ec2:*:*:security-group/* 83 | Condition: 84 | StringEquals: 85 | ec2:CreateAction: CreateSecurityGroup 86 | 'Null': 87 | aws:RequestTag/elbv2.k8s.aws/cluster: 'false' 88 | - Effect: Allow 89 | Action: 90 | - ec2:CreateTags 91 | - ec2:DeleteTags 92 | Resource: arn:aws:ec2:*:*:security-group/* 93 | Condition: 94 | 'Null': 95 | aws:RequestTag/elbv2.k8s.aws/cluster: 'true' 96 | aws:ResourceTag/elbv2.k8s.aws/cluster: 'false' 97 | - Effect: Allow 98 | Action: 99 | - ec2:AuthorizeSecurityGroupIngress 100 | - ec2:RevokeSecurityGroupIngress 101 | - ec2:DeleteSecurityGroup 102 | Resource: "*" 103 | Condition: 104 | 'Null': 105 | aws:ResourceTag/elbv2.k8s.aws/cluster: 'false' 106 | - Effect: Allow 107 | Action: 108 | - elasticloadbalancing:CreateLoadBalancer 109 | - elasticloadbalancing:CreateTargetGroup 110 | Resource: "*" 111 | Condition: 112 | 'Null': 113 | aws:RequestTag/elbv2.k8s.aws/cluster: 'false' 114 | - Effect: Allow 115 | Action: 116 | - elasticloadbalancing:CreateListener 117 | - elasticloadbalancing:DeleteListener 118 | - elasticloadbalancing:CreateRule 119 | - elasticloadbalancing:DeleteRule 120 | Resource: "*" 121 | - Effect: Allow 122 | Action: 123 | - elasticloadbalancing:AddTags 124 | - elasticloadbalancing:RemoveTags 125 | Resource: 126 | - arn:aws:elasticloadbalancing:*:*:targetgroup/*/* 127 | - arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/* 128 | - arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/* 129 | Condition: 130 | 'Null': 131 | aws:RequestTag/elbv2.k8s.aws/cluster: 'true' 132 | aws:ResourceTag/elbv2.k8s.aws/cluster: 'false' 133 | - Effect: Allow 134 | Action: 135 | - elasticloadbalancing:AddTags 136 | - elasticloadbalancing:RemoveTags 137 | Resource: 138 | - arn:aws:elasticloadbalancing:*:*:listener/net/*/*/* 139 | - arn:aws:elasticloadbalancing:*:*:listener/app/*/*/* 140 | - arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/* 141 | - arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/* 142 | - Effect: Allow 143 | Action: 144 | - elasticloadbalancing:ModifyLoadBalancerAttributes 145 | - elasticloadbalancing:SetIpAddressType 146 | - elasticloadbalancing:SetSecurityGroups 147 | - elasticloadbalancing:SetSubnets 148 | - elasticloadbalancing:DeleteLoadBalancer 149 | - elasticloadbalancing:ModifyTargetGroup 150 | - elasticloadbalancing:ModifyTargetGroupAttributes 151 | - elasticloadbalancing:DeleteTargetGroup 152 | Resource: "*" 153 | Condition: 154 | 'Null': 155 | aws:ResourceTag/elbv2.k8s.aws/cluster: 'false' 156 | - Effect: Allow 157 | Action: 158 | - elasticloadbalancing:RegisterTargets 159 | - elasticloadbalancing:DeregisterTargets 160 | Resource: arn:aws:elasticloadbalancing:*:*:targetgroup/*/* 161 | - Effect: Allow 162 | Action: 163 | - elasticloadbalancing:SetWebAcl 164 | - elasticloadbalancing:ModifyListener 165 | - elasticloadbalancing:AddListenerCertificates 166 | - elasticloadbalancing:RemoveListenerCertificates 167 | - elasticloadbalancing:ModifyRule 168 | Resource: "*" 169 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | ***Status:** Work-in-progress. Please create issues or pull requests if you have ideas for improvement.* 2 | 3 | # **Amazon EKS full automated deployment with Ansible** 4 | Example deployment of Amazon EKS using Ansible and Cloudformation. 5 | 6 | ## Summary 7 | This project demonstrates the deployment of an Amazon EKS cluster and basic services using Ansible and Amazon Cloudformation. The deployment is fully automated and will enable you to start learing and testing the elasticity and agility of AWS Services used with Kubernetes based microservice architectures. 8 | 9 | ## High-Level Architecture 10 | 11 | ![Architecture](./docs/architecture/EksExampleArchitectureDiagram.png) 12 | 13 | ## Disclaimer 14 | This project is an example of an deployment and meant to be used for testing and learning purposes only. Do not use in production. 15 | 16 | **Be aware that the deployment is not covered by the AWS free tier. Please use the [AWS pricing calculator](https://calculator.aws/#/estimate) to an estimation beforehand** 17 | 18 | # Table of Contents 19 | 20 | 1. [Getting started](#Getting-started) 21 | 2. [Prerequisites](#Prerequisites) 22 | 3. [Parameters](#Parameters) 23 | 4. [Templates](#Templates) 24 | 5. [Testing](#Testing) 25 | 6. [Resources](#Resources) 26 | 7. [Security](#Security) 27 | 8. [License](#License) 28 | 29 | # Getting started 30 | 31 | Just a few steps are needed to get started with the example deployment. 32 | the deployment process is seperated in a cluster deployment containing the creation of the Amazon EKS cluster itself and various cluster extensions and optional demo/example deployments to show the Amazon EKS cluster and the extensions in action. 33 | 34 | You may use the [deployment playbook](./eks-deploy-cluster.playbook.yaml) for the [automatic deployment](#automatic) of Amazon EKS via Ansible. To destroy/remove the Amazon EKS deployment from your AWS Account you can use the [destroy playbook](./eks-destroy-cluster.playbook.yaml). 35 | 36 | ## Prerequisites 37 | 38 | To run the Ansible based deployment you need to have some software installed and configured on your device: 39 | 40 | - bash (zsh, csh, sh should also work, not tesed though) 41 | - an [installed and configured ](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) aws-cli 42 | - [a named profile](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) at the aws-cli configuration reflecting the account you are planning to use for the deployment 43 | - [jq](https://stedolan.github.io/jq/) 44 | - a working [Ansible installation](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) 45 | - an install of the community kubernetes [Ansible module](https://github.com/ansible-collections/community.kubernetes) 46 | - some pip modules: botocore boto boto3 47 | 48 | For the DNS Automation to work you'll need to have a [Hosted Zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/AboutHZWorkingWith.html) setup at your AWS Account 49 | 50 | ## Parameters 51 | 52 | **Deployment parameters:** 53 | 54 | Some static deployment variables are to be altered/placed into the [vars/static/definitions.yaml](vars/static/definitions.yaml) 55 | 56 | | Parameter Name | Default Value | Description | Comment | 57 | | ---- | ---- | ---- | ---- | 58 | | eksexample_region | eu-central-1 | the region to be used for deployments | define the region to be used. Please be aware that the Amazon EKS on AWS Fargate used in some examples is not available in all [regions](https://docs.aws.amazon.com/eks/latest/userguide/fargate.html) 59 | | eksexample_worker_desiredcount | 2 | desired worker nodes to start with | 60 | | eksexample_worker_maxcount | 10 | maximum workers to be provisoned if scaling out the cluster | 61 | | eksexample_worker_mincount | 2 | minimum worker nodes | i recommend at least 2 | 62 | | eksexample_worker_instancetype | t3a.medium | instance size of the worker nodes | 63 | | eksexample_bastion_instancetype | t3a.small | instance size of the bastion host | 64 | | eksexample_clustername | ansible-eks-testcluster | name of the Amazon EKS cluster | 65 | | eksexample_clusterversion | 1.18 | version of the Amazon EKS cluster | versions <1.16 are not tested with this automation 66 | | eksexample_aws_profilename | ansible | the [profile name setup](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) for the local awscli | i recommend to setup a local profile. if you decide to shift it directly to instance_profile based EC2 admin instances, alter the ansible module parameters to not use "profile:" 67 | 68 | rename the [vars/static/custom_definitions.yaml](vars/static/custom_definitions.yaml.example) and alter the parameters according to your needs 69 | | Parameter Name | Default Value | Description | Comment | 70 | | ---- | ---- | ---- | ---- | 71 | | eksexample_hostedzoneid | | the ID of your Route53 Zone where the DNS automation should work on. | 72 | | eksexample_hostedzonename | | the Domainname of the Hosted Zone on Route53 | 73 | 74 | 75 | # Deployment 76 | 77 | The deployment will take approx 30-45 minutes. 78 | 79 | # Template structure and deployment workflow 80 | 81 | The Deployment consists of one main playbook triggering multible tasks, cloudformation templates and kubernetes manifests 82 | 83 | ## Playbooks 84 | 85 | - eks-deploy-cluster.playbook.yaml: this playbook starts the overall deployment of the Amazon EKS cluster and triggers also the deployment of all extensions. can be started with ansible-playbook ./eks-deploy-cluster.playbook.yaml 86 | - eks-destroy-cluster.playbook.yaml: this playbook destroys the whole deployment. If you deployed the example deployments into the cluster, make sure these get destroyed first using the ./docs/examples/destroy-examples.playbook.yaml playbook. 87 | - ./docs/examples/deploy-examples.playbook.yaml: this playbook will deploy some microservice and overall deployment examples to demonstrate the functionality of the extensions. 88 | - ./docs/examples/destroy-examples.playbook.yaml: will remove the example deployments from the cluster (but leaves the cluster intact) 89 | 90 | ## Tasks 91 | - acm.tasks.yaml: Sets up ACM and adds the validation Records into the defined Hosted Zone. 92 | - bastion.tasks.yaml: Sets up a Bastion Hosts used for the Amazon EKS deplyoment as well as all Kubernetes Deployments. Using the Bastion we'll not have to expose any ports/services of the Amazon EKS cluster backend to public internet. 93 | - eks-cluster.task.yaml: deploys the Amazon EKS cluster and enables the logging for the masterplane 94 | - eks-cluster-autoscaler.task.yaml: setup of the [cluster-autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 95 | - eks-container-insights.task.yaml: enable [container insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html) for the Amazon EKS cluster 96 | - eks-external-dns.task.yaml: setup of the Route53 automation via [external-dns](https://github.com/kubernetes-sigs/external-dns) 97 | - eks-ingress-controller.task.yaml: setup of the [aws-load-balancer-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller) to automate service exposure 98 | - eks-metrics-server.task.yaml: setup of the metrics server used by the [Horizontal Pod Autoscaler](https://kubernetes.io/de/docs/tasks/run-application/horizontal-pod-autoscale/) 99 | - eks-storage-provider-ebscsi.task.yaml: setup of the [Amazon Elastic Block Store (EBS) CSI driver](https://github.com/kubernetes-sigs/aws-ebs-csi-driver). The driver will ensure automatic provisioning of persistent block storage volumes for workloads 100 | - eks-storage-provider-efscsi.task.yaml: setup of the [Amazon EFS CSI driver](https://github.com/kubernetes-sigs/aws-efs-csi-driver). The driver will ensure automatic provisioning of persistent shared storage volumes for workloads 101 | - eks-xray.task.yaml: setup of the [X-Ray deamon setup](https://github.com/aws-samples/aws-xray-kubernetes) to trace application deployments 102 | 103 | ## Cloudformation Templates 104 | - eks-bastion.template.yaml 105 | - eks-cluster-autoscaler-iam.template.yaml: provisioning of the IAM Policy granting access for the cluster autoscaler to Amazon EC2 and EC2 Autoscaling groups. 106 | - eks-container-insights-iam.template.yaml: provisioning of the IAM Policy allowing Amazon Cloudwatch Access via the Worker Nodes 107 | - eks-external-dns-iam.template.yaml: provisioning of the IAM Policy granting access for the external-dns pods to Route53 108 | - eks-ingress-controller-iam.template.yaml: provisioning of the IAM Policy granting access for the aws-load-balancer-controller towards Elastic Load Balancing 109 | - eks-storage-provider-ebscsi-iam.template.yaml: IAM Policies to Allow EBS Access via the CSI Driver Deployment 110 | - eks-storage-provider-efscsi-storage.template.yaml: provisioning of the EFS FileSystem, Mountpoints and related Securitygroups 111 | 112 | ## Kubernetes Manifests 113 | 114 | All Manifests used for the Kubernetes Service and Application deployments are seperated into subfolders of either [./k8s/](./k8s) or [./docs/examples/k8s](./docs/examples/k8s) 115 | These Manifests are triggered using the community.kubernetes modules via the Ansible tasks. 116 | 117 | ## additional Files 118 | - [ansible.cfg](./ansible.cfg): contains some tweaks for the SSH connectivity, logging and so on. 119 | - ansible.log: will be written on each run but not checked into the git repo (-> [.gitignore](.gitignore) ) 120 | - [./vars/dynamic/*.yaml](./vars/dynamic): Variable files written by the playbooks. Contain information about SSL Arns and Bastion Host IP/Name Details. 121 | - [./secrets/id_rsa_eks](./secrets/id_rsa_eks): this file contains the private ssh key to log into the bastion host via SSH. this is used by the Ansible playbooks but may be also used by you to log into the bastion to do some testing. this file will not be checked into git (-> [.gitignore](.gitignore) ) 122 | --- 123 | # Testing 124 | 125 | When the deployment of the cluster is fullfilled you may test your setup. some useful commands to see what actually got deployed: 126 | 127 | first of all you should log into your bastion host. from there you will find a ready to use kubeconfig within [.kube/config](.kube/config) 128 | 129 | to see if nodes are there and your access to the Amazon EKS cluster is working type: 130 | ``` 131 | kubectl get nodes 132 | ``` 133 | 134 | should give you something like: 135 | ``` 136 | NAME STATUS ROLES AGE VERSION 137 | ip-192-168-43-140.eu-central-1.compute.internal Ready 15m v1.17.9-eks-4c6976 138 | ip-192-168-93-136.eu-central-1.compute.internal Ready 15m v1.17.9-eks-4c697 139 | ``` 140 | 141 | to see if the pods of the extensions are up and running you may use: 142 | ``` 143 | kubectl get pod -o=wide -n kube-system 144 | ``` 145 | 146 | which should show something like: 147 | ``` 148 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES 149 | aws-load-balancer-controller-7568799df8-pnch4 1/1 Running 0 7m30s 192.168.45.158 ip-192-168-43-140.eu-central-1.compute.internal 150 | aws-node-7vg6h 1/1 Running 0 17m 192.168.93.136 ip-192-168-93-136.eu-central-1.compute.internal 151 | aws-node-scl29 1/1 Running 0 17m 192.168.43.140 ip-192-168-43-140.eu-central-1.compute.internal 152 | cluster-autoscaler-7884f5ff6d-k6vpw 1/1 Running 0 8m44s 192.168.68.113 ip-192-168-93-136.eu-central-1.compute.internal 153 | coredns-5fdf64ff8-7m4bd 1/1 Running 0 21m 192.168.70.235 ip-192-168-93-136.eu-central-1.compute.internal 154 | coredns-5fdf64ff8-cnwlc 1/1 Running 0 21m 192.168.52.7 ip-192-168-43-140.eu-central-1.compute.internal 155 | ebs-csi-controller-668bbc964-2ttdt 4/4 Running 0 13m 192.168.88.219 ip-192-168-93-136.eu-central-1.compute.internal 156 | ebs-csi-controller-668bbc964-pt8n4 4/4 Running 0 13m 192.168.41.152 ip-192-168-43-140.eu-central-1.compute.internal 157 | ebs-csi-node-qq5r8 3/3 Running 0 13m 192.168.43.140 ip-192-168-43-140.eu-central-1.compute.internal 158 | ebs-csi-node-zsxs9 3/3 Running 0 13m 192.168.93.136 ip-192-168-93-136.eu-central-1.compute.internal 159 | ebs-snapshot-controller-0 1/1 Running 0 13m 192.168.32.10 ip-192-168-43-140.eu-central-1.compute.internal 160 | efs-csi-node-dzz5j 3/3 Running 0 11m 192.168.93.136 ip-192-168-93-136.eu-central-1.compute.internal 161 | ... 162 | ``` 163 | 164 | you can check if for instance the ingress-controller is working as expected using: 165 | ``` 166 | kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o alb-ingress[a-zA-Z0-9-]+) 167 | ``` 168 | 169 | if everything is cool it should look like: 170 | ``` 171 | ------------------------------------------------------------------------------- 172 | AWS ALB Ingress controller 173 | Release: v1.1.8 174 | Build: git-ec387ad1 175 | Repository: https://github.com/kubernetes-sigs/aws-load-balancer-controller.git 176 | ------------------------------------------------------------------------------- 177 | 178 | W0813 14:32:48.050307 1 client_config.go:549] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work. 179 | I0813 14:32:48.096117 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null}}} 180 | I0813 14:32:48.096518 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{},"status":{"loadBalancer":{}}}} 181 | I0813 14:32:48.096622 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"= 182 | I0813 14:32:48.096910 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{},"status":{"loadBalancer":{}}}} 183 | I0813 14:32:48.096963 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"= 184 | I0813 14:32:48.097188 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null}}} 185 | I0813 14:32:48.098011 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}} 186 | I0813 14:32:48.103658 1 controller.go:121] kubebuilder/controller "level"=0 "msg"="Starting EventSource" "controller"="aws-load-balancer-controller" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{"containers":null},"status":{}}} 187 | I0813 14:32:48.105447 1 leaderelection.go:205] attempting to acquire leader lease kube-system/ingress-controller-leader-alb... 188 | I0813 14:32:48.119414 1 leaderelection.go:214] successfully acquired lease kube-system/ingress-controller-leader-alb 189 | I0813 14:32:48.119775 1 recorder.go:53] kubebuilder/manager/events "level"=1 "msg"="Normal" "message"="aws-load-balancer-controller-7568799df8-pnch4_dc09d9d6-dd71-11ea-a82f-6e94ec7ac6f2 became leader" "object"={"kind":"ConfigMap","namespace":"kube-system","name":"ingress-controller-leader-alb","uid":"5e3275ce-3936-411a-9de5-4503c2223c8b","apiVersion":"v1","resourceVersion":"3156"} "reason"="LeaderElection" 190 | I0813 14:32:48.222253 1 controller.go:134] kubebuilder/controller "level"=0 "msg"="Starting Controller" "controller"="aws-load-balancer-controller" 191 | I0813 14:32:48.322547 1 controller.go:154] kubebuilder/controller "level"=0 "msg"="Starting workers" "controller"="aws-load-balancer-controller" "worker count"=1 192 | ``` 193 | if you replace *alb-ingress* with *external-dns* or *cluster-autoscaler* you can use the same command to get the logs of these extensions as well. 194 | 195 | ## Testing the example deployments 196 | 197 | if you deployed the example(s) via [./docs/examples/deploy-examples.playbook.yaml](./docs/examples/deploy-examples.playbook.yaml) you can check some neat details. 198 | 199 | to check the Horizontal Pod Autscaler coming with the example-microservice use: 200 | 201 | ``` 202 | watch -n 1 kubectl get hpa -n eksdemo 203 | ``` 204 | which will give you: 205 | ``` 206 | NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE 207 | eksdemo-crystal Deployment/eksdemo-crystal 1%/30% 2 10 1 17s 208 | eksdemo-frontend Deployment/eksdemo-frontend 3%/30% 2 10 0 14s 209 | eksdemo-nodejs Deployment/eksdemo-nodejs 2%/30% 2 10 1 20s 210 | ``` 211 | 212 | then open the test webpage using your browser of choise. the web address will be "https://eksdemo. + what you used for the variable "eksexample_hostedzonename" 213 | open the page on multiple tabs should generate some load you'll recordnize. 214 | you also can use for instance curl as a load generator 215 | 216 | ``` 217 | watch -n 0.1 curl -v https://eksdemo.example.com 218 | ``` 219 | 220 | There are many other things to try out. Feel free to share your ideas :) 221 | 222 | --- 223 | # Resources 224 | 225 | - AWS Services 226 | - [Amazon Cloudformation](https://aws.amazon.com/cloudformation/) 227 | - [Amazon EKS](https://aws.amazon.com/ec2/) 228 | - [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/) 229 | - [Amazon Cloudwatch](https://aws.amazon.com/cloudwatch/) 230 | - [Amazon Route53](https://aws.amazon.com/route53/) 231 | - [Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) 232 | - [Amazon EC2 Auto Scaling](https://aws.amazon.com/ec2/autoscaling/) 233 | - [Amazon Virtual Private Cloud](https://aws.amazon.com/vpc/) 234 | - [Amazon Elastic File Service](https://aws.amazon.com/efs/) 235 | 236 | - Open Source Projects 237 | - [Ansible](https://github.com/ansible/ansible) 238 | - [Kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) 239 | - [eksctl](https://github.com/weaveworks/eksctl) 240 | - [cluster-autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 241 | - [external-dns](https://github.com/kubernetes-sigs/external-dns) 242 | - [aws-load-balancer-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller) 243 | - [Horizontal Pod Autoscaler](https://kubernetes.io/de/docs/tasks/run-application/horizontal-pod-autoscale/) 244 | - [Amazon EFS CSI driver](https://github.com/kubernetes-sigs/aws-efs-csi-driver) 245 | - [Amazon Elastic Block Store (EBS) CSI driver](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) 246 | 247 | # Security 248 | 249 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 250 | 251 | # License 252 | 253 | This Example is licensed under the MIT-0 License. See the LICENSE file. 254 | 255 | Individual files may contain code by other authors under other 256 | licenses. See their license headers for details. --------------------------------------------------------------------------------