javascript - AWS ECS (Fargate) 无法挂载 EFS 文件系统 "Failed to resolve"

标签 javascript amazon-web-services aws-fargate amazon-efs

在我的测试床项目中,我尝试使用 AWS Javascript SDK 将 EFS 安装到我的 Fargate 容器。我一直在使用这篇博客文章作为我正在实现的引用: https://aws.amazon.com/blogs/containers/developers-guide-to-using-amazon-efs-with-amazon-ecs-and-aws-fargate-part-3/

我的步骤似乎与 AWS 博客文章中的 EFS 部分相同。但我遇到了 ECS 任务状态中显示的以下错误:

“ResourceInitializationError:无法调用 EFS utils 命令来设置 EFS 卷:stderr:无法解析“fs-XXXXX.efs.us-east-1.amazonaws.com” - 检查您的文件系统 ID 是否正确。请参阅 https://docs.aws.amazon.com/console/efs/mount-d...',"

我的 VPC 中均启用了 DNS 解析和 DNS 主机名。

这是最重要的代码:

import * as SDK from 'aws-sdk';
import Config from '../config';
import Networking from '../cluster/networking';
import Logging from '../cluster/logging';
import BuildJobParams from './buildJobParams';

import ExecutionRole from '../executionRole/executionRole';

class BuildJob {
    static async run() {
        let taskDefinitionArn = await this.registerJob();
        let params = {
            cluster: Config.default.clusterName,
            taskDefinition: taskDefinitionArn,
            platformVersion: "1.4.0",
            launchType: "FARGATE",
            networkConfiguration: {
                awsvpcConfiguration: {
                    subnets: [
                        await Networking.get()
                        ],
                    assignPublicIp: "ENABLED",
                    securityGroups: [
                        await Networking.getSecurityGroup()
                    ]
                }
            },
        };
        let ECS = new SDK.ECS();
        console.log("Build job starting");
        let task = await ECS.runTask(params).promise();
        await this.watch(task.tasks[0].taskArn);

        return task;
    }

    static async watch(task) {
        let ECS = new SDK.ECS();
        try{

        await ECS.waitFor("tasksRunning", {
            cluster: Config.default.clusterName,
            tasks: [task]
        }).promise();

        console.log("Build job is running, watching logs");
        await Logging.watch(async () => {
            return (await (new SDK.ECS()).describeTasks({ tasks: [task], cluster: Config.default.clusterName }).promise()).tasks[0].lastStatus;
        });


        await ECS.waitFor("tasksStopped", {
            cluster: Config.default.clusterName,
            tasks: [task]
        }).promise();

        console.log("Build job has ended");
        }catch(err){
           console.log( await ECS.describeTasks({
            cluster: Config.default.clusterName,
            tasks: [task]}).promise())
            console.error(err);
        }
    }

    static async registerJob() {
        let ECS = new SDK.ECS();
        let taskDefinitionResult = await ECS.registerTaskDefinition(await BuildJobParams.get()).promise();
        return taskDefinitionResult.taskDefinition.taskDefinitionArn;
    }
}

export default BuildJob
import Config from '../config'
import ElasticFileSystem from '../cluster/fileSystem';
import ExecutionRole from '../executionRole/executionRole';

class BuildJobParams{
    static async get(){
        return {
            containerDefinitions: [
                {
                    name: "BuildWorker",
                    command: Config.default.buildJobCommand,
                    environment: [
                        { name: "ws", value: "" }
                    ],
                    image: "ubuntu",
                    logConfiguration: {
                        logDriver: "awslogs",
                        options: {
                            "awslogs-group": Config.default.logGroupName,
                            "awslogs-stream-prefix": "ecs",
                            "awslogs-region": Config.default.region
                        }
                    },
                    mountPoints: [
                        {
                            containerPath: "/efs/",
                            sourceVolume: 'test'
                        }
                    ],
                    portMappings:[
                        {
                            containerPort: "2049", 
                            hostPort:"2049", 
                            protocol: "tcp"
                            }
                    ]
                }
            ],
            memory: "512",
            cpu: "256",
            family: "GameCI",
            volumes: [
                {
                    name: "test",
                    efsVolumeConfiguration: {
                        fileSystemId: ElasticFileSystem.getFileSystemId(),
                        transitEncryption: "ENABLED",
                        authorizationConfig: {
                            accessPointId: ElasticFileSystem.getAccessPointId(),
                            iam: "DISABLED"
                        }
                    }
                }
            ],
            requiresCompatibilities: ["FARGATE"],
            networkMode: "awsvpc", 
            taskRoleArn: (await ExecutionRole.getRunArn()),
            executionRoleArn : (await ExecutionRole.getLoggingArn())
        };
    }
}
export default BuildJobParams
import * as SDK from 'aws-sdk';
import Config from '../config';
import Networking from './networking';

class ElasticFileSystem {
    static async get() {
        let EFS = new SDK.EFS();
        let params = {
            CreationToken: Config.default.clusterName,
            PerformanceMode: "generalPurpose",
            Encrypted: true,
            Tags: [
                {
                    Key: "Name",
                    Value: "MyFileSystem"
                }
            ]
        };

        let result = await EFS.createFileSystem(params).promise();
        while((await EFS.describeFileSystems().promise()).FileSystems.find(element=>element.FileSystemId==result.FileSystemId).LifeCycleState != "available")
        {
            await (new Promise((resolve) => setTimeout(resolve, 10000)));
            let state = (await EFS.describeFileSystems().promise()).FileSystems.find(element=>element.CreationToken==Config.default.clusterName).LifeCycleState;
            if(state != "creating" && state != "available" && state != "updating"){
                throw `Failed to create file system (${state})`;
            }
        }
        let accessPoint = await EFS.createAccessPoint({
            FileSystemId: result.FileSystemId,
            ClientToken: Config.default.clusterName
        }).promise();
        let mt = await EFS.createMountTarget({
            FileSystemId: result.FileSystemId,
            SubnetId: `${await Networking.get()}`,
            SecurityGroups: [
                `${await Networking.getSecurityGroup()}`
            ],
        }).promise();
        console.log("File System created");
        
        
        Object.assign(ElasticFileSystem, {
            fileSystemId: result.FileSystemId,
            accessPointId: accessPoint.AccessPointId,
            mountTargetId: mt.MountTargetId
        });
        return result;
    }

    static getFileSystemId(){
        console.log(this.fileSystemId);
        return this.fileSystemId;
    }

    static getAccessPointId(){
        console.log(this.fileSystemId);
        return this.accessPointId;
    }

    static getMountTargetId(){
        console.log(this.fileSystemId);
        return this.mountTargetId;
    }

    static async delete() {
        let EFS = new SDK.EFS();
        let params = {
            FileSystemId: this.fileSystemId
        };
        //await EFS.deleteFileSystem(params).promise();
        let fs = await EFS.describeFileSystems().promise();
        for (let index = 0; index < fs.FileSystems.length; index++) {
            const element = fs.FileSystems[index];
            await EFS.deleteFileSystem({FileSystemId:element.FileSystemId}).promise();
        }
    }
}

export default ElasticFileSystem
import * as SDK from 'aws-sdk';

import Logging from './logging';
import ElasticFileSystem from './fileSystem';
import Config from '../config';

class ElasticCluster {
    static async get() {
        console.log("Creating cluster");

        await Logging.get(Config.default.logGroupName);
        let fileSystem = await ElasticFileSystem.get();
        let ECS = new SDK.ECS();
        Object.assign(ElasticCluster, {
            ECS: ECS
        });

        let data = await this.create();
        await ElasticCluster.waitForClusterReady();
        console.log("Created cluster");
        return data;
    }

    static async create() {
        let params = {
            capacityProviders: [
                'FARGATE'
            ],
            clusterName: Config.default.clusterName,
            defaultCapacityProviderStrategy: [
                {
                    capacityProvider: 'FARGATE',
                    base: '0',
                    weight: '1'
                }
            ],
            settings: [],
            tags: [
                {
                    key: 'STRING_VALUE',
                    value: 'STRING_VALUE'
                }
            ]
        };
        return await this.ECS.createCluster(params).promise();
    }

    static async exists(){
        let params = {
            clusters: [
                Config.default.clusterName,
            ]
        };
        return (await this.ECS.describeClusters(params).promise()).clusters.length > 0;
    }

    static async getCluster(){
        let params = {
            clusters: [
                Config.default.clusterName,
            ]
        };
        return (await this.ECS.describeClusters(params).promise()).clusters[0];
    }

    static async waitForClusterReady() {
        let cluster = await this.getCluster();
        if (cluster.status == "ACTIVE" || cluster.status == "INACTIVE") {
            return;
        }
        else {
            await new Promise(res => setTimeout(res, 10000));
            await this.waitForClusterReady();
        }
    }


    static async delete() {
        let ecs = new SDK.ECS();

        try {
            //await this.ECS.deleteCluster({
            //    cluster: Config.default.clusterName
            //}).promise();
            let clusters = (await ecs.listClusters().promise()).clusterArns;
            for (let index = 0; index < clusters.length; index++) {
                const element = clusters[index];
                await ecs.deleteCluster({
                    cluster: element
                }).promise();
            }
        } catch (err) {

        }
        await ElasticFileSystem.delete();
        await Logging.delete();
        console.log("garbage collected");
    }
}

export default ElasticCluster
import * as SDK from 'aws-sdk';
import Config from '../config';


class Networking {
    static async get() {
        return (await this.getAll())[0].SubnetId;
    }

    static async getAll() {
        let EC2 = new SDK.EC2();
        let params = {
            Filters: [
                {
                    Name: "vpc-id",
                    Values: [
                        await this.getVpcId()
                    ]
                }
            ]
        };
        let value = await EC2.describeSubnets(params).promise();
        return value.Subnets;
    }

    static async getSecurityGroup() {
        let EC2 = new SDK.EC2();
        if (this.securityGroup != null){
            return this.securityGroup;
        }
        console.log("creating security group");
        let sg = await EC2.createSecurityGroup({
            GroupName: Config.default.clusterName,
            Description: "test",
            VpcId: await this.getVpcId(),
            
        }).promise();
        await EC2.authorizeSecurityGroupIngress({
            GroupId: sg.GroupId,
            IpPermissions: [{
                
                FromPort: "2049",
                ToPort: "2049",
                IpProtocol: "tcp",
            }]
        }).promise();
        Object.assign(this, {securityGroup:sg.GroupId});
        return sg.GroupId;
    }

    static async getVpcId() {
        return "vpc-XXXXXXX";
    }
}

export default Networking

最佳答案

TLDR:检查您的 DHCP 选项集有AmazonProvidedDNS

我的 CDK 堆栈也遇到同样的问题。我的任务正在 VPC 的私有(private)子网中运行,并且我已确认 EFS 设置正确,因为我将 lambda 设置为在同一私有(private)子网中运行,并且它可以正常连接到 EFS。

我尝试了 EFS 的 VPC 接口(interface)端点,没有雪茄。

我还无法测试,但您的解决方案可能基于我在 acloud.guru 上找到的信息,奇怪的是,那篇文章说是 2 年前的事,不是 2020 年才添加对 EFS 对 Fargate 的支持吗?

我的 VPC 启用了 DNS 主机名和解析,但我的 DHCP 选项集没有 AmazonProvidedDNS 作为名称服务器,这可以解释为什么我们会出现无法解析“fs-XXXXX.efs.us-east”的消息-1.amazonaws.com"

关于javascript - AWS ECS (Fargate) 无法挂载 EFS 文件系统 "Failed to resolve",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65550544/

相关文章:

javascript - jQuery 日期选择器 - 从第一个日期选择器中选择后禁用日期

javascript - 有 promise 的 Angular 过滤服务

amazon-web-services - ECS 容器路由与 AWS 中的应用程序负载均衡器

aws-fargate - 使用 CDK 使用正确的端口注册 Fargate 服务 ELB 目标?

amazon-web-services - 在 ECS Fargate 上获取 CannotPullContainerError

spring-boot-actuator - 对 Spring 执行器的 AWS Fargate 运行状况检查进行故障排除

javascript - Jquery事件捕获margin-left的变化

javascript - redux-thunk 将调度传递给另一个函数?

python - 如果我使用 pip3 安装 AWS CLI,如何修复 "dyld: Library not loaded"?

amazon-web-services - 如何使用 AmazonS3Client 在沙盒环境中测试 amazon s3