Aws beanstalk docker ecs amazon linux 2023

  • December 6, 2024
  • 144

Tìm hiểu các bước để build server sử dụng aws beanstalk docker ecs amazon linux 2023. Build server với beanstalk giúp tiết kiệm thời gian, dễ dàng nâng cấp và bảo trì cho hệ thống của bạn.

1. Create beanstalk env

Truy cập vào service beanstalk trên aws, tạo một môi trường để chạy ứng dụng web hoặc worker, flatform sử dụng là docker, sử dụng ecs 2023, sau đó cấu hình các thông tin cần thiết cho server của bạn. Chúng ta sẽ sử dụng docker để chạy application.
aws beanstalk

2. Define docker container

Định nghĩa các container sử dụng để chạy các service của bạn trong file Dockerrun.aws.json để trong thư mục root.


{
  "AWSEBDockerrunVersion": 2,
  "volumes": [
    {
      "name": "app",
      "host": {
        "sourcePath": "/var/app/current/app"
      }
    },
    {
      "name": "nginx-proxy-conf",
      "host": {
        "sourcePath": "/var/app/current/docker/nginx/dev/conf.d"
      }
    },
    {
      "name": "app-logs",
      "host": {
        "sourcePath": "/var/app/support/logs"
      }
    },
    {
      "name": "supervisord-conf",
      "host": {
        "sourcePath": "/var/app/current/docker/phpfpm/supervisord-app.ini"
      }
    },
    {
      "name": "app2",
      "host": {
        "sourcePath": "/var/app/current/app2"
      }
    },
    {
      "name": "app2-logs",
      "host": {
        "sourcePath": "/var/app2/support/logs"
      }
    },
  ],
  "containerDefinitions": [
    {
      "name": "app",
      "image": "AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION",
      "essential": true,
      "memory": 256,
      "mountPoints": [
        {
          "sourceVolume": "app",
          "containerPath": "/var/www/html/app"
        },
        {
          "sourceVolume": "app-logs",
          "containerPath": "/var/www/html/app/logs"
        },
        {
          "sourceVolume": "supervisord-conf",
          "containerPath": "/etc/supervisor.d/supervisord.ini",
          "readOnly": true
        }
      ]
    },
    {
      "name": "app2",
      "image": "AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME_APP2_DOCKER_VERSION",
      "essential": false,
      "memory": 256,
      "mountPoints": [
        {
          "sourceVolume": "app2",
          "containerPath": "/var/www/html/app2"
        },
        {
          "sourceVolume": "app2-logs",
          "containerPath": "/var/www/html/app2/logs"
        }
      ]
    },
    {
      "name": "nginx-proxy",
      "image": "nginx:1.19.2-alpine",
      "essential": true,
      "memory": 128,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80
        },
        {
          "hostPort": 81,
          "containerPort": 81
        }
      ],
      "links": [
        "app",
        "app2",
      ],
      "mountPoints": [
        {
          "sourceVolume": "app",
          "containerPath": "/var/www/html/app"
        },
        {
          "sourceVolume": "app2",
          "containerPath": "/var/www/html/app2"
        },
        {
          "sourceVolume": "awseb-logs-nginx-proxy",
          "containerPath": "/var/log/nginx"
        },
        {
          "sourceVolume": "nginx-proxy-conf",
          "containerPath": "/etc/nginx/conf.d"
        }
      ]
    }
  ]
}

Tài liệu tham khảo:

https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_v2config.html

3. Config global

Tạo file config global config.global.yml


global:
  application_name: APPLICATIONNAME
  default_region: APPLICATION_REGION

4. Config extentions

Tạo các config cho elastic beanstalk trong thư mục .ebextensions

4.1 Create loadbalancer

Tạo config cho load balancer trong file .ebextensions/00.network-load-balancer.config


Resources:
  AWSEBV2LoadBalancer:
    Properties:
      LoadBalancerAttributes:
        - Key: idle_timeout.timeout_seconds
          Value: 600
    Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
  AWSEBV2LoadBalancerTargetGroup:
    Properties:
      TargetGroupAttributes:
        - Key: stickiness.enabled
          Value: true
    Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'


option_settings:
  aws:elasticbeanstalk:environment:process:default:
    DeregistrationDelay: '20'
    HealthCheckInterval: '30'
    HealthCheckPath: /health.html
    HealthCheckTimeout: '5'
    HealthyThresholdCount: '3'
    UnhealthyThresholdCount: '5'
    Port: '80'
    Protocol: HTTP
    StickinessEnabled: 'true'
    StickinessLBCookieDuration: '43200'

Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-alb.html

4.2 Create targer groups

Config target group trong file .ebextensions/00.target-group.config


option_settings:
  # Define the app 2 process listening on port 81
  aws:elb:listener:81:
    ListenerProtocol: HTTP
    InstanceProtocol: HTTP
    InstancePort: 81
    Rules: app2
  aws:elasticbeanstalk:environment:process:app2:
    HealthCheckPath: /
    Port: '81'
    Protocol: HTTP
    StickinessEnabled: true
    StickinessLBCookieDuration: 86400
  aws:elbv2:listenerrule:app2:
    HostHeaders: app2.com
    Priority: 2
    Process: app2

Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-alb.html

4.3 Config crontab

Kiểm tra crontab trong khi deploy, nếu trong quá trình deploy có crontab đang chạy thì chờ chạy xong rồi mới deploy

. Tạo file .ebextensions/02.crontab.config


container_commands:
  65_01_wait_for_php_cli_not_running:
    command: |
      # Retrieve the Docker container ID of the PHP image running in the instance
      # Use the image identifier in the form of `AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/IMAGE_NAME:IMAGE_VERSION`
      CONTAINER_ID=`docker ps -q --filter 'ancestor=AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION'`

      # If no container ID is found (e.g., during the first deployment), assume no PHP processes are running and exit successfully
      if [ -z "${CONTAINER_ID}" ]; then
        exit 0
      fi

      # Backup the current crontab for the webapp user in case it needs to be restored later
      crontab -u webapp -l > .crontab || true

      # Remove the existing crontab for the webapp user to avoid deployment conflicts
      # This will be reconfigured in other container commands
      crontab -u webapp -r || true

      # Wait for any PHP CLI processes to stop running in the container
      # Retry with increasing intervals (1, 1, 5, 10, 20, 30, 60, 100 seconds)
      for interval in 1 1 5 10 20 30 60 100; do
        # Check if any PHP processes are running using `pidof php`
        # `pidof` exits with code 0 if a process is found, otherwise with code 1
        docker exec $CONTAINER_ID bash -c "pidof php > /dev/null 2>&1"
        if [ "$?" != "0" ]; then
          # If no PHP processes are found, exit successfully
          exit 0
        fi
        # Wait for the specified interval before retrying
        sleep $interval
      done

      # If PHP processes are still running after all retries, restore the original crontab and exit with an error
      echo "Error: PHP CLI processes are still running!"
      crontab -u webapp .crontab
      exit 1
    test: "[ \"${INSTANCE_TYPE}\"x = \"workerx\" ]"

  65_02_cronjob:
    command: |
      # Copy the environment-specific crontab file to the default crontab location
      cp $CRONTAB app/config/crontabs/crontab.default
    env:
      # Define the path to the crontab file based on the current Elastic Beanstalk environment name
      CRONTAB: "app/config/crontabs/crontab.`{ \"Ref\" : \"AWSEBEnvironmentName\" }`"
    test: "[ -f $CRONTAB ]"  # Run only if the specified crontab file exists

4.4 Config clound watch

Config clound watch để quản lý log cho ứng dụng. Tạo file .ebextensions/03.cloundwatch.config


packages:
  yum:
    amazon-cloudwatch-agent: []

option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false

files:
  "/etc/awslogs/awscli.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [plugins]
      cwlogs = cwlogs
      [default]
      region = ap-southeast-1
  "/opt/aws/amazon-cloudwatch-agent/etc/cloudwatch.json" :
    mode: "0644"
    owner: root
    group: root
    content: |
      {
        "logs": {
          "logs_collected": {
            "files": {
              "collect_list": [
                {
                  "file_path": "/var/log/containers/nginx-proxy/access.log",
                  "auto_removal": true,
                  "log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "nginx"]]}`",
                  "log_stream_name": "{instance_id}_access.log"
                },
                {
                  "file_path": "/var/log/containers/nginx-proxy/error.log",
                  "auto_removal": true,
                  "log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "nginx"]]}`",
                  "log_stream_name": "{instance_id}_error.log"
                },
                {
                  "file_path": "/var/app/support/logs/**.log",
                  "auto_removal": true,
                  "log_group_name": "`{"Fn::Join":["-", [{ "Ref":"AWSEBEnvironmentName" }, "app"]]}`",
                  "log_stream_name": "{instance_id}_pm-app.log"
                }
              ]
            }
          }
        }
      }

container_commands:
  01:
    command: "sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/cloudwatch.json"
  02:
    command: "sudo systemctl enable amazon-cloudwatch-agent.service"
  03:
    command: "sudo systemctl restart amazon-cloudwatch-agent"

Tài liệu tham khảo:
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html

5. Migrate database and set permission

Khi chạy xong ứng dụng chúng ta cần migrate database và set quyền cho thư mục code. Tạo file set permission .platform/hooks/postdeploy/01_set_permissions.sh


#!/usr/bin/env bash

for dir in \
    /var/app/current/app/logs \
    /var/app2/support/logs \
    /var/app/current/app/tmp \
    /var/log/eb-docker/containers/app
do
    [ ! -d "$dir" ] && mkdir -p $dir
    chmod -R 777 $dir
done

Tạo file migrate database .platform/hooks/postdeploy/02_migrations.sh


#!/usr/bin/env bash

docker ps
DOCKER_PHP_ID=`docker ps -q --filter 'ancestor=AWS_ACCOUNT_ID.dkr.ecr.AWS_DEFAULT_REGION.amazonaws.com/DOCKER_IMAGE_NAME:DOCKER_IMAGE_VERSION'`
echo "Docker id: $DOCKER_PHP_ID"
docker exec -i $DOCKER_PHP_ID chown -R www-data:www-data ./
docker exec -i $DOCKER_PHP_ID chmod -R 777 logs
docker exec -i $DOCKER_PHP_ID composer install --no-interaction --prefer-dist --optimize-autoloader
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate -p LoginAttempts --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake migrations migrate -p Queue --no-lock
docker exec -i $DOCKER_PHP_ID bin/cake schema_cache clear

Tài liệu tham khảo:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.workflow.html

Tổng kết

Trên đây là các bước để config deploy project sử dụng elastic beanstalk, docker ecs amazon linux 2023. Thanks for reading...