如何在Ubuntu 14.04上使用Ansible部署多个PHP应用程序

介绍

本教程是关于在Ubuntu 14.04上使用Ansible部署PHP应用程序的系列文章中的第三篇。第一个教程涵盖了部署应用程序的基本步骤; 在第二个教程介绍更高级的主题,如数据库,队列守护进程和任务调度(crons)。

在本教程中,我们将基于我们在前面的教程中学到的内容,将我们的单应用程序Ansible playbook转换为支持在一个或多个服务器上部署多个PHP应用程序的playbook。在使用Ansible以最小的努力部署应用程序时,这是最后一块拼图。

我们将使用几个简单的Lumen应用程序作为我们示例的一部分。但是,如果您已拥有自己的框架和应用程序,则可以轻松修改这些说明以支持其他框架和应用程序。建议您使用示例应用程序,直到您可以轻松地对剧本进行更改。

先决条件

要学习本教程,您需要:

  • 按照本系列的第一第二个教程设置两个腾讯CVM 。
  • 新的(第三个)Ubuntu 14.04腾讯CVM设置与第一个教程中的原始PHP 腾讯CVM一样,具有sudo非root用户和SSH密钥。此腾讯CVM将用于演示如何使用一个Ansible playbook将多个应用程序部署到多个服务器。我们将把原来的PHP腾讯CVM的IP地址和这个新的PHP腾讯CVM的IP地址分别作为your_first_server_ipyour_second_server_ip
  • 在本地计算机上的更新文件/etc/hosts中,添加以下行。您可以在本教程的第6步中了解有关此文件的更多信息。
your_first_server_ip laravel.example.com one.example.com two.example.com
your_second_server_ip laravel.example2.com two.example2.com

我们将在本教程中使用的示例网站是laravel.example.comone.example.comtwo.example.com

第1步 - 设置Playbook变量

在这一步中,我们将设置playbook变量来定义我们的新应用程序。

在之前的教程中,我们对所有配置细节进行了硬编码,这对于执行特定应用程序特定任务的许多剧本来说是正常的。但是,当您希望支持多个应用程序或扩大您的剧本范围时,将所有内容硬编码就都不再具有意义。

正如我们之前看到的,Ansible提供了可以在任务定义和文件模板中使用的变量。我们还没有看到的是如何手动设置变量。在你的剧本的顶部,除了旁边的hoststasks参数,你还可以自己定义一个vars参数,并在那里设置变量。

如果您还没有这样做,请从以前的教程中学习并将目录更改为ansible-php

cd ~/ansible-php/

打开我们现有的剧本进行编辑。

nano php.yml

文件顶部应如下所示:

---
- hosts: php
  sudo: yes
​
  tasks:
. . .

要定义变量,我们可以就在在hostssudotasks的旁边添加一个vars部分。为了简单起见,我们将从一个非常基本用户名变量www-data开始,如下所示:

---
- hosts: php
  sudo: yes
​
  vars:
    wwwuser: www-data
​
  tasks:
. . .

接下来,检查并使用新变量{{ wwwuser }}将所有出现的www-data用户更新。这种格式您应该很熟悉,因为我们已经在外观和查找中使用了它。

要查找和替换使用nano,请按CTRL+\。你会看到一个提示,这表示搜索(更换)。输入www-data,然后按ENTER。这时提示会更改为替换为:。在此处输入{{wwwuser}}并再按ENTER一次。Nano将带您通过www-data的每个实例并询问替换此实例?。您可以按y来逐个替换每个,或者按a来进行全部替换。

注意:确保我们刚刚添加到顶部的变量声明也不会更改。应该有11个需要更换的www-data实例。

在我们进一步讨论之前,当涉及变量时,有一些事项需要我们注意。当它们在更长的行内时,我们通常可以像这样添加它们:

- name: create /var/www/ directory
  file: dest=/var/www/ state=directory owner={{ wwwuser }} group={{ wwwuser }} mode=0700

但是,如果变量是字符串中唯一的值,我们需要将其包装在引号中,以便YAML解析器可以正确理解它:

- name: Run artisan migrate
  shell: php /var/www/laravel/artisan migrate --force
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: dbpwd.changed

在你的剧本中,任何时候当你有sudo_user: {{ wwwuser }}时,你都需要执行此步骤。您可以使用全局查找然后以同样的方式进行替换,来取代sudo_user:{{wwwuser}}sudo_user: “{{wwwuser}}” 。这里应该有四行需要这种改变。

更改完所有内容后,保存并运行playbook:

ansible-playbook php.yml --ask-sudo-pass

当没有更改任务的时候,就意味着我们的wwwuser变量正常工作。

第2步 - 为复杂配置定义嵌套变量

在本节中,我们将介绍复杂配置选项的嵌套变量。

在上一步中,我们设置了一个基本变量。但是,也可以嵌套变量并定义变量列表。这提供了我们需要来定义我们希望在服务器上建立的站点列表的功能。

首先,让我们考虑一下我们在playbook中设置的现有git存储库:

- name: Clone git repository
  git: >
    dest=/var/www/laravel
    repo=https://github.com/do-community/do-ansible-adv-php.git
    update=yes
    version=example

我们可以提取以下有用的信息:名称(目录),存储库,分支和域。因为我们正在设置多个应用程序,所以我们还需要一个域名来响应。在这里,我们将使用laravel.example.com,但如果您有自己的域名,则可以替换它。

这导致我们可以为此应用程序定义以下四个变量:

name: laravel
repository: https://github.com/do-community/do-ansible-adv-php.git
branch: example
domain: laravel.example.com

现在,打开你的剧本进行编辑:

nano php.yml

在顶部vars部分,我们可以将我们的应用程序添加到新的应用程序列表中:

更新了php.yml中的应用程序变量

---
- hosts: php
  sudo: yes
​
  vars:
    wwwuser: www-data
​
    applications:
      - name: laravel
        domain: laravel.example.com
        repository: https://github.com/do-community/do-ansible-adv-php.git
        branch: example
​
...

如果你现在运行你的剧本(使用ansible-playbook php.yml --ask-sudo-pass),并没有什么会发生改变,因为我们还没有设置我们的任务来使用我们的新applications变量。但是,如果您在浏览器中访问http://laravel.example.com/,它应该显示我们的原始应用程序。

第3步 - 在任务中循环变量

在本节中,我们将学习如何遍历任务中的变量列表。

如前所述,变量列表需要在我们希望使用它们的每个任务中循环。正如我们在install packages任务中看到的那样,我们需要定义一个项循环,然后为列表中的每个项应用任务。

打开你的剧本进行编辑:

nano php.yml

我们先从一些简单的任务开始。在游戏手册的中间,您应该找到以下两个env任务:

- name: set APP_DEBUG=false
  lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
​
- name: set APP_ENV=production
  lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production

您会注意到它们目前使用该laravel目录进行了硬编码。我们想要更新它以使用每个应用程序的name属性。为此,我们添加with_items选项以循环我们的applications列表。在任务本身内,我们将换出变量{{ item.name }}laravel引用,这应该是和我们以前使用过的格式很类似的。

它应该如下所示:

- name: set APP_DEBUG=false
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false
  with_items: applications
​
- name: set APP_ENV=production
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_ENV=' line=APP_ENV=production
  with_items: applications

接下来,向下移动两个Laravel artisan cron任务。它们的更新方式与我们刚刚完成的env任务完全相同。我们还将添加item.name到cron条目的name参数中,因为Ansible使用此字段来唯一标识每个cron条目。如果我们按原样离开它们,我们将无法在同一服务器上拥有多个站点,因为它们会不断地覆盖每个站点,最终只会保存最后一个站点。

任务应如下所示:

- name: Laravel Scheduler
  cron: >
    job="run-one php /var/www/{{ item.name }}/artisan schedule:run 1>> /dev/null 2>&1"
    state=present
    user={{ wwwuser }}
    name="{{ item.name }} php artisan schedule:run"
  with_items: applications
​
- name: Laravel Queue Worker
  cron: >
    job="run-one php /var/www/{{ item.name }}/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1"
    state=present
    user={{ wwwuser }}
    name="{{ item.name }} Laravel Queue Worker"
  with_items: applications

如果您现在保存并运行该剧本(使用ansible-playbook php.yml --ask-sudo-pass),您应该只看到两个更新的cron任务被更新。这是由于name参数的变化。除此之外,没有任何变化,这意味着我们的应用程序列表正在按预期工作,我们还没有通过重构我们的playbook对我们的服务器进行任何更改。

第4步 - 在模板中应用循环变量

在本节中,我们将介绍如何在模板中使用循环变量。

模板中的循环变量非常简单。它们的使用方式与在任务中使用的方式完全相同,就像所有其他变量一样。当你考虑文件路径和变量时会出现复杂性,因为在某些用途中我们需要考虑文件名,甚至因为新文件而运行其他命令。

对于Nginx,我们需要为每个应用程序创建一个新的配置文件,并告诉Nginx应该启用它。我们还希望在此过程中删除原始配置文件/etc/nginx/sites-available/default

首先,打开你的剧本进行编辑:

nano php.yml

找到Configure Nginx任务(靠近剧本中间),并像我们完成其他任务一样更新它:

- name: Configure nginx
  template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }}
  with_items: applications
  notify:
    - restart php5-fpm
    - restart nginx

虽然我们已经到了这一步,但我们还将增加上面提到的两个任务。首先,我们将告诉Nginx我们的新站点配置文件。这是通过在/var/nginx/中的sites-availablesites-enabled目录之间的符号链接来完成的。

在任务之后添加此Configure nginx任务:

- name: Configure nginx symlink
  file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link
  with_items: applications
  notify:
    - restart php5-fpm
    - restart nginx

接下来,我们要删除已启用的站点配置文件default,以免它导致我们的新站点配置文件出现问题。这可以通过file模块轻松完成:

- name: Remove default nginx site
  file: path=/etc/nginx/sites-enabled/default state=absent
  notify:
    - restart php5-fpm
    - restart nginx

请注意,我们不需要循环applications,因为我们正在寻找单个文件。

您的剧本中的Nginx块现在应该如下所示:

- name: Configure nginx
  template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }}
  with_items: applications
  notify:
    - restart php5-fpm
    - restart nginx
​
- name: Configure nginx symlink
  file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link
  with_items: applications
  notify:
    - restart php5-fpm
    - restart nginx
​
- name: Remove default nginx site
  file: path=/etc/nginx/sites-enabled/default state=absent
  notify:
    - restart php5-fpm
    - restart nginx

保存您的剧本并打开nginx.conf文件进行编辑:

nano nginx.conf

更新配置文件,使其使用我们的变量:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
​
    root /var/www/{{ item.name }}/public;
    index index.php index.html index.htm;
​
    server_name {{ item.domain }};
​
    location / {
        try_files $uri $uri/ =404;
    }
​
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/{{ item.name }}/public;
    }
​
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

但是,我们尚未完成。请注意顶部的default_server?我们希望仅包含laravel应用程序的内容,使其成为默认值。为此,我们可以使用基本的IF语句来检查item.name是否等于laravel,如果是,则显示default_server

它看起来像这样:

server {
    listen 80{% if item.name == "laravel" %} default_server{% endif %};
    listen [::]:80{% if item.name == "laravel" %} default_server ipv6only=on{% endif %};

相应地更新nginx.conf并保存。

现在是时候运行我们的剧本了:

ansible-playbook php.yml --ask-sudo-pass

您应该注意到Nginx任务已标记为已更改。完成运行后,在浏览器中刷新站点,它应该显示与上一个教程末尾相同的内容:

Queue: YES
Cron: YES

第5步 - 一起循环多个变量

在这一步中,我们将在任务中循环多个变量。

现在是时候解决一个更复杂的循环示例,特别是注册变量。为了支持不同的状态并防止任务不必要地运行,您将记住我们在克隆git存储库任务中使用的register: cloned的方法是将cloned变量注册成为任务的状态。然后,我们在以下任务中使用when: cloned|changed来条件地触发任务。现在我们需要更新这些引用以支持应用程序循环。

首先,打开你的剧本进行编辑:

nano php.yml

往继续下看Clone git仓库任务:

- name: Clone git repository
  git: >
    dest=/var/www/laravel
    repo=https://github.com/do-community/do-ansible-adv-php.git
    update=yes
    version=example
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  register: cloned

当我们在此任务中注册变量时,我们不需要执行任何我们尚未执行的操作:

- name: Clone git repository
  git: >
    dest=/var/www/{{ item.name }}
    repo={{ item.repository }}
    update=yes
    version={{ item.branch }}
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  with_items: applications
  register: cloned

现在,向下移动您的剧本,直到找到composer create-project任务:

- name: composer create-project
  composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: cloned|changed

现在,我们需要通过将其更新为同时循环 applicationscloned。这是通过使用with_together选项完成的,并将其传入applicationscloned。当with_together循环通过两个变量时,通过使用item.#来完成访问项,其中#是定义的变量的索引。例如:

with_together:
- list_one
- list_two

item.0可以参考list_oneitem.1可以参考list_two

这意味着,对于applications,我们可以通过item.0.name的方式访问这些属性:。对于cloned,我们需要从任务中传递结果,这些结果可以通过cloned.results进行访问,然后我们可以检查它是否已通过item.1.changed进行更改。

这意味着任务变为:

- name: composer create-project
  composer: command=create-project working_dir=/var/www/{{ item.0.name }} optimize_autoloader=no
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: item.1.changed
  with_together:
    - applications
    - cloned.results

现在保存并运行你的剧本:

ansible-playbook php.yml --ask-sudo-pass

此次运行应该没有任何变化。但是,我们现在有一个注册变量在循环中很好地工作。

第6步 - 复杂的注册变量和循环

在本节中,我们将了解更复杂的已注册变量和循环。

转换中最复杂的部分是处理我们用于MySQL数据库密码生成的注册变量。也就是说,在我们尚未涉及的这一步骤中我们不得不做更多的事情,我们只需要立即更新一些任务。

打开您的剧本进行编辑:

nano php.yml

找到MySQL任务,在我们的初始传递中,我们将添加基本变量,就像我们在之前的任务中所做的那样:

- name: Create MySQL DB
  mysql_db: name={{ item.name }} state=present
  with_items: applications

- name: Generate DB password
  shell: makepasswd --chars=32
  args:
    creates: /var/www/{{ item.name }}/.dbpw
  with_items: applications
  register: dbpwd

- name: Create MySQL User
  mysql_user: name={{ item.name }} password={{ dbpwd.stdout }} priv={{ item.name }}.*:ALL state=present
  when: dbpwd.changed

- name: set DB_DATABASE
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }}
  with_items: applications

- name: set DB_USERNAME
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }}
  with_items: applications

- name: set DB_PASSWORD
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }}
  when: dbpwd.changed

- name: Save dbpw file
  lineinfile: dest=/var/www/{{ item.name }}/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: dbpwd.changed

- name: Run artisan migrate
  shell: php /var/www/{{ item.name }}/artisan migrate --force
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: dbpwd.changed

接下来我们将添加 with_together ,以便我们可以使用我们的数据库密码。对于我们的密码生成,我们需要循环dbpwd.results,并且能够从item.1.stdout中访问密码,因为我们将通过item.0访问applications

我们可以相应地更新我们的剧本:

- name: Create MySQL DB
  mysql_db: name={{ item.name }} state=present
  with_items: applications

- name: Generate DB password
  shell: makepasswd --chars=32
  args:
    creates: /var/www/{{ item.name }}/.dbpw
  with_items: applications
  register: dbpwd

- name: Create MySQL User
  mysql_user: name={{ item.0.name }} password={{ item.1.stdout }} priv={{ item.0.name }}.*:ALL state=present
  when: item.1.changed
  with_together:
  - applications
  - dbpwd.results

- name: set DB_DATABASE
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }}
  with_items: applications

- name: set DB_USERNAME
  lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }}
  with_items: applications

- name: set DB_PASSWORD
  lineinfile: dest=/var/www/{{ item.0.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ item.1.stdout }}
  when: item.1.changed
  with_together:
  - applications
  - dbpwd.results

- name: Save dbpw file
  lineinfile: dest=/var/www/{{ item.0.name }}/.dbpw line="{{ item.1.stdout }}" create=yes state=present
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: item.1.changed
  with_together:
  - applications
  - dbpwd.results

- name: Run artisan migrate
  shell: php /var/www/{{ item.0.name }}/artisan migrate --force
  sudo: yes
  sudo_user: "{{ wwwuser }}"
  when: item.1.changed
  with_together:
  - applications
  - dbpwd.results

更新了Playbook后,保存并运行它:

ansible-playbook php.yml --ask-sudo-pass

尽管我们对我们的剧本进行了所有更改,但数据库任务应该没有变化。通过此步骤的更改,我们应该完成从单个应用程序手册到多个应用程序手册的转换。

第7步 - 添加更多应用程序

在这一步中,我们将在我们的剧本中配置另外两个应用程序。

既然我们已经重构了我们的playbook从而可以使用变量来定义应用程序,那么向我们的服务器添加新应用程序的过程非常简单。只需将它们添加到applications变量列表中即可。这就是Ansible变量的力量真正闪耀的地方。

打开您的剧本进行编辑:

nano php.yml

在顶部,在该vars部分中,找到applications块:

applications:
  - name: laravel
    domain: laravel.example.com
    repository: https://github.com/do-community/do-ansible-adv-php.git
    branch: example

现在再添加两个应用程序:

applications:
  - name: laravel
    domain: laravel.example.com
    repository: https://github.com/do-community/do-ansible-adv-php.git
    branch: example

  - name: one
    domain: one.example.com
    repository: https://github.com/do-community/do-ansible-php-example-one.git

    branch: master

  - name: two
    domain: two.example.com
    repository: https://github.com/do-community/do-ansible-php-example-two.git
    branch: master

保存你的剧本。

现在是时候运行你的剧本了:

ansible-playbook php.yml --ask-sudo-pass

当设计者设置新的应用程序时,此步骤可能需要一段时间。完成后,您会注意到一些任务被更改,如果您仔细查看,您会注意到每个循环项目都会被列出。首先,我们的原始应用程序应该说ok或者skipped,而新的两个应用程序应该说changed

更重要的是,如果您在Web浏览器中访问已配置站点的所有三个域,则应注意三个不同的网站。

第一个应该看起来很熟悉。另外两个应该显示:

This is example app one!

This is example app two!

有了它,我们只需更新我们的应用程序列表就可以部署两个新的Web应用程序。

第8步 - 使用主机变量

在这一步中,我们将变量提取到宿主变量。

退一步来说,Playbook变量很好,但是如果我们想使用相同的playbook将不同的应用程序部署到不同的服务器上呢?我们可以对每个任务进行条件检查,以确定哪个服务器正在运行任务,或者我们可以使用主机变量。主变量就是它们听起来的样子:适用于特定主机的变量,而不是整个剧本中的所有主机。

主机变量可以在hosts文件中内联定义,就像我们使用ansible_ssh_user变量一样,或者可以在目录中的每个主机的专用host_vars文件中被定义。

首先,在我们的hosts文件和我们的剧本旁边创建一个新目录。叫做host_vars目录:

mkdir host_vars

接下来,我们需要为主机创建一个文件。Ansible使用的约定是文件名与hosts文件中的主机名匹配。因此,例如,如果您的hosts文件如下所示:

[php]
your_first_server_ip ansible_ssh_user=sammy

然后你应该创建一个名为host_vars/your_first_server_ip的文件。我们现在创建:

nano host_vars/your_first_server_ip

与我们的剧本一样,主机文件使用YAML进行格式化。这意味着我们可以将applications列表复制到新的主机文件中,因此它看起来像这样:

---
applications:
  - name: laravel
    domain: laravel.example.com
    repository: https://github.com/do-community/do-ansible-adv-php.git
    branch: example

  - name: one
    domain: one.example.com
    repository: https://github.com/do-community/do-ansible-php-example-one.git
    branch: master

  - name: two
    domain: two.example.com
    repository: https://github.com/do-community/do-ansible-php-example-two.git
    branch: master

保存新的主机文件,然后打开您的剧本进行编辑:

nano php.yml

更新顶部以删除整个applications部分:

---
- hosts: php
  sudo: yes

  vars:
    wwwuser: www-data

  tasks:
. . .

保存剧本,然后运行它:

ansible-playbook php.yml --ask-sudo-pass

即使我们已将变量从我们的playbook移动到我们的宿主文件,输出应该看起来完全相同,并且Ansible不应该报告这里有任何变化。正如您所看到的,host_vars工作方式与vars在剧本中的工作方式完全相同; 它们仅适用于主机。

host_vars文件中定义的变量也可以在管理服务器的所有剧本中被访问,这对于常用选项和设置很有用。但是,请注意不要在不同的剧本中使用可能意味着不同内容的通用名称。

步骤9 - 在另一台服务器上部署应用程序

在此步骤中,我们将使用新的主机文件并在第二台服务器上部署应用程序。

首先,我们需要使用新主机更新我们的hosts文件。打开它进行编辑:

nano hosts

并添加到您的新主机:

[php]
your_first_server_ip ansible_ssh_user=sammy
your_second_server_ip ansible_ssh_user=sammy

保存并关闭文件。

接下来,我们需要创建一个新的hosts文件,就像我们在第一个文件中所做的那样。

nano host_vars/your_second_server_ip

您可以选择一个或多个示例应用程序并将其添加到主机文件中。例如,如果要将原始示例和示例2部署到新服务器,可以使用:

---
applications:
  - name: laravel
    domain: laravel.example2.com
    repository: https://github.com/do-community/do-ansible-adv-php.git
    branch: example

  - name: two
    domain: two.example2.com
    repository: https://github.com/do-community/do-ansible-php-example-two.git
    branch: master

保存你的剧本。

最后我们可以运行我们的剧本:

ansible-playbook php.yml --ask-sudo-pass

Ansible需要一段时间才能运行,因为它是在第二台服务器上设置了所有内容。完成后,在浏览器中打开您选择的应用程序(我们在示例中使用了laravel.example2.com two.example2.com)并确认它们已正确设置。您应该看到为主机文件选择的特定应用程序,并且原始服务器应该没有更改。

结论

本教程采用了功能齐全的单一应用程序手册,并将其转换为支持跨多个服务器的多个应用程序。结合前面教程中介绍的主题,您应该拥有编写完整的Playbook来部署应用程序所需的一切。根据之前的教程,我们仍然没有使用SSH直接登录到服务器。

一旦我们完成了剧本的结构,您就会注意到添加更多应用程序和另一台服务器是多么简单。这是Ansible的强大功能,也是它如此灵活易用的原因。

更多Ubuntu教程请前往腾讯云+社区学习更多知识。


参考文献:《How To Deploy Multiple PHP Applications using Ansible on Ubuntu 14.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏流媒体

gcc用法以及静态/动态链接

-E:只进行预处理,不编译 -S:只编译,不汇编 -c:只编译、汇编,不链接 -g:编译器在编译的时候产生调试信息。 -I:指定include包含文件的...

862
来自专栏林德熙的博客

win10 uwp Markdown 输入需求文件文件格式文件类保存设置界面拼写检查云创建Html创建pdfGit

输入标题方式可以使用快捷键,也可以手动输入“#”,一个“#” 表示一级标题,两个个“#” 表示二级标题,三个“#” 表示三级标题,其他表示多级标题。

1013
来自专栏有趣的django

Django搭建blog网站(一)

一、前言 1.1.环境 python版本:3.6 Django版本:1.11.6 1.2.预览效果 最终搭建的blog的样子,基本上满足需求了。框架搭好了,至于...

8478
来自专栏Aloys的开发之路

Eclipse相关问题

MANIFEST.MF文件 在Eclipse的.classpath和runableX.jar中的MANIFEST.MF文件中都指定了可依赖jar包的顺序,所以只...

2806
来自专栏知晓程序

开发 | 如何在微信小程序的页面间传递数据?

我们在之前发布过小程序页面传值方法的简单介绍,说明了在小程序开发中,两种常见的页面之间传值方法。

1112
来自专栏守望轩

Visual Studio 2008 每日提示(十一)

#101、块缩进和智能缩进的差异 原文链接:what’s the difference between smart indenting and block i...

2933
来自专栏微信终端开发团队的专栏

XCode基本使用及调试技巧

对于初学iOS开发的同学,了解了Objective-C的基本使用后,最关心的应该是如何把OC程序运行起来。由于Xcode的基本使用比较简单,所以本文着重介绍一些...

6277
来自专栏计算机编程

Vue 单文件组件详解<1>--简单上手

vue 的webpack的结构非常简单,简单的一眼就可以知道每个目录下是干啥的,在components目录下就有属于我们想要详细解析的内容,这两个vue文件即为...

931
来自专栏挖坑填坑

angular页面打印局部功能实现方法思考

在页面显示的时候是分页现实的,当前页面只有10条数据,但是打印需要打印完整的100条数据。 并且在当前页面包含了表格之外的标题,菜单等其他元素。 后天api...

1042
来自专栏西安-晁州

nodejs初印象

初学Nodejs,特意在此记录学习过程,算是对这段时间的一个summary吧,相互勉励,共同进步嘛,Now Begin: 1、什么是nodejs nodejs ...

2160

扫码关注云+社区

领取腾讯云代金券