From 1db7fb091f717fbdb051c976c9c742ff3541551c Mon Sep 17 00:00:00 2001 From: gregharvey Date: Thu, 22 Jun 2023 17:26:05 +0200 Subject: [PATCH 01/15] Adding container push and build code. --- docs/_Sidebar.md | 1 + docs/roles/deploy_container.md | 28 +++++++++++ roles/deploy_container/README.md | 30 ++++++++++++ roles/deploy_container/defaults/main.yml | 15 ++++++ roles/deploy_container/tasks/main.yml | 49 +++++++++++++++++++ .../deploy_container/templates/Dockerfile.j2 | 7 +++ 6 files changed, 130 insertions(+) create mode 100644 docs/roles/deploy_container.md create mode 100644 roles/deploy_container/README.md create mode 100644 roles/deploy_container/defaults/main.yml create mode 100644 roles/deploy_container/tasks/main.yml create mode 100644 roles/deploy_container/templates/Dockerfile.j2 diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index 16139d8f..3d47469a 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -31,6 +31,7 @@ - [Data backups](/roles/database_backup) - [MySQL backups](/roles/database_backup/database_backup-mysql) - [Deploy](/roles/deploy_code) + - [Deploy container](/roles/deploy_container) - [Init](/roles/_init) - [LHCI run](/roles/lhci_run) - ["Meta"](/roles/_meta) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md new file mode 100644 index 00000000..46285580 --- /dev/null +++ b/docs/roles/deploy_container.md @@ -0,0 +1,28 @@ +# Deploy container +Step that deploys the codebase in a Docker container image. + + + + + +## Default variables +```yaml +--- +deploy_container: + container_name: "example/example" + container_tag: latest # tag will take format container_name:container_tag + docker_registry_url: https://index.docker.io/v1/ + docker_registry_user: example + docker_registry_pass: asdf1234 + docker_base_command: "docker image build" + docker_build_dir: "{{ _ce_deploy_build_dir }}" + environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template + # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached + aws_ecr: + enabled: false # set to true if using AWS ECR + region: eu-west-1 + profile: example + +``` + + diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md new file mode 100644 index 00000000..0647af50 --- /dev/null +++ b/roles/deploy_container/README.md @@ -0,0 +1,30 @@ +# Deploy container +Step that deploys the codebase in a Docker container image. Requires Docker and the `community.docker` collection for Ansible to be installed on your deploy server. This can be handled by [`ce-provision`](https://github.com/codeenigma/ce-provision) using the `ce_deploy` and `docker_ce` roles. + +AWS ECR registries require the AWS CLI user provided for `ce-deploy` to have the managed AWS `EC2InstanceProfileForImageBuilderECRContainerBuilds` policy attached via IAM to allow access to fetch credentials and push containers. + + + + + +## Default variables +```yaml +--- +deploy_container: + container_name: "example/example" + container_tag: latest # tag will take format container_name:container_tag + docker_registry_url: https://index.docker.io/v1/ + docker_registry_user: example + docker_registry_pass: asdf1234 + docker_base_command: "docker image build" + docker_build_dir: "{{ _ce_deploy_build_dir }}" + environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template + # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached + aws_ecr: + enabled: false # set to true if using AWS ECR + region: eu-west-1 + profile: example + +``` + + diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml new file mode 100644 index 00000000..4e4d30c3 --- /dev/null +++ b/roles/deploy_container/defaults/main.yml @@ -0,0 +1,15 @@ +--- +deploy_container: + container_name: "example/example" + container_tag: latest # tag will take format container_name:container_tag + docker_registry_url: https://index.docker.io/v1/ + docker_registry_user: example + docker_registry_pass: asdf1234 + docker_base_command: "docker image build" + docker_build_dir: "{{ _ce_deploy_build_dir }}" + environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template + # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached + aws_ecr: + enabled: false # set to true if using AWS ECR + region: eu-west-1 + profile: example diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml new file mode 100644 index 00000000..4eb9d87a --- /dev/null +++ b/roles/deploy_container/tasks/main.yml @@ -0,0 +1,49 @@ +--- +# @TODO - for AWS ECR we'll need certain policies attaching to the deploy IAM user +- name: Create Dockerfile from template. + local_action: + module: ansible.builtin.template + src: Dockerfile.j2 + dest: "{{ deploy_container.docker_build_dir }}/Dockerfile" + +- name: Set Docker registry username and password. + ansible.builtin.set_fact: + _docker_registry_username: "{{ deploy_container.docker_registry_user }}" + _docker_registry_password: "{{ deploy_container.docker_registry_pass }}" + +# Token valid for 12 hours +- name: Fetch AWS ECR registry login token. + ansible.builtin.command: + command: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.profile }}" + when: deploy_container.aws_ecr.enabled + register: _docker_registry_ecr_token + +- name: Set AWS ECR registry password. + ansible.builtin.set_fact: + _docker_registry_password: "{{ _docker_registry_ecr_token.stdout }}" + when: deploy_container.aws_ecr.enabled + +- name: Set AWS ECR registry username. + ansible.builtin.set_fact: + _docker_registry_username: "AWS" + when: deploy_container.aws_ecr.enabled + +- name: Log into Docker registry. + community.docker.docker_login: + registry_url: "{{ deploy_container.docker_registry_url }}" + username: "{{ _docker_registry_username }}" + password: "{{ _docker_registry_password }}" + reauthorize: true + delegate_to: localhost + when: deploy_container.docker_registry_login + +- name: Build and push container image. + community.docker.docker_image: + build: + path: "{{ deploy_container.docker_build_dir }}" + repository: "{{ deploy_container.docker_registry_url }}" + name: "{{ deploy_container.container_name }}" + tag: "{{ deploy_container.container_tag | default('latest') }}" + push: true + source: build + delegate_to: localhost diff --git a/roles/deploy_container/templates/Dockerfile.j2 b/roles/deploy_container/templates/Dockerfile.j2 new file mode 100644 index 00000000..d0f5e81c --- /dev/null +++ b/roles/deploy_container/templates/Dockerfile.j2 @@ -0,0 +1,7 @@ +# Basic Dockerfile example +FROM debian:bullseye-slim +MAINTAINER sysadm@codeenigma.com + +RUN apt-get update +RUN apt-get install –y nginx +CMD ["echo","Image created"] \ No newline at end of file From b45c182875d1984ae6c2f7d02fe5d783ea5971a1 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Thu, 22 Jun 2023 17:54:10 +0200 Subject: [PATCH 02/15] Fixing some minor issues. --- roles/deploy_container/tasks/main.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 4eb9d87a..37013df2 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -10,23 +10,27 @@ ansible.builtin.set_fact: _docker_registry_username: "{{ deploy_container.docker_registry_user }}" _docker_registry_password: "{{ deploy_container.docker_registry_pass }}" + delegate_to: localhost # Token valid for 12 hours - name: Fetch AWS ECR registry login token. ansible.builtin.command: - command: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.profile }}" + cmd: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.profile }}" when: deploy_container.aws_ecr.enabled + delegate_to: localhost register: _docker_registry_ecr_token - name: Set AWS ECR registry password. ansible.builtin.set_fact: _docker_registry_password: "{{ _docker_registry_ecr_token.stdout }}" when: deploy_container.aws_ecr.enabled + delegate_to: localhost - name: Set AWS ECR registry username. ansible.builtin.set_fact: _docker_registry_username: "AWS" when: deploy_container.aws_ecr.enabled + delegate_to: localhost - name: Log into Docker registry. community.docker.docker_login: @@ -35,7 +39,6 @@ password: "{{ _docker_registry_password }}" reauthorize: true delegate_to: localhost - when: deploy_container.docker_registry_login - name: Build and push container image. community.docker.docker_image: From 621176754b0be6bb4cd306f5b827c91dd53342a7 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Thu, 22 Jun 2023 18:11:39 +0200 Subject: [PATCH 03/15] Docs updates and template flexibility improvement. --- docs/roles/deploy_container.md | 12 +++++++++++- roles/deploy_container/README.md | 10 +++++++++- roles/deploy_container/defaults/main.yml | 1 + roles/deploy_container/tasks/main.yml | 2 +- .../templates/{Dockerfile.j2 => example.j2} | 2 +- 5 files changed, 23 insertions(+), 4 deletions(-) rename roles/deploy_container/templates/{Dockerfile.j2 => example.j2} (80%) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index 46285580..e34d028c 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -1,5 +1,14 @@ # Deploy container -Step that deploys the codebase in a Docker container image. +Step that deploys the codebase in a Docker container image. Requires Docker and the `community.docker` collection for Ansible to be installed on your deploy server. You will also need to add a `docker` group and make sure your local deploy user is in that group, for example: + +``` +sudo groupadd docker +sudo usermod -aG docker deploy +``` + +This can be handled automatically by [`ce-provision`](https://github.com/codeenigma/ce-provision) using the `ce_deploy` and `docker_ce` roles. + +AWS ECR registries require the AWS CLI user provided for `ce-deploy` to have the managed AWS `EC2InstanceProfileForImageBuilderECRContainerBuilds` policy attached via IAM to allow access to fetch credentials and push containers. @@ -16,6 +25,7 @@ deploy_container: docker_registry_pass: asdf1234 docker_base_command: "docker image build" docker_build_dir: "{{ _ce_deploy_build_dir }}" + dockerfile_template: example.j2 # provide a templates directory next to your playbook and change this to match your Dockerfile template name environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached aws_ecr: diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index 0647af50..e34d028c 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -1,5 +1,12 @@ # Deploy container -Step that deploys the codebase in a Docker container image. Requires Docker and the `community.docker` collection for Ansible to be installed on your deploy server. This can be handled by [`ce-provision`](https://github.com/codeenigma/ce-provision) using the `ce_deploy` and `docker_ce` roles. +Step that deploys the codebase in a Docker container image. Requires Docker and the `community.docker` collection for Ansible to be installed on your deploy server. You will also need to add a `docker` group and make sure your local deploy user is in that group, for example: + +``` +sudo groupadd docker +sudo usermod -aG docker deploy +``` + +This can be handled automatically by [`ce-provision`](https://github.com/codeenigma/ce-provision) using the `ce_deploy` and `docker_ce` roles. AWS ECR registries require the AWS CLI user provided for `ce-deploy` to have the managed AWS `EC2InstanceProfileForImageBuilderECRContainerBuilds` policy attached via IAM to allow access to fetch credentials and push containers. @@ -18,6 +25,7 @@ deploy_container: docker_registry_pass: asdf1234 docker_base_command: "docker image build" docker_build_dir: "{{ _ce_deploy_build_dir }}" + dockerfile_template: example.j2 # provide a templates directory next to your playbook and change this to match your Dockerfile template name environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached aws_ecr: diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 4e4d30c3..8b1e8e69 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -7,6 +7,7 @@ deploy_container: docker_registry_pass: asdf1234 docker_base_command: "docker image build" docker_build_dir: "{{ _ce_deploy_build_dir }}" + dockerfile_template: example.j2 # provide a templates directory next to your playbook and change this to match your Dockerfile template name environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached aws_ecr: diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 37013df2..2b037a40 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -3,7 +3,7 @@ - name: Create Dockerfile from template. local_action: module: ansible.builtin.template - src: Dockerfile.j2 + src: "{{ deploy_container.dockerfile_template }}" dest: "{{ deploy_container.docker_build_dir }}/Dockerfile" - name: Set Docker registry username and password. diff --git a/roles/deploy_container/templates/Dockerfile.j2 b/roles/deploy_container/templates/example.j2 similarity index 80% rename from roles/deploy_container/templates/Dockerfile.j2 rename to roles/deploy_container/templates/example.j2 index d0f5e81c..5a155197 100644 --- a/roles/deploy_container/templates/Dockerfile.j2 +++ b/roles/deploy_container/templates/example.j2 @@ -3,5 +3,5 @@ FROM debian:bullseye-slim MAINTAINER sysadm@codeenigma.com RUN apt-get update -RUN apt-get install –y nginx +RUN apt-get install -y nginx CMD ["echo","Image created"] \ No newline at end of file From 3eecd60fd7e5e9109ac83dcba0a55cd194e05a3e Mon Sep 17 00:00:00 2001 From: gregharvey Date: Thu, 22 Jun 2023 18:20:07 +0200 Subject: [PATCH 04/15] Creating separate registry name for handling docker push. --- roles/deploy_container/defaults/main.yml | 1 + roles/deploy_container/tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 8b1e8e69..77fedec4 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -2,6 +2,7 @@ deploy_container: container_name: "example/example" container_tag: latest # tag will take format container_name:container_tag + docker_registry_name: index.docker.io docker_registry_url: https://index.docker.io/v1/ docker_registry_user: example docker_registry_pass: asdf1234 diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 2b037a40..f8984bcc 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -44,7 +44,7 @@ community.docker.docker_image: build: path: "{{ deploy_container.docker_build_dir }}" - repository: "{{ deploy_container.docker_registry_url }}" + repository: "{{ deploy_container.docker_registry_name }}" name: "{{ deploy_container.container_name }}" tag: "{{ deploy_container.container_tag | default('latest') }}" push: true From a7948552f6df758182022f2acd6b9a12688b2db7 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Thu, 22 Jun 2023 18:33:24 +0200 Subject: [PATCH 05/15] Trying to get the registry name right. --- docs/roles/deploy_container.md | 4 ++-- roles/deploy_container/README.md | 4 ++-- roles/deploy_container/defaults/main.yml | 5 ++--- roles/deploy_container/tasks/main.yml | 3 +-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index e34d028c..9730b01e 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -18,9 +18,9 @@ AWS ECR registries require the AWS CLI user provided for `ce-deploy` to have the ```yaml --- deploy_container: - container_name: "example/example" + container_name: example container_tag: latest # tag will take format container_name:container_tag - docker_registry_url: https://index.docker.io/v1/ + docker_registry_name: index.docker.io/example # combines with container_name to make the full registry name, docker_registry_name/container_name docker_registry_user: example docker_registry_pass: asdf1234 docker_base_command: "docker image build" diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index e34d028c..9730b01e 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -18,9 +18,9 @@ AWS ECR registries require the AWS CLI user provided for `ce-deploy` to have the ```yaml --- deploy_container: - container_name: "example/example" + container_name: example container_tag: latest # tag will take format container_name:container_tag - docker_registry_url: https://index.docker.io/v1/ + docker_registry_name: index.docker.io/example # combines with container_name to make the full registry name, docker_registry_name/container_name docker_registry_user: example docker_registry_pass: asdf1234 docker_base_command: "docker image build" diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 77fedec4..3578e12a 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -1,9 +1,8 @@ --- deploy_container: - container_name: "example/example" + container_name: example container_tag: latest # tag will take format container_name:container_tag - docker_registry_name: index.docker.io - docker_registry_url: https://index.docker.io/v1/ + docker_registry_name: index.docker.io/example # combines with container_name to make the full registry name, docker_registry_name/container_name docker_registry_user: example docker_registry_pass: asdf1234 docker_base_command: "docker image build" diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index f8984bcc..c58bb8b1 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -44,8 +44,7 @@ community.docker.docker_image: build: path: "{{ deploy_container.docker_build_dir }}" - repository: "{{ deploy_container.docker_registry_name }}" - name: "{{ deploy_container.container_name }}" + name: "{{ deploy_container.docker_registry_name }}/{{ deploy_container.container_name }}" tag: "{{ deploy_container.container_tag | default('latest') }}" push: true source: build From 6c6db266edf776558533fefd26ad3a273f94d36a Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 12:46:16 +0200 Subject: [PATCH 06/15] Adding AWS stack components to ECS builds. --- docs/roles/deploy_container.md | 64 ++++- roles/deploy_container/README.md | 64 ++++- roles/deploy_container/defaults/main.yml | 64 ++++- roles/deploy_container/tasks/main.yml | 297 ++++++++++++++++++++++- roles/deploy_container/tasks/subnet.yml | 13 + 5 files changed, 495 insertions(+), 7 deletions(-) create mode 100644 roles/deploy_container/tasks/subnet.yml diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index 9730b01e..0e4fe6fc 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -31,7 +31,69 @@ deploy_container: aws_ecr: enabled: false # set to true if using AWS ECR region: eu-west-1 - profile: example + aws_profile: example + # Requires the deploy IAM user to have the managed AmazonECS_FullAccess and ElasticLoadBalancingFullAccess policies attached + # Note, you can if you wish make more restrictive roles and policies + aws_ecs: + enabled: false + region: eu-west-1 + aws_profile: example + tags: {} + domain_name: www.example.com + route_53: + zone: example.com + aws_profile: example2 # might not be the same account + vpc_name: example + #vpc_id: vpc-XXXXXXX # optionally specify VPC ID to use + subnets: # list of public subnet names + - example-dev-a + - example-dev-b + security_groups: [] # list of security groups, accepts names or IDs + cluster_name: example + family_name: example + task_definition_revision: "" # integer, but must be presented as a string for Jinja2 + task_count: 1 + task_minimum_count: 1 + task_maximum_count: 4 + # See docs for values: https://docs.aws.amazon.com/autoscaling/application/APIReference/API_TargetTrackingScalingPolicyConfiguration.html + service_autoscale_metric_type: ECSServiceAverageCPUUtilization + service_autoscale_up_cooldown: 120 + service_autoscale_down_cooldown: 120 + service_autoscale_target_value: 70 # the value to trigger a scaling event at + service_elb_container_name: example # the name of the container to be load balanced + execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable + containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers + #cpu: 512 # these values can be set globally or per container + #memory: 1024 + launch_type: FARGATE + network_mode: awsvpc + #volumes: [] # list of additional volumes to attach + target_group_name: example # 32 character limit + target_group_protocol: http + target_group_port: 80 + targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service + #- Id: 10.0.0.2 + # Port: 80 + # AvailabilityZone: all + health_check: + protocol: http + path: / + response_codes: "200" + # Requires the deploy IAM user to have the managed AWSCertificateManagerFullAccess and AmazonRoute53FullAccess policies attached + acm: # see https://github.com/codeenigma/ce-provision/tree/1.x/roles/aws/aws_acm + create_cert: false + extra_domains: [] # list of Subject Alternative Name domains and zones + ssl_certificate_ARN: "" # optional SSL cert ARN if you imported one into AWS Certificate Manager + elb_security_groups: [] # default SG is used if none provided - module supports names or IDs + elb_http_port: 80 + elb_https_port: 443 + elb_ssl_policy: ELBSecurityPolicy-TLS13-1-2-2021-06 # see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies + elb_listener_http_rules: [] + elb_listener_https_rules: [] + # Add custom listeners. See https://docs.ansible.com/ansible/latest/collections/amazon/aws/elb_application_lb_module.html + elb_listeners: [] + elb_idle_timeout: 60 + elb_ip_address_type: "ipv4" # Can be 'ipv4' or 'dualstack' (the latter includes IPv4 and IPv6 addresses). ``` diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index 9730b01e..0e4fe6fc 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -31,7 +31,69 @@ deploy_container: aws_ecr: enabled: false # set to true if using AWS ECR region: eu-west-1 - profile: example + aws_profile: example + # Requires the deploy IAM user to have the managed AmazonECS_FullAccess and ElasticLoadBalancingFullAccess policies attached + # Note, you can if you wish make more restrictive roles and policies + aws_ecs: + enabled: false + region: eu-west-1 + aws_profile: example + tags: {} + domain_name: www.example.com + route_53: + zone: example.com + aws_profile: example2 # might not be the same account + vpc_name: example + #vpc_id: vpc-XXXXXXX # optionally specify VPC ID to use + subnets: # list of public subnet names + - example-dev-a + - example-dev-b + security_groups: [] # list of security groups, accepts names or IDs + cluster_name: example + family_name: example + task_definition_revision: "" # integer, but must be presented as a string for Jinja2 + task_count: 1 + task_minimum_count: 1 + task_maximum_count: 4 + # See docs for values: https://docs.aws.amazon.com/autoscaling/application/APIReference/API_TargetTrackingScalingPolicyConfiguration.html + service_autoscale_metric_type: ECSServiceAverageCPUUtilization + service_autoscale_up_cooldown: 120 + service_autoscale_down_cooldown: 120 + service_autoscale_target_value: 70 # the value to trigger a scaling event at + service_elb_container_name: example # the name of the container to be load balanced + execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable + containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers + #cpu: 512 # these values can be set globally or per container + #memory: 1024 + launch_type: FARGATE + network_mode: awsvpc + #volumes: [] # list of additional volumes to attach + target_group_name: example # 32 character limit + target_group_protocol: http + target_group_port: 80 + targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service + #- Id: 10.0.0.2 + # Port: 80 + # AvailabilityZone: all + health_check: + protocol: http + path: / + response_codes: "200" + # Requires the deploy IAM user to have the managed AWSCertificateManagerFullAccess and AmazonRoute53FullAccess policies attached + acm: # see https://github.com/codeenigma/ce-provision/tree/1.x/roles/aws/aws_acm + create_cert: false + extra_domains: [] # list of Subject Alternative Name domains and zones + ssl_certificate_ARN: "" # optional SSL cert ARN if you imported one into AWS Certificate Manager + elb_security_groups: [] # default SG is used if none provided - module supports names or IDs + elb_http_port: 80 + elb_https_port: 443 + elb_ssl_policy: ELBSecurityPolicy-TLS13-1-2-2021-06 # see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies + elb_listener_http_rules: [] + elb_listener_https_rules: [] + # Add custom listeners. See https://docs.ansible.com/ansible/latest/collections/amazon/aws/elb_application_lb_module.html + elb_listeners: [] + elb_idle_timeout: 60 + elb_ip_address_type: "ipv4" # Can be 'ipv4' or 'dualstack' (the latter includes IPv4 and IPv6 addresses). ``` diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 3578e12a..d84b0d72 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -13,4 +13,66 @@ deploy_container: aws_ecr: enabled: false # set to true if using AWS ECR region: eu-west-1 - profile: example + aws_profile: example + # Requires the deploy IAM user to have the managed AmazonECS_FullAccess and ElasticLoadBalancingFullAccess policies attached + # Note, you can if you wish make more restrictive roles and policies + aws_ecs: + enabled: false + region: eu-west-1 + aws_profile: example + tags: {} + domain_name: www.example.com + route_53: + zone: example.com + aws_profile: example2 # might not be the same account + vpc_name: example + #vpc_id: vpc-XXXXXXX # optionally specify VPC ID to use + subnets: # list of public subnet names + - example-dev-a + - example-dev-b + security_groups: [] # list of security groups, accepts names or IDs + cluster_name: example + family_name: example + task_definition_revision: "" # integer, but must be presented as a string for Jinja2 + task_count: 1 + task_minimum_count: 1 + task_maximum_count: 4 + # See docs for values: https://docs.aws.amazon.com/autoscaling/application/APIReference/API_TargetTrackingScalingPolicyConfiguration.html + service_autoscale_metric_type: ECSServiceAverageCPUUtilization + service_autoscale_up_cooldown: 120 + service_autoscale_down_cooldown: 120 + service_autoscale_target_value: 70 # the value to trigger a scaling event at + service_elb_container_name: example # the name of the container to be load balanced + execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable + containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers + #cpu: 512 # these values can be set globally or per container + #memory: 1024 + launch_type: FARGATE + network_mode: awsvpc + #volumes: [] # list of additional volumes to attach + target_group_name: example # 32 character limit + target_group_protocol: http + target_group_port: 80 + targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service + #- Id: 10.0.0.2 + # Port: 80 + # AvailabilityZone: all + health_check: + protocol: http + path: / + response_codes: "200" + # Requires the deploy IAM user to have the managed AWSCertificateManagerFullAccess and AmazonRoute53FullAccess policies attached + acm: # see https://github.com/codeenigma/ce-provision/tree/1.x/roles/aws/aws_acm + create_cert: false + extra_domains: [] # list of Subject Alternative Name domains and zones + ssl_certificate_ARN: "" # optional SSL cert ARN if you imported one into AWS Certificate Manager + elb_security_groups: [] # default SG is used if none provided - module supports names or IDs + elb_http_port: 80 + elb_https_port: 443 + elb_ssl_policy: ELBSecurityPolicy-TLS13-1-2-2021-06 # see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies + elb_listener_http_rules: [] + elb_listener_https_rules: [] + # Add custom listeners. See https://docs.ansible.com/ansible/latest/collections/amazon/aws/elb_application_lb_module.html + elb_listeners: [] + elb_idle_timeout: 60 + elb_ip_address_type: "ipv4" # Can be 'ipv4' or 'dualstack' (the latter includes IPv4 and IPv6 addresses). diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index c58bb8b1..dd64309f 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -1,5 +1,5 @@ --- -# @TODO - for AWS ECR we'll need certain policies attaching to the deploy IAM user +# Build and ship a container image - name: Create Dockerfile from template. local_action: module: ansible.builtin.template @@ -12,10 +12,9 @@ _docker_registry_password: "{{ deploy_container.docker_registry_pass }}" delegate_to: localhost -# Token valid for 12 hours -- name: Fetch AWS ECR registry login token. +- name: Fetch AWS ECR registry login token. # token valid for 12 hours ansible.builtin.command: - cmd: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.profile }}" + cmd: "aws ecr get-login-password --region {{ deploy_container.aws_ecr.region }} --profile {{ deploy_container.aws_ecr.aws_profile }}" when: deploy_container.aws_ecr.enabled delegate_to: localhost register: _docker_registry_ecr_token @@ -49,3 +48,293 @@ push: true source: build delegate_to: localhost + +# Fetch the ACM role from ce-provision +- name: Ensure the aws_acm directory exists. + ansible.builtin.file: + path: "{{ _ce_deploy_base_dir }}/roles/aws_acm/{{ item }}" + state: directory + mode: '0755' + delegate_to: localhost + with_items: + - tasks + - defaults + +- name: Fetch the aws_acm files. + ansible.builtin.get_url: + url: "https://raw.githubusercontent.com/codeenigma/ce-provision/1.x/roles/aws/aws_acm/{{ item }}/main.yml" + dest: "{{ _ce_deploy_base_dir }}/roles/aws_acm/{{ item }}/main.yml" + delegate_to: localhost + with_items: + - tasks + - defaults + +- name: Fetch the aws_acm tasks. + ansible.builtin.get_url: + url: https://raw.githubusercontent.com/codeenigma/ce-provision/1.x/roles/aws/aws_acm/tasks/main.yml + dest: "{{ _ce_deploy_base_dir }}/roles/aws_acm/tasks/main.yml" + delegate_to: localhost + +# Gather all network information +- name: Gather VPC information. + amazon.aws.ec2_vpc_net_info: + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + region: "{{ deploy_container.aws_ecs.region }}" + filters: + "tag:Name": "{{ deploy_container.aws_ecs.vpc_name }}" + register: _aws_ecs_cluster_vpc + delegate_to: localhost + when: + - deploy_container.aws_ecs.enabled + - deploy_container.aws_ecs.vpc_name is defined + - deploy_container.aws_ecs.vpc_name | length > 0 + +- name: Set the VPC id from name. + ansible.builtin.set_fact: + _aws_ecs_cluster_vpc_id: "{{ _aws_ecs_cluster_vpc.vpcs[0].vpc_id }}" + when: + - deploy_container.aws_ecs.enabled + - deploy_container.aws_ecs.vpc_name is defined + - deploy_container.aws_ecs.vpc_name | length > 0 + +- name: Use provided VPC id. + ansible.builtin.set_fact: + _aws_ecs_cluster_vpc_id: "{{ deploy_container.aws_ecs.vpc_id }}" + when: + - deploy_container.aws_ecs.enabled + - (deploy_container.aws_ecs.vpc_name is not defined or deploy_container.aws_ecs.vpc_name | length < 0) + +- name: Reset subnets lists. + ansible.builtin.set_fact: + _aws_ecs_cluster_public_subnets_ids: [] + when: deploy_container.aws_ecs.enabled + +- name: Construct list of public subnet IDs. + ansible.builtin.include_tasks: subnet.yml + with_items: "{{ deploy_container.aws_ecs.subnets }}" + loop_control: + loop_var: subnet + when: deploy_container.aws_ecs.enabled + +# Construct AWS supporting assets +- name: Create task definition. + community.aws.ecs_taskdefinition: + region: "{{ deploy_container.aws_ecs.region }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + family: "{{ deploy_container.aws_ecs.family_name }}" + execution_role_arn: "{{ deploy_container.aws_ecs.execution_role_arn }}" + containers: "{{ deploy_container.aws_ecs.containers }}" + launch_type: "{{ deploy_container.aws_ecs.launch_type }}" + cpu: "{{ deploy_container.aws_ecs.cpu | default(omit) }}" + memory: "{{ deploy_container.aws_ecs.memory | default(omit) }}" + state: present + network_mode: "{{ deploy_container.aws_ecs.network_mode }}" + volumes: "{{ deploy_container.aws_ecs.volumes | default(omit) }}" + delegate_to: localhost + when: deploy_container.aws_ecs.enabled + +- name: Create a target group with IP address targets. + community.aws.elb_target_group: + region: "{{ deploy_container.aws_ecs.region }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + name: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" # 32 char limit + protocol: "{{ deploy_container.aws_ecs.target_group_protocol }}" + port: "{{ deploy_container.aws_ecs.target_group_port }}" + vpc_id: "{{ _aws_ecs_cluster_vpc_id }}" + health_check_protocol: "{{ deploy_container.aws_ecs.health_check.protocol }}" + health_check_path: "{{ deploy_container.aws_ecs.health_check.path }}" + successful_response_codes: "{{ deploy_container.aws_ecs.health_check.response_codes }}" + target_type: ip + targets: "{{ deploy_container.aws_ecs.targets }}" + state: present + wait_timeout: 200 + wait: true + register: _aws_ecs_target_group + delegate_to: localhost + when: deploy_container.aws_ecs.enabled + +- name: Create SSL certificate for load balancer. + ansible.builtin.include_role: + name: aws_acm + vars: + aws_acm: + export: false + domain_name: "{{ deploy_container.aws_ecs.domain_name }}" + extra_domains: "{{ deploy_container.aws_ecs.acm.extra_domains }}" + route_53: + aws_profile: "{{ deploy_container.aws_ecs.route_53.aws_profile }}" + zone: "{{ deploy_container.aws_ecs.route_53.zone }}" + when: + - deploy_container.aws_ecs.acm.create_cert + - deploy_container.aws_ecs.enabled + +- name: Default to provided SSL certificate ARN. + ansible.builtin.set_fact: + _ssl_certificate_ARN: "{{ deploy_container.aws_ecs.ssl_certificate_ARN }}" + when: deploy_container.aws_ecs.enabled + +- name: If provided, override SSL certificate ARN with the one received from ACM. + ansible.builtin.set_fact: + _ssl_certificate_ARN: "{{ aws_acm_certificate_arn }}" + when: + - deploy_container.aws_ecs.acm.create_cert + - deploy_container.aws_ecs.enabled + +- name: Define default ALB listeners. + ansible.builtin.set_fact: + _aws_ecs_cluster_listeners_http: + Protocol: HTTP + Port: "{{ deploy_container.aws_ecs.elb_http_port }}" + DefaultActions: + - Type: forward + TargetGroupName: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" + Rules: "{{ deploy_container.aws_ecs.elb_listener_http_rules }}" + _aws_ecs_cluster_listeners_redirect: + Protocol: HTTP + Port: "{{ deploy_container.aws_ecs.elb_http_port }}" + DefaultActions: + - Type: redirect + RedirectConfig: + Protocol: HTTPS + Host: "#{host}" + Query: "#{query}" + Path: "/#{path}" + Port: "{{ deploy_container.aws_ecs.elb_https_port }}" + StatusCode: HTTP_301 + _aws_ecs_cluster_listeners_https: + Protocol: HTTPS + Port: "{{ deploy_container.aws_ecs.elb_https_port }}" + SslPolicy: "{{ deploy_container.aws_ecs.elb_ssl_policy }}" + Certificates: + - CertificateArn: "{{ _ssl_certificate_ARN }}" + DefaultActions: + - Type: forward + TargetGroupName: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" + Rules: "{{ deploy_container.aws_ecs.elb_listener_https_rules }}" + when: deploy_container.aws_ecs.enabled + +- name: Add HTTP listeners. + ansible.builtin.set_fact: + _aws_ecs_cluster_listeners: "{{ [ _aws_ecs_cluster_listeners_http ] }}" + when: + - _ssl_certificate_ARN | length < 1 + - deploy_container.aws_ecs.enabled + +- name: Add HTTPS Listener. + ansible.builtin.set_fact: + _aws_ecs_cluster_listeners: "{{ [ _aws_ecs_cluster_listeners_redirect, _aws_ecs_cluster_listeners_https ] }}" + when: + - _ssl_certificate_ARN | length > 1 + - deploy_container.aws_ecs.enabled + +- name: Add custom Listeners. + ansible.builtin.set_fact: + _aws_ecs_cluster_listeners: "{{ _aws_ecs_cluster_listeners + deploy_container.aws_ecs.elb_listeners }}" + when: + - deploy_container.aws_ecs.elb_listeners is defined + - deploy_container.aws_ecs.elb_listeners | length + - deploy_container.aws_ecs.enabled + +- name: Create an ALB. + amazon.aws.elb_application_lb: + region: "{{ deploy_container.aws_ecs.region }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + name: "{{ deploy_container.aws_ecs.target_group_name | truncate(32, true, '', 0) }}" # 32 char limit + state: present + tags: "{{ deploy_container.aws_ecs.tags }}" + subnets: "{{ _aws_ecs_cluster_public_subnets_ids }}" + security_groups: "{{ deploy_container.aws_ecs.elb_security_groups }}" + listeners: "{{ _aws_ecs_cluster_listeners }}" + idle_timeout: "{{ deploy_container.aws_ecs.elb_idle_timeout }}" + ip_address_type: "{{ aws_elb.ip_address_type }}" + register: _aws_ecs_cluster_alb + delegate_to: localhost + when: deploy_container.aws_ecs.enabled + +- name: Set task definition name. + ansible.builtin.set_fact: + _aws_ecs_service_task_definition: "{{ deploy_container.aws_ecs.family_name }}" + when: deploy_container.aws_ecs.enabled + +- name: Set task definition revision if applicable. + ansible.builtin.set_fact: + _aws_ecs_service_task_definition: "{{ deploy_container.aws_ecs.family_name }}:{{ deploy_container.aws_ecs.task_definition_revision }}" + when: + - deploy_container.aws_ecs.task_definition_revision | length > 0 + - deploy_container.aws_ecs.enabled + +- name: Create ECS service. + community.aws.ecs_service: + region: "{{ deploy_container.aws_ecs.region }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + state: present + name: "{{ deploy_container.aws_ecs.family_name }}" + cluster: "{{ deploy_container.aws_ecs.cluster_name }}" + task_definition: "{{ _aws_ecs_service_task_definition }}" + desired_count: "{{ deploy_container.aws_ecs.task_count }}" + launch_type: "{{ deploy_container.aws_ecs.launch_type }}" + platform_version: LATEST + load_balancers: # see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LoadBalancer.html + - containerName: "{{ deploy_container.aws_ecs.service_elb_container_name }}" + containerPort: "{{ deploy_container.aws_ecs.target_group_port }}" + targetGroupArn: "{{ _aws_ecs_target_group.target_group_arn }}" + network_configuration: + subnets: "{{ _aws_ecs_cluster_public_subnets_ids }}" + security_groups: "{{ deploy_container.aws_ecs.security_groups }}" + assign_public_ip: true # must be true for now - details: https://stackoverflow.com/a/66802973 + tags: "{{ deploy_container.aws_ecs.tags }}" + wait: true + delegate_to: localhost + when: deploy_container.aws_ecs.enabled + +- name: Create target tracking scaling policy for ECS service. + community.aws.application_autoscaling_policy: + region: "{{ deploy_container.aws_ecs.region }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" + state: present + policy_name: "{{ deploy_container.aws_ecs.family_name }}" + service_namespace: ecs + resource_id: "service/{{ deploy_container.aws_ecs.cluster_name }}/{{ deploy_container.aws_ecs.family_name }}" + scalable_dimension: ecs:service:DesiredCount + minimum_tasks: "{{ deploy_container.aws_ecs.task_minimum_count }}" + maximum_tasks: "{{ deploy_container.aws_ecs.task_maximum_count }}" + policy_type: TargetTrackingScaling + target_tracking_scaling_policy_configuration: + PredefinedMetricSpecification: + PredefinedMetricType: "{{ deploy_container.aws_ecs.service_autoscale_metric_type }}" + ScaleInCooldown: "{{ deploy_container.aws_ecs.service_autoscale_up_cooldown }}" + ScaleOutCooldown: "{{ deploy_container.aws_ecs.service_autoscale_down_cooldown }}" + DisableScaleIn: false + TargetValue: "{{ deploy_container.aws_ecs.service_autoscale_target_value }}" + delegate_to: localhost + when: deploy_container.aws_ecs.enabled + +- name: Initialise the domains loop var with main domain entry DNS settings. + ansible.builtin.set_fact: + _aws_ecs_cluster_dns_all_domains: + - domain: "{{ deploy_container.aws_ecs.domain_name }}" + zone: "{{ deploy_container.aws_ecs.route_53.zone }}" + aws_profile: "{{ deploy_container.aws_ecs.route_53.aws_profile }}" + when: deploy_container.aws_ecs.enabled + +- name: Add extra_domains so we can loop through DNS records. + ansible.builtin.set_fact: + _aws_ecs_cluster_dns_all_domains: "{{ _aws_ecs_cluster_dns_all_domains + [{'domain': item.domain, 'zone': item.zone, 'aws_profile': item.aws_profile}] }}" + loop: "{{ deploy_container.aws_ecs.acm.extra_domains }}" + when: + - deploy_container.aws_ecs.acm.extra_domains | length > 0 + - deploy_container.aws_ecs.enabled + +- name: Add DNS records in Route 53. + amazon.aws.route53: + state: present + profile: "{{ item.aws_profile }}" + zone: "{{ item.zone }}" + record: "{{ item.domain }}" + type: CNAME + value: "{{ _aws_ecs_cluster_alb.dns_name }}" + overwrite: true + loop: "{{ _aws_ecs_cluster_dns_all_domains }}" + when: + - deploy_container.aws_ecs.route_53.zone | length > 0 + - deploy_container.aws_ecs.enabled \ No newline at end of file diff --git a/roles/deploy_container/tasks/subnet.yml b/roles/deploy_container/tasks/subnet.yml new file mode 100644 index 00000000..3cb3a06a --- /dev/null +++ b/roles/deploy_container/tasks/subnet.yml @@ -0,0 +1,13 @@ +- name: Gather public subnet information. + amazon.aws.ec2_vpc_subnet_info: + profile: "{{ deploy_container.aws_ecs.profile }}" + region: "{{ deploy_container.aws_ecs.region }}" + filters: + vpc-id: "{{ _aws_ecs_cluster_vpc_id }}" + tag:Name: "{{ subnet }}" + register: _aws_ecs_cluster_public_subnet + delegate_to: localhost + +- name: Add public subnet to the list. + ansible.builtin.set_fact: + _aws_ecs_cluster_public_subnets_ids: "{{ _aws_ecs_cluster_public_subnets_ids + [ _aws_ecs_cluster_public_subnet.subnets[0].subnet_id ] }}" From 21312cf9793c085a2e8485b76c05ab96f13fea61 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 13:11:56 +0200 Subject: [PATCH 07/15] Force a docker logout. --- roles/deploy_container/defaults/main.yml | 1 - roles/deploy_container/tasks/main.yml | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index d84b0d72..cee7ce12 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -42,7 +42,6 @@ deploy_container: service_autoscale_up_cooldown: 120 service_autoscale_down_cooldown: 120 service_autoscale_target_value: 70 # the value to trigger a scaling event at - service_elb_container_name: example # the name of the container to be load balanced execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers #cpu: 512 # these values can be set globally or per container diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index dd64309f..17f339be 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -31,6 +31,10 @@ when: deploy_container.aws_ecr.enabled delegate_to: localhost +- name: Log out of Docker registry to force a login. + community.docker.docker_login: + state: absent + - name: Log into Docker registry. community.docker.docker_login: registry_url: "{{ deploy_container.docker_registry_url }}" @@ -275,7 +279,7 @@ launch_type: "{{ deploy_container.aws_ecs.launch_type }}" platform_version: LATEST load_balancers: # see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LoadBalancer.html - - containerName: "{{ deploy_container.aws_ecs.service_elb_container_name }}" + - containerName: "{{ deploy_container.container_name }}" containerPort: "{{ deploy_container.aws_ecs.target_group_port }}" targetGroupArn: "{{ _aws_ecs_target_group.target_group_arn }}" network_configuration: From 9005d12d6ae34961de06b94da9aa048417510a5a Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 13:26:17 +0200 Subject: [PATCH 08/15] Need to delegate docker commands to the controller. --- docs/roles/deploy_container.md | 1 - roles/deploy_container/README.md | 1 - roles/deploy_container/tasks/main.yml | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index 0e4fe6fc..10292af6 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -60,7 +60,6 @@ deploy_container: service_autoscale_up_cooldown: 120 service_autoscale_down_cooldown: 120 service_autoscale_target_value: 70 # the value to trigger a scaling event at - service_elb_container_name: example # the name of the container to be load balanced execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers #cpu: 512 # these values can be set globally or per container diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index 0e4fe6fc..10292af6 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -60,7 +60,6 @@ deploy_container: service_autoscale_up_cooldown: 120 service_autoscale_down_cooldown: 120 service_autoscale_target_value: 70 # the value to trigger a scaling event at - service_elb_container_name: example # the name of the container to be load balanced execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers #cpu: 512 # these values can be set globally or per container diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 17f339be..05e1ffc0 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -34,6 +34,7 @@ - name: Log out of Docker registry to force a login. community.docker.docker_login: state: absent + delegate_to: localhost - name: Log into Docker registry. community.docker.docker_login: From a609bfb2e62a7b88cb627279b0021d9e4aadadff Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 13:31:07 +0200 Subject: [PATCH 09/15] Trying deleting the credentials file instead. --- roles/deploy_container/tasks/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 05e1ffc0..83cb959a 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -31,9 +31,10 @@ when: deploy_container.aws_ecr.enabled delegate_to: localhost -- name: Log out of Docker registry to force a login. - community.docker.docker_login: +- name: Remove Docker credentials file. + ansible.builtin.file: state: absent + path: "/home/{{ deploy_user }}/.docker/config.json" delegate_to: localhost - name: Log into Docker registry. From 5990127c29d61c7510731dbf240908f5f1220a6f Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 13:38:06 +0200 Subject: [PATCH 10/15] Fixing var name in subnet.yml. --- roles/deploy_container/tasks/subnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/deploy_container/tasks/subnet.yml b/roles/deploy_container/tasks/subnet.yml index 3cb3a06a..a0701a36 100644 --- a/roles/deploy_container/tasks/subnet.yml +++ b/roles/deploy_container/tasks/subnet.yml @@ -1,6 +1,6 @@ - name: Gather public subnet information. amazon.aws.ec2_vpc_subnet_info: - profile: "{{ deploy_container.aws_ecs.profile }}" + profile: "{{ deploy_container.aws_ecs.aws_profile }}" region: "{{ deploy_container.aws_ecs.region }}" filters: vpc-id: "{{ _aws_ecs_cluster_vpc_id }}" From 40b26871170f20da2c3ad1f0448a0b0fcb7b268e Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 13:51:08 +0200 Subject: [PATCH 11/15] Missing some ACM variables. --- roles/deploy_container/tasks/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 83cb959a..af1164eb 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -164,6 +164,9 @@ name: aws_acm vars: aws_acm: + region: "{{ deploy_container.aws_ecs.region }}" + aws_profile: "{{ deploy_container.aws_ecs.aws_profile }}" + tags: "{{ deploy_container.aws_ecs.tags }}" export: false domain_name: "{{ deploy_container.aws_ecs.domain_name }}" extra_domains: "{{ deploy_container.aws_ecs.acm.extra_domains }}" From d32257d068646ababd3d59031649a5e71e5d1305 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 16:35:00 +0200 Subject: [PATCH 12/15] Allowing us to set wait timeout for TG creation. --- docs/roles/deploy_container.md | 1 + roles/deploy_container/README.md | 1 + roles/deploy_container/defaults/main.yml | 1 + roles/deploy_container/tasks/main.yml | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index 10292af6..1ebaa80f 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -70,6 +70,7 @@ deploy_container: target_group_name: example # 32 character limit target_group_protocol: http target_group_port: 80 + target_group_wait_timeout: 200 # how long to wait for target group events to complete targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service #- Id: 10.0.0.2 # Port: 80 diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index 10292af6..1ebaa80f 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -70,6 +70,7 @@ deploy_container: target_group_name: example # 32 character limit target_group_protocol: http target_group_port: 80 + target_group_wait_timeout: 200 # how long to wait for target group events to complete targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service #- Id: 10.0.0.2 # Port: 80 diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index cee7ce12..00195f6a 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -52,6 +52,7 @@ deploy_container: target_group_name: example # 32 character limit target_group_protocol: http target_group_port: 80 + target_group_wait_timeout: 200 # how long to wait for target group events to complete targets: [] # typically we do not specify targets at this point, this will be handled automatically by the ECS service #- Id: 10.0.0.2 # Port: 80 diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index af1164eb..053e7ab9 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -153,7 +153,7 @@ target_type: ip targets: "{{ deploy_container.aws_ecs.targets }}" state: present - wait_timeout: 200 + wait_timeout: "{{ deploy_container.aws_ecs.target_group_wait_timeout }}" wait: true register: _aws_ecs_target_group delegate_to: localhost From 687ff1349556539331247ca94e6ceb2e3ebb9c5b Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 16:42:31 +0200 Subject: [PATCH 13/15] Uncommenting cpu and memory vars for ECS with Fargate. --- docs/roles/deploy_container.md | 4 ++-- roles/deploy_container/README.md | 4 ++-- roles/deploy_container/defaults/main.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/roles/deploy_container.md b/docs/roles/deploy_container.md index 1ebaa80f..d1befb03 100644 --- a/docs/roles/deploy_container.md +++ b/docs/roles/deploy_container.md @@ -62,8 +62,8 @@ deploy_container: service_autoscale_target_value: 70 # the value to trigger a scaling event at execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers - #cpu: 512 # these values can be set globally or per container - #memory: 1024 + cpu: 512 # these values can be set globally or per container + memory: 1024 launch_type: FARGATE network_mode: awsvpc #volumes: [] # list of additional volumes to attach diff --git a/roles/deploy_container/README.md b/roles/deploy_container/README.md index 1ebaa80f..d1befb03 100644 --- a/roles/deploy_container/README.md +++ b/roles/deploy_container/README.md @@ -62,8 +62,8 @@ deploy_container: service_autoscale_target_value: 70 # the value to trigger a scaling event at execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers - #cpu: 512 # these values can be set globally or per container - #memory: 1024 + cpu: 512 # these values can be set globally or per container + memory: 1024 launch_type: FARGATE network_mode: awsvpc #volumes: [] # list of additional volumes to attach diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 00195f6a..22380049 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -44,8 +44,8 @@ deploy_container: service_autoscale_target_value: 70 # the value to trigger a scaling event at execution_role_arn: "arn:aws:iam::000000000000:role/ecsTaskExecutionRole" # ARN of the IAM role to run the task as, must have access to the ECR repository if applicable containers: [] # list of container definitions, see docs: https://docs.ansible.com/ansible/latest/collections/community/aws/ecs_taskdefinition_module.html#parameter-containers - #cpu: 512 # these values can be set globally or per container - #memory: 1024 + cpu: 512 # these values can be set globally or per container + memory: 1024 launch_type: FARGATE network_mode: awsvpc #volumes: [] # list of additional volumes to attach From 3113716ca7c1e201f562b97ce088b68faf97b500 Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 16:53:04 +0200 Subject: [PATCH 14/15] Missed a variable in ELB creation. --- roles/deploy_container/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 053e7ab9..0fafdfc2 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -255,7 +255,7 @@ security_groups: "{{ deploy_container.aws_ecs.elb_security_groups }}" listeners: "{{ _aws_ecs_cluster_listeners }}" idle_timeout: "{{ deploy_container.aws_ecs.elb_idle_timeout }}" - ip_address_type: "{{ aws_elb.ip_address_type }}" + ip_address_type: "{{ deploy_container.aws_ecs.elb_ip_address_type }}" register: _aws_ecs_cluster_alb delegate_to: localhost when: deploy_container.aws_ecs.enabled From a78b57a6cc2ab47057ac57e9dfd538cbb11aadeb Mon Sep 17 00:00:00 2001 From: gregharvey Date: Tue, 27 Jun 2023 18:14:18 +0200 Subject: [PATCH 15/15] Couple of linting fixes. --- roles/deploy_container/defaults/main.yml | 2 +- roles/deploy_container/tasks/main.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/deploy_container/defaults/main.yml b/roles/deploy_container/defaults/main.yml index 22380049..77be7a6a 100644 --- a/roles/deploy_container/defaults/main.yml +++ b/roles/deploy_container/defaults/main.yml @@ -8,7 +8,7 @@ deploy_container: docker_base_command: "docker image build" docker_build_dir: "{{ _ce_deploy_build_dir }}" dockerfile_template: example.j2 # provide a templates directory next to your playbook and change this to match your Dockerfile template name - environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template + environment_vars: {} # dictionary you can populate for use in a custom Dockerfile template # Requires the deploy IAM user to have the managed EC2InstanceProfileForImageBuilderECRContainerBuilds policy attached aws_ecr: enabled: false # set to true if using AWS ECR diff --git a/roles/deploy_container/tasks/main.yml b/roles/deploy_container/tasks/main.yml index 0fafdfc2..23f4d996 100644 --- a/roles/deploy_container/tasks/main.yml +++ b/roles/deploy_container/tasks/main.yml @@ -1,10 +1,10 @@ --- # Build and ship a container image - name: Create Dockerfile from template. - local_action: - module: ansible.builtin.template + ansible.builtin.template: src: "{{ deploy_container.dockerfile_template }}" dest: "{{ deploy_container.docker_build_dir }}/Dockerfile" + delegate_to: localhost - name: Set Docker registry username and password. ansible.builtin.set_fact: