Setup 配方 - AWS OpsWorks

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Setup 配方

重要

这些区域有: AWS OpsWorks Stacks 该服务已于 2024 年 5 月 26 日终止,新客户和现有客户均已禁用。我们强烈建议客户尽快将其工作负载迁移到其他解决方案。如果您对迁移有疑问,请联系 AWS Support 团队开启 AWS re: post 或通过 AWS 高级支持

Setup 配方分配给了该层的 Setup 生命周期事件,这些配方在实例启动后运行。它们执行安装程序包、创建配置文件和启动服务等任务。安装配方完成运行后, AWS OpsWorks Stacks 运行 Deploy 配方将任何应用程序部署到新实例。

tomcat::setup

tomcat::setup 配方适合分配给层的 Setup 生命周期事件。

include_recipe 'tomcat::install' include_recipe 'tomcat::service' service 'tomcat' do action :enable end # for EBS-backed instances we rely on autofs bash '(re-)start autofs earlier' do user 'root' code <<-EOC service autofs restart EOC notifies :restart, resources(:service => 'tomcat') end include_recipe 'tomcat::container_config' include_recipe 'apache2' include_recipe 'tomcat::apache_tomcat_bind'

tomcat::setup 配方基本上是一个元配方。它包括一组从属配方,这些配方用于处理安装和配置 Tomcat 及相关程序包的大部分详细信息。tomcat::setup 的第一部分运行以下配方,我们将在后面的部分进行介绍:

tomcat::setup 的中间部分可启用并启动 Tomcat 服务:

  • Chef service 资源可在启动时启用 Tomcat 服务。

  • Chef bash 资源运行 Bash 脚本来启动 autofs 守护程序,这对于亚马逊支持的实例来说是必需的。EBS然后,该资源通知 service 资源重新启动 Tomcat 服务。

    有关更多信息,请参阅:autofs (对于 Amazon Linux) 或 Autofs (对于 Ubuntu)。

tomcat::setup 的最后一部分可创建配置文件并安装和配置前端 Apache 服务器:

  • tomcat::container_config 配方可创建配置文件。

  • apache2食谱(简写为apache2::default)是 AWS OpsWorks 堆叠用于安装和配置 Apache 服务器的内置配方。

  • tomcat::apache_tomcat_bind 配方可将 Apache 服务器配置为作为 Tomcat 服务器的前端运行。

注意

您通常可以通过使用内置配方执行某些所需任务来节约时间和精力。此配方使用内置 apache2::default 配方来安装 Apache,而不是从头实施 Apache。有关另一个关于如何使用内置配方的示例,请参阅Deploy 配方

后面的部分更加详细地介绍了 Tomcat 说明书的 Setup 配方。有关 apache2 配方的更多信息,请参阅 opsworks-cookbooks/apache2

tomcat::install

tomcat::install 配方安装了 Tomcat 服务器、Open JDK 以及处理与 “我的SQL服务器” 连接的 Java 连接器库。

tomcat_pkgs = value_for_platform( ['debian', 'ubuntu'] => { 'default' => ["tomcat#{node['tomcat']['base_version']}", 'libtcnative-1', 'libmysql-java'] }, ['centos', 'redhat', 'fedora', 'amazon'] => { 'default' => ["tomcat#{node['tomcat']['base_version']}", 'tomcat-native', 'mysql-connector-java'] }, 'default' => ["tomcat#{node['tomcat']['base_version']}"] ) tomcat_pkgs.each do |pkg| package pkg do action :install end end link ::File.join(node['tomcat']['lib_dir'], node['tomcat']['mysql_connector_jar']) do to ::File.join(node['tomcat']['java_dir'], node['tomcat']['mysql_connector_jar']) action :create end # remove the ROOT webapp, if it got installed by default include_recipe 'tomcat::remove_root_webapp'

该配方执行以下任务:

  1. 创建要安装的程序包的列表,具体取决于实例的操作系统。

  2. 安装列表中的每个程序包。

    Chef package 资源使用适当的提供程序 (对于 Amazon Linux,使用 yum;对于 Ubuntu,使用 apt-get) 来处理安装任务。软件包提供程序将 Open 安装JDK为 Tomcat 依赖项,但必须明确安装我的SQL连接器库。

  3. 使用 Chef 链接资源在 Tomcat 服务器的 lib 目录中创建指向中我的SQL连接器库的符号链接。JDK

    使用默认属性值,Tomcat lib 目录为/usr/share/tomcat6/lib,我的SQL连接器库 (mysql-connector-java.jar) 位于其中。/usr/share/java/

tomcat::remove_root_webapp配方会删除 ROOT Web 应用程序(/var/lib/tomcat6/webapps/ROOT默认情况下),以避免出现一些安全问题。

ruby_block 'remove the ROOT webapp' do block do ::FileUtils.rm_rf(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT'), :secure => true) end only_if { ::File.exists?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) && !::File.symlink?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) } end

only_if 语句可确保配方仅在文件存在时删除文件。

注意

Tomcat 版本由 ['tomcat']['base_version'] 属性指定,该属性在属性文件中被设置为 6。要安装 Tomcat 7,您可以使用自定义JSON属性来覆盖该属性。只需编辑您的堆栈设置,然后在 Custo m Chef JSON 框JSON中输入以下内容,或者将其添加到任何现有的自定义设置中JSON:

{ 'tomcat' : { 'base_version' : 7 } }

自定义JSON属性会覆盖默认属性并将 Tomcat 版本设置为 7。有关覆盖属性的更多信息,请参阅覆盖属性

tomcat::service

tomcat::service 配方创建 Tomcat 服务定义。

service 'tomcat' do service_name "tomcat#{node['tomcat']['base_version']}" case node[:platform] when 'centos', 'redhat', 'fedora', 'amazon' supports :restart => true, :reload => true, :status => true when 'debian', 'ubuntu' supports :restart => true, :reload => false, :status => true end action :nothing end

该配方使用 Chef service 资源指定 Tomcat 服务名称 (默认情况下为 tomcat6),并设置 supports 属性以定义 Chef 如何管理服务在不同操作系统上的重新启动、重新加载和状态命令。

  • true 表示 Chef 可以使用 init 脚本或其他服务提供程序来运行该命令。

  • false 表示 Chef 必须尝试以其他方式运行该命令。

请注意,action 的设置为 :nothing。对于每个生命周期事件, AWS OpsWorks Stacks 会启动 Chef 运行以执行相应的配方集。Tomcat 说明书采用常见模式:使配方创建服务定义,但不重新启动服务。Chef 运行中的其他配方处理重新启动,这通常是通过在用于创建配置文件的 notifies 资源中添加 template 命令来实现的。通知是重新启动服务的一种简便方法,因为它们仅在配置发生改变时重新启动服务。此外,如果 Chef 运行拥有针对一项服务的多个重新启动通知,Chef 最多重新启动服务一次。这种做法可以避免在尝试重新启动运行不正常的服务 (Tomcat 错误的常见起因) 时可能发生的问题。

必须为使用重新启动通知的任何 Chef 运行定义 Tomcat 服务。因此,多个配方都包含 tomcat::service,以确保为每个 Chef 运行都定义了该服务。如果一次 Chef 运行包含 tomcat::service 的多个实例,不会造成损失,因为 Chef 确保每一次运行,配方仅执行一次,而无论包括了几次实例。

tomcat::container_config

tomcat::container_config 配方基于说明书模板文件创建配置文件。

include_recipe 'tomcat::service' template 'tomcat environment configuration' do path ::File.join(node['tomcat']['system_env_dir'], "tomcat#{node['tomcat']['base_version']}") source 'tomcat_env_config.erb' owner 'root' group 'root' mode 0644 backup false notifies :restart, resources(:service => 'tomcat') end template 'tomcat server configuration' do path ::File.join(node['tomcat']['catalina_base_dir'], 'server.xml') source 'server.xml.erb' owner 'root' group 'root' mode 0644 backup false notifies :restart, resources(:service => 'tomcat') end

该配方首先调用 tomcat::service,以在必要时定义该服务。批量配方包含两个 template 资源,每个资源都基于一个说明书模板文件创建配置文件,设置文件属性,以及通知 Chef 重新启动服务。

Tomcat 环境配置文件

第一个 template 资源使用 tomcat_env_config.erb 模板文件创建 Tomcat 环境配置文件,该配置文件用于设置环境变量,如 JAVA_HOME。默认文件名是 template 资源的参数。tomcat::container_config 使用 path 属性覆盖默认值,并将配置文件命名为 /etc/sysconfig/tomcat6 (Amazon Linux) 或 /etc/default/tomcat6 (Ubuntu)。template 资源还指定文件的所有者、组和模式设置,并指示 Chef 不要创建备份文件。

如果您查看源代码,实际上有三个版本的 tomcat_env_config.erb,这些版本分别位于 templates 目录的不同子目录中。ubuntuamazon 目录包含适用于它们各自操作系统的模板。default 文件夹包含一个仅具有一个注释行的伪模板,仅当您尝试使用不受支持的操作系统在一个实例上运行此配方时,才会使用这个模板。tomcat::container_config 配方不需要指定要使用哪个 tomcat_env_config.erb。Chef 根据 File Specificity 中介绍的规则自动为实例的操作系统选择适当的目录。

此示例中的 tomcat_env_config.erb 文件主要包含注释。要设置其他环境变量,取消相应行的注释并提供您的首选值即可。

注意

可能发生更改的任何配置设置都应当定义为一个属性,而不应当在模板中对其进行硬编码。这样,您就无需重写模板来更改设置,只需覆盖该属性即可。

Amazon Linux 模板仅设置一个环境变量,如以下摘录中所示。

... # Use JAVA_OPTS to set java.library.path for libtcnative.so #JAVA_OPTS="-Djava.library.path=/usr/lib" JAVA_OPTS="${JAVA_OPTS} <%= node['tomcat']['java_opts'] %>" # What user should run tomcat #TOMCAT_USER="tomcat" ...

JAVA_ OPTS 可用于指定 Java 选项,例如库路径。如果使用默认的属性值,则模板不会为 Amazon Linux 设置 Java 选项。您可以通过覆盖['tomcat']['java_opts']属性来设置自己的 Java 选项,例如,使用自定义JSON属性。有关示例,请参阅创建堆栈

Ubuntu 模板设置多个环境变量,如以下模板片段所示。

# Run Tomcat as this user ID. Not setting this or leaving it blank will use the # default of tomcat<%= node['tomcat']['base_version'] %>. TOMCAT<%= node['tomcat']['base_version'] %>_USER=tomcat<%= node['tomcat']['base_version'] %> ... # Run Tomcat as this group ID. Not setting this or leaving it blank will use # the default of tomcat<%= node['tomcat']['base_version'] %>. TOMCAT<%= node['tomcat']['base_version'] %>_GROUP=tomcat<%= node['tomcat']['base_version'] %> ... JAVA_OPTS="<%= node['tomcat']['java_opts'] %>" <% if node['tomcat']['base_version'].to_i < 7 -%> # Unset LC_ALL to prevent user environment executing the init script from # influencing servlet behavior. See Debian bug #645221 unset LC_ALL <% end -%>

在使用默认属性值时,模板会将 Ubuntu 环境变量设置如下:

  • TOMCAT6_USERTOMCAT6_GROUP (表示 Tomcat 用户和组) 均被设置为 tomcat6

    如果您将 ['tomcat']['base_version'] 设置为 tomcat7,则变量名称将解析为 TOMCAT7_USERTOMCAT7_GROUP,并且均被设置为 tomcat7

  • JAVA_OPTS 被设置为 -Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC

    • -Djava.awt.headless 设置为 true 可告知图形引擎,实例处于无管模式,没有控制台,这会解决特定图形应用程序的错误行为。

    • -Xmx128m确保JVM有足够的内存资源,在本例中为 128MB。

    • -XX:+UseConcMarkSweepGC 指定并发标记清除垃圾收集,这有助于限制垃圾收集引发的暂停。

      有关更多信息,请参阅:Concurrent Mark Sweep Collector Enhancements

  • 如果 Tomcat 版本低于 7,则模板取消 LC_ALL 的设置,这可以解决 Ubuntu 错误。

注意

使用默认属性,其中一些环境变量会直接被设置为其默认值。但是,将环境变量显式设置为属性意味着您可以定义自定义JSON属性来覆盖默认属性并提供自定义值。有关覆盖属性的更多信息,请参阅覆盖属性

要查看完整的模板文件,请参阅 source code

Server.xml 配置文件

第二个template资源用于创建配置文件server.xml.erb,该文件用于system.xml配置 s ervletJSP/容器。 server.xml.erb不包含操作系统特定的设置,因此它位于template目录的default子目录中。

该模板使用标准设置,但它可以为 Tomcat 6 或 Tomcat 7 创建一个 system.xml 文件。例如,模板的服务器部分中的以下代码可为指定版本正确配置侦听器。

<% if node['tomcat']['base_version'].to_i > 6 -%> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> --> <% end -%> <!--APR library loader. Documentation at /docs/apr.html --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> <Listener className="org.apache.catalina.core.JasperListener" /> <!-- Prevent memory leaks due to use of particular java/javax APIs--> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <% if node['tomcat']['base_version'].to_i < 7 -%> <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --> <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" /> <% end -%> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <% if node['tomcat']['base_version'].to_i > 6 -%> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <% end -%>

模板使用属性代替硬编码设置,因此您可以通过定义自定义JSON属性轻松更改设置。例如:

<Connector port="<%= node['tomcat']['port'] %>" protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="<%= node['tomcat']['uri_encoding'] %>" redirectPort="<%= node['tomcat']['secure_port'] %>" />

有关更多信息,请参阅 source code

tomcat::apache_tomcat_bind

tomcat::apache_tomcat_bind 配方使 Apache 服务器能够充当 Tomcat 的前端,接收传入请求、将其转发到 Tomcat 并将响应返回给客户端。此示例使用 mod_proxy 作为 Apache 代理/网关。

execute 'enable mod_proxy for apache-tomcat binding' do command '/usr/sbin/a2enmod proxy' not_if do ::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', 'proxy.load')) || node['tomcat']['apache_tomcat_bind_mod'] !~ /\Aproxy/ end end execute 'enable module for apache-tomcat binding' do command "/usr/sbin/a2enmod #{node['tomcat']['apache_tomcat_bind_mod']}" not_if {::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', "#{node['tomcat']['apache_tomcat_bind_mod']}.load"))} end include_recipe 'apache2::service' template 'tomcat thru apache binding' do path ::File.join(node['apache']['dir'], 'conf.d', node['tomcat']['apache_tomcat_bind_config']) source 'apache_tomcat_bind.conf.erb' owner 'root' group 'root' mode 0644 backup false notifies :restart, resources(:service => 'apache2') end

要启用 mod_proxy,您必须启用 proxy 模块和一个基于协议的模块。对于协议模块,您有两个选项:

配方的这两个 execute 资源 都运行 a2enmod 命令,该命令通过创建所需的符号链接来启用特定模块:

  • 第一个 execute 资源启用 proxy 模块。

  • 第二个 execute 资源启用协议模块,它在默认情况下被设置为 proxy_http

    如果您更愿意使用AJP,则可以定义 custom JSON 来覆盖该apache_tomcat_bind_mod属性并将其设置为proxy_ajp

apache2::service食谱是 AWS OpsWorks 堆叠定义 Apache 服务的内置配方。有关更多信息,请参阅中的食谱 AWS OpsWorks 堆栈 GitHub 存储库。

template 资源使用 apache_tomcat_bind.conf.erb 创建一个配置文件,默认情况下,该文件被命名为 tomcat_bind.conf。它将该配置文件放在 ['apache']['dir']/.conf.d 目录中。['apache']['dir'] 属性在内置 apache2 属性文件中定义,默认情况下它被设置为 /etc/httpd (Amazon Linux) 或 /etc/apache2 (Ubuntu)。如果 template 资源创建或更改配置文件,则 notifies 命令将计划重新启动 Apache 服务。

<% if node['tomcat']['apache_tomcat_bind_mod'] == 'proxy_ajp' -%> ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/ ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/ <% else %> ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/ ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/ <% end -%>

该模板使用ProxyPassProxyPassReverse指令来配置用于在 Apache 和 Tomcat 之间传递流量的端口。由于两台服务器都在同一个实例上,因此它们可以使用本地主机,URL并且默认情况下都设置为http://localhost:8080