在 AWS Linux 2 上运行的 NGINX 配置中访问 Elastic Beanstalk 环境属性

Oli*_*ull 7 nginx environment-variables amazon-web-services amazon-elastic-beanstalk amazon-linux-2

我之前在 AWS Linux AMI 上有过这个工作,但在 AWS Linux 2 上没有运气。

我需要在 EB 应用程序部署期间从 Nginx 配置文件访问我的环境属性。它是一个单实例节点服务器。

我使用 AWS Linux AMI 是这样做的,并且没有问题:

.ebextensions/00_options.config

option_settings:
   aws:elasticbeanstalk:application:environment:
      DOMAIN: socket.example.com
      MASTER_DOMAIN: https://example.com
      etc..
Run Code Online (Sandbox Code Playgroud)

.ebextensions/10_proxy.config

... some configs ...

files:

  /etc/nginx/conf.d/proxy.conf:
    mode: "000644"
    owner: root
    group: root
    content: |

      upstream nodejs {
          server 127.0.0.1:8081;
          keepalive 256;
      }

      map $http_origin $cors_header {
          hostnames;
          default "";
          `{"Fn::GetOptionSetting": {"Namespace": "aws:elasticbeanstalk:application:environment", "OptionName": "MASTER_DOMAIN"}}` "$http_origin";
      }

      server {

          listen 80;
          listen 8080;

          server_name `{"Fn::GetOptionSetting": {"Namespace": "aws:elasticbeanstalk:application:environment", "OptionName": "DOMAIN"}}`;

          location ~ /.well-known {
              allow all;
              root /usr/share/nginx/html;
          }
          location / {
              return 301 https://$host$request_uri;
          }
      }
      
      etc..


.... some more configs ....
      
Run Code Online (Sandbox Code Playgroud)

我不包括上面的大部分配置,因为它们不相关。

所以当我之前这样做时,一切都按预期进行。配置文件插入了我的属性并在文件/etc/nginx/conf.d/proxy.conf夹中创建了文件。


现在使用 AWS Linux 2,规范发生了变化,我们必须在.platform/nginx/conf.d位于应用程序包根文件夹的文件夹中添加我们的 Nginx 配置文件。

这里参考(见反向代理配置)

所以我在proxy.conf上面提到的位置创建了一个文件,其中包含之前插入的内容/etc/nginx/conf.d/proxy.conf。


.platform/nginx/conf.d/proxy.conf

upstream nodejs {
    server 127.0.0.1:8081;
    keepalive 256;
}
    
map $http_origin $cors_header {
    hostnames;
    default "";
   `{"Fn::GetOptionSetting": {"Namespace": "aws:elasticbeanstalk:application:environment", "OptionName": "MASTER_DOMAIN"}}` "$http_origin";
}

etc...
Run Code Online (Sandbox Code Playgroud)

然后问题就开始了..

这第一次试验unexpected "{" in /var/proxy/staging/nginx/conf.d/proxy.conf:11向我抛出。

之后我尝试了很多东西。尝试使用${MASTER_DOMAIN}新的 EB AWS Linux 2 并弄乱了它hooks(请参阅平台挂钩上方的链接)。一切都无济于事,似乎您无法从 Nginx 配置访问属性。我读过一篇来自 Nginx 的文章或文档,今天提到了类似的东西,但我再也找不到了(做了很多谷歌搜索)。


我还尝试创建一个配置文件,就像我在工作版本中所做的那样,目的是将临时文件保存在包含属性的某处,然后将此文件包含在所需.platform/nginx/conf.d/proxy.conf文件中,因为我开始认为没有办法包含它们直接使用新规格。

.ebextensions/10_proxy.config

... some configs ....

files:

  /var/proxy/staging/custom_folder/proxy.conf:
    mode: "000644"
    owner: root
    group: root
    content: |
    
    etc...
Run Code Online (Sandbox Code Playgroud)

.platform/nginx/conf.d/proxy.conf

include custom_folder/proxy.conf;
Run Code Online (Sandbox Code Playgroud)

考虑到这个想法,我做了很多废话,我创建了hooks用于创建 ( mkdir) 目录,我试图在其中临时保存导致新权限错误的文件。我无法为prebuild,postdeploy文件授予适当的权限,但这是另一个问题。

还有更多的尝试和失败......


但后来我读过(也来自上面的链接):

“如果您将代理配置为向多个应用程序进程发送流量,您可以配置多个环境属性,并在代理配置和应用程序代码中使用它们的值。 ”

并希望回来了..这是否意味着我其实CAN直接添加环境变量到Nginx的CONFIGS地处.platform目录?......我不知道......你知道吗?


我可以继续描述我整夜尝试的所有事情,所以我会在这里停下来。我希望你明白这个问题。如果不问我,我会尽力使这一切都可以理解。

在与这个问题作斗争 14 小时后,我的头脑也不再很清楚了。我需要休息一下。

如果你做到了最后感谢你的时间和帮助将不胜感激。

djv*_*jvg 6

概括

一种方法是在.platform/hooks/postdeploy.

以下是一个简化示例,假设您有一个名为 的 Elastic Beanstalk 环境属性MASTER_DOMAIN:

#!/bin/bash
    
# write nginx config file
cat > /etc/nginx/conf.d/elasticbeanstalk/test.conf << LIMIT_STRING
location /test/ {
  default_type text/html;
  return 200 "nginx variable: \$host, and EB env property: $MASTER_DOMAIN";
}
LIMIT_STRING
    
# restart nginx service so the config takes effect
systemctl restart nginx.service
Run Code Online (Sandbox Code Playgroud)

此示例中的块location可以替换为content原始.ebextensions/10_proxy.config帖子中的 nginx。不过不需要这些Fn::GetOptionSetting东西。

我认为您还需要一个重复的脚本.platform/confighooks/postdeploy。

详细信息如下。

(抱歉文字墙)

nginx 中的环境变量

实际上,正如此处和此处所讨论的,不可能(开箱即用)在 nginx 配置文件中的 、 或 块http内server使用操作系统环境变量。location有一些解决方法,例如使用 lua、perl 或模板,但我们不讨论这些。这部分与AWS无关。

在 OP 的 Amazon Linux AMI (AL1) 原始配置中,使用files中的部分.ebextensions/10_proxy.config,他们实际上在部署期间使用 shell 脚本编写 nginx 配置文件。shell脚本扩展了环境变量,但是nginx的结果proxy.conf实际上并没有访问任何环境变量。

这就是它在 AL1 上起作用的原因。

平台挂钩

.platform/hooks现在,对于 Amazon Linux 2 (AL2),我们可以使用和文件夹中的 shell 脚本执行类似的操作.platform/confighooks。

这些.platform挂钩脚本以用户身份执行root,并且可以访问 Elastic Beanstalk (EB) 环境属性。EB 环境属性可以像普通操作系统环境变量一样访问,因此不需要使用这些Fn::GetOptionSetting东西。

基本上,我们需要创建一个 shell 脚本,用content原始.ebextensions/10_proxy.config. 然而,有两个问题我们需要考虑:

  1. 我们应该使用prebuild、predeploy或postdeploy钩子吗?

  2. 我们的 nginx 文件的正确目标目录是什么proxy.conf?

文件位置

要回答这些问题,我们必须参阅有关扩展 Elastic Beanstalk Linux 平台的 AWS 文档,特别是实例部署工作流程部分。

...平台挂钩的当前工作目录(cwd)是应用程序的根目录。对于预构建和预部署文件,它是应用程序暂存目录,对于部署后文件,它是当前应用程序目录。如果其中一个文件失败(以非零退出代码退出),部署将中止并失败。

这很有趣,但留下了一些问题,例如“应用程序暂存目录”位于哪里?我们可以通过检查我们的部署日志文件之一来填补空白。根据我们的eb-engine.log,以下是应用程序部署期间平台挂钩和 nginx 配置文件发生的情况(跳过很多细节):

  1. 源包从 S3 下载并解压到/var/app/staging/
  2. .platform/hooks/prebuild/执行平台钩子
  3. 代理服务器配置从 复制/var/app/staging/.platform/nginx/到/var/proxy/staging/nginx
  4. .platform/hooks/predeploy/执行平台钩子
  5. 代理服务器启动,配置从 复制/var/proxy/staging/nginx/到/etc/nginx
  6. .platform/hooks/postdeploy/执行平台钩子

请注意,部署后应用程序位于/var/app/current.

基于以上,有以下几种选择:

  1. .platform/hooks/postdeploy创建一个写入 的shell 脚本/etc/nginx/conf.d/proxy.conf。

    此时nginx服务已经运行,所以我们需要重启才能使配置生效。

    下面是一个最小的测试示例。在此示例中,我们写入子目录,因为我们只想在默认块内elasticbeanstalk添加一个。然后我们可以在浏览器中访问该页面,以检查配置是否有效。locationserver/test/

    我们使用一些bash io 重定向(<<、>)来编写 nginx 配置文件。

    请注意,我们需要转义任何 nginx 变量,例如$host变成\$host,否则 shell 会将它们解释为环境变量。

    另请注意,shell 脚本需要具有执行权限,如文档中有关平台挂钩的更多信息中所述。

#!/bin/bash
    
cat > /etc/nginx/conf.d/elasticbeanstalk/test.conf << LIMIT_STRING
location /test/ {
  default_type text/html
  return 200 "nginx variable: \$host, and EB env property: $MASTER_DOMAIN";
}
LIMIT_STRING
    
systemctl restart nginx.service
Run Code Online (Sandbox Code Playgroud)
  1. 或者,我们可以创建一个 shell 脚本来.platform/hooks/predeploy写入/var/proxy/staging/nginx/conf.d/proxy.conf.

    在这种情况下不需要重新启动 nginx 服务,因为该钩子是在应用服务器配置之前执行的。

谨防:

不确定这是一个错误还是一个设计功能,但是我们新创建的内容在配置部署(而不是应用程序proxy.conf部署)后就会消失,除非我们将重复的脚本放入目录中。不是很干....platform/confighooks/postdeploy

编辑:AWS 支持确认我们在这种情况下需要重复的hooks脚本confighooks。文档中的应用程序示例hooks还显示了和中的一些重复项(至少是重复的文件名)confighooks。

编辑:我们还可以编写一个调用钩子的配置钩子,而不是复制脚本,例如.platform/confighooks/predeploy/01_my_confighook.sh可以如下所示:

#!/bin/bash
source "/var/app/current/.platform/hooks/predeploy/01_my_hook.sh"
Run Code Online (Sandbox Code Playgroud)

免责声明:这是在新创建的单实例EB 环境中进行测试的,其中“Python 3.7 在 64 位 Amazon Linux 2/3.1.5 上运行”,使用所有默认配置和默认 AWS Python 示例应用程序(仅使用我们的自定义挂钩进行扩展)。