在 AWS Linux 2 上运行的 NGINX 配置中访问 Elastic Beanstalk 环境属性
Posted
技术标签:
【中文标题】在 AWS Linux 2 上运行的 NGINX 配置中访问 Elastic Beanstalk 环境属性【英文标题】:Access Elastic Beanstalk environment properties in NGINX configs running on AWS Linux 2 【发布时间】:2020-08-19 12:01:49 【问题描述】:我之前在 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
文件夹中。
Here the reference(参见反向代理配置)
所以我在上面提到的位置创建了一个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
(请参阅上面的链接 Platform 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
文件提供适当的权限,但这是另一个问题。
还有更多的尝试和失败......
但后来我读到(也来自上面的链接):
"如果您将代理配置为向多个应用程序进程发送流量,您可以配置多个环境属性,并在代理配置和您的应用程序代码。"
希望回来了.. 这是否意味着我实际上 CAN 直接将环境变量添加到位于 .platform
目录中的 Nginx 配置中? ...我不知道..你呢?
我可以继续描述我整晚尝试的所有事情,所以我会在这里停下来。我希望你能得到这个问题。如果不问我,我会尽力让这一切变得可以理解。
另外,在与这个问题作斗争 14 小时后,我的想法也不是很清楚了。我需要休息一下。
如果您坚持到最后,感谢您的宝贵时间和帮助,我们将不胜感激。
【问题讨论】:
【参考方案1】:总结
一种方法是在.platform/hooks/postdeploy
中创建一个shell 脚本。
这是一个简化的示例,假设您有一个名为 MASTER_DOMAIN
的 Elastic Beanstalk 环境属性:
#!/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
块可以替换为原始帖子中 .ebextensions/10_proxy.config
中的 nginx content
。不过不需要Fn::GetOptionSetting
的东西。
我认为您还需要在.platform/confighooks/postdeploy
中复制一个脚本。
详情如下。
(对不起文字墙)
nginx中的环境变量
实际上,正如here 和here 中所讨论的,在http
、server
中使用os 环境变量是不可能的(开箱即用) , 或 location
nginx 配置文件中的块。有一些变通方法,例如使用 lua、perl 或模板,但我们不讨论这些。这部分与AWS无关。
在 OP 的 Amazon Linux AMI (AL1) 原始配置中,使用 .ebextensions/10_proxy.config
中的 files
部分,他们实际上是在部署期间使用 shell 脚本编写 nginx 配置文件。 shell 脚本扩展了环境变量,但生成的 nginx 的 proxy.conf
实际上并没有访问任何环境变量。
这就是它在 AL1 上起作用的原因。
平台挂钩
现在,对于 Amazon Linux 2 (AL2),我们可以使用 .platform/hooks
和 .platform/confighooks
文件夹中的 shell 脚本执行类似的操作。
这些.platform
挂钩脚本以root
用户身份执行,它们可以访问Elastic Beanstalk (EB) 环境属性。 EB 环境属性可以像普通操作系统环境变量一样访问,所以不需要使用Fn::GetOptionSetting
的东西。
基本上,我们需要创建一个 shell 脚本,该脚本使用原始 .ebextensions/10_proxy.config
中的 content
写入文件。但是,我们需要考虑两个问题:
我们应该使用prebuild
、predeploy
或postdeploy
挂钩吗?
我们的 nginx proxy.conf
文件的正确目标目录是什么?
文件位置
要回答这些问题,我们必须参考 Extending Elastic Beanstalk Linux platforms 的 AWS 文档,特别是 Instance deployment workflow 部分。
... 平台挂钩的当前工作目录 (cwd) 是应用程序的根目录。对于 prebuild 和 predeploy 文件,它是应用程序暂存目录,对于 postdeploy 文件,它是当前应用程序目录。如果其中一个文件失败(以非零退出代码退出),部署将中止并失败。
这很有趣,但留下了一些问题,例如“应用程序暂存目录”在哪里?我们可以通过检查我们的部署日志文件之一来填补空白。根据我们的eb-engine.log
,以下是应用部署期间平台挂钩和 nginx 配置文件发生的情况(跳过很多细节):
-
源包从S3下载并解压到
/var/app/staging/
.platform/hooks/prebuild/
中的平台挂钩已执行
代理服务器配置从/var/app/staging/.platform/nginx/
复制到/var/proxy/staging/nginx
.platform/hooks/predeploy/
中的平台挂钩已执行
代理服务器启动,配置从/var/proxy/staging/nginx/
复制到/etc/nginx
.platform/hooks/postdeploy/
中的平台挂钩已执行
注意,部署后应用位于/var/app/current
。
基于以上,有几种选择:
在.platform/hooks/postdeploy
中创建一个写入/etc/nginx/conf.d/proxy.conf
的shell 脚本。
nginx服务已经在运行,这个阶段需要重启才能使配置生效。
下面是一个最小的测试示例。在本例中,我们写入elasticbeanstalk
子目录,因为我们只想在默认的server
块内添加location
。然后我们可以在浏览器中访问/test/
页面,检查配置是否有效。
我们使用一些bash io redirection(<<
,>
)来编写nginx配置文件。
请注意,我们需要转义任何 nginx 变量,例如$host
变为 \$host
,否则 shell 会将它们解释为环境变量。
另请注意,shell 脚本需要具有执行权限,如文档中More about platform hooks 中所述。
#!/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
或者,我们可以在.platform/hooks/predeploy
中创建一个写入/var/proxy/staging/nginx/conf.d/proxy.conf
的shell 脚本。
这种情况下不需要重启nginx服务,因为这个钩子是在应用服务器配置之前执行的。
注意:
不确定这是错误还是设计功能,但我们新创建的proxy.conf
在配置 部署(与应用程序 部署相反)后消失了,除非我们在.platform/confighooks/postdeploy
目录中放了一个重复的脚本。不是很干...
编辑:AWS 支持确认我们在这种情况下需要 hooks
和 confighooks
中的重复脚本。文档中的application example 还显示了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 示例应用程序(在 64 位 Amazon Linux 2/3.1.5 上运行 Python 3.7)进行测试的(仅使用我们的自定义挂钩进行扩展)。
【讨论】:
嘿,谢谢你的回答,我会在回到这个问题时尝试一下。以上是关于在 AWS Linux 2 上运行的 NGINX 配置中访问 Elastic Beanstalk 环境属性的主要内容,如果未能解决你的问题,请参考以下文章
在 AWS Elastic Beanstalk 上运行 Docker 容器 - 502 Bad Gateway nginx/1.6.2
如何在运行 AWS Linux 2 的 AWS Elastic Beanstalk 上配置 Linux 交换空间?
amazon aws ec云Linux ami上安装配置Nginx+PHP+MySQL环境
在 AWS 上安装 nginx 后禁止 403(不欢迎 nginx 消息)
在 aws linux 2 实例上使用弹性 beanstalk 运行 django-q
在 64 位 Amazon Linux 2/3.2.2 和 Dockerrun.aws.json v3 上运行 Docker 的 Elastic Beanstalk