简要的线上环境部署概览
  谈到线上环境,⼀般开发同学,不太容易接触到。即使接触到,也只是其中的冰⼭⼀⾓!
  所以,其实说起线上环境的部署,咱们好像都有点懂,但是⼜都不⼀定完全懂!⽹上的知识⽆穷⽆尽,但往往都是各司⼀职,对于普通同学,很难窥其全貌!
  所以,我今天就来说说,⼀些普通的线上环境的部署步骤,和⼀些脚本⼩技巧吧。只希望通过这篇⽂章,能够让⼤家有⼀个运维的全局观!
  我将会分⼏条线来整理咱们的运维思路!
⼀、从理论上讲,我们应该怎么做?
1. 针对的是什么样的⽤户体,体量⼤概会有多少?
  这是⼀个部署规划的前题。为啥呢?
  ⼀、如果你针对的是后台管理员,⼈数也不多,那么你可能只需要⼀个服务器就可以了,前后端也都可以部署在同⼀台服务器上;如果稍微考虑下单点故障问题,则顶多两台服务器搞定!
  ⼆、如果针对的是前端普通⽤户,那么,往往就会考虑多机部署,前后端分离,单点问题,负载均衡了;⾄于具体要部署多少台,则要根据你的⽤户情况来定了,当然,前期⼀般没必要部署很多台服务器!更多的考虑是横向扩展的能⼒。只要能⽀持横向扩展,则短期内,往往不⽤担⼼性能和架构问题!
2. 为⽀持预估的⽤户量,⼤概需要多少的带宽?
  有访问就会有流量产⽣,⽽预估的⽤户量,则是⼀个带宽资源需求的⼀个决断依据!
  ⼀般针对前期⽤户不太确定的场景,可以先买个 10M 左右的共享带宽,基本能够应付;经过⼀段时间的观察后,再进⾏带宽的变更也可以;
  当然,考虑带宽,⾃然也会存在⼀个公⽹IP的问题,因为流量是从IP进来的。
  ⽽在IP之前,则是域名的访问。域名问题则⼜涉及到DNS,不必细说!
  公⽹IP可以是直接指向机器的,也可以是指向负载均衡器的。如果想要⽀持横向扩展,则IP的指向⼀定是⼀个负载均衡器。因为只有这样,当遇到流量突增,或者做活动的时候,才能更快速的进⾏扩容!
webapp是什么架构
3. 数据库规划如何?
  数据在当下时代,算是重中之重了。机器没了可以再买,代码没了可以再写,但是数据没了就完蛋了!
  数据库⼀般要遵从⼏个基本原则: ⼀、带宽要⼤;⼆、运算速度要快;三、要能承受⾜够⼤的运算空间;(即:带宽⾜够⼤/cpu核数够多/内存容量够⼤/最⼤并发连接数/...)
  所以,⼀般不要在数据库上省钱,能多点就多点!
  另外,也不要什么样的数据都往数据库(关系型数据库)存,搞清楚各类型数据库的强项与弱项,做出明智的选择。否则会带来很多不必要的⿇烦!
4. 应⽤要基于操作系统来部署还是基于容器来部署?
  这是个决策性的问题!基于操作系统的部署,是⼀种⽐较传统和常见的部署⽅式。优点是,很多系统⼯具都是完善的,只要你⼤概知道要部署什么,部署下来⼀般不会有太多问题,因为这是个完整的系统。
  但是,由于系统与系统之间可能不能完全⼀致,有各种各样的差异,所以,你在这个机器上运⾏成功的东西,在另外的机器上则不⼀定能成功。因此,基于系统的部署将会使我们的问题排查难度⼤⼤增加,⽽且移值性会很差。⽐如你在机器A上安装了10个软件,你可能配置了n个选项,但是,当你在安装
B机器的时候,你并不能很好的利⽤原有的配置,你还得从头⼀个个地来!
  因此,有另⼀个部署⽅案,基于容器的部署(我这⾥是基于docker容器的部署)。docker就类似于⼀个个的虚拟机,但是它更加轻量级,当⼀个docker部署好后,你可以任意复制到其他机器上运⾏,看起来很诱⼈吧。不过,docker只是⼊门级容器,对于⼤量集容器的管理,还是显得⼒不从⼼,当然你很容易到另⼀个⽅案: Kubernetes (K8s); 你只要花上少许的时间了解下,你就可以应⽤了!当然了,使⽤容器的⽅案,有没有什么缺点呢?应该是有的,⽐如本来可以基于系统的监控⽅案,因为接⼊容器后,监控指标则不⼀定适⽤了,当然现成的⽅案还是有的,不过得另外再花点时间研究了。再⽐如:如果容器出了问题,是否能排查出来,这也是另⼀个问题!
5. 都有些什么样的基础设施或者中间件?
  想要运⾏应⽤程序,⾃然是先考虑运⾏环境的。⽐如:应⽤需要 nginx 来做http服务器,⽤ tomcat 来做java web应⽤服务器,⽤redis来做缓存中间件,⽤zk来做应⽤协调中间件,⽤rabbitmq来做消息中间件,等等!
  因此,要在代码跑起来之前,先要把这些环境给准备好咯。
  准备这些中间件或基础设施之前,也要问下当下的形势,是否有⾼性能⾼可⽤应⽤需求?⽐如:是否需要集部署,或者单机部署?往往集部署⼜会依赖其他的中间件!也更复杂!
  当然,这些都不是事。事⼉是在出问题之后,能够有意识,能够猜测到问题发⽣的点!
6. 应⽤代码应该怎样部署?
  当基础环境就绪后,就应该让主⾓上场了。应⽤代码怎么部署?
  最简单的: 通过ftp上传代码到服务器上后,⼀个个部署!这种⽅案是最原始的,也是在没有办法搞更好的⽅案的时候使⽤的,不应长期使⽤;
  稍微好点的: 使⽤集成⼯具(如jenkins)进⾏打包,然后上传⼀个私有yum镜像服务器(yum 源)。然后在线进⾏yum 安装;这种⽅式,借助了集成⼯具,⼏个好处:
    1. 可以检测代码合法性如:单元测试、代码规范(可能需要插件);
    2. 对任何的改动有简单留档,可以备查的同时,也为代码的回滚提供了可能;
    3. 减少了⼿动上传导致的包破坏的可能性;
    4. 适合⼤规模应⽤;
  再成熟点的: 再往后⾯,⼿动 yum 安装也已经太累了,所以急需⼀个部署平台,实现⾃动化部署;(
这⾥的⾃动化部署可能就是基于CI 集成部署的⼀种升级版)。总之,⼤⼤减⼩了⼈⼯参与程序,提升了效率,同时也保证了质量!当然,这种部署平台已经经过了严格的测试,出错的可能性也⽐较⼩了!
7. 服务器的安全性?
  不考虑服务器的安全性的应⽤,⽆异于⾃暴⾃弃。⿊客⽆处不在,不过幸好现在系统也是越来越完善,只要稍加控制,即不那么容易被攻破了。但是如果放弃安全防护,则随便来⼀个菜鸟程序员就把你搞死了,那时的损失就⼤了。
  ⽹络安全是个很专业的领域,我不敢造次去谈它。不过我们可以简单的做下防护: 如防⽕墙、授权操作、病毒库等等。当然,如果使⽤xx云服务,则轻松⽅便多了,在后台点点设置⼏下搞定!
8. 服务的可监控性?
  ⽆监控,不上线!
  这是⼀个警⽰,如果线上服务没有监控,则所有线上的东西,都成了盲区,这对程序员GG们来说,简直太糟糕了,虽然他们很⾃信!
  监控分两个⽅⾯:⼀是系统级别的监控;⼆是应⽤级别的监控;(⼀般忽略其他监控: 如⽹络)
  系统级别的监控⼀般可以安装第三⽅的软件来解决: 如 zabbix, grafana ...
  ⽽应⽤级别的监控,则需要⾃⼰拥有⼀套监控代码了,⽽这对初期项⽬,则往往⽐较吃⼒。当然,如果引⼊⼀些开源的解决⽅案也是可以的,⽐如 ELK, 做到分布式⽇志中⼼的作⽤的同时,也可以根据⽇志做相应的应⽤报错监控!然⽽这⼜涉及另外的机器费⽤和⼈⼒成本问题,也显得不那么简单了。
  ⽽如果使⽤xx云服务,则往往都会⾃带服务器监控的,可以很⽅便地查看到服务器情况,站在⾼层次预估应⽤是否存在潜藏的问题!
如上,就是⼀些个⼈觉得的在部署⼀整套线上环境的时候,需要考虑的事项!从理论上讲解了下个⼈见解,不对之处,请赐教!
⼆、接下来,我将给到⼀些实际的操作捷径或提⽰?(linux)
1. 免密登录服务器?
  在n服务器之间跳转,如果每次都要求输⼊密码,那确实太烦了。尤其在密码⼀般还很不容易记住的情况下!
  所以,可以将⼀台服务器作为跳板机,在这台服务器上,可以免密地登录到允许的n台⼦服务器;
  操作步骤有⼆:
# 1. 先使⽤ssh-keygen⽣成本机的key
ssh-keygen -t rsa            # 如果已⽣成不要重复⽣成
# 2. 使⽤ssh-copy-id将本机的 key 发送到需要免密登录的服务器,⾸次copy时会要求输⼊密码,后续则免密了
ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.1.2.111
2. 服务器之间⽂件(夹)拷贝?
  拷贝⽂件的⽬的有很多,⽐如:代码同步,⽂件同步,资源同步,甚⾄是会话同步。。。
# 1. 使⽤scp 拷贝⽂件
scp /home/ol-web.war root@xxx:/www/tomcat/wepapps/    # 从本机拷贝到远程
scp /home/ol-web.war root@xxx:/www/tomcat/wepapps/    # 从远程拷贝到本机
scp -r /www/nginx/html/ root@$1.2.3.2:/www/nginx/html/    # 从本机拷贝⽂件夹到远程
# 2. 使⽤ rsync 同步⽂件,(可能需要安装 rsync 服务)
rsync -av --delete /www/nginx/html/ root@$1.2.3.1:/www/nginx/html/        # 同步所有属性,本地删除的⽂件也同步远程删除
其中,scp⼀般是系统⾃带的命令,⽽rsync则需要⾃⾏安装服务。
scp复制你可以认为是增量复制,所以远程⽂件往往会越来越⼤,垃圾⽂件越来越多。
⽽rsync则是保持两端完全⼀致,可能会符合应⽤场景!但是,别忘了把rsync服务加⼊到开机启动项中!
3. 快捷使⽤ ssh 等等命令,使⽤ tab 键进⾏信息补全?
  当使⽤ ssh / scp 等等命令操作的时候,其操作对象往往 1.2.3.x 这样的ip显⽰,如果不能友好点,那确实太累了!我们可以如下操作,以实现 ssh 也能更好的记忆:
# 在⽂件 /root/.bashrc 中,添加脚本如下,使⾃动补全添加ssh
# auto complete ...
complete -W "$(echo $(grep -v '^$|#' .ssh/config | sort -u | sed 's/^ssh //'))"ssh
# 在⽂件 /root/.ssh/config 中,添加需要⾃动补全的服务器,
Host 172.2.3.5 server-api-01
Host 172.2.3.6 server-api-02
# 以上服务器名字需要在 /etc/hosts ⽂件中添加相应解析
# ⽽登录 server时,只需, ssh server-api-01 即可
  如上补全⼯作,⽆需在所有服务器上进⾏操作,只需在相应的跳板机上提供功能即可!
4. 简要 saltstack 搭建指南?
  salt 是个⽅便易⽤的集管理⼯具,⽐如你可以⽤于批量重启服务,全局搜索⽇志等等;
# 1. 安装, 仅需到相应机器上安装即可
yum install salt-master salt-minion
# 2. 配置 /etc/salt/master /etc/salt/minion, 最简单的,只需修改 minion 配置,指向 master 的ip即可;
#指定master,冒号后有⼀个空格, minion
master: 172.1.2.22
id: server-api-01
user: root
# 3. 启动所有节点, status, restart
systemctl start salt-master        # 162机器可⽤
systemctl start salt-minion
/etc/init.d/salt-master start    # 155机器可⽤
/etc/init.d/salt-minion start
# 4. 将所有salt-minion 添加到 master 集管理
salt-key -A
# 5. 登录跳板机 api_01, 运⾏salt 操作,执⾏集管理⼯作
salt server-api-02 cmd.run 'lsof -i:80'
salt '*' test.ping
5. 简要集复制shell脚本?
  有时,你可能需要将你的应⽤发布到n台服务中,你可以直接改如下shell,也可以依赖于salt这样的⾼级⼯具进⾏发布!shell 参考如下:
#!/bin/bash
# find out my ip
MY_MERCHINE_IP=`ifconfig eth0 |awk -F "[: ]+"'/inet addr/{print $4}'`;
MERCHINE_IP_LIST="172.1.2.7 172.1.3.4";
for m_ip in $MERCHINE_IP_LIST;
do
if [[ $m_ip != $MY_MERCHINE_IP ]]; then
echo"- Installing apps to mechine@${m_ip} ...";
# install api apps
scp /www/test/hello-1.0.0-SNAPSHOT.jar root@${m_ip}:/www/test/
rsync -av --delete /www/html/ root@${m_ip}:/www/html/
echo"- Install apps to merchine@${m_ip} done.";
fi;
done;
6. 简要docker搭建指南?
  docker 作为⼀个容器化的基⽯,⼀出世就被追棒。包括现在的 k8s ,也是基于docker的。docker 可以
让你在⼀处搭建,处处运⾏,从⽽避免每次新买机器就要搞很久的尴尬局⾯;其搭建也是很简单的(简单应⽤):
  为⽅便任意发挥,我们可以基于centos这种系统级别的镜像进⾏创建⾃⼰的image;
# docker 安装:
yum install docker
service docker start
# 拉取 centos6 的 docker 镜像
docker pull centos:6
docker images
# 构建⼀个 image, 创建空⽬录,编辑 Dockerfile
vim Dockerfile        # 内容可变
FROM centos:6
MAINTAINER oom <w@163>
# move all configuration files into container
# RUN yum install -y lsof
# EXPOSE 80
# CMD ["sh","-c","service httpd start;bash"]
# 创建镜像
docker build -t tmp_image:1.0 .
# 创建并运⾏容器
docker run -h tmp_container -itd --name tmp_container -v /opt/docker/webapps:/www/webapp tmp_image:1.0
# 进⼊容器,相当于进⼊ centos 操作系统
docker exec -it tmp_container bash
# 保存容器修改到images
  docker commit -m 'web final.' 49d79fc19eaa tmp_image:1.2
# 备份容器修改后的docker镜像
  docker save > /opt/images/images_final/tmp_image.final.tar tmp_image:1.2
# 恢复你的备份镜像,即全⽹发布
# 可以在任何装 docker 的地⽅加载保存的镜像
  docker load -i /opt/images/images_final/tmp_image.final.tar
7. 定制你的登录欢迎语?
  由于可能存在线上环境与测试环境共存的情况,⼀不⼩⼼的切换错误,就可能导致不可挽回的损失。所以,如果我们能在登录的时候,做⼀个简单的提⽰,那么就会少⼀点出错的可能性。所以,订制你的登录欢迎语吧!
# 修改登录欢迎语 vim /etc/motd
*****************************************************************
WARNING:  欢迎来到线上机器: service-api-01,请谨慎操作哦
*****************************************************************
  这样,⽤户登录后,就会清楚的知道⾃⼰是在操作⽣产环境了!
8. 更⽅便的查看nginx的访问⽇志?
  对于后端的⽇志⽽⾔,往往都是主动打印到某个固定位置,从⽽开发⼈员可以直接使⽤ tail -f xxx.log 进⾏⽇志的查看!
  然⽽对于前端的代码⽽⾔,则往往没有相应的开发⽇志,唯⼀可以借助的就是 http 服务器的⽇志来排查问题了!
  所以,⽐如使⽤ nginx 作为 http 服务器,那么就应该把尽可能多的有⽤⽇志打印出来。那么,如何快速查看 nginx ⽇志,则是有必要的!⽐如我们可以这样:
# vim /usr/bin/log_nginx_host , 使⽤ log_nginx_host 直接查看所有 nginx ⽇志
tail -f /var/log/nginx/access.log /var/log/nginx/error.log
如上,将会把访问⽇志与错误⽇志⼀起打印出来,从⽽快速定位问题!
  。。。