为生产而构建:Web应用程序——部署
介绍
在本教程的这一部分,我们将部署示例 PHP 应用程序、WordPress 和私有 DNS:
您的用户将通过域名通过 HTTPS 访问您的应用程序,例如 “https://www.example.com”,指向负载均衡器。 负载平衡器将充当应用程序服务器的反向代理,应用程序服务器将连接到数据库服务器。 私有 DNS 将使我们能够使用名称来引用我们服务器的私有网络地址,从而简化我们服务器的配置过程。
我们将按以下顺序在六台服务器上设置我们刚刚讨论过的组件:
- 私有 DNS(ns1 和 ns2)
- 数据库服务器 (db1)
- 应用服务器(app1 和 app2)
- 负载平衡器 (lb1)
让我们开始设置 DNS。
私有 DNS 服务器
使用地址名称有助于识别您正在使用的服务器,并且对于维护更大的服务器设置至关重要,因为您可以通过简单地更新您的 DNS 记录(在一个地方)来替换服务器,而不是更新无数的配置文件IP 地址。 在我们的设置中,我们将设置我们的 DNS,以便我们可以通过名称而不是 IP 地址来引用我们服务器的专用网络地址。
我们将通过“nyc3.example.com”子域下的主机名来引用每个服务器的私有网络地址。 例如,数据库服务器的专用网络地址将是“db1.nyc3.example.com”,它解析为它的专用 IP 地址。 请注意,示例子域几乎是完全任意的,通常是根据逻辑组织目的选择的; 在我们的例子中,“nyc3”表示服务器位于 NYC3 数据中心,“example.com”是我们应用程序的域名。
按照本教程进行设置,并为设置中的每个服务器添加 DNS 记录:
完成 DNS 教程后,您应该有两个 BIND 服务器:ns1 和 ns2。 如果您已经知道设置中所有服务器的私有 IP 地址,请立即将它们添加到您的 DNS; 否则,请在创建服务器时添加适当的 DNS 记录。
现在我们已经准备好设置我们的数据库服务器了。
设置数据库服务器
因为我们要对我们的应用服务器进行负载均衡,即 对于运行 Apache 和 PHP 的那些,我们需要将数据库与应用程序服务器分离,方法是将其设置在单独的服务器上。 将数据库与应用程序解耦是在水平扩展许多类型的应用程序之前必不可少的步骤,如本博文所述:水平扩展 PHP 应用程序:实用概述 。
本节介绍了设置我们的数据库服务器的所有必要步骤,但您可以在本教程中了解有关为 PHP 应用程序设置远程、解耦 MySQL 数据库服务器的更多信息:如何设置远程 MySQL 数据库[ X241X]。
安装 MySQL
在数据库服务器 db1 上,安装 MySQL 服务器:
sudo apt-get update sudo apt-get -y install mysql-server
在提示符处输入您想要的 MySQL root 密码。
现在运行:
sudo mysql_install_db sudo mysql_secure_installation
您必须输入在上述步骤中设置的 MySQL 管理员密码。 之后,它会询问您是否要更改该密码。 如果您对当前密码感到满意,请输入“N”表示否。 用默认值回答其余问题。
将 MySQL 配置为侦听专用网络接口
打开 MySQL 配置文件:
sudo vi /etc/mysql/my.cnf
找到 bind-address
设置,并将其更改为您的数据库服务器的私有网络地址的地址:
/etc/mysql/my.cnf
bind-address = db1.nyc3.example.com
保存并退出。
重启 MySQL:
sudo service mysql restart
设置数据库和数据库用户
现在我们需要创建应用程序服务器将用来连接的数据库和数据库用户。
进入 MySQL 控制台:
mysql -u root -p
在提示符处输入 MySQL root 密码。
在 MySQL 提示符下,为您的应用程序创建数据库:
CREATE DATABASE app;
MySQL 将其用户与他们应该连接的服务器相关联。 在我们的例子中,我们有两个将要连接的应用服务器,所以我们应该为每个服务器创建一个用户。 创建一个数据库用户,在我们的示例中为“appuser”,可以从每个应用程序服务器的专用网络地址(app1 和 app2)连接到该用户。 您应该为每个用户使用相同的密码:
CREATE USER 'appuser'@'app1.nyc3.example.com' IDENTIFIED BY 'password'; CREATE USER 'appuser'@'app2.nyc3.example.com' IDENTIFIED BY 'password';
稍后我们将配置最终的数据库用户权限,但让 appuser 完全控制 app 数据库:
GRANT ALL PRIVILEGES ON app.* TO 'appuser'@'app1.nyc3.example.com'; GRANT ALL PRIVILEGES ON app.* TO 'appuser'@'app2.nyc3.example.com'; FLUSH PRIVILEGES;
这些宽松的权限确保应用程序的安装程序能够在数据库中安装应用程序。 如果您有两个以上的应用程序服务器,您现在应该创建所有必要的数据库用户。
现在退出 MySQL 提示:
exit
数据库服务器设置完成。 让我们设置应用程序服务器。
设置应用程序服务器
应用程序服务器将运行我们应用程序的代码,该代码将连接到数据库服务器。 我们的示例应用程序是 WordPress,它是一个 PHP 应用程序,通过 Apache 或 Nginx 等 Web 服务器提供服务。 因为我们要对应用程序服务器进行负载平衡,所以我们将设置两个相同的服务器。
本节涵盖了设置我们的应用程序服务器的所有必要步骤,但该主题将在以下教程中详细介绍,从 设置 Web 服务器 部分开始:如何设置远程数据库。
安装 Apache 和 PHP
在两个应用服务器 app1 和 app2 上,安装 Apache 和 PHP:
sudo apt-get update sudo apt-get -y install apache2 php5-mysql php5 libapache2-mod-php5 php5-mcrypt
配置阿帕奇
我们将在负载平衡器服务器上使用 HAProxy 来处理 SSL 终止,因此我们不希望我们的用户直接访问应用程序服务器。 因此,我们将 Apache 绑定到每个服务器的专用网络地址。
在每个应用程序服务器 app1 和 app2 上,打开 Apache 端口配置文件。 默认情况下,这是 ports.conf
文件:
sudo vi /etc/apache2/ports.conf
找到显示 Listen 80
的行,并将您的私有 IP 地址添加到其中,如下所示(替换为您服务器的实际 IP 地址):
Apache ports.conf — 监听私有接口
Listen private_IP:80
保存并退出。 这将 Apache 配置为仅在专用网络接口上侦听,这意味着公共 IP 地址或主机名无法访问它。
重新启动 Apache 以使更改生效:
sudo service apache2 restart
现在只能通过应用程序服务器的专用网络地址访问 Apache。 稍后,我们将配置负载均衡器以在此处发送用户请求。
下载和配置应用程序
在我们的示例中,我们使用 WordPress 作为我们的应用程序。 如果您使用不同的 PHP 应用程序,请下载它并执行任何相关配置(例如 数据库连接信息),然后跳到下一节。
在第一个应用服务器 app1 上,下载 WordPress 存档:
cd ~ wget http://wordpress.org/latest.tar.gz
提取 WordPress 存档:
tar xvf latest.tar.gz
切换到解压目录:
cd wordpress
WordPress 需要为其上传创建一个目录,wp-content/uploads
。 现在让我们这样做:
mkdir wp-content/uploads
我们将使用示例 WordPress 配置文件作为模板。 将其复制到正确的位置:
cp wp-config-sample.php wp-config.php
现在打开配置文件进行编辑:
vi wp-config.php
通过更改以下行中突出显示的信息来配置 WordPress 数据库连接:
wp-config.php
/** The name of the database for WordPress */ define('DB_NAME', 'app'); /** MySQL database username */ define('DB_USER', 'appuser'); /** MySQL database password */ define('DB_PASSWORD', 'password'); /** MySQL hostname */ define('DB_HOST', 'db1.nyc3.example..com');
因为我们将在负载均衡服务器上使用 TLS/SSL 加密,所以我们必须添加以下行,以便 WordPress 知道它位于使用 SSL 的反向代理后面:
define('FORCE_SSL_ADMIN', true); if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS']='on';
您还需要更新密钥和盐,以便您可以在需要时使 cookie 无效。 我们不会在这里介绍,但请确保它们在您的所有应用程序服务器上都是相同的。
保存并退出。
WordPress 现在已配置,但必须将其文件复制到我们的 Web 服务器软件提供服务的正确位置。
将应用程序文件复制到文档根目录
现在我们已经配置了我们的应用程序,我们需要将它复制到 Apache 的文档根目录中,在那里它可以提供给我们网站的访问者。
Apache DocumentRoot 的默认位置是 /var/www/html
,因此我们将在示例中使用它。
首先,删除默认的index.html
文件:
sudo rm /var/www/html/index.html
然后使用 rsync 将 WordPress 文件复制到 /var/www/html
,并将 www-data
(Apache 运行的用户)设为所有者:
sudo rsync -avP ~/wordpress/ /var/www/html sudo chgrp -R www-data /var/www/html/*
我们的第一个应用服务器 app1 已准备就绪。 我们将设置另一个应用程序服务器。
将应用程序文件复制到其他服务器
为了使您的应用程序文件在各种应用程序服务器之间保持一致,您应该设置 Web 服务器文档根目录的文件复制。 对于 WordPress,使用 Web 界面上传文件和安装插件会将文件存储在处理请求的特定服务器上。 如果这些文件没有复制到您的所有应用程序服务器,您的一些用户将看到缺少图像和损坏插件的页面。 如果您的 PHP 应用程序不是 WordPress 并且不存储其任何数据(例如 上传的文件或下载的插件)在应用程序服务器上,您只需手动复制应用程序文件一次。 如果是这种情况,请使用 rsync 将应用程序文件从 app1 复制到 app2。
GlusterFS 可用于创建必要文件的复制卷,并在本教程的 同步 Web 应用程序文件 部分进行了演示:如何使用 HAProxy 作为 WordPress 应用程序服务器的负载均衡器。 按照说明操作(跳过 Edit Hosts File 部分,因为我们的 DNS 会处理这些)并设置 app1 和 app2 之间的复制。
正确设置复制后,您的两个应用程序服务器都应该正确配置。 现在让我们设置我们的负载均衡器。
设置负载均衡器服务器
我们的负载均衡器服务器将运行 HAProxy,它将作为我们应用程序服务器的反向代理负载均衡器。 您的用户将通过 https://www.example.com
之类的 URL 通过负载平衡器服务器访问您的应用程序。
本节涵盖了设置负载均衡器服务器的所有必要步骤,但以下教程将详细介绍该主题:
- 如何在 Ubuntu 14.04 上使用 HAProxy 作为 WordPress 和 Nginx 的第 7 层负载均衡器
- 如何在 Ubuntu 14.04 上使用 HAProxy 实现 SSL 终止:
复制 SSL 证书
在负载平衡器服务器 lb1 上执行这些步骤。
在包含您的 SSL 证书(第 1 部分中的先决条件之一)的目录中,将您的证书、任何中间 CA 证书和证书的密钥组合到一个 .pem
文件中。 例如(我们的证书在 /root/certs
中:
cd /root/certs cat www.example.com.crt CAintermediate.ca-bundle www.example.com.key > www.example.com.pem
然后将pem文件复制到/etc/ssl/private
:
sudo cp www.example.com.pem /etc/ssl/private/ ``` This file will be used by HAProxy for SSL termination. ### Install HAProxy On the load balancer server, **lb1**, install HAProxy: ```command sudo add-apt-repository ppa:vbernat/haproxy-1.5 sudo apt-get update sudo apt-get -y install haproxy ``` Now let's configure HAProxy. ### HAProxy Configuration We need to configure HAProxy with some reasonable settings, SSL termination, and the appropriate frontends and backends to make it work with our application servers. Open the HAProxy configuration file for editing: ```command sudo vi /etc/haproxy/haproxy.cfg ``` #### HAProxy Configuration: General Settings The first thing you will want to do is set maxconn to a reasonable number. This setting affects how many concurrent connections HAProxy will allow, which can affect QoS and prevent your web servers from crashing from trying to serve too many requests. You will need to play around with it to find what works for your environment. Add the following line (with a value you think is reasonable) to the global section of the configuration: ``` [label haproxy.cfg — maxconn] maxconn 2048 ``` Add this line, to configure the maximum size of temporary DHE keys that are generated: ``` [label haproxy.cfg — tune.ssl.default-dh-param] tune.ssl.default-dh-param 2048 ``` Next, in the defaults section, add the following lines under the line that says mode http: ``` [label haproxy.cfg ] option forwardfor option http-server-close ``` If you would like to enable the HAProxy stats page, add the following lines in the defaults section (substitute user and password with secure values): ``` [label haproxy.cfg ] stats enable stats uri /stats stats realm Haproxy\ Statistics stats auth user:password ``` This will allow you to look at the HAProxy stats page by going to your domain on /stats (e.g. "https://www.example.com/stats"). Do not close the config file yet! We will add the proxy configuration next. #### HAProxy Configuration: Proxies The first thing we want to add is a frontend to handle incoming HTTP connections. At the end of the file, let's add a frontend called www-http: ``` frontend www-http bind www.example.com:80 reqadd X-Forwarded-Proto:\ http default_backend app-backend ``` The purpose of this frontend is to accept HTTP connections so they can be redirected to HTTPS. Now add a frontend to handle the incoming HTTPS connections. Make sure to specify the appropriate `pem` certificate: ``` frontend www-https bind www.example.com:443 ssl crt /etc/ssl/private/www.example.com.pem reqadd X-Forwarded-Proto:\ https default_backend app-backend ``` After you are finished configuring the frontends, continue adding your backend by adding the following lines: ``` backend app-backend redirect scheme https if !{ ssl_fc } server app1 app1.nyc3.example.com:80 check server app2 app2.nyc3.example.com:80 check ``` This backend specifies which application servers to send the load balanced traffic to. Also, the `redirect scheme https` line tells it to redirect HTTP connections to HTTPS. Now save and exit haproxy.cfg. HAProxy is now ready to be started, but let's enable logging first. ### Enable HAProxy Logging Open the rsyslog configuration file: ```command sudo vi /etc/rsyslog.conf ``` Then find the following lines and uncomment them to enable UDP syslog reception. It should look like the following when you're done: ``` [label /etc/rsyslog.conf] $ModLoad imudp $UDPServerRun 514 $UDPServerAddress 127.0.0.1 ``` Now restart rsyslog to enable the new configuration: ``` sudo service rsyslog restart ``` HAProxy logging is is now enabled! The log file will be created at `/var/log/haproxy.log` once HAProxy is started. ### Restart HAProxy Restart HAProxy to put the changes into effect: ```command sudo service haproxy restart ``` Our load balancer is now set up. Now we need to run the application's install script. ## Install WordPress We must run the WordPress installation script, which prepares the database for its use, before we can use it. Open your site in a web browser: ``` [secondary_label Open in a Web Browser] https://www.example.com/wp-admin/install.php ``` This will display the WordPress installation screen. Fill out the forms and click the **Install WordPress** button. After WordPress installs, the application is ready to be used. ## Conclusion The servers that comprise your application are now set up, and your application is ready to be used. You may log in as the admin user, and your users may access the site over HTTPS via the proper domain name. Be sure to test out your application and make sure that it works as expected before moving on. Continue to the next tutorial to start working on the recovery plan for your production application setup: [Building for Production: Web Applications — Recovery Planning](building-for-production-web-applications-recovery-planning).