This topic describes how to use the Ansible ali_ros_stack module to call the ROS API operations for deploying an LNMP (Linux, NGINX, MySQL, and PHP) environment.

Prerequisites

Ansible is installed and configured on Linux.

Procedure

  1. Create a file named create_lnmp.yml and open it in the visual editor.
    vi create_lnmp.yml
  2. In the edit mode, copy the following playbook code to the create_lnmp.yml file:
    Note For more information about the ali_ros_stack module parameters, see Parameters.
    - hosts: localhost
      remote_user: root
      tasks:
        - name: Create LNMP Instance
          ali_ros_stack:
            state: present
            stack_name: create_lnmp_instance
            template: create_lnmp_instance.json
            timeout_in_minutes: 60
            template_parameters:
              ZoneId: cn-beijing-g
              ImageId: centos_7_03_64_20G_alibase_2017****.vhd
              InstancePassword: XXXXXXXX
              SystemDiskCategory: cloud_ssd
              InstanceType: ecs.c5.large
              DBName: MyDatabase
              DBUser: DefaultUser
              DBRootPassword: XXXXXX
              DBPassword: XXXXXX
              NginxDownloadUrl: http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
  3. Save the file and exit the edit mode.
  4. Create a file named create_lnmp_instance.json and open it in the visual editor.
    vi create_lnmp_instance.json
  5. In the edit mode, copy the following playbook code to the create_lnmp_instance.json file:
    {
      "Description": "Deploy LNMP(Linux+Nginx+MySQL+PHP) stack on 1 ECS instance. *** WARNING *** Only support CentOS-7.",
      "Parameters": {
        "NginxDownloadUrl": {
          "Type": "String",
          "Description": {
            "en-us": "The download path of nginx-*.rpm.",
          },
          "Label": "Nginx Download Url",
          "Default": "http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm"
        },
        "DBPassword": {
          "NoEcho": true,
          "Type": "String",
          "Description": {
            "en-us": "The MySQL password. It must be 6 to 32 characters in length and can contain letters, digits, and underscores (_)."
          },
          "Label": "DB Password",
          "ConstraintDescription": "Consisting of letters, numbers, and underline(_), 6 to 32 characters in length",
          "MinLength": 6,
          "MaxLength": 32
        },
        "ZoneId": {
          "Type": "String",
          "AssociationProperty": "ALIYUN::ECS::Instance:ZoneId",
          "Description": {
            "en-us": "The ID of the zone where the ECS instance resides. </font><a href='https://www.alibabacloud.com/help/doc-detail/123712.html' target='_blank'><b>Regions and zones</b><font color='blue'></a>"
          },
          "Label": "Available Zone ID"
        },
        "ImageId": {
          "Type": "String",
          "Description": {
            "en-us": "The ID of the image. To view image resources of an ECS instance, see <font><a href='https://www.alibabacloud.com/help/doc-detail/112977.html' target='_blank'><b>Search for an image</b></font color='blue'></a>"
          },
          "Label": "Image ID",
          "Default": "centos_7"
        },
        "DBName": {
          "Type": "String",
          "Description": {
            "en-us": "The name of the MySQL database. It must be 1 to 64 characters in length and can contain letters, digits, periods (.), underscores (_), and hyphens (-). It must start with a letter."
          },
          "Label": "DB Name",
          "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters.",
          "MinLength": 1,
          "MaxLength": 64,
          "Default": "MyDatabase"
        },
        "DBUser": {
          "Type": "String",
          "Description": {
            "en-us": "The username used to access the MySQL database. It must start with a letter and can contain lowercase letters, digits, and underscores (_). It can be up to 16 characters in length.
          },
          "Label": "DB Username",
          "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters.",
          "MinLength": 1,
          "MaxLength": 16,
          "Default": "DefaultUser"
        },
        "DBRootPassword": {
          "NoEcho": true,
          "Type": "String",
          "Description": {
            "en-us": "The password of the MySQL root user. It must be 6 to 32 characters in length and can contain letters, digits, and underscores (_)."
          },
          "Label": "DB Root Password",
          "ConstraintDescription": "Consisting of letters, numbers, and underline(_), 6 to 32 characters in length",
          "MinLength": 6,
          "MaxLength": 32
        },
        "InstanceType": {
          "Type": "String",
          "Description": {
            "en-us": "The ECS instance type. Log on to the ECS console to check the availability of the current instance. For more information, see <font><a href='https://www.alibabacloud.com/help/doc-detail/25378.html' target='_blank'><b>Instance families</b></font color='blue'></a>"
          },
          "Label": "Instance Type",
          "Default": "ecs.c5.large"
        },
        "SystemDiskCategory": {
          "Type": "String",
          "Description": {
            "en-us": "The type of the system disk, which can be ultra disk (cloud_efficiency) or standard SSD (cloud_ssd)."
          },
          "AllowedValues": [
            "cloud_efficiency",
            "cloud_ssd"
          ],
          "Label": "System Disk Category",
          "Default": "cloud_ssd"
        },
        "InstancePassword": {
          "NoEcho": true,
          "Type": "String",
          "Description": {
            "en-us": "It must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include () ` ~ ! @#$%^&*_-+=|{}[]:;'<>,.? /"
          },
          "AllowedPattern": "[0-9A-Za-z\\_\\-&:;'<>,=%`~! @#\\(\\)\\$\\^\\*\\+\\|\\{\\}\\[\\]\\. \\? \\/]+$",
          "Label": "Instance Password",
          "ConstraintDescription": "Length 8-30, must contain upper case letters, lower case letters, Numbers, special symbols three; special characters include: ()`~! @#$%^&*_-+=|{}[]:;'<>,.? /",
          "MinLength": "8",
          "MaxLength": "30"
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "ParameterGroups": [
            {
              "Parameters": [
                "ZoneId",
                "ImageId",
                "InstanceType",
                "SystemDiskCategory",
                "InstancePassword"
              ],
              "Label": {
                "default": "ECS"
              }
            },
            {
              "Parameters": [
                "DBName",
                "DBUser",
                "DBPassword",
                "DBRootPassword"
              ],
              "Label": {
                "default": "DATABASE"
              }
            },
            {
              "Parameters": [
                "NginxDownloadUrl"
              ],
              "Label": {
                "default": "Nginx"
              }
            }
          ],
          "TemplateTags": [
            "Deploy LNMP(Linux+Nginx+MySQL+PHP) stack on 1 ECS instance."
          ]
        }
      },
      "Outputs": {
        "NginxWebsiteURL": {
          "Description": "URL for newly created Nginx home page.",
          "Value": {
            "Fn::Join": [
              "",
              [
                "http://",
                {
                  "Fn::GetAtt": [
                    "WebServer",
                    "PublicIp"
                  ]
                },
                ":80/test.php"
              ]
            ]
          }
        }
      },
      "Resources": {
        "VSwitch": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "VpcId": {
              "Fn::GetAtt": [
                "Vpc",
                "VpcId"
              ]
            },
            "ZoneId": {
              "Ref": "ZoneId"
            },
            "CidrBlock": "192.168.1.0/24"
          }
        },
        "WebServerConditionHandle": {
          "Type": "ALIYUN::ROS::WaitConditionHandle"
        },
        "WebServer": {
          "Type": "ALIYUN::ECS::Instance",
          "Properties": {
            "InternetMaxBandwidthOut": 80,
            "IoOptimized": "optimized",
            "VpcId": {
              "Fn::GetAtt": [
                "Vpc",
                "VpcId"
              ]
            },
            "UserData": {
              "Fn::Replace": [
                {
                  "ros-notify": {
                    "Fn::GetAtt": [
                      "WebServerConditionHandle",
                      "CurlCli"
                    ]
                  }
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      "#! /bin/bash \n",
                      "NginxUrl=",
                      {
                        "Ref": "NginxDownloadUrl"
                      },
                      "\n",
                      "dbname=",
                      {
                        "Ref": "DBName"
                      },
                      "\n",
                      "dbuser=",
                      {
                        "Ref": "DBUser"
                      },
                      "\n",
                      "dbpassword=",
                      {
                        "Ref": "DBPassword"
                      },
                      "\n",
                      "dbrootpassword=",
                      {
                        "Ref": "DBRootPassword"
                      },
                      "\n",
                      "export HOME=/root \n",
                      "export HOSTNAME=`hostname` \n",
                      "systemctl stop firewalld.service \n",
                      "systemctl disable firewalld.service \n",
                      "sed -i 's/^SELINUX=/# SELINUX=/' /etc/selinux/config \n",
                      "sed -i '/# SELINUX=/a SELINUX=disabled' /etc/selinux/config \n",
                      "setenforce 0 \n",
                      "yum install yum-priorities -y \n",
                      "yum -y install aria2 \n",
                      "aria2c $NginxUrl \n",
                      "rpm -ivh nginx-*.rpm \n",
                      "yum -y install nginx \n",
                      "systemctl start nginx.service \n",
                      "systemctl enable nginx.service \n",
                      "yum -y install php-fpm \n",
                      "systemctl start php-fpm.service \n",
                      "systemctl enable php-fpm.service \n",
                      "sed -i '/FastCGI/,/htaccess/s/    #/    /' /etc/nginx/conf.d/default.conf \n",
                      "sed -i '/FastCGI/s/^    /    #/' /etc/nginx/conf.d/default.conf \n",
                      "sed -i '/htaccess/s/^    /    #/' /etc/nginx/conf.d/default.conf \n",
                      "sed -i '/SCRIPT_FILENAME/s/\\/scripts/\\/usr\\/share\\/nginx\\/html\\//' /etc/nginx/conf.d/default.conf \n",
                      "yum -y install mariadb mariadb-server \n",
                      "systemctl start mariadb.service \n",
                      "systemctl enable mariadb.service \n",
                      "yum -y install php php-mysql php-gd libjpeg* php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-bcmath php-mhash php-mcrypt \n",
                      "MDSRING=`find / -name mbstring.so` \n",
                      "echo extension=$MDSRING >> /etc/php.ini \n",
                      "systemctl restart mariadb.service \n",
                      "mysqladmin -u root password \"$dbrootpassword\" \n",
                      "$(mysql $dbname -u root --password=\"$dbrootpassword\" >/dev/null 2>&1 </dev/null); (( $? ! = 0 )) \n",
                      "echo CREATE DATABASE $dbname \\; > /tmp/setup.mysql \n",
                      "echo GRANT ALL ON $dbname. * TO \"$dbuser\"@\"localhost\" IDENTIFIED BY \"'$dbpassword'\" \\; >> /tmp/setup.mysql \n",
                      "mysql -u root --password=\"$dbrootpassword\" < /tmp/setup.mysql \n",
                      "$(mysql $dbname -u root --password=\"$dbrootpassword\" >/dev/null 2>&1 </dev/null); (( $? ! = 0 )) \n",
                      "cd /root \n",
                      "systemctl restart php-fpm.service \n",
                      "systemctl restart nginx.service \n",
                      "echo \\<? php >  /usr/share/nginx/html/test.php \n",
                      "echo \\$conn=mysql_connect\\(\"'127.0.0.1'\", \"'$dbuser'\", \"'$dbpassword'\"\\)\\; >>  /usr/share/nginx/html/test.php \n",
                      "echo if \\(\\$conn\\){ >>  /usr/share/nginx/html/test.php \n",
                      "echo   echo \\\"LNMP platform connect to mysql is successful\\! \\\"\\; >>  /usr/share/nginx/html/test.php \n",
                      "echo   }else{  >>  /usr/share/nginx/html/test.php \n",
                      "echo echo \\\"LNMP platform connect to mysql is failed\\! \\\"\\;  >>  /usr/share/nginx/html/test.php \n",
                      "echo }  >>  /usr/share/nginx/html/test.php \n",
                      "echo  phpinfo\\(\\)\\;  >>  /usr/share/nginx/html/test.php \n",
                      "echo \\? \\>  >>  /usr/share/nginx/html/test.php \n",
                      "ros-notify -d '{\"data\" : \"Install LNMP stack.\"}'\n"
                    ]
                  ]
                }
              ]
            },
            "SecurityGroupId": {
              "Ref": "SecurityGroup"
            },
            "VSwitchId": {
              "Ref": "VSwitch"
            },
            "ImageId": {
              "Ref": "ImageId"
            },
            "InstanceType": {
              "Ref": "InstanceType"
            },
            "SystemDiskCategory": {
              "Ref": "SystemDiskCategory"
            },
            "Password": {
              "Ref": "InstancePassword"
            }
          }
        },
        "WebServerWaitCondition": {
          "Type": "ALIYUN::ROS::WaitCondition",
          "DependsOn": "WebServer",
          "Properties": {
            "Timeout": 1800,
            "Count": 1,
            "Handle": {
              "Ref": "WebServerConditionHandle"
            }
          }
        },
        "Vpc": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "192.168.0.0/16"
          }
        },
        "SecurityGroup": {
          "Type": "ALIYUN::ECS::SecurityGroup",
          "Properties": {
            "VpcId": {
              "Ref": "Vpc"
            },
            "SecurityGroupIngress": [
              {
                "PortRange": "-1/-1",
                "Priority": 1,
                "SourceCidrIp": "0.0.0.0/0",
                "IpProtocol": "all",
                "NicType": "intranet"
              }
            ],
            "SecurityGroupEgress": [
              {
                "PortRange": "-1/-1",
                "Priority": 1,
                "IpProtocol": "all",
                "DestCidrIp": "0.0.0.0/0",
                "NicType": "intranet"
              }
            ]
          }
        }
      }
    }
  6. Save the file and exit the edit mode.
  7. Run the Ansible playbook to deploy an LNMP environment.
    ansible-playbook create_lnmp.yml