ROS 中使用 Chef 部署应用-阿里云开发者社区

开发者社区> 云计算> 正文

ROS 中使用 Chef 部署应用

简介: 以 WordPress 为例,讲解 ROS 如何集成第三方配管工具 Chef 安装配置应用。

是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。

通过阿里云的资源编排服务,ROS,可以很方便的创建一组资源。但是创建资源只是第一步,接下来我们需要把应用部署上去,有两种方式供你使用,ROS 的 UserData 脚本或者集成配置管理工具,例如 Chef 或Puppet。本文将重点讲述ROS 集成 Chef 实现应用的部署与配置。关于使用 UserData 脚本的方式,大家可以参考《基于资源编排一键交付连接RDS的应用》


通过 Chef,你可以自动实现在 ECS 上的部署配置应用而不用手动构建各种脚本。通过把 Chef 和 ROS 集成,这样能更方便的把生产资源和部署应用集成到一块,并且通过ROS的模板,可以实现随时随地无限次的搭建相同应用环境,很轻松的把搭建环境集成到 DevOps 中去。


本文将以部署 WordPress 为例,讲解如何通过 ROS 去构建一个高可用的 Web Server 环境,最后通过执行 Chef 的 Recipe 在高可用的 Web Server 基础设施环境中安装配置 WordPress 。通过最终的这个 ROS模板,你可以简洁快速的获取一个 WordPress 应用。当然你还可以通过 Git 或 SVN 管理这个 ROS 的模板,实现对自己 WordPress 应用环境的版本控制。


ROS 安装部署 WordPress 架构概览

此模板讲创建一个高可用的带有负载均衡能力的 WordPress 环境,并通过阿里云的 RDS 提供后端的数据存储。基本的架构如下图所示:

wordpress_arch



在上面的架构图里面,通过 ROS 的 ALIYUN::ECS::InstanceGroup 创建多个 ECS 节点,这样就可以保证 WordPress 有多个实例,提高 WordPress 的高可用性。在 ECS 的前面部署了一个 SLB, 来保证均衡后端 ECS 的负载,给用户暴露唯一的 WordPress 访问地址,同时能够在添加或减少后端 ECS 服务器的时候,用户无感知。SLB 通过 ALIYUN::SLB::LoadBalancer 创建。通过 ALIYUN::SLB::Listener 配置SLB监听那些端口, ALIYUN::SLB::BackendServerAttachment 把后端服务器 ECS 加入到SLB监听列表中。通过使用 RDS 提供 WordPress 的后端数据存储能力。ROS 通过 ALIYUN::RDS::DBInstance 创建 RDS 实例配置数据库。以上所有的资源都部署在一个安全组里面,通过安全组控制数据出入规则,提高安全性。


最终,当 ECS 实例启动的时候,ROS 通过利用 Chef 的本地模式安装和配置 WordPress。 Chef 的本地模式是使用本地的 Chef 仓库来管理 cookbook 而不用通过 Chef Server。


WordPress 一键部署

一键部署>>>

点击一键部署后,默认会在华北2 region 部署 WordPress。 如果你需要调整 region,请点击页面右下角的【上一步】,然后重新选择 region,接着点击【下一步】,你只需要填入如下图中必填的信息或者根据你的需求调整信息后,点击【创建】按钮就可以部署一套 WordPress 高可用环境。

chef_wordpress_ros


模板详解

创建 VPC 网络

在本例中,所有资源的都处于VPC网络下,保证网络的隔离性和安全性。为了保证 ECS 能够访问外网,获取到 Chef 的安装包,下载到 WordPress 的 cookbook,我们配置了 VPC 的 SNAT 网关。请参考《新玩法,ROS帮你一键搭建NatGateway让VPC与Internet的互访》,了解如何详细的配置你的 VPC 网络。

   "SNatEntry": {
      "Type": "ALIYUN::ECS::SNatEntry",
      "DependsOn": "WPLoadBalancer",
      "Properties": {
        "SNatIp": {
          "Fn::Select": [
            "0",
            {
              "Fn::GetAtt": [
                "NatGateway",
                "BandwidthPackageIps"
              ]
            }
          ]
        },
        "SourceVSwitchId": {
          "Fn::GetAtt": [
            "VSwitch",
            "VSwitchId"
          ]
        },
        "SNatTableId": {
          "Fn::GetAtt": [
            "NatGateway",
            "SNatTableId"
          ]
        }
      }
    },
   "NatGateway": {
      "Type": "ALIYUN::ECS::NatGateway",
      "Properties": {
        "Spec": "Small",
        "NatGatewayName": "NatGateway",
        "BandwidthPackage": [
          {
            "IpCount": 1,
            "Bandwidth": 5
          }
        ],
        "VSwitchId": {
          "Ref": "VSwitch"
        },
        "VpcId": {
          "Fn::GetAtt": [
            "Vpc",
            "VpcId"
          ]
        }
      }
    },
    "Vpc": {
      "Type": "ALIYUN::ECS::VPC",
      "Properties": {
        "CidrBlock": "192.168.0.0/16"
      }
    },
   "VSwitch": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "CidrBlock": "192.168.33.0/24",
        "ZoneId": {
          "Fn::Select": [
            "0",
            {
              "Fn::GetAZs": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "VpcId": {
          "Fn::GetAtt": [
            "Vpc",
            "VpcId"
          ]
        }
      }
    }

创建安全组

在本例中,所有的ECS都加入到一个默认安全组。同时,给安全组资源配置允许外部用户可通过80和22端口访问 WordPress 部署环境。

  "DefaultSecurityGroup": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "Properties": {
        "Description": "DDC default security group",
        "SecurityGroupIngress": [
          {
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp",
            "NicType": "intranet",
            "PortRange": "22/22"
          },
          {
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp",
            "NicType": "intranet",
            "PortRange": "443/443"
          },
          {
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp",
            "NicType": "intranet",
            "PortRange": "80/80"
          }
        ],
        "SecurityGroupEgress": [
          {
            "IpProtocol": "all",
            "DestCidrIp": "0.0.0.0/0",
            "NicType": "intranet",
            "PortRange": "-1/-1",
            "Priority": 1
          }
        ],
        "VpcId": {
          "Ref": "Vpc"
        }
      }
   }

创建 ECS 实例

本例中,创建了两种 ECS 实例,一种是用 ALIYUN::ECS::InstanceGroup 创建用来部署 WordPress 的 ECS实例,这个资源可以通过 MaxAmount 来指定一次创建多少台 ECS 实例。一个是用 ALIYUN::ECS::Instance 创建一台运维使用的跳板机。跳板机也部署在相同的 VPC 网络中,但是给跳板机分配了公网 IP。


"WPEcsInstance": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "DependsOn": "SNatEntry",
      "Properties": {
        "IoOptimized": {
          "Ref": "WPEcsIoOptimized"
        },
        "ImageId": {
          "Ref": "WPEcsImageId"
        },
        "SecurityGroupId": {
          "Fn::GetAtt": [
            "DefaultSecurityGroup",
            "SecurityGroupId"
          ]
        },
        "Password": {
          "Ref": "WPEcsInstancePassword"
        },
        "MinAmount": {
          "Ref": "WPEcsMaxAmount"
        },
        "AllocatePublicIP": "false",
        "SystemDiskCategory": {
          "Ref": "WPEcsSystemDiskCategory"
        },
        "UserData": {
          "Fn::Replace": [
            {
              "ros-notify": {
                "Fn::GetAtt": [
                  "WPEcsConditionHandle",
                  "CurlCli"
                ]
              }
            },
            {
              "Fn::Join": [
                "",
                [
                  "#!/bin/sh\n",
                  "apt-get update\n",
                  "apt-get install -y rails\n",
                  "apt-get install -y unzip\n",
                  "\n",
                  "wget -P /tmp http://ros-om-dependence.oss-cn-shanghai.aliyuncs.com/chef-ubuntu-64/chef_12.18.31-1_amd64.deb\n",
                  "dpkg -i /tmp/chef_12.18.31-1_amd64.deb\n",
                  "wget -P /tmp http://ros-om-dependence.oss-cn-shanghai.aliyuncs.com/chef-ubuntu-64/chefdk_1.2.22-1_amd64.deb\n",
                  "dpkg -i /tmp/chefdk_1.2.22-1_amd64.deb\n",
                  "\n",
                  "mkdir -p /var/chef/chef-repo/.chef\n",
                  "# chef local repo setting\n",
                  "# wget -P /tmp http://github.com/opscode/chef-repo/tarball/master/chef-boneyard-chef-repo-605eeda.tar.gz\n",
                  "wget -P /tmp http://ros-om-dependence.oss-cn-shanghai.aliyuncs.com/chef-ubuntu-64/chef-boneyard-chef-repo-605eeda.tar.gz\n",
                  "tar -xzf /tmp/chef-boneyard-chef-repo-605eeda.tar.gz -C /var/chef/chef-repo\n",
                  "cp -rf /var/chef/chef-repo/chef-boneyard-chef-repo-605eeda/* /var/chef/chef-repo\n",
                  "rm -rf /var/chef/chef-repo/chef-boneyard-chef-repo-605eeda\n",
                  "echo install chef > /tmp/log\n",
                  "# set default knife.rb\n",
                  "echo \"cookbook_path [ '/var/chef/chef-repo/cookbooks' ]\" > /var/chef/chef-repo/.chef/knife.rb\n",
                  "echo \"node_path [ '/var/chef/chef-repo/nodes' ]\" >> /var/chef/chef-repo/.chef/knife.rb\n",
                  "\n",
                  "# set default client.rb\n",
                  "echo \"cookbook_path [ '/var/chef/chef-repo/cookbooks' ]\" > /var/chef/chef-repo/.chef/client.rb\n",
                  "echo \"node_path [ '/var/chef/chef-repo/nodes' ]\" >> /var/chef/chef-repo/.chef/client.rb\n",
                  "\n",
                  "# set init chef conf\n",
                  "orig_home=$HOME\n",
                  "export HOME='/var/chef'\n",
                  "\n",
                  "# create node list\n",
                  "cd /var/chef/chef-repo\n",
                  "chef-client -z -c /var/chef/chef-repo/.chef/client.rb\n",
                  "echo config chef repo >> /tmp/log\n",
                  "\n",
                  "\n",
                  "# download wordpress cookbook\n",
                  "wget -P /tmp http://ros-om-dependence.oss-cn-shanghai.aliyuncs.com/chef-ubuntu-64/wordpress.tar.gz\n",
                  "tar -xzf /tmp/wordpress.tar.gz -C /var/chef/chef-repo/cookbooks\n",
                  "\n",
                  "# set default knife.rb\n",
                  "echo \"cookbook_path [ '/var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks' ]\" > /var/chef/chef-repo/.chef/knife.rb\n",
                  "echo \"node_path [ '/var/chef/chef-repo/nodes' ]\" >> /var/chef/chef-repo/.chef/knife.rb\n",
                  "\n",
                  "# set default client.rb\n",
                  "echo \"cookbook_path [ '/var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks' ]\" > /var/chef/chef-repo/.chef/client.rb\n",
                  "echo \"node_path [ '/var/chef/chef-repo/nodes' ]\" >> /var/chef/chef-repo/.chef/client.rb\n",
                  "echo config wordpress cookbook >> /tmp/log\n",
                  "\n",
                  "\n",
                  "# set wordpress datebase conf\n",
                  "echo \"normal['wordpress']['db']['pass'] = '",
                  {
                    "Ref": "WPDBPassword"
                  },
                  "'\" > /var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks/wordpress/attributes/aliyun_rds_config.rb\n",
                  "echo \"normal['wordpress']['db']['user'] = '",
                  {
                    "Ref": "WPDBUser"
                  },
                  "'\" >> /var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks/wordpress/attributes/aliyun_rds_config.rb\n",
                  "echo \"normal['wordpress']['db']['host'] = '",
                  {
                    "Fn::GetAtt": [
                      "WPDBDatabase",
                      "InnerConnectionString"
                    ]
                  },
                  "'\" >> /var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks/wordpress/attributes/aliyun_rds_config.rb\n",
                  "echo \"normal['wordpress']['db']['name'] = '",
                  {
                    "Ref": "WPDBName"
                  },
                  "'\" >> /var/chef/chef-repo/cookbooks/wordpress/berks-cookbooks/wordpress/attributes/aliyun_rds_config.rb\n",
                  "\n",
                  "\n",
                  "echo run install wordpress cookbook >> /tmp/log\n",
                  "knife node run_list add -z `knife node list -z` recipe[wordpress]\n",
                  "\n",
                  "chef-client -z -c /var/chef/chef-repo/.chef/client.rb | tee -a /tmp/chef_runing_log\n",
                  "ros-notify\n"
                ]
              ]
            }
          ]
        },
        "MaxAmount": {
          "Ref": "WPEcsMaxAmount"
        },
        "VSwitchId": {
          "Ref": "VSwitch"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "InstanceType": {
          "Ref": "WPEcsInstanceType"
        }
      }
    },
 "JumpHost": {
      "Type": "ALIYUN::ECS::Instance",
      "Properties": {
        "IoOptimized": "optimized",
        "ImageId": {
          "Ref": "WPEcsImageId"
        },
        "SecurityGroupId": {
          "Fn::GetAtt": [
            "DefaultSecurityGroup",
            "SecurityGroupId"
          ]
        },
        "Password": {
          "Ref": "WPEcsInstancePassword"
        },
        "AllocatePublicIP": "true",
        "SystemDiskCategory": "cloud_efficiency",
        "VSwitchId": {
          "Ref": "VSwitch"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "InstanceType": {
          "Ref": "WPEcsInstanceType"
        }
      }
    },

ROS 通过 UserData 集成了 Chef, 首先安装 Chef 所依赖的 ruby 环境。由于网络原因,我们把 Chef 的安装包,本地仓库和相应的 cookbook 都做了镜像,方便大家在国内访问。然后配置 Chef 的 knife.rb 和 client.rb 文件指向本地仓库中的 cookbook。调用 chef-client -z 指定本地模式生成 node list。然后添加RDS实例中的数据库名称,用户名,密码和机器名称到 WordPress cookbook 的 attributes 中,保证 Chef 能正确配置 WordPress 数据库属性。最后调用下面的 Chef 命令,在本机上安装配置 WordPress 实例。

knife node run_list add -z `knife node list -z` recipe[wordpress]
chef-client -z -c /var/chef/chef-repo/.chef/client.rb

SLB

要高可用的环境,SLB 是必不可少的一个资源。通过 SLB 即可均衡分配请求到后端服务,更可以做用户无感知地增加,减少或者替换有问题的后端 ECS 实例。同时,通过 SLB 可以给用户提供一个唯一的WordPress 访问地址。本例中,创建 SLB 后,配置了 SLB 监听后端的 ECS 的80端口。

  "WPLoadBalancerListener80": {
      "Type": "ALIYUN::SLB::Listener",
      "DependsOn": "WPLoadBalancer",
      "Properties": {
        "Persistence": {
          "StickySession": "on",
          "PersistenceTimeout": 600
        },
        "HealthCheck": {
          "Timeout": "2",
          "Port": "80",
          "Interval": "5",
          "HealthyThreshold": "2",
          "UnhealthyThreshold": "4"
        },
        "LoadBalancerId": {
          "Ref": "WPLoadBalancer"
        },
        "BackendServerPort": "80",
        "Protocol": "tcp",
        "Bandwidth": -1,
        "ListenerPort": "80"
      }
    },
   "WPSLBAttachment": {
      "Type": "ALIYUN::SLB::BackendServerAttachment",
      "Properties": {
        "BackendServerList": {
          "Fn::GetAtt": [
            "WPEcsInstance",
            "InstanceIds"
          ]
        },
        "LoadBalancerId": {
          "Ref": "WPLoadBalancer"
        }
      }
    },
   "WPLoadBalancer": {
      "Type": "ALIYUN::SLB::LoadBalancer",
      "Properties": {
        "LoadBalancerName": "WordPressLoadBalancer",
        "AddressType": "internet"
      }
    },

RDS

WordPress 需要存储用户的博文和评论,后端数据库是必不可少的一个组件。阿里云 RDS 资源是一个很好的选择。通过 ROS 可以简便的把创建 RDS 实例和配置数据库一步搞定。

   "WPDBDatabase": {
      "Type": "ALIYUN::RDS::DBInstance",
      "DependsOn": "SNatEntry",
      "Properties": {
        "DBInstanceClass": {
          "Ref": "WPDBInstanceClass"
        },
        "DBMappings": [
          {
            "DBName": {
              "Ref": "WPDBName"
            },
            "CharacterSetName": "utf8"
          }
        ],
        "ZoneId": {
          "Fn::Select": [
            "0",
            {
              "Fn::GetAZs": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "DBInstanceStorage": {
          "Ref": "WPDBInstanceStorage"
        },
        "VSwitchId": {
          "Ref": "VSwitch"
        },
        "Engine": {
          "Ref": "WPDBEngine"
        },
        "MasterUserPassword": {
          "Ref": "WPDBPassword"
        },
        "MasterUsername": {
          "Ref": "WPDBUser"
        },
        "PreferredBackupPeriod": [
          "Monday",
          "Wednesday"
        ],
        "VPCId": {
          "Ref": "Vpc"
        },
        "EngineVersion": {
          "Ref": "WPDBEngineVersion"
        },
        "PreferredBackupTime": "23:00Z-24:00Z",
        "SecurityIPList": "0.0.0.0/0"
      }
    },

总结

从本例来看,不仅通过 ROS 能安装配置应用,也可以通过集成第三方的官配工具实现相同的目的。本例以Chef 为例相大家展示了 ROS 如何通过集成 第三方配管工具。希望通过这个例子,大家通过 Chef 不光能部署 WordPress ,更能部署自己的应用。关于 ROS 的详细指导请参考这里

是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
云计算
使用钉钉扫一扫加入圈子
+ 订阅

时时分享云计算技术内容,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

其他文章