7

我之前在 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..

.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 ....
      

我没有包括上面的大多数配置,因为它们不相关。

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


现在使用 AWS Linux 2,规格已经改变,我们必须将 Nginx 配置文件添加到.platform/nginx/conf.d位于我们的应用程序包根文件夹中的文件夹中。

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

所以我在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...

然后问题就开始了。。

第一次审判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...

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

include custom_folder/proxy.conf;

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

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


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

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

希望回来了..这是否意味着我实际上可以直接将环境变量添加到位于目录中的 Nginx 配置中.platform?...我不知道..你呢?


我可以继续描述我整晚尝试的所有事情,所以我会在这里停下来。我希望你能得到这个问题。如果不问我,我会尽力让这一切变得可以理解。

在与这个问题作斗争 14 小时后,我的想法也不是很清楚了。我需要休息。

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

4

1 回答 1

5

概括

一种方法是在.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

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

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

详情如下。

(对不起文字墙)

nginx中的环境变量

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

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

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

平台挂钩

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

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

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

  1. 我们应该使用prebuild, predeploy, 还是postdeploy钩子?

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

文件位置

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

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

这很有趣,但留下了一些问题,例如“应用程序暂存目录”在哪里?我们可以通过检查我们的部署日志文件之一来填补空白。根据我们的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写入/etc/nginx/conf.d/proxy.conf.

    nginx服务已经在运行,这个阶段需要重启才能使配置生效。

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

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

    请注意,我们需要转义任何 nginx 变量,例如$hostbecome \$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
  1. 或者,我们可以在其中创建一个.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"

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

于 2021-02-02T16:35:14.127 回答