centos7.2环境nginx+mysql+php-fpm+svn配置walle自动化部署系统详解
操作系统:centos 7.2 x86_64
安装walle系统服务端
1.以下安装,均在宿主机(一台配置了LAMP/LNMP的linux机器)上操作
安装lnmp环境,建议使用centos7 yum安装,因为centos7 yum源默认支持Php5.4以上版本,避免walle系统不兼容
yum install -y git mariadb mariadb-server nginx php php-bcmath php-fpm php-gd* php-json freetype freetype-devel php-mbstring php-mcrypt php-mysql php-opcache php-pdo php-pdo_dblib php-pgsql php-recode php-snmp php-soap php-xml php-pecl-zip mhash libmcrypt libmcrypt-devel
2.创建walle的web目录,我把web根目录配置成/data/www/walle-web(需要配置nginx指向,后面会详述)
mkdir -p /data/www/walle-web && cd /data/www/walle-web # 新建目录
下载walle-web-master.zip并解压(下载地址:https://github.com/meolu/walle-web)
unzip walle-web-master.zip
cd walle-web-master
3.设置mariadb数据库(mysql的操作一样),只需要创建数据库,建表的操作交给walle的setup.php安装程序
# 启动 mariadb 并配置开机自启动
systemctl start mariadb.service
systemctl enable mariadb.service
# 设置 root 密码、删除匿名用户、禁止 root 远程登录、删除 test 数据库、重新加载权限表,一路 Y 下去
mysql_secure_installation
MariaDB [(none)]> create database walle charset=utf8mb4 collate utf8mb4_unicode_ci;
MariaDB [(none)]> grant all privileges on walle.* to 'walleuser'@'%' identified by 'wallepass';
修改walle的web连接
vim /data/www/walle-web/walle-web-master/config/local.php +14
'db' => [
'dsn' => 'mysql:host=127.0.0.1;dbname=walle', # 新建数据库walle
'username' => 'walleuser', # 连接的用户名
'password' => 'wallepass', # 连接的密码
],
4.安装composer,如果已安装跳过
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer # PATH目录
5.安装vendor
cd /data/www/walle-web/walle-web-master
composer install --prefer-dist --no-dev --optimize-autoloader -vvvv
安装速度慢或失败,可直接下载vendor解压到项目根目录(即/data/www/walle-web/walle-web-master目录下)
6.初始化项目
cd /data/www/walle-web/walle-web-master
./yii walle/setup # 需要输入yes
--------------------------------------------------------------------------------------
create dir 创建目录...
mkdiring dir: /tmp/walle/
mkdiring dir: /data/www/walle-web/walle-web-master/runtime/ansible_hosts/
mkdiring dir: /data/www/walle-web/walle-web-master/vendor/bower/jquery/dist
set writable 设置可写权限...
Setting writable: /data/www/walle-web/walle-web-master/runtime
Setting writable: /data/www/walle-web/walle-web-master/web/assets
Setting writable: /tmp/walle/
Setting writable: /data/www/walle-web/walle-web-master/runtime/ansible_hosts/
set executable 设置可执行权限...
Setting executable: /data/www/walle-web/walle-web-master/yii
update database 更新数据库: yii migrate/up ...
Yii Migration Tool (based on Yii v2.0.7-dev) Creating migration history table "migration"...Done.
Total new migrations to be applied:
m140328_144900_init
m150926_151034_init_user
m150927_061454_alter_conf_to_mysql
m150929_004629_change_record_action
m150929_034627_session_to_mysql
m150929_115951_project_user_group
m151005_001053_alter_conf_2_project
m151010_050344_group_user_admin
m151011_054352_task_need_more_long
m151012_135612_task_add_branch
m151014_115546_add_pre_release_task
m151018_032238_support_svn
m151027_063246_keep_version_num
m160307_082032_ansible
m160402_173643_add_post_release_delay
m160418_035413_user_status_migrate
m160420_015223_add_file_transmission_mode Apply the above migrations? (yes|no) [no]:yes
*** applying m140328_144900_init
> create table user ... done (time: .047s)
> create table conf ... done (time: .042s)
> create table task ... done (time: .016s)
> create table record ... done (time: .018s)
*** applied m140328_144900_init (time: .134s) *** applying m150926_151034_init_user
> insert into {{%user}} ... done (time: .006s)
> insert into {{%user}} ... done (time: .002s)
*** applied m150926_151034_init_user (time: .088s) *** applying m150927_061454_alter_conf_to_mysql
> drop column conf from table conf ... done (time: .050s)
> add column git_url string() DEFAULT "" COMMENT "git地址" to table conf ... done (time: .016s)
> add column deploy_from string() NOT NULL COMMENT "宿主机存放clone出来的文件" to table conf ... done (time: .017s)
> add column excludes string() DEFAULT "" COMMENT "要排除的文件" to table conf ... done (time: .027s)
> add column release_user string() NOT NULL COMMENT "目标机器用户" to table conf ... done (time: .059s)
> add column release_to string() NOT NULL COMMENT "目标机器的目录,相当于nginx的root,可直接web访问" to table conf ... done (time: .010s)
> add column release_library string() NOT NULL COMMENT "目标机器版本发布库" to table conf ... done (time: .018s)
> add column hosts string() NOT NULL COMMENT "目标机器列表" to table conf ... done (time: .016s)
> add column pre_deploy string() DEFAULT "" COMMENT "部署前置任务" to table conf ... done (time: .025s)
> add column post_deploy string() DEFAULT "" COMMENT "同步之前任务" to table conf ... done (time: .023s)
> add column post_release string() DEFAULT "" COMMENT "同步之后任务" to table conf ... done (time: .020s)
> add column git_type string() DEFAULT "branch" COMMENT "两种上线方式,分支、tag" to table conf ... done (time: .034s)
> add column audit smallint() DEFAULT COMMENT "是否需要审核任务0不需要,1需要" to table conf ... done (time: .025s)
> drop column created_at from table conf ... done (time: .012s)
> add column created_at datetime COMMENT "创建时间" after audit to table conf ... done (time: .022s)
> add column updated_at datetime COMMENT "修改时间" to table conf ... done (time: .014s)
> drop column created_at from table task ... done (time: .021s)
> add column created_at datetime COMMENT "创建时间" to table task ... done (time: .011s)
> add column updated_at datetime COMMENT "修改时间" to table task ... done (time: .055s)
*** applied m150927_061454_alter_conf_to_mysql (time: .495s) *** applying m150929_004629_change_record_action
> alter column action in table record to integer() unsigned DEFAULT COMMENT "任务执行到的阶段" ... done (time: .021s)
*** applied m150929_004629_change_record_action (time: .027s) *** applying m150929_034627_session_to_mysql
> create table session ... done (time: .005s)
*** applied m150929_034627_session_to_mysql (time: .012s) *** applying m150929_115951_project_user_group
> create table group ... done (time: .004s)
> add column avatar string() DEFAULT "default.jpg" COMMENT "头像图片地址" AFTER email to table {{%user}} ... done (time: .014s)
*** applied m150929_115951_project_user_group (time: .023s) *** applying m151005_001053_alter_conf_2_project
> rename table conf to project ... done (time: .004s)
*** applied m151005_001053_alter_conf_2_project (time: .011s) *** applying m151010_050344_group_user_admin
> add column type smallint() DEFAULT COMMENT "用户在项目中的关系类型 0普通用户, 1管理员" to table group ... done (time: .032s)
> alter column user_id in table group to integer() NOT NULL COMMENT "用户id" ... done (time: .013s)
*** applied m151010_050344_group_user_admin (time: .051s) *** applying m151011_054352_task_need_more_long
> alter column excludes in table project to text COMMENT "要排除的文件" ... done (time: .013s)
> alter column hosts in table project to text COMMENT "目标机器列表" ... done (time: .015s)
> alter column pre_deploy in table project to text COMMENT "部署前置任务" ... done (time: .013s)
> alter column post_deploy in table project to text COMMENT "同步之前任务" ... done (time: .012s)
> alter column post_release in table project to text COMMENT "同步之后任务" ... done (time: .015s)
*** applied m151011_054352_task_need_more_long (time: .073s) *** applying m151012_135612_task_add_branch
> add column branch string() DEFAULT "master" comment "选择上线的分支" to table task ... done (time: .011s)
> alter column name in table project to string() DEFAULT "master" comment "项目名字" ... done (time: .009s)
*** applied m151012_135612_task_add_branch (time: .026s) *** applying m151014_115546_add_pre_release_task
> alter column post_release in table project to text COMMENT "同步之前目标机器执行的任务" ... done (time: .003s)
> rename column post_release in table project to pre_release ... done (time: .011s)
> add column post_release text COMMENT "同步之后目标机器执行的任务" AFTER pre_release to table project ... done (time: .013s)
*** applied m151014_115546_add_pre_release_task (time: .033s) *** applying m151018_032238_support_svn
> rename column git_url in table project to repo_url ... done (time: .040s)
> rename column git_type in table project to repo_mode ... done (time: .016s)
> alter column repo_mode in table project to string() DEFAULT "branch" COMMENT "上线方式:branch/tag" AFTER repo_url ... done (time: .015s)
> add column repo_type string() DEFAULT "git" COMMENT "上线方式:git/svn" AFTER repo_mode to table project ... done (time: .014s)
> add column repo_username string() DEFAULT "" COMMENT "版本管理系统的用户名,一般为svn的用户名" AFTER repo_url to table project ... done (time: .013s)
> add column repo_password string() DEFAULT "" COMMENT "版本管理系统的密码,一般为svn的密码" AFTER repo_username to table project ... done (time: .037s)
> add column file_list text COMMENT "文件列表,svn上线方式可能会产生" to table task ... done (time: .009s)
> alter column commit_id in table task to string() DEFAULT "" COMMENT "git commit id" ... done (time: .010s)
*** applied m151018_032238_support_svn (time: .159s) *** applying m151027_063246_keep_version_num
> add column keep_version_num integer() NOT NULL DEFAULT COMMENT "线上版本保留数" AFTER audit to table project ... done (time: .012s)
> add column enable_rollback integer() NOT NULL DEFAULT COMMENT "能否回滚此版本:0no 1yes" to table task ... done (time: .011s)
*** applied m151027_063246_keep_version_num (time: .030s) *** applying m160307_082032_ansible
> add column ansible smallint() NOT NULL DEFAULT COMMENT "是否启用Ansible 0关闭,1开启" AFTER audit to table project ... done (time: .038s)
*** applied m160307_082032_ansible (time: .059s) *** applying m160402_173643_add_post_release_delay
> add column post_release_delay integer() NOT NULL DEFAULT COMMENT "每台目标机执行post_release任务间隔/延迟时间 单位:秒" AFTER post_release to table project ... done (time: .010s)
*** applied m160402_173643_add_post_release_delay (time: .015s) *** applying m160418_035413_user_status_migrate
> alter column role in table {{%user}} to smallint() NOT NULL DEFAULT ... done (time: .005s)
> alter column status in table {{%user}} to smallint() NOT NULL DEFAULT ... done (time: .003s)
> update {{%user}} ... done (time: .006s)
> update {{%user}} ... done (time: .002s)
> update {{%user}} ... done (time: .002s)
> update {{%user}} ... done (time: .003s)
> update {{%user}} ... done (time: .001s)
*** applied m160418_035413_user_status_migrate (time: .028s) *** applying m160420_015223_add_file_transmission_mode
> alter column created_at in table task to datetime COMMENT "创建时间" AFTER enable_rollback ... done (time: .016s)
> alter column updated_at in table task to datetime COMMENT "修改时间" AFTER created_at ... done (time: .052s)
> add column file_transmission_mode smallint() NOT NULL DEFAULT COMMENT "上线文件模式: 1.全量所有文件 2.指定文件列表" AFTER branch to table task ... done (time: .039s)
*** applied m160420_015223_add_file_transmission_mode (time: .111s)
Migrated up successfully.
--------------------------------------------------------------------------------------
7.配置nginx
刷新页面看到50x或者404均是nginx配置不当,需要查看nginx日志
nginx简单配置
server {
listen 80;
server_name 192.168.3.13; # 改你的host
root /data/www/walle-web/walle-web-master/web; # 根目录为web
index index.php;
# 建议放内网
# allow 192.168.0.0/24;
# deny all;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# 启动nginx
nginx -t
systemctl start nginx
# 启动php-fpm服务
systemctl start php-fpm
8.访问地址:http://192.168.3.13
当然,可能你配置nginx时的server_name是walle.chinasoft.com时,配置本地hosts之后,直接访问:walle.chinasoft.com亦可。
管理员默认账户密码都为:
admin
至此walle系统的部署告一段落
walle系统的使用:
几个术语:
宿主机:walle服务安装所在的机器
目标机:代码要分发到的机群
ssh-key信任:可免密码登录,一个机器的一个用户与一个机器的一个用户通过ssh-key来建立信任(一般为RSA)
实验环境:
宿主机 192.168.3.13(部署了walle系统的服务器)
目标机器 192.168.3.17(需要部署web项目的环境)
svn服务器 192.168.3.18
宿主机walle系统上的操作:
1.安装ansible,需要ansible命令操作远程主机
yum install -y ansible
添加用户www_php并设置成walle web端php-fpm的运行用户,该用户主要是宿主机walle用来操作项目部署(代码拉取、项目部署操作等的用户)
useradd www_php
echo 'www_php' |passwd --stdin www_php
vim /etc/php-fpm.d/www.conf #配置www_php有运行权限
listen.owner = www_php
listen.group = www_php
user = www_php
group = www_php
修改walle_web目录权限,否则不可写
chown -R www_php.www_php /data/www/walle-web
2.把宿主机的php进程用户的ssh-key添加到gitlab/github(svn不需要添加,直接使用访问svn的账号密码即可walle有具体的配置界面),所有目标服务器机群,配置就完成了90%。
确认宿主机的php进程用户:
vi php-fpm.conf
user = php-user # 看下用的是哪个用户
ps aux|grep php-fpm # 也是可以的
2. 获取宿主机的php进程用户www_php的ssh-key并添加到目标主机信任
su - www_php
cat ~/.ssh/id_rsa.pub
www_php用户设置为no-login,先取消no-login,添加完ssh-key认证后再设置为no-login
具体步骤:
su - www_php
ssh-keygen
ssh-copy-id -i .ssh/id_rsa.pub release_user@192.168.3.17
添加目标机器的信任
[www_php@localhost ~]$ ssh-copy-id -i .ssh/id_rsa.pub release_user@192.168.3.17
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
release_user@192.168.3.17's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'release_user@192.168.3.17'"
and check to make sure that only the key(s) you wanted were added.
目标主机
chown -R release_user.release_user /data/www
chmod 755 -R /data/www
useradd release_user
echo 'release_user' |passwd --stdin release_user
关于walle的错误调试:
默认日志打印在/tmp/walle/目录下,centos7.2没有这个日志目录
原因:centos 7 yum 安装的php-fpm默认/tmp目录不可写:/usr/lib/systemd/system/php-fpm.service 中的 PrivateTmp=true 禁止了向tmp目录写日志
解决办法:
mkdir /tmp/walle
chmod 777 -R /tmp
vim /usr/lib/systemd/system/php-fpm.service
PrivateTmp=false
重新加载配置生效
systemctl daemon-reload
systemctl reload php-fpm
注意:
建议赋权给一个用户,比如walle对需要部署的项目都拥有只读的权限,然后通过这个用户去svn仓库获取代码并部署
第一次的时候通过svn用户账户密码
安装svn客户端
# yum install -y subversion
初次测试获取代码报错,需要进行验证,如下:
[www@u04elk ~]$ svn checkout -q https://chinasoft.com/svn/chinasoft-test/src/server/test-web/v2.0.0/test-web/src/web3.0pc --username='walle' --password='walle'
Error validating server certificate for 'https://chinasoft.com:443':
- The certificate is not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
- The certificate hostname does not match.
- The certificate has expired.
Certificate information:
- Hostname: JUYUN
- Valid: from Mon, Nov :: GMT until Wed, Dec :: GMT
- Issuer: JUYUN, JUYUN, SZ, GD, CN
- Fingerprint: :::d2::a3:3d:9f:a0:fe::9f:7f:::d6::a3::5d
(R)eject, accept (t)emporarily or accept (p)ermanently? p -----------------------------------------------------------------------
ATTENTION! Your password for authentication realm: <https://chinasoft.com:443> Subversion Repository can only be stored to disk unencrypted! You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible. See the documentation for details. You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/home/www/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? yes 再次获取代码发现可以正常获取了
[www@u04elk ~]$ svn co https://chinasoft.com/svn/chinasoft-test/src/server/test-web/v2.0.0/test-web/src/web3.0pc
Checked out revision .
[www@u04elk ~]$ ll
drwxrwxr-x www www Jul : web3.0pc
对svn不熟悉的朋友可以看下:
关于SVN的trunk、branch、tag相关概念,网上摘抄的文章
——简单的对比
SVN的工作机制在某种程度上就像一颗正在生长的树:
一颗有树干和许多分支的树
分支从树干生长出来,并且细的分支从相对较粗的树干中长出
一棵树可以只有树干没有分支(但是这种情况不会持续很久,随着树的成长,肯定会有分支啦,^^)
一颗没有树干但是有很多分支的树看起来更像是地板上的一捆树枝
如果树干患病了,最终分支也会受到影响,然后整棵树就会死亡
如果分支患病了,你可以剪掉它,然后其他分支还会生长出来的哦!
如果分支生长太快了,对于树干它可能会非常沉重,最后整棵树会垮塌掉
当你感觉你的树、树干或者是分支看起来很漂亮的时候,你可以给它照张相,这样就就可以记得它在那时是多么的赞。
——Trunk
Trunk是放置稳定代码的主要环境,就好像一个汽车工厂,负责将成品的汽车零件组装在一起。
以下内容将告诉你如何使用SVN trunk:
除非你必须处理一些容易且能迅速解决的BUG,或者你必须添加一些无关逻辑的文件(比如媒体文件:图像,视频,CSS等等),否则永远不要在trunk直接做开发
不要因为特殊的需求而去对先前的版本做太大的改变,如何相关的情况都意味着需要建立一个branch(如下所述)
不要提交一些可能破坏trunk的内容,例如从branch合并
如果你在某些时候偶然间破坏了trunk,bring some cake the next day (”with great responsibilities come… huge cakes”)
——Branches
一个branch就是从一个SVN仓库中的子树所作的一份普通拷贝。通常情况它的工作类似与UNIX系统上的符号链接,但是你一旦在一个SVN branch里修改了一些文件,并且这些被修改的文件从拷贝过来的源文件独立发展,就不能这么认为了。当一个branch完成了,并且认为它足够稳定的时候,它必须合并回它原来的拷贝的地方,也就是说:如果原来是从trunk中拷贝的,就应该回到trunk去,或者合并回它原来拷贝的父级branch。
以下内容将告诉你如何使用SVN branches:
如果你需要修改你的应用程序,或者为它开发一个新的特性,请从trunk中创建一个新的branch,然后基于这个新的分支进行开发
除非是因为必须从一个branch中创建一个新的子branch,否则新的branch必须从trunk创建
当你创建了一个新branch,你应当立即切换过去。如果你没有这么做,那你为什么要在最初的地方创建这个分支呢?
——Tags
从表面上看,SVN branches和SVN tags没有什么差别,但是从概念上来说,它们有许多差别。其实一个SVN tags就是上文所述的“为这棵树照张相”:一个trunk或者一个branch修订版的命名快照。
以下内容将告诉你如何使用SVN tags:
作为一个开发者,永远不要切换至、取出,或者向一个SVN tag提交任何内容:一个tag好比某种“照片”,并不是实实在在的东西,tags只可读,不可写。
在特殊或者需要特别注意的环境中,如:生产环境(production)、?(staging)、测试环境(testing)等等,只能从一个修复过的(fixed)tag中checkout和update,永远不要commit至一个tag。
对于上述提及到的环境,可以创建如下的tags:“production”,“staging”,“testing”等等。你也可以根据软件版本、项目的成熟程度来命名tag:“1.0.3”,“stable”,“latest”等等。
当trunk已经稳定,并且可以对外发布,也要相应地重新创建tags,然后再更新相关的环境(production, staging, etc)
——工作流样例
假设你必须添加了一个特性至一个项目,且这个项目是受版本控制的,你差不多需要完成如下几个步骤:
使用SVN checkout或者SVN switch从这个项目的trunk获得一个新的工作拷贝(branch)
使用SVN切换至新的branch
完成新特性的开发(当然,要做足够的测试,包括在开始编码前)
一旦这个特性完成并且稳定(已提交),并经过你的同事们确认,切换至trunk
合并你的分支至你的工作拷贝(trunk),并且解决一系列的冲突
重新检查合并后的代码
如果可能的话,麻烦你的同事对你所编写、更改的代码进行一次复查(review)
提交合并后的工作拷贝至trunk
如果某些部署需要特殊的环境(生成环境等等),请更新相关的tag至你刚刚提交到trunk的修订版本
使用SVN update部署至相关环境