如何在 ECS 内通信 postgres 数据库和 Django 容器?

问题描述 投票:0回答:1

我需要一些有关此管道的指导来将测试部署到 ECS,我知道与 RDS 和其他解决方案相比,容器中的 postgres 数据库并不是最好的解决方案,但我至少想知道是否可能,呵呵。我被这个问题困扰了好几天,它只是卡在运行 wait-for-it.sh 文件的一部分并且无法连接到数据库,我检查了 AWS cloudwatch 并且数据库正准备接受连接,但 Django 从未连接到它。我使用连接到 ECS 集群的默认 VPC,并在其内部有一个安全组,该安全组具有入站规则,允许 y IP 的端口 8000 中的流量,以及其他 5432 端口中的流量,也允许流量到达任何 IP,有什么问题吗?

name: CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  deploy-ecs:
    name: Deploy to ECS
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Log in to Amazon ECR
        uses: aws-actions/amazon-ecr-login@v1

      
      - name: Check if backend Docker image exists
        id: backend-image-check
        run: |
          IMAGE_TAG=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest
          if aws ecr describe-images --repository-name backend --image-ids imageTag=latest; then
            echo "Backend image exists."
            echo "::set-output name=exists::true"
          else
            echo "Backend image does not exist."
            echo "::set-output name=exists::false"
          fi


      - name: Build and push backend Docker image
        if: steps.backend-image-check.outputs.exists == 'false'
        run: |
          docker buildx build --platform linux/amd64,linux/arm64 -f ./backend/DockerfileProd -t ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest --push ./backend

      - name: Check if frontend Docker image exists
        id: frontend-image-check
        run: |
          IMAGE_TAG=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest
          if aws ecr describe-images --repository-name frontend --image-ids imageTag=latest; then
            echo "Frontend image exists."
            echo "::set-output name=exists::true"
          else
            echo "Frontend image does not exist."
            echo "::set-output name=exists::false"
          fi

      - name: Build and push frontend Docker image
        if: steps.frontend-image-check.outputs.exists == 'false'
        run: |
          docker buildx build --platform linux/amd64,linux/arm64 -f ./frontend/DockerfileProd -t ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest --push ./frontend

      - name: Install AWS CLI
        run: |
          sudo apt-get update
          sudo apt-get install -y awscli

      - name: Create CloudWatch Logs group
        run: |
          aws logs create-log-group --log-group-name /ecs/kanastra || true


      - name: Create ECS Task Definition
        run: |
          echo '{
            "family": "kanastra-task",
            "networkMode": "awsvpc",
            "containerDefinitions": [
              {
                "name": "db",
                "image": "postgres",
                "essential": true,
                "memory": 512,
                "cpu": 256,
                "environment": [
                  { "name": "POSTGRES_DB", "value": "kanastra_db" },
                  { "name": "POSTGRES_USER", "value": "kanastra_user" },
                  { "name": "POSTGRES_PASSWORD", "value": "mypassword" },
                  { "name": "POSTGRES_PORT", "value": "5432" }
                ],
                "portMappings": [
                  { "containerPort": 5432,
                    "protocol": "tcp" }
                ],
                "logConfiguration": {
                  "logDriver": "awslogs",
                  "options": {
                    "awslogs-group": "/ecs/kanastra",
                    "awslogs-region": "${{ secrets.AWS_REGION }}",
                    "awslogs-stream-prefix": "db"
                  }
                }
              },
              {
                "name": "web",
                "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest",
                "essential": true,
                "memory": 512,
                "cpu": 256,
                "environment": [
                  { "name": "DB_NAME", "value": "kanastra_db" },
                  { "name": "DB_USER", "value": "kanastra_user" },
                  { "name": "DB_PASSWORD", "value": "mypassword" },
                  { "name": "DB_HOST", "value": "db" },
                  { "name": "DB_PORT", "value": "5432" }
                ],
                "portMappings": [
                  { "containerPort": 8000,
                    "protocol": "tcp" }
                ],
                "command": [
                  "sh", "-c",
                  "echo 'Waiting for DB to be ready...' && /usr/local/bin/wait-for-it.sh db:5432 -- echo 'DB is ready, starting application...' && python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
                ],
                "logConfiguration": {
                  "logDriver": "awslogs",
                  "options": {
                    "awslogs-group": "/ecs/kanastra",
                    "awslogs-region": "${{ secrets.AWS_REGION }}",
                    "awslogs-stream-prefix": "web"
                  }
                }
              },
              {
                "name": "frontend",
                "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest",
                "essential": true,
                "memory": 512,
                "cpu": 256,
                "portMappings": [
                  { "containerPort": 3000, "hostPort": 3000 }
                ],
                "logConfiguration": {
                  "logDriver": "awslogs",
                  "options": {
                    "awslogs-group": "/ecs/kanastra",
                    "awslogs-region": "${{ secrets.AWS_REGION }}",
                    "awslogs-stream-prefix": "frontend"
                  }
                }
              }
            ],
            "requiresCompatibilities": ["FARGATE"],
            "cpu": "1024",
            "memory": "2048",
            "executionRoleArn": "arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/ecsTaskExecutionRole"
          }' > ecs-task-def.json

      - name: Register ECS Task Definition
        run: |
          aws ecs register-task-definition \
            --cli-input-json file://ecs-task-def.json

      - name: Create or Update ECS Service
        run: |
          SERVICE_NAME=${{ secrets.ECS_SERVICE }}
          CLUSTER_NAME=${{ secrets.ECS_CLUSTER }}
          TASK_DEFINITION=kanastra-task

          while true; do
            SERVICE_STATE=$(aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME --query 'services[0].status' --output text)
            if [ "$SERVICE_STATE" == "ACTIVE" ]; then
              echo "Service is active, updating..."
              aws ecs update-service \
                --cluster $CLUSTER_NAME \
                --service $SERVICE_NAME \
                --task-definition $TASK_DEFINITION \
                --force-new-deployment
              break
            elif [ "$SERVICE_STATE" == "INACTIVE" ] || [ "$SERVICE_STATE" == "None" ]; then
              echo "Service is inactive, creating a new service..."
              aws ecs create-service \
                --cluster $CLUSTER_NAME \
                --service-name $SERVICE_NAME \
                --task-definition $TASK_DEFINITION \
                --desired-count 1 \
                --launch-type FARGATE \
                --network-configuration "awsvpcConfiguration={subnets=[${{ secrets.AWS_SUBNET }}],securityGroups=[${{ secrets.AWS_SECURITY_GROUP }}],assignPublicIp=ENABLED}"
              break
            else
              echo "Service is in state $SERVICE_STATE, waiting for it to become active..."
              sleep 30
            fi
          done

和我的 wait-for-it.sh 文件:

#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available

TIMEOUT=60
QUIET=0
HOST="$1"
PORT="$2"

echo "Waiting for $HOST:$PORT to be available..."

for i in `seq $TIMEOUT` ; do
    echo "Attempt $i: Checking connection to $HOST:$PORT..."
    nc -zv "$HOST" "$PORT" > /dev/null 2>&1
    result=$?
    if [ $result -eq 0 ] ; then
        echo "Connection to $HOST:$PORT succeeded."
        exit 0
    fi
    echo "Attempt $i: Connection to $HOST:$PORT failed."
    sleep 1
done

echo "Operation timed out after $TIMEOUT seconds" >&2
exit 1```



I tried change the localhost from db to localhost but did not work, im expecting the container to do not stop and see this functional, remembering that im pushing images to ECR from a macbook m1, but i think i fixed this in build part and ECS service is working, and db container is good, if was something behind i think i would not have gotten so far to ECS.
django postgresql security amazon-ecs amazon-vpc
1个回答
0
投票

您正在部署到 Fargate。使用 Fargate,在同一任务中运行的所有容器共享一个弹性网络接口,并且可以通过各自的端口通过

localhost
127.0.0.1
相互通信。这记录在此处

如果你改变这个:

{ "name": "DB_HOST", "value": "db" },

对此:

{ "name": "DB_HOST", "value": "127.0.0.1" },

应该可以。

© www.soinside.com 2019 - 2024. All rights reserved.