【问题标题】:Environment specific ebextensions Beanstalk commands环境特定的 ebextensions Beanstalk 命令
【发布时间】:2016-10-08 03:29:42
【问题描述】:

我有一个 spring-boot 应用程序,我需要为其指定石墨服务器和端口(以发送指标)。为此,我必须安装和配置statsd。我使用ebextensions 文件来做到这一点。

commands:
  01_nodejs_install:
    command: sudo yum -y install nodejs npm --enablerepo=epel
    ignoreErrors: true

  02_mkdir_statsd:
    command: mkdir /home/ec2-user/statsd
    ignoreErrors: true

  03_fetch_statsd:
    command: git clone https://github.com/etsy/statsd.git /home/ec2-user/statsd
    ignoreErrors: true

  04_change_example_config:
    command: "cat exampleConfig.js | sed 's/2003/<graphite-port>/g' | sed 's/graphite.example.com/<my-graphite-server>/g' > config.js"
    cwd: /home/ec2-user/statsd

  05_run_statsd:
    command: setsid node stats.js config.js >/dev/null 2>&1 < /dev/null &
    cwd: /home/ec2-user/statsd

这个配置的问题是我只能在这里为所有环境指定 1 个石墨服务器。

所以我决定将命令 04 和 05 移动到 container_commands。我正在考虑使用 beanstalk 控制台/UI 定义一个名为 ENV_NAME 的环境变量,并根据环境将其设置为 devqaprod。然后我可以使用container_commandstest 选项,仅针对基于此ENV_NAME 的特定环境运行04 和05 命令。

所以我的问题是 - 我如何使用 AWS 控制台来定义环境变量?我尝试使用 Beanstalk 控制台来定义我的变量,如文档 here 中所述,但它不起作用。我还 found(看到 5 个赞成的答案)这个方法只设置 JVM 属性而不是 ENV 变量。

我无法使用ebextensions 定义环境变量,因为那样我会遇到同样的问题 - 无法为不同的环境定义不同的环境变量 :)

所以我需要帮助:

  • 使用 beanstalk UI 设置 ENV_NAME 环境变量。

或者

  • 建议使用container_commands 中的ENV_NAME 系统属性来根据ENV_NAME 的值判断是否运行命令。

如果您知道为不同环境指定不同 Graphite 服务器的更简单/更好的方法,请随时参与。

【问题讨论】:

    标签: amazon-web-services environment-variables amazon-elastic-beanstalk ebextensions


    【解决方案1】:

    我解决此问题的方法是将ENV_NAME 分别定义为开发和生产环境中的devprod,并使用以下ebextensions 配置。

    commands:
      01_nodejs_install:
        command: sudo yum -y install nodejs npm --enablerepo=epel
        ignoreErrors: true
    
      02_mkdir_statsd:
        command: mkdir /home/ec2-user/statsd
        ignoreErrors: true
    
      03_fetch_statsd:
        command: git clone https://github.com/etsy/statsd.git /home/ec2-user/statsd
        ignoreErrors: true
    
    container_commands:
      04a_container_change_example_config:
        command: "cat exampleConfig.js | sed 's/2003/<graphite-dev-port>/g' | sed 's/graphite.example.com/<graphite-dev-host>/g' > config.js"
        cwd: /home/ec2-user/statsd
        test: '[ "${ENV_NAME}" == "dev" ]'
    
      04b_container_change_example_config:
        command: "cat exampleConfig.js | sed 's/2003/<graphite-prod-port>/g' | sed 's/graphite.example.com/<graphite-prod-host>/g' > config.js"
        cwd: /home/ec2-user/statsd
        test: '[ "${ENV_NAME}" == "prod" ]'
    
      05_run_statsd:
        command: setsid node stats.js config.js >/dev/null 2>&1 < /dev/null &
        cwd: /home/ec2-user/statsd
    

    使用test,我可以在我已经在 beanstalk 环境中定义的ENV_NAME 属性上设置container command 的执行条件。

    【讨论】:

    • 这看起来不错。只是想知道您是如何找到用于测试的语法的。你知道一个官方的aws文档吗?谢谢。
    • @Dennis 我不记得我到底是怎么想出来的,但是一些 AWS 文档页面上的示例有所帮助。也许this。我必须进行一些试验和错误才能使其正常工作。
    • 感谢您的链接。我猜它实际上只是 bash 脚本?
    • 不熟悉 bash 脚本,this reference 帮助我理解了语法的一些特殊性。
    • 两项测试对我来说都是阳性。
    【解决方案2】:

    除了@Nik 的回答:

    除了手动添加环境变量ENV_NAME,您还可以获取实际环境名称并将其自动存储在ENV_NAME中。这是在您的ebextensions 配置文件中使用option_settings 实现的。

    例如:

    option_settings:
      aws:elasticbeanstalk:application:environment:
        ENV_NAME: '`{ "Ref" : "AWSEBEnvironmentName" }`'  # assign the actual env name to ENV_NAME
    
    container_commands:
      0100_execute_only_in_dev:
        command: echo "this is the development environment"  # this will turn up in ebactivity.log
        test: '[[ $ENV_NAME = "dev" ]]'
    

    附注,对于像我这样不太熟悉 shell 脚本的人:测试表达式中的空格很重要 (example)。

    更新:

    截至 2021 年,Amazon Linux 2 is the new standard。 Amazon Linux 2 使用 platform hooks 而不是 .ebextensions 中的 container_commands

    这是一个等效于上面定义的 0100_execute_only_in_dev 容器命令的 bash 脚本,可用作 Amazon Linux 2 上的平台挂钩:

    0100_execute_only_in_dev.sh

    #!/bin/bash
    if [ $ENV_NAME = "dev" ]
    # the following output will end up in "/var/log/eb-hooks.log"
    then echo "this is the development environment" 
    fi
    

    shell 脚本需要执行权限,如 here 所述,并且可以放置在源包中 .platform/hooks 和/或 .platform/confighooks 的任何子目录中,具体取决于适用的部署阶段 (@987654339 @、predeploypostdeploy)。有关更多信息,请参阅部署 workflow。它还有助于检查 /var/log/eb-engine.log,了解部署期间究竟发生了什么。

    请注意,平台挂钩也可以访问 EB 环境属性。

    【讨论】:

    【解决方案3】:

    答案就在这个春天documentation,不过我还是用我的话说吧: 由于您正在运行 spring-boot 应用程序,因此您可以创建不同的“application.properties”文件,如下所示:

    您可以在每个文件中放置您的石墨(或其他)配置:

    在我的 application-dev.yml 中:

    在我的 application-prod.yml 中:

    如您所见,每个环境都有一个配置。

    您可以使用不同的 maven 配置文件运行您的应用程序,在这种情况下,假设:dev 和 prod... 在我的情况下,我的“dev”配置文件是默认设置的,因此当应用程序启动时它将加载 dev 配置文件因此,application-dev.yml 配置。

    我的 pom.xml 的 sn-p

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                ...
    

    然后,当您使用每个配置文件运行应用程序时,它将加载所需的 .yml 文件

    让我们看看,如果我运行:

    java -jar mywar.war
    

    我的控制台加载开发配置文件(因为记住这是我的默认配置文件)

    但如果我指定 prod 配置文件,例如:

    java -jar mywar.war --spring.profiles.active=prod
    

    我的控制台会显示:

    要在 Elastic Beanstalk 中设置环境变量,请转到配置 -> 软件配置:

    并设置spring.profile.active,像这样:

    最后一条评论:不要将环境属性与环境标签混淆!

    • 环境属性:我刚刚向您展示的那些:环境变量。
    • 环境标签:资源的 Elastic Beanstalk 标签,如 here 所述

    【讨论】:

    • 感谢您的回复。但是,这对我来说无济于事。请注意,我这里的目标是配置statsd,而不是配置spring-boot 应用程序。我已经在使用您描述的方法为在我的应用程序中 中的不同环境指定不同的Graphite 设置。但是,我想配置 statsd,它作为守护进程在每个主机上与 spring-boot 应用程序一起运行。
    猜你喜欢
    • 2015-07-20
    • 2021-06-15
    • 2017-05-24
    • 2016-04-09
    • 2021-11-25
    • 2023-03-26
    • 2017-08-14
    • 2019-12-21
    • 2017-05-06
    相关资源
    最近更新 更多