验证通过提示"time zone deny"是timezone什么意思原因导致的,怎么解决

Access denied | answermug.com used Cloudflare to restrict access
Please enable cookies.
What happened?
The owner of this website (answermug.com) has banned your access based on your browser's signature (b5e53ea-ua98).中国科大 LUG 的 &a data-hash=&f2efaaed2de8d50eee749a& href=&//www.zhihu.com/people/f2efaaed2de8d50eee749a& class=&member_mention& data-editable=&true& data-title=&@高一凡& data-hovercard=&p$b$f2efaaed2de8d50eee749a&&@高一凡&/a& 在 LUG HTTP 代理服务器上部署了 Linux 4.9 的 TCP BBR 拥塞控制算法。从科大的移动出口到新加坡 DigitalOcean 的实测下载速度&b&从 647 KB/s 提高到了 22.1 MB/s&/b&(截屏如下)。&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-2218943eab7a6b70ad0f4a213cb1f393_b.jpg& data-rawwidth=&840& data-rawheight=&167& class=&origin_image zh-lightbox-thumb& width=&840& data-original=&https://pic4.zhimg.com/50/v2-2218943eab7a6b70ad0f4a213cb1f393_r.jpg&&&/figure&(应评论区各位 dalao 要求,补充测试环境说明:是在新加坡的服务器上设置了 BBR,&b&新加坡的服务器是数据的发送方&/b&。这个服务器是访问墙外资源的 HTTP 代理。科大移动出口到 DigitalOcean 之间不是 dedicated 的专线,是走的公网,科大移动出口这边是 1 Gbps 无限速(但是要跟其他人 share),DigitalOcean 实测是限速 200 Mbps。RTT 是 66 ms。实测结果这么好,也是因为大多数人用的是 TCP Cubic (Linux) / Compound TCP (Windows),&b&在有一定丢包率的情况下,TCP BBR 更加激进,抢占了更多的公网带宽&/b&。因此也是有些不道德的感觉。)&br&&br&此次 Google 提交到 Linux 主线并发表在 ACM queue 期刊上的 TCP BBR 拥塞控制算法,继承了 Google “先在生产环境部署,再开源和发论文” 的研究传统。TCP BBR 已经在 Youtube 服务器和 Google 跨数据中心的内部广域网(B4)上部署。&br&&br&&b&TCP BBR 致力于解决两个问题:&/b&&br&&ol&&li&&b&在有一定丢包率的网络链路上充分利用带宽。&/b&&/li&&li&&b&降低网络链路上的 buffer 占用率,从而降低延迟。&/b&&/li&&/ol&&br&TCP 拥塞控制的目标是最大化利用网络上瓶颈链路的带宽。一条网络链路就像一条水管,要想用满这条水管,最好的办法就是给这根水管灌满水,也就是:&br&&b&水管内的水的数量 = 水管的容积 = 水管粗细 × 水管长度&/b&&br&换成网络的名词,也就是:&br&&b&网络内尚未被确认收到的数据包数量 = 网络链路上能容纳的数据包数量 = 链路带宽 × 往返延迟&/b&&br&&br&TCP 维护一个&b&发送窗口&/b&,估计当前网络链路上能容纳的数据包数量,希望在有数据可发的情况下,回来一个确认包就发出一个数据包,总是保持发送窗口那么多个包在网络中流动。&br&&br&&figure&&img src=&https://pic2.zhimg.com/50/v2-c81d606af6f0cfaf2de62_b.jpg& data-rawwidth=&451& data-rawheight=&225& class=&origin_image zh-lightbox-thumb& width=&451& data-original=&https://pic2.zhimg.com/50/v2-c81d606af6f0cfaf2de62_r.jpg&&&/figure&&br&&i&TCP 与水管的类比示意(图片来源:Van Jacobson,Congestion Avoidance and Control,1988)&/i&&br&&br&如何估计水管的容积呢?一种大家都能想到的方法是不断往里灌水,直到溢出来为止。标准 TCP 中的拥塞控制算法也类似:&b&不断增加发送窗口,直到发现开始丢包&/b&。这就是所谓的 ”加性增,乘性减”,也就是当收到一个确认消息的时候慢慢增加发送窗口,当确认一个包丢掉的时候较快地减小发送窗口。&br&&br&标准 TCP 的这种做法有两个问题:&br&&br&首先,假定网络中的丢包都是由于拥塞导致(网络设备的缓冲区放不下了,只好丢掉一些数据包)。事实上网络中有可能存在传输错误导致的丢包,基于丢包的拥塞控制算法并不能区分&b&拥塞丢包&/b&和&b&错误丢包&/b&。在数据中心内部,错误丢包率在十万分之一(1e-5)的量级;在广域网上,错误丢包率一般要高得多。&br&&br&更重要的是,“加性增,乘性减” 的拥塞控制算法要能正常工作,&b&错误丢包率需要与发送窗口的平方成反比&/b&。数据中心内的延迟一般是 10-100 微秒,带宽 10-40 Gbps,乘起来得到稳定的发送窗口为 12.5 KB 到 500 KB。而广域网上的带宽可能是 100 Mbps,延迟 100 毫秒,乘起来得到稳定的发送窗口为 10 MB。广域网上的发送窗口比数据中心网络高 1-2 个数量级,错误丢包率就需要低 2-4 个数量级才能正常工作。因此标准 TCP 在有一定错误丢包率的&b&长肥管道(long-fat pipe,即延迟高、带宽大的链路)&/b&上只会收敛到一个很小的发送窗口。这就是很多时候客户端和服务器都有很大带宽,运营商核心网络也没占满,但下载速度很慢,甚至下载到一半就没速度了的一个原因。&br&&br&其次,网络中会有一些 buffer,就像输液管里中间膨大的部分,用于吸收网络中的流量波动。由于标准 TCP 是通过 “灌满水管” 的方式来估算发送窗口的,在连接的开始阶段,buffer 会被倾向于占满。后续 buffer 的占用会逐渐减少,但是并不会完全消失。客户端估计的水管容积(发送窗口大小)总是略大于水管中除去膨大部分的容积。这个问题被称为 &b&bufferbloat(缓冲区膨胀)&/b&。&br&&figure&&img src=&https://pic3.zhimg.com/50/v2-47da56cba0cf246e6d8b_b.jpg& data-rawwidth=&423& data-rawheight=&283& class=&origin_image zh-lightbox-thumb& width=&423& data-original=&https://pic3.zhimg.com/50/v2-47da56cba0cf246e6d8b_r.jpg&&&/figure&&br&&i&缓冲区膨胀现象图示&/i&&br&&br&缓冲区膨胀有两个危害:&br&&ol&&li&&b&增加网络延迟&/b&。buffer 里面的东西越多,要等的时间就越长嘛。&/li&&li&共享网络瓶颈的连接较多时,可能导致&b&缓冲区被填满而丢包&/b&。很多人把这种丢包认为是发生了网络拥塞,实则不然。&/li&&/ol&&figure&&img src=&https://pic4.zhimg.com/50/v2-c623d2f88cc5f3ad568c2ce97e6ec9e1_b.jpg& data-rawwidth=&476& data-rawheight=&273& class=&origin_image zh-lightbox-thumb& width=&476& data-original=&https://pic4.zhimg.com/50/v2-c623d2f88cc5f3ad568c2ce97e6ec9e1_r.jpg&&&/figure&&br&&i&往返延迟随时间的变化。&/i&&i&红线:标准 TCP(可见周期性的延迟变化,以及 buffer 几乎总是被填满);绿线:TCP BBR&/i&&br&&i&(图片引自 Google 在 ACM queue 2016 年 9-10 月刊上的论文 [1],下同)&/i&&br&&br&有很多论文提出在网络设备上把当前缓冲区大小的信息反馈给终端,比如在数据中心广泛应用的 ECN(Explicit Congestion Notification)。然而广域网上网络设备众多,更新换代困难,需要网络设备介入的方案很难大范围部署。&br&&br&TCP BBR 是怎样解决以上两个问题的呢?&br&&ol&&li&&b&既然不容易区分拥塞丢包和错误丢包,TCP BBR 就干脆不考虑丢包。&br&&/b&&/li&&li&&b&既然灌满水管的方式容易造成缓冲区膨胀,TCP BBR 就分别估计带宽和延迟,而不是直接估计水管的容积。&/b&&/li&&/ol&带宽和延迟的乘积就是发送窗口应有的大小。发明于 2002 年并已进入 Linux 内核的 TCP Westwood 拥塞控制算法,就是分别估计带宽和延迟,并计算其乘积作为发送窗口。然而&b&带宽和延迟就像粒子的位置和动量,是没办法同时测准的&/b&:要测量最大带宽,就要把水管灌满,缓冲区中有一定量的数据包,此时延迟就是较高的;要测量最低延迟,就要保证缓冲区为空,网络里的流量越少越好,但此时带宽就是较低的。&br&&br&TCP BBR 解决&b&带宽和延迟无法同时测准&/b&的方法是:&b&交替测量带宽和延迟;用一段时间内的带宽极大值和延迟极小值作为估计值。&/b&&br&&br&在连接刚建立的时候,TCP BBR 采用类似标准 TCP 的&b&慢启动&/b&,指数增长发送速率。然而标准 TCP 遇到任何一个丢包就会立即进入拥塞避免阶段,它的本意是填满水管之后进入拥塞避免,然而(1)如果链路的错误丢包率较高,没等到水管填满就放弃了;(2)如果网络里有 buffer,总要把缓冲区填满了才会放弃。&br&&br&TCP BBR 则是根据收到的确认包,发现有效带宽不再增长时,就进入拥塞避免阶段。(1)链路的错误丢包率只要不太高,对 BBR 没有影响;(2)当发送速率增长到开始占用 buffer 的时候,有效带宽不再增长,BBR 就及时放弃了(事实上放弃的时候占的是 3 倍带宽 × 延迟,后面会把多出来的 2 倍 buffer 清掉),这样就不会把缓冲区填满。&br&&figure&&img src=&https://pic3.zhimg.com/50/v2-bdcb_b.jpg& data-rawwidth=&354& data-rawheight=&479& class=&content_image& width=&354&&&/figure&&i&发送窗口与往返延迟和有效带宽的关系。BBR 会在左右两侧的拐点之间停下,基于丢包的标准 TCP 会在右侧拐点停下(图片引自 TCP BBR 论文,下同)&/i&&br&&br&在慢启动过程中,由于 buffer 在前期几乎没被占用,延迟的最小值就是延迟的初始估计;慢启动结束时的最大有效带宽就是带宽的初始估计。&br&&br&慢启动结束后,为了把多占用的 2 倍带宽 × 延迟消耗掉,BBR 将进入&b&排空(drain)阶段&/b&,指数降低发送速率,此时 buffer 里的包就被慢慢排空,直到往返延迟不再降低。如下图绿线所示。&br&&figure&&img src=&https://pic3.zhimg.com/50/v2-39bd5ebffb4bc1a1e9bf2_b.jpg& data-rawwidth=&480& data-rawheight=&413& class=&origin_image zh-lightbox-thumb& width=&480& data-original=&https://pic3.zhimg.com/50/v2-39bd5ebffb4bc1a1e9bf2_r.jpg&&&/figure&&br&&i&TCP BBR(绿线)与标准 TCP(红线)有效带宽和往返延迟的比较&/i&&br&&br&排空阶段结束后,BBR 进入稳定运行状态,交替探测带宽和延迟。由于网络带宽的变化比延迟的变化更频繁,&b&BBR 稳定状态的绝大多数时间处于带宽探测阶段&/b&。带宽探测阶段是一个正反馈系统:定期尝试增加发包速率,如果收到确认的速率也增加了,就进一步增加发包速率。&br&&br&具体来说,以每 8 个往返延迟为周期,在第一个往返的时间里,BBR 尝试增加发包速率 1/4(即以估计带宽的 5/4 速度发送)。在第二个往返的时间里,为了把前一个往返多发出来的包排空,BBR 在估计带宽的基础上降低 1/4 作为发包速率。剩下 6 个往返的时间里,BBR 使用估计的带宽发包。&br&&br&当网络带宽增长一倍的时候,每个周期估计带宽会增长 1/4,每个周期为 8 个往返延迟。其中向上的尖峰是尝试增加发包速率 1/4,向下的尖峰是降低发包速率 1/4(排空阶段),后面 6 个往返延迟,使用更新后的估计带宽。3 个周期,即 24 个往返延迟后,估计带宽达到增长后的网络带宽。&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-a738f6aab8262cfecc4fa_b.jpg& data-rawwidth=&326& data-rawheight=&279& class=&content_image& width=&326&&&/figure&&br&&i&网络带宽增长一倍时的行为。绿线为网络中包的数量,蓝线为延迟&/i&&br&&br&当网络带宽降低一半的时候,多出来的包占用了 buffer,导致网络中包的延迟显著增加(下图蓝线),有效带宽降低一半。延迟是使用极小值作为估计,增加的实际延迟不会反映到估计延迟(除非在延迟探测阶段,下面会讲)。带宽的估计则是使用一段滑动窗口时间内的极大值,当之前的估计值超时(移出滑动窗口)之后,降低一半后的有效带宽就会变成估计带宽。估计带宽减半后,发送窗口减半,发送端没有窗口无法发包,buffer 被逐渐排空。&br&&figure&&img src=&https://pic2.zhimg.com/50/v2-d07aebb5e_b.jpg& data-rawwidth=&320& data-rawheight=&279& class=&content_image& width=&320&&&/figure&&i&网络带宽降低一半时的行为。&/i&&i&绿线为网络中包的数量,蓝线为延迟&/i&&br&&br&&b&当带宽增加一倍时,BBR 仅用 1.5 秒就收敛了;而当带宽降低一半时,BBR 需要 4 秒才能收敛。&/b&前者由于带宽增长是指数级的;后者主要是由于带宽估计采用滑动窗口内的极大值,需要一定时间有效带宽的下降才能反馈到带宽估计中。&br&&br&当网络带宽保持不变的时候,稳定状态下的 TCP BBR 是下图这样的:(我们前面看到过这张图)可见每 8 个往返延迟为周期的延迟细微变化。&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-c623d2f88cc5f3ad568c2ce97e6ec9e1_b.jpg& data-rawwidth=&476& data-rawheight=&273& class=&origin_image zh-lightbox-thumb& width=&476& data-original=&https://pic4.zhimg.com/50/v2-c623d2f88cc5f3ad568c2ce97e6ec9e1_r.jpg&&&/figure&&br&&i&往返延迟随时间的变化。&/i&&i&红线:标准 TCP;绿线:TCP BBR&/i&&br&&br&上面介绍了 BBR 稳定状态下的带宽探测阶段,那么什么时候探测延迟呢?在带宽探测阶段中,估计延迟始终是使用极小值,如果实际延迟真的增加了怎么办?TCP BBR 每过 10 秒,如果估计延迟没有改变(也就是没有发现一个更低的延迟),就进入延迟探测阶段。延迟探测阶段持续的时间仅为 200 毫秒(或一个往返延迟,如果后者更大),这段时间里发送窗口固定为 4 个包,也就是几乎不发包。这段时间内测得的最小延迟作为新的延迟估计。也就是说,&b&大约有 2% 的时间 BBR 用极低的发包速率来测量延迟&/b&。&br&&br&&b&TCP BBR 还使用 pacing 的方法降低发包时的 burstiness&/b&,减少突然传输的一串包导致缓冲区膨胀。发包的 burstiness 可能由两个原因引起:&br&&ol&&li&数据接收方为了节约带宽,把多个确认(ACK)包累积成一个发出,这叫做 ACK Compression。数据发送方收到这个累积确认包后,如果没有 pacing,就会发出一连串的数据包。&/li&&li&数据发送方没有足够的数据可传输,积累了一定量的空闲发送窗口。当应用层突然需要传输较多的数据时,如果没有 pacing,就会把空闲发送窗口大小这么多数据一股脑发出去。&/li&&/ol&&br&下面我们来看 TCP BBR 的效果如何。&br&&br&首先看 BBR 试图解决的第一个问题:在有随机丢包情况下的吞吐量。如下图所示,&b&只要有万分之一的丢包率,标准 TCP 的带宽就只剩 30%;千分之一丢包率时只剩 10%;有百分之一的丢包率时几乎就卡住了。而 TCP BBR 在丢包率 5% 以下几乎没有带宽损失,在丢包率 15% 的时候仍有 75% 带宽&/b&。&br&&figure&&img src=&https://pic1.zhimg.com/50/v2-1df6e7ba0cae0147dddb01aac0d0f309_b.jpg& data-rawwidth=&483& data-rawheight=&277& class=&origin_image zh-lightbox-thumb& width=&483& data-original=&https://pic1.zhimg.com/50/v2-1df6e7ba0cae0147dddb01aac0d0f309_r.jpg&&&/figure&&i&100 Mbps,100ms 下的丢包率和有效带宽(红线:标准 TCP,绿线:TCP BBR)&br&&/i&&br&&b&异地数据中心间跨广域网的传输往往是高带宽、高延迟的,且有一定丢包率,TCP BBR 可以显著提高传输速度&/b&。这也是中国科大 LUG HTTP 代理服务器和 Google 广域网(B4)部署 TCP BBR 的主要原因。&br&&br&再来看 BBR 试图解决的第二个问题:&b&降低延迟,减少缓冲区膨胀&/b&。如下图所示,&b&标准 TCP 倾向于把缓冲区填满,缓冲区越大,延迟就越高&/b&。当用户的网络接入速度很慢时,这个延迟可能超过操作系统连接建立的超时时间,导致连接建立失败。使用 TCP BBR 就可以避免这个问题。&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-78cabc327d487caf1309e0_b.jpg& data-rawwidth=&453& data-rawheight=&250& class=&origin_image zh-lightbox-thumb& width=&453& data-original=&https://pic4.zhimg.com/50/v2-78cabc327d487caf1309e0_r.jpg&&&/figure&&br&&i&缓冲区大小与延迟的关系(红线:标准 TCP,绿线:TCP BBR)&/i&&br&&br&Youtube 部署了 TCP BBR 之后,全球范围的中位数延迟降低了 53%(也就是快了一倍),发展中国家的中位数延迟降低了 80%(也就是快了 4 倍)。从下图可见,&b&延迟越高的用户,采用 TCP BBR 后的延迟下降比例越高,原来需要 10 秒的现在只要 2 秒了&/b&。如果您的网站需要让用 GPRS 或者慢速 WiFi 接入网络的用户也能流畅访问,不妨试试 TCP BBR。&br&&figure&&img src=&https://pic3.zhimg.com/50/v2-febab4b4a48caaa8bf569e8d033757cf_b.jpg& data-rawwidth=&476& data-rawheight=&272& class=&origin_image zh-lightbox-thumb& width=&476& data-original=&https://pic3.zhimg.com/50/v2-febab4b4a48caaa8bf569e8d033757cf_r.jpg&&&/figure&&br&&i&标准 TCP 与 TCP BBR 的往返延迟中位数之比&/i&&br&&br&综上,&b&TCP BBR 不再使用丢包作为拥塞的信号,也不使用 “加性增,乘性减” 来维护发送窗口大小,而是分别估计极大带宽和极小延迟,把它们的乘积作为发送窗口大小。&/b&&br&&br&&br&BBR 的连接开始阶段由慢启动、排空两阶段构成。为了解决带宽和延迟不易同时测准的问题,BBR 在连接稳定后交替探测带宽和延迟,其中探测带宽阶段占绝大部分时间,通过正反馈和周期性的带宽增益尝试来快速响应可用带宽变化;偶尔的探测延迟阶段发包速率很慢,用于测准延迟。&br&&br&BBR 解决了两个问题:&br&&ol&&li&&b&在有一定丢包率的网络链路上充分利用带宽。非常适合高延迟、高带宽的网络链路。&/b&&/li&&li&&b&降低网络链路上的 buffer 占用率,从而降低延迟。非常适合慢速接入网络的用户。&/b&&/li&&/ol&&br&看到评论区很多客户端和服务器哪个部署 TCP BBR 有效的问题,需要提醒:&b&TCP 拥塞控制算法是数据的发送端决定发送窗口,因此在哪边部署,就对哪边发出的数据有效。&/b&如果是下载,就应在服务器部署;如果是上传,就应在客户端部署。&br&&br&如果希望加速访问国外网站的速度,且下载流量远高于上传流量,在客户端上部署 TCP BBR(或者任何基于 TCP 拥塞控制的加速算法)是没什么效果的。需要在 VPN 的国外出口端部署 TCP BBR,并做 TCP Termination & TCP Proxy。也就是客户建立连接事实上是跟 VPN 的国外出口服务器建联,国外出口服务器再去跟目标服务器建联,使得丢包率高、延迟大的这一段(从客户端到国外出口)是部署了 BBR 的国外出口服务器在发送数据。或者在 VPN 的国外出口端部署 BBR 并做 HTTP(S) Proxy,原理相同。&br&&br&大概是由于 ACM queue 的篇幅限制和目标读者,这篇论文并没有讨论(仅有拥塞丢包情况下)TCP BBR 与标准 TCP 的公平性。也没有讨论 BBR 与现有拥塞控制算法的比较,如基于往返延迟的(如 TCP Vegas)、综合丢包和延迟因素的(如 Compound TCP、TCP Westwood+)、基于网络设备提供拥塞信息的(如 ECN)、网络设备采用新调度策略的(如 CoDel)。期待 Google 发表更详细的论文,也期待各位同行报告 TCP BBR 在实验或生产环境中的性能。&br&&br&本人不是 TCP 拥塞控制领域的专家,如有错漏不当之处,恳请指正。&br&&br&[1] Cardwell, Neal, et al. &BBR: Congestion-Based Congestion Control.& &i&Queue&/i&14.5 (2016): 50.
中国科大 LUG 的
在 LUG HTTP 代理服务器上部署了 Linux 4.9 的 TCP BBR 拥塞控制算法。从科大的移动出口到新加坡 DigitalOcean 的实测下载速度从 647 KB/s 提高到了 22.1 MB/s(截屏如下)。 (应评论区各位 dalao 要求,补充测试环境说明:是在新…
&figure&&img src=&https://pic2.zhimg.com/v2-3bf6a08dc1dc_b.jpg& data-rawwidth=&565& data-rawheight=&414& class=&origin_image zh-lightbox-thumb& width=&565& data-original=&https://pic2.zhimg.com/v2-3bf6a08dc1dc_r.jpg&&&/figure&&h2&原文链接:&a href=&http://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/lpMW-ngen23xt-V15i9DiA& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&中小型运维团队如何设计运维自动化平台&/a&&/h2&&blockquote&&b&关于作者&/b&&br&温峥峰,百田信息运维技术专家,DevOps Team Leader,超过8年互联网运维经验,曾就职于网易游戏,经受过各类海量规模互联网业务模式的历练,专注于运维自动化、DevOps实践、运维服务体系建设与SRE时代下的运维价值挖掘。&br&知乎专栏:&a href=&https://zhuanlan.zhihu.com/hiphone-devops& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/hiph&/span&&span class=&invisible&&one-devops&/span&&span class=&ellipsis&&&/span&&/a&&/blockquote&&h2&前言
&/h2&&p&我给中小型运维团队的定义是整个团队人数(所有运维工程师 + 运维开发工程师)为 20 人以下,一般这样的团队,能为自动化投入的资源也许就 1、2 个开发人员。&/p&&p&BAT 等大公司的 DevOps 平台功能涵盖的范围非常全面而且各种高大上,这么庞大的体系对于中小型运维团队,要靠手头顶多 2 名运维开发工程师来实现落地就懵了,不知该从何入手。所以往往大部分中小型运维团队要么传统人肉运维黑路走到底,要么指望公司咬牙上 DevOps 商业服务。&/p&&p&然而,仅靠购买商业服务也未必能完全解决问题,主要原因有:&/p&&p&1 . 历史项目成本考虑:商业平台不支持个性化,历史项目未必能直接对接商业平台,需要通过运维与业务侧均重构以适应商业平台,对接成本甚至高于自建平台,且要高速运行的业务侧停下配合也并不靠谱;&/p&&p&2 . 商业机密数据的考虑:商业平台会存储运维 / 部分业务相关数据,这对于安全要求较高的行业来说,自建平台的可控度更高;&/p&&p&&br&&/p&&p&然而,中小型公司的自建平台大多都算是重复造轮子,虽然各家业务情况各异,但也有可以抽象成可复用的架构体系,这也是商业自动化平台的价值所在,如果团队是 10 人以下且没专职开发人员再且业务技术历史债务不重的情况下,选择商业服务也不失为明智之举。&/p&&p&我们经常看到各种大厂的自动化平台一般包含且不限于以下内容:CMDB、配置中心、管控平台、数据平台、CI/CD、作业平台、容器管理、扩容缩容、辅助运营、监控中心 等等,各种高大上词汇让人目不暇接。&/p&&p&由于中小型团队的用人成本必须控制得极其精确,一般不会有太多人力资源投入到自动化平台的开发,所以必须找出最核心功能,以达到快速落地投入生产环节使用为目的。我们不可能对上述功能点面面俱到,这样只会让自己无从下手。&/p&&p&其实最核心的功能模块只有两个:CMDB(配置平台)和作业平台。我们作为中小型的运维团队,其实能把这两部分完成即可满足 80% 的业务需求,在此基础上,再根据自身业务需求再考虑开发其他高级扩展功能如 CI/CD、数据分析、业务监控、辅助运营等。&/p&&h2&项目背景
&/h2&&p&需求驱动导向,大家也不会因为上线一个小项目就招人做自动化平台,在什么情况下我们才需要做自动化平台呢?&/p&&p&去年,随着手游项目的发展,公司业务需求处于一个飞速增长的阶段,在短时间内已经发展到将近数十个项目(含各种渠道、平台、分区),业务形态各异,包括页游、手游、站点、app 等,这样众多的项目运维管理成本非常高,传统的运维管理方式很难高效率、高质量地管理和把控如此多的产品和项目。&/p&&p&随着虚拟化、云、微服务等技术的发展,再加上有众多的云服务提供商(阿里云、腾讯云、UCloud 等),应用程序的底层运行环境愈发多样化,各种运维对象都需要通过一个平台进行统一的操作和管理。&/p&&p&为了应对以上问题并高质量完成运维保障服务,我们必须做到:&/p&&ul&&li&通过平台统一管理所有运维对象,对项目组、对运维部门的所有操作都程序固化;&/li&&li&实现所有项目的持续集成、自动化部署、项目组自助操作以提升发布效率和降低故障率;&/li&&li&有一个完善的配置中心为所有运维自动化的底层数据和配置基础,驱动所有运维脚本、工具、组件正常运行;&/li&&/ul&&h2&如何达成目标
&/h2&&p&明确了目标之后,你会发现这三个目标正好对应三个运维术语:标准化、流程规范化和 CMDB。&/p&&ul&&li&标准化:从主机名、IP、操作系统、文件目录、脚本等一系列运维对象都制定标准规范,业务部门和运维部门都遵守同一套标准,基于这套标准去建设统一的平台。&/li&&li&流程规范化:主要是涉及 程序文件打包、开发测试线上环境管理、发布流程 等多部门协作的规范,必须落实到程序固化或者文档固化,打造 Dev 和 Ops 之间的标准交付环境。&/li&&li&CMDB:这是一切运维自动化体系建设的基石,其它如配置管理、作业执行、资产管理等需要基于 CMDB 才能形成体系,构建完善的运维对象生命周期和操作闭环。&/li&&/ul&&p&&br&&/p&&h2&标准化
&/h2&&p&标准化包含的范畴非常多,从最简单的操作系统版本、主机名、IP 段、系统帐号密码到软件安装的目录、参数、配置文件等等,也许不同的公司有其特有习惯和历史遗留,所以这个没有一个全业界的统一模式。&/p&&p&现在只需要把贵司的习惯用文档的形式固化下来,再彻底检查生产环境的情况是否满足规范所述,不满足则按规范操作。&/p&&p&对于历史不是太悠久的项目要修正不会太困难,如果连这点都嫌麻烦的话,也不用谈什么运维自动化了。&/p&&p&简单画个思维导图,标准化的范畴主要包含但不限于以下内容:&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-f8d2a6f40d8dd216bb70384ed02ddb47_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&820& data-rawheight=&759& class=&origin_image zh-lightbox-thumb& width=&820& data-original=&https://pic4.zhimg.com/v2-f8d2a6f40d8dd216bb70384ed02ddb47_r.jpg&&&/figure&&h2&流程规范化
&/h2&&p&流程规范化是在建立了标准化之后,为了规范运维内部以及与外部门合作的一系列复杂事件的细节做法,比如要发布新版本、上线新项目、业务扩容缩容等。&/p&&p&这一部分不太容易展开,因为不同公司有自己的做法和习惯,无论是怎样做,请用文档规范和约束各部门人员的行为,这样才能方便程序化和自动化,不然程序就要写多很多 if-else 语句或者需要配置化来兼容各种不规范情况,徒增开发人力消耗。&/p&&h2&CMDB
&/h2&&p&不用赘述,CMDB 的设计肯定是运维自动化建设的重中之重,设计好的话,运维平台的开发可以有事半功倍的效果。&/p&&p&CMDB(Configuration Management Database)配置管理数据库,是记录所有运维对象信息的数据库,所有运维流程需要基于 CMDB 的数据进行操作,形成操作闭环,操作的结果会反馈到 CMDB 中。&/p&&p&此系统提供了一整套接口界面与其它任何需要信息的系统进行对接,这也是设计初衷,将信息从一个统一的、标准的源头输出给各垂直或水平业务功能系统,而运维需要做的就是维护 CMDB 本身基础数据的完整性、准确性,CMDB 与各流程系统、垂直功能系统结合之后实现信息数据一处变更,处处同步。&/p&&p&一个机器下架的操作:&/p&&p&&b&传统方式:&/b&通过 SSH 登录到该机器,关闭所有业务程序,关机,在控制列表删除该 IP,下架,登录资源管理系统删除该机器信息。&/p&&p&&b&自动化方式:&/b&在 CMDB 中编辑其状态,系统自动调用底层工具关闭服务、关机,并自动将机器信息在 CMDB 中更新状态&/p&&p&&b&区别:&/b& 传统方式各个步骤都是非原子性,每一步都可能有错漏的问题,如忘记删除控制列表 IP 或者忘记更新资源管理系统信息,运维流程无法达到操作闭环。而真正的自动化方式是应该需要达到操作闭环,无需人工干预。&/p&&p&如何设计&/p&&p&CMDB 的设计有一个最大的误区是想建立一个大而全的属性表,恨不得想把全部运维对象的全部属性都找出来,比如:&/p&&figure&&img src=&https://pic3.zhimg.com/v2-6d654ed47e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&599& data-rawheight=&1878& class=&origin_image zh-lightbox-thumb& width=&599& data-original=&https://pic3.zhimg.com/v2-6d654ed47e_r.jpg&&&/figure&&p&从零散的运维对象来拼凑 CMDB 基本都是吃力不讨好的,因为这样的设计方式根本没有从业务出发。&/p&&p&而真正能解决业务问题的 CMDB 必须回到业务上面来,从核心的三层关系开始组建 CMDB,这三层概念从大到小分别是:业务、集群、模块(游戏行业术语一般叫项目、分区、服务)&/p&&p&设计思路应该是这样的,我所运维一个业务,它有哪些集群?集群下有哪些模块?模块下有哪些机器?机器有哪些属性?各种属性之间有什么关联关系?&/p&&p&通过这样的思维方式慢慢把真正的 CMDB 组织起来......&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-1db89a98fdc3f47b0cfbe454feaef815_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&508& data-rawheight=&354& class=&origin_image zh-lightbox-thumb& width=&508& data-original=&https://pic2.zhimg.com/v2-1db89a98fdc3f47b0cfbe454feaef815_r.jpg&&&/figure&&p&当然,运维对象远不止那么少,还需要大家根据自家业务多多挖掘,这个过程比较艰辛,但不需要一步到位,先确定好核心对象,再慢慢完善补充其他对象。&/p&&h2&配置项属性&/h2&&p&我们把 CMDB 的某个对象称为配置项,一个典型的配置项如一台主机、一个域名、一个 IP 。&/p&&p&举个例子,一台主机,其属性获取的三种方式:&/p&&ul&&li&agent 获得:如 cpu、memery、disk、ethX 之类的硬件信息,一般用 python psutil 模块可以获取大部分所需要的属性;&/li&&li&云服务商 api:有部分属性不能通过 agent 获得的如 EIP、Region、Zone 等,如果不是用云主机的就不需要这一部分;&/li&&li&手工维护:有些属性不能自动获取,只能通过人工录入,不过这类属性还是尽量越少越好;&/li&&/ul&&p&由点到面可以看出,配置项的属性类别基本可以分成三类:&/p&&p&&b&人工录入 :&/b& 自动化系统所需的业务 - 集群 - 模块关系,每台主机运行什么服务等等。&/p&&p&&b&外系统 API:&/b& 需要通过云服务商 API、Zabbix API、K8s API、其他业务系统 API 等途径。&/p&&p&&b&自发现:&/b& 机器内部获得,如 python psutil、puppet fact、ansible setup 等途径。&/p&&p&了解属性类别可以帮助我们更好更快地完善配置项的各种属性自动获取机制,尽量避免人工干预。&/p&&p&再聊聊主机,主机是一个承上启下的核心对象,在它身上有很多属性会被各种功能所使用,所以我们要先理清它和其他对象的关联关系。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-3bf6a08dc1dc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&565& data-rawheight=&414& class=&origin_image zh-lightbox-thumb& width=&565& data-original=&https://pic3.zhimg.com/v2-3bf6a08dc1dc_r.jpg&&&/figure&&p&这里的 &b&业务 - 集群 - 模块 - 主机&/b& 属于物理概念,是机器所在的物理层次关系,因为机器必然伴随着机房、网络、光纤之类的硬件概念,虽然说是物理层次,但是你用云服务的话,就不存在主机这个实体。&/p&&p&而 &b&服务&/b& 是机器的一个业务属性,一个机器可以对应多个服务,作为服务的下一级别是进程,比如一个 web 服务会有 nginx、tomcat 等若干个进程,定义一个服务则需要与之关联的进程,进程的主要属性会有进程名称、起停命令、占用端口等。&/p&&h2&作业平台&/h2&&p&定义
&/p&&p&作业是一系列运维操作的抽象定义,任何一个运维操作都可以分解成一步一步的操作步骤和操作对象,不论是发布变更还是告警处理,都是可以分步骤的。&/p&&p&&b&命令:&/b& 一个可以独立的操作,最简单的如关服、开服、执行 xx 脚本等;&/p&&p&&b&文件分发:&/b& 把指定的文件分发到目标机器的目标路径;&/p&&p&&b&作业:&/b& 一系列命令、文件分发的有序组合,作业的步骤可以由 “命令”、“文件分发” 以及 “执行对象” 组成;&/p&&p&举一个相对复杂的操作过程,如更新代码并重启服务:&/p&&p&1 . 对 web:关闭 tomcat (/home/tomcat/bin/shutdown.sh)&/p&&p&2 . 对 server:关闭业务主进程 (/home/server/bin/stop.sh)&/p&&p&3 . 对 web:分发新的站点文件 (scp xxx yyy)&/p&&p&4 . 对 server:分发服务端文件 (scp xxx yyy)&/p&&p&5 . 对 web:启动 tomcat (/home/tomcat/bin/startup.sh)&/p&&p&6 . 对 server:启动业务主进程 (/home/server/bin/start.sh)&/p&&p&可以看出,流程包含了一系列 “对象”-“操作”
的有序的命令以及文件分发的集合。“对象”可以是一个组、一个或者多个 IP,在执行命令时候可以在系统的页面动态指定目标对象。&/p&&p&作业定义时有各种增删改查操作,每个执行过的作业需要记录执行人、执行时间、结束时间、返回值等信息。&/p&&p&执行顺序
&/p&&p&作业需要按顺序执行,当一个步骤成功后才能执行下一个步骤,如果执行失败需要停止运行作业,并保留执行的各种日志。&/p&&p&比如一个作业定义如下:&/p&&ol&&li&对 web 组(3 台机器):执行 stop tomcat;&/li&&li&对 server 组(4 台机器):执行 stop server;&/li&&li&对 app 组(2 台机器):执行 stop app;&/li&&/ol&&p&执行细节是第一步对 web 组的 3 台机器同时发起 stop tomcat 命令,等待 3 台机器全部返回结果后,如果结果返回 0 表示命令执行成功,这时候才继续进行第二步对 server 组的流程。如果第一步返回结果不为 0,则提示流程执行失败,提示需要人工检查,终止后面的流程。&/p&&p&主要对象
&/p&&p&下面可以大致画个图勾勒出作业平台的主要对象&/p&&figure&&img src=&https://pic1.zhimg.com/v2-baeedd42d93e814c15eb064_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&819& data-rawheight=&430& class=&origin_image zh-lightbox-thumb& width=&819& data-original=&https://pic1.zhimg.com/v2-baeedd42d93e814c15eb064_r.jpg&&&/figure&&p&作业这个概念的提出,即可以将运维工作的各种“变更”、“发布”、“故障处理”等零碎操作分解成一个个可复用、可扩展、可执行的独立操作命令,那么最终平台化的自动调度将成为可能。&/p&&p&开发的时候其界面和操作方式可以参考蓝鲸的作业平台(&a href=&http://link.zhihu.com/?target=http%3A//bk.tencent.com/document/bkprod/000119.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&bk.tencent.com/document&/span&&span class=&invisible&&/bkprod/000119.html&/span&&span class=&ellipsis&&&/span&&/a& ),我所接触过的几个自动化平台(包括商业的和网易内部的)都是应用了类似的设计方式 ,这算是一个经过众多运维团队考验的最佳实践,如果没有什么特殊业务需求,基本可以按这种模式启动以提高开发效率。&/p&&p&然而,每家公司的具体业务形态决定了必然会有差异化的需求,随意列举几个吧。&/p&&ul&&li&作业权限系统,不同角色用户可操作不同级别的作业;&/li&&li&作业运行前确认,比如某测试同事启动作业,需要对应主程或者主策划确认才启动;&/li&&li&等待确认超时时间,比如等待 30 分钟,未确认则取消启动;&/li&&li&作业异常返回则报警邮件通知到运维组以及对应项目组同事;&/li&&li&灰度执行,按作业的设置,先在测试服运行,再到正式服;&/li&&li&作业配置克隆,快速搭建新的项目的作业配置;&/li&&/ul&&p&差异化需求的开发可以在后期慢慢迭代改进。&/p&&p&&br&&/p&&h2&作业执行情况分析
&/h2&&p&节约人力预估&/p&&p&因为作业平台是一个让运维定制各种线上操作,封装任意能通过脚本完成的功能,可以供自己或者项目组自助使用,尽可能做到运维无人值守,运维提供解决方案,那么其最大作用就是为运维部门节约人力,杜绝重复劳动。&/p&&p&作业执行作为自动化平台的核心功能,必须挖掘其利用效率,比如根据执行日志统计每天、每周、每月执行次数,执行总耗时等数据,以估算出平台为运维人员节省多少人力。&/p&&p&&b&使用平台前:&/b&&/p&&p&&b&项目同事放下手头工作 -&通过邮件或者 IM 通知运维同事执行某项操作 -&运维同事放下手头工作,读邮件或 IM,理解项目同事的操作内容 -&执行操作 -&通过邮件或者 IM 反馈项目同事 -&运维同事返回原来工作 -&项目同事放下工作读邮件或 IM 再返回原工作&/b&&/p&&p&&b&使用平台后:&/b&&/p&&p&&b&项目同事操作平台直接执行某项操作得到反馈&/b&&/p&&p&这个过程对于项目同事和运维同事双方总共至少能节约人力 15 分钟,减少了很多沟通、理解、反馈的时间成本。&/p&&p&对于比较常规的普通操作则无需运维同事干预,除非执行异常才需要运维人员介入。&/p&&p&我们通过统计得知平台每月执行作业的总次数为 N,每次预计节约人力资源 15 分钟(0.25 小时),则每月总节约人力为 0.25*N 小时,假设 N 为 1000,则每月节约运维部门 250 个小时的人力资源。&/p&&p&一个运维人员一天也就工作 8 小时(不加班的话~),一个月为 21*8=168 小时,那么节约 250 小时则约等于 1.5 个运维人员的月工时。&/p&&p&由此可见当作业平台的执行次数越大越能形成规模化,对人力资源的节省效果越有利,假设当 N = 10000 的时候,相当于节约了近 15 个运维人员的月工时,效果还是相当可观的。&/p&&p&平台的执行数据可以利用 echarts 做报表,让运维同事实时查看历史执行次数和预计节约人力。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-49c16dcb34b7d0c51f43d0dc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&976& data-rawheight=&728& class=&origin_image zh-lightbox-thumb& width=&976& data-original=&https://pic2.zhimg.com/v2-49c16dcb34b7d0c51f43d0dc_r.jpg&&&/figure&&p&&b&图表解析:&/b&X 轴是时间,以每个月作为一个时间区间,统计该月一共执行了多少个作业。Y 轴的是作业的执行总次数(蓝色轴,单位次),然后假设每个作业约节约人力 15 分钟,最终计算出每月节约人力总时间(红色轴,单位小时)。&/p&&p&作业异常分析&/p&&p&作业平台可以让运维人员解放了很多劳动力,但是我们也不可能保证每个作业都能正常运行,若在执行异常的情况下,我们可以为异常的原因打上标签,打标签可以根据错误输出关键字匹配自动分类或者人工归类,然后统计各种异常情况的比例,再重点分析并处理异常比例高的情况。&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-1ca37ae82f4703c66dea7a717d23b85c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&748& data-rawheight=&636& class=&origin_image zh-lightbox-thumb& width=&748& data-original=&https://pic1.zhimg.com/v2-1ca37ae82f4703c66dea7a717d23b85c_r.jpg&&&/figure&&p&&b&图表解析:&/b& 由上图可以看出这是各种异常的数量分布情况,异常的分类是需要运维预先定义并且有足够的区分度。然后根据作业在一个时间区间内统计出各种异常的比例,再利用饼状图可以方便找到比例最高的若干项,如上图是【运维脚本 bug】和【业务代码异常】比例最高,再着重分析解决这类异常的原因来降低运维操作故障率。&/p&&h2&总结
&/h2&&p&运维自动化平台的建设本质是运维团队服务化能力的变现过程,它让我们从大量重复无规律的人肉操作中解放出来,专注于运维服务质量的提升。由于文章篇幅所限,未能和大家全面介绍整个自动化平台的设计思路,按系统的核心程度来划分,最核心的是 CMDB 和作业平台,当完成这两部分之后,次核心的 CI/CD、数据平台、监控平台也可以投入开发,后面的运营辅助、故障自愈、智能扩容缩容甚至 AiOps 等也需要 DevOps 团队继续探索。&/p&
原文链接:关于作者 温峥峰,百田信息运维技术专家,DevOps Team Leader,超过8年互联网运维经验,曾就职于网易游戏,经受过各类海量规模互联网业务模式的历练,专注于运维自动化、DevOps实践、运维服务体系建设与SRE…
&figure&&img src=&https://pic2.zhimg.com/v2-717f8f54c773f4ed48d01edc_b.jpg& data-rawwidth=&1000& data-rawheight=&569& class=&origin_image zh-lightbox-thumb& width=&1000& data-original=&https://pic2.zhimg.com/v2-717f8f54c773f4ed48d01edc_r.jpg&&&/figure&&p&这是我们的 LAMP 系列教程的开始:如何在 Ubuntu 上安装 Apache web 服务器。&/p&&p&这些说明适用于任何基于 Ubuntu 的发行版,包括 Ubuntu 14.04、 Ubuntu 16.04、 &a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/ubuntu-18-04-new-features-release-date/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Ubuntu 18.04&/a&,甚至非 LTS 的 Ubuntu 发行版,例如 Ubuntu 17.10。这些说明经过测试并为 Ubuntu 16.04 编写。&/p&&p&Apache (又名 httpd) 是最受欢迎和使用最广泛的 web 服务器,所以这应该对每个人都有用。&/p&&h2&&b&开始安装 Apache 之前&/b&&/h2&&p&在我们开始之前,这里有一些要求和说明:&/p&&ul&&li&Apache 可能已经在你的服务器上安装了,所以开始之前首先检查一下。你可以使用 &code&apachectl -V&/code& 命令来显示你正在使用的 Apache 的版本和一些其他信息。&/li&&li&你需要一个 Ubuntu 服务器。你可以从 &a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/go/vultr/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Vultr&/a& 购买一个,它们是&a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/cheap-cloud-hosting-providers-comparison/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&最便宜的云托管服务商&/a&之一。它们的服务器价格每月 2.5 美元起。(LCTT 译注:广告 ≤_≤ )&/li&&li&你需要有 root 用户或具有 sudo 访问权限的用户。下面的所有命令都由 root 用户执行,所以我们不必为每个命令都添加 &code&sudo&/code&。&/li&&li&如果你使用 Ubuntu,则需要&a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/how-to-enable-ssh-on-ubuntu/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&启用 SSH&/a&,如果你使用 Windows,则应该使用类似 &a href=&https://link.zhihu.com/?target=https%3A//mobaxterm.mobatek.net/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MobaXterm&/a&的 SSH 客户端。&/li&&/ul&&p&这就是全部要求和注释了,让我们进入安装过程。&/p&&h2&&b&在 Ubuntu 上安装 Apache&/b&&/h2&&p&你需要做的第一件事就是更新 Ubuntu,这是在你做任何事情之前都应该做的。你可以运行:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get update && apt-get upgrade
&/code&&/pre&&/div&&p&接下来,安装 Apache,运行以下命令:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get install apache2
&/code&&/pre&&/div&&p&如果你愿意,你也可以安装 Apache 文档和一些 Apache 实用程序。对于我们稍后将要安装的一些模块,你将需要一些 Apache 实用程序。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get install apache2-doc apache2-utils
&/code&&/pre&&/div&&p&*&i&就是这样。你已经成功安装了 Apache *&/i&&/p&&p&你仍然需要配置它。&/p&&h2&&b&在 Ubuntu 上配置和优化 Apache&/b&&/h2&&p&你可以在 Apache 上做各种各样的配置,但是主要的和最常见的配置将在下面做出解释。&/p&&h2&&code&检查 Apache 是否正在运行&/code&&/h2&&p&默认情况下,Apache 设置为在机器启动时自动启动,因此你不必手动启用它。你可以使用以下命令检查它是否正在运行以及其他相关信息:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&systemctl status apache2
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-aa2bc04df7cd1d62d716_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&642& data-rawheight=&208& class=&origin_image zh-lightbox-thumb& width=&642& data-original=&https://pic4.zhimg.com/v2-aa2bc04df7cd1d62d716_r.jpg&&&/figure&&p&&br&&/p&&p&&i&check if apache is running&/i&&/p&&p&并且你可以检查你正在使用的版本:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apachectl -V
&/code&&/pre&&/div&&p&一种更简单的检查方法时访问服务器的 IP 地址,如果你得到默认的 Apache 页面,那么一切都正常。&/p&&h2&&code&更新你的防火墙&/code&&/h2&&p&如果你使用防火墙(你应该使用它),则可能需要更新防火墙规则并允许访问默认端口。Ubuntu 上最常用的防火墙是 UFW,因此以下说明使用于 UFW。&/p&&p&要允许通过 80(http)和 443(https)端口的流量,运行以下命令:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ufw allow 'Apache Full'
&/code&&/pre&&/div&&h2&&code&安装常见的 Apache 模块&/code&&/h2&&p&一些模块经常被建议使用,所以你应该安装它们。我们将包含最常见模块的说明:&/p&&p&&b&使用 PageSpeed 加速你的网站&/b&&/p&&p&PageSpeed 模块将自动优化并加速你的 Apache 服务器。&/p&&p&首先,进入 &a href=&https://link.zhihu.com/?target=https%3A//www.modpagespeed.com/doc/download& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&PageSpeed 下载页&/a&并选择你需要的的文件。我们使用的是 64 位 Ubuntu 服务器,所以我们安装最新的稳定版本。使用 &code&wget&/code& 下载它:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_amd64.deb
&/code&&/pre&&/div&&p&然后,使用以下命令安装它:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dpkg -i mod-pagespeed-stable_current_amd64.deb
apt-get -f install
&/code&&/pre&&/div&&p&重启 Apache 以使更改生效:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&systemctl restart apache2
&/code&&/pre&&/div&&p&&b&使用 mod_rewrite 模块启动重写/重定向&/b&&/p&&p&顾名思义,该模块用于重写(重定向)。如果你使用 WordPress 或任何其他 CMS 来处理此问题,你就需要它。要安装它,只需运行:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&a2enmod rewrite
&/code&&/pre&&/div&&p&然后再次重新启动 Apache。你可能需要一些额外的配置,具体取决于你使用的 CMS,如果有的话。为你的设置 Google 一下得到它的具体说明。&/p&&p&&b&使用 ModSecurity 模块保护你的 Apache&/b&&/p&&p&顾名思义,ModSecurity 是一个用于安全性的模块,它基本上起着防火墙的作用,它可以监控你的流量。要安装它,运行以下命令:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get install libapache2-modsecurity
&/code&&/pre&&/div&&p&再次重启 Apache:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&systemctl restart apache2
&/code&&/pre&&/div&&p&ModSecurity 自带了一个默认的设置,但如果你想扩展它,你可以使用 &a href=&https://link.zhihu.com/?target=https%3A//www.owasp.org/index.php/Category%3AOWASP_ModSecurity_Core_Rule_Set_Project& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&OWASP 规则集&/a&。&/p&&p&&b&使用 mod_evasive 模块抵御 DDoS 攻击&/b&&/p&&p&尽管 mod_evasive 在防止攻击方面有多大用处值得商榷,但是你可以使用它来阻止和防止服务器上的 DDoS 攻击。要安装它,使用以下命令:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get install libapache2-mod-evasive
&/code&&/pre&&/div&&p&默认情况下,mod_evasive 是禁用的,要启用它,编辑以下文件:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&nano /etc/apache2/mods-enabled/evasive.conf
&/code&&/pre&&/div&&p&取消注释所有行(即删除 &code&#&/code&),根据你的要求进行配置。如果你不知道要编辑什么,你可以保持原样。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-0f9fbfacc6bbcfba80cacb3f11f95c1b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1153& data-rawheight=&194& class=&origin_image zh-lightbox-thumb& width=&1153& data-original=&https://pic4.zhimg.com/v2-0f9fbfacc6bbcfba80cacb3f11f95c1b_r.jpg&&&/figure&&p&&br&&/p&&p&&i&mod_evasive&/i&&/p&&p&创建一个日志文件:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&mkdir /var/log/mod_evasive
chown -R www-data:www-data /var/log/mod_evasive
&/code&&/pre&&/div&&p&就是这样。现在重启 Apache 以使更改生效。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&systemctl restart apache2
&/code&&/pre&&/div&&p&你可以安装和配置&a href=&https://link.zhihu.com/?target=https%3A//httpd.apache.org/docs/2.4/mod/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&附加模块&/a&,但完全取决于你和你使用的软件。它们通常不是必需的。甚至我们上面包含的 4 个模块也不是必需的。如果特定应用需要模块,那么它们可能会注意到这一点。&/p&&h2&&code&用 Apache2Buddy 脚本优化 Apache&/code&&/h2&&p&Apache2Buddy 是一个可以自动调整 Apache 配置的脚本。你唯一需要做的就是运行下面的命令,脚本会自动完成剩下的工作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl
&/code&&/pre&&/div&&p&如果你没有安装 &code&curl&/code&,那么你可能需要安装它。使用以下命令来安装 &code&curl&/code&:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&apt-get install curl
&/code&&/pre&&/div&&h2&&code&额外配置&/code&&/h2&&p&用 Apache 还可以做一些额外的东西,但我们会留下它们作为另一个教程。像启用 http/2 支持,关闭(或打开) KeepAlive,调整你的 Apache 甚至更多。这些东西你现在不需要做,但是如果你在网上找到了教程,并且如果你等不及我们的教程,那就去做吧。&/p&&h2&&b&使用 Apache 创建你的第一个网站&/b&&/h2&&p&现在我们已经完成了所有的调优工作,让我们开始创建一个实际的网站。按照我们的指示创建一个简单的 HTML 页面和一个在 Apache 上运行的虚拟主机。&/p&&p&你需要做的第一件事是为你的网站创建一个新的目录。运行以下命令来执行此操作:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&mkdir -p /var/www/example.com/public_html
&/code&&/pre&&/div&&p&当然,将 &code&example.com&/code& 替换为你所需的域名。你可以从 &a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/neamcheap-review-cheap-domains-cool-names& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Namecheap&/a& 获得一个便宜的域名。&/p&&p&不要忘记在下面的所有命令中替换 &code&example.com&/code&。&/p&&p&接下来,创建一个简单的静态网页。创建 HTML 文件:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&nano /var/www/example.com/public_html/index.html
&/code&&/pre&&/div&&p&粘贴这些:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&html&
&title&Simple Page&/title&
&p&If you're seeing this in your browser then everything works.&/p&
&/code&&/pre&&/div&&p&保存并关闭文件。&/p&&p&配置目录的权限:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&chown -R www-data:www-data /var/www/example.com
chmod -R og-r /var/www/example.com
&/code&&/pre&&/div&&p&为你的网站创建一个新的虚拟主机:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&nano /etc/apache2/sites-available/example.com.conf
&/code&&/pre&&/div&&p&粘贴以下内容:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&VirtualHost *:80&
ServerAdmin
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
&/VirtualHost&
&/code&&/pre&&/div&&p&这是一个基础的虚拟主机。根据你的设置,你可能需要更高级的 &code&.conf&/code& 文件。&/p&&p&在更新所有内容后保存并关闭文件。&/p&&p&现在,使用以下命令启用虚拟主机:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&a2ensite example.com.conf
&/code&&/pre&&/div&&p&最后,重启 Apache 以使更改生效:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&systemctl restart apache2
&/code&&/pre&&/div&&p&这就是全部了,你做完了。现在你可以访问 http://example.com 并查看你的页面。&/p&&hr&&p&via: &a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/how-to-install-optimize-apache-ubuntu/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&thishosting.rocks/how-t&/span&&span class=&invisible&&o-install-optimize-apache-ubuntu/&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&作者:&a href=&https://link.zhihu.com/?target=https%3A//thishosting.rocks/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ThisHosting&/a& 译者:&a href=&https://link.zhihu.com/?target=https%3A//github.com/MjSeven& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MjSeven&/a& 校对:&a href=&https://link.zhihu.com/?target=https%3A//github.com/wxy& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&wxy&/a&&/p&&p&本文由 &a href=&https://link.zhihu.com/?target=https%3A//github.com/LCTT/TranslateProject& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&LCTT&/a& 原创编译,&a href=&https://link.zhihu.com/?target=https%3A//linux.cn/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Linux中国&/a& 荣誉推出&/p&
这是我们的 LAMP 系列教程的开始:如何在 Ubuntu 上安装 Apache web 服务器。这些说明适用于任何基于 Ubuntu 的发行版,包括 Ubuntu 14.04、 Ubuntu 16.04、 ,甚至非 LTS 的 Ubuntu 发行版,例如 Ubuntu 17.10。这些说明经过测试并为 Ubuntu 1…
&figure&&img src=&https://pic4.zhimg.com/v2-d4bdb5aaf5deacdc165c_b.jpg& data-rawwidth=&1366& data-rawheight=&768& class=&origin_image zh-lightbox-thumb& width=&1366& data-original=&https://pic4.zhimg.com/v2-d4bdb5aaf5deacdc165c_r.jpg&&&/figure&&p&一个阳光明媚的早晨,老婆又在翻看我订阅的技术杂志。&/p&&p&“老公,什么是RPC呀,为什么你们程序员那么多黑话!”,老婆还是一如既往的好奇。&br&“RPC,就是&b&Remote Procedure Call&/b&的简称呀,翻译成中文就是&b&远程过程调用&/b&嘛”,我一边看着书,一边漫不经心的回答着。&br&“啥?你在说啥?谁不知道翻译成中文是什么意思?你个废柴,快给我滚去洗碗!”&br&“我去。。。”,我如梦初醒,我对面坐着的可不是一个程序员,为了不去洗碗,我瞬间调动起全部脑细胞,星辰大海在我脑中汇聚,灵感涌现……&/p&&p&“是这样,远程过程调用,自然是相对于本地过程调用来说的嘛。” &br&“嗯哼,那先给老娘讲讲,本地过程调用是啥子?”&br&“本地过程调用,就好比你现在在家里,你要想洗碗,那你直接把碗放进洗碗机,打开洗碗机开关就可以洗了。这就叫本地过程调用。”&/p&&p&“哎呦,我可不干,那啥是远程过程调用?”&br&“远程嘛,那就是你现在不在家,跟姐妹们浪去了,突然发现碗还没洗,打了个电话过来,叫我去洗碗,这就是远程过程调用啦”,多么通俗易懂的解释,我真是天才!&/p&&p&“哦!我明白了”,说着,老婆开始收拾包包。&br&“你这是干啥去哦”&br&“我?我要出门浪去呀,待会记得接收我的远程调用哦,哦不,咱们要专业点,应该说,待会记得接收我的RPC哦!”&br&……&/p&&blockquote&非程序员请就此止步,程序员请继续往前走……&/blockquote&&h2&如何科学的解释RPC&/h2&&p&说起RPC,就不能不提到&b&分布式&/b&,这个促使RPC诞生的领域。&/p&&p&假设你有一个计算器接口,Calculator,以及它的实现类CalculatorImpl,那么在系统还是&b&单体应用&/b&时,你要调用Calculator的add方法来执行一个加运算,直接new一个CalculatorImpl,然后调用add方法就行了,这其实就是非常普通的&b&本地函数调用&/b&,因为在&b&同一个地址空间&/b&,或者说在同一块内存,所以通过方法栈和参数栈就可以实现。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-f173a307dabb218a7f60c0be2629affc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&540& data-rawheight=&540& class=&origin_image zh-lightbox-thumb& width=&540& data-original=&https://pic3.zhimg.com/v2-f173a307dabb218a7f60c0be2629affc_r.jpg&&&/figure&&p&&br&&/p&&p&现在,基于高性能和高可靠等因素的考虑,你决定将系统改造为分布式应用,将很多可以共享的功能都单独拎出来,比如上面说到的计算器,你单独把它放到一个服务里头,让别的服务去调用它。&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-c6a24fe26f6baa71532dacd02a5364b7_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&901& data-rawheight=&473& class=&origin_image zh-lightbox-thumb& width=&901& data-original=&https://pic1.zhimg.com/v2-c6a24fe26f6baa71532dacd02a5364b7_r.jpg&&&/figure&&p&这下问题来了,服务A里头并没有CalculatorImpl这个类,那它要怎样调用服务B的CalculatorImpl的add方法呢?&/p&&p&有同学会说,可以模仿B/S架构的调用方式呀,在B服务暴露一个Restful接口,然后A服务通过调用这个Restful接口来间接调用CalculatorImpl的add方法。&/p&&p&很好,这已经很接近RPC了,不过如果是这样,那每次调用时,是不是都需要写一串发起http请求的代码呢?比如httpClient.sendRequest…之类的,能不能像本地调用一样,去发起远程调用,让使用者感知不到远程调用的过程呢,像这样:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&nd&&@Reference&/span&
&span class=&kd&&private&/span& &span class=&n&&Calculator&/span& &span class=&n&&calculator&/span&&span class=&o&&;&/span&
&span class=&o&&...&/span&
&span class=&n&&calculator&/span&&span class=&o&&.&/span&&span class=&na&&add&/span&&span class=&o&&(&/span&&span class=&mi&&1&/span&&span class=&o&&,&/span&&span class=&mi&&2&/span&&span class=&o&&);&/span&
&span class=&o&&...&/span&
&/code&&/pre&&/div&&p&这时候,有同学就会说,用&b&代理模式&/b&呀!而且最好是结合Spring IoC一起使用,通过Spring注入calculator对象,注入时,如果扫描到对象加了@Reference注解,那么就给它生成一个代理对象,将这个代理对象放进容器中。而这个代理对象的内部,就是通过httpClient来实现RPC远程过程调用的。&/p&&p&可能上面这段描述比较抽象,不过这就是很多RPC框架要解决的问题和解决的思路,比如阿里的Dubbo。&/p&&p&总结一下,&b&RPC要解决的两个问题:&/b&&/p&&ol&&li&&b&解决分布式系统中,服务之间的调用问题。&/b&&/li&&li&&b&远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。&/b&&/li&&/ol&&h2&如何实现一个RPC&/h2&&p&实际情况下,RPC很少用到http协议来进行数据传输,毕竟我只是想传输一下数据而已,何必动用到一个文本传输的应用层协议呢,我为什么不直接使用&b&二进制传输&/b&?比如直接用Java的Socket协议进行传输?&/p&&p&不管你用何种协议进行数据传输,&b&一个完整的RPC过程,都可以用下面这张图来描述&/b&:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-43aee8a0ece9dc27f26ccea_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&263& data-rawheight=&221& class=&content_image& width=&263&&&/figure&&p&&br&&/p&&p&以左边的Client端为例,Application就是rpc的调用方,Client Stub就是我们上面说到的代理对象,也就是那个看起来像是Calculator的实现类,其实内部是通过rpc方式来进行远程调用的代理对象,至于Client Run-time Library,则是实现远程调用的工具包,比如jdk的Socket,最后通过底层网络实现实现数据的传输。&/p&&p&这个过程中最重要的就是&b&序列化&/b&和&b&反序列化&/b&了,因为数据传输的数据包必须是二进制的,你直接丢一个Java对象过去,人家可不认识,你必须把Java对象序列化为二进制格式,传给Server端,Server端接收到之后,再反序列化为Java对象。&/p&&p&下一次我也将通过代码,给大家演示一下,如何实现一个简单的RPC。&/p&&h2&RPC vs Restful&/h2&&p&其实这两者并不是一个维度的概念,总得来说RPC涉及的维度更广。&/p&&p&如果硬要比较,那么可以从RPC风格的url和Restful风格的url上进行比较。&/p&&p&比如你提供一个查询订单的接口,用RPC风格,你可能会这样写:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&/queryOrder?orderId=123
&/code&&/pre&&/div&&p&用Restful风格呢?&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&Get
/order?orderId=123
&/code&&/pre&&/div&&p&再精炼一点,甚至可以这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&Get
/order/123
&/code&&/pre&&/div&&p&&b&RPC是面向过程,Restful是面向资源&/b&,并且使用了Http动词。从这个维度上看,Restful风格的url在表述的精简性、可读性上都要更好。&/p&&h2&RPC vs RMI&/h2&&p&严格来说这两者也不是一个维度的。&/p&&p&RMI是Java提供的一种访问远程对象的协议,是已经实现好了的,可以直接用了。&/p&&p&而RPC呢?人家只是一种编程模型,并没有规定你具体要怎样实现,&b&你甚至都可以在你的RPC框架里面使用RMI来实现数据的传输&/b&,比如Dubbo:&a href=&https://link.zhihu.com/?target=http%3A//dubbo.apache.org/books/dubbo-user-book/references/protocol/rmi.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dubbo - rmi协议&/a&&/p&&h2&RPC没那么简单&/h2&&p&&b&要实现一个RPC不算难,难的是实现一个高性能高可靠的RPC框架。&/b&&/p&&p&比如,既然是分布式了,那么一个服务可能有多个实例,你在调用时,要如何获取这些实例的地址呢?&/p&&p&这时候就需要一个服务注册中心,比如在Dubbo里头,就可以使用Zookeeper作为注册中心,在调用时,从Zookeeper获取服务的实例列表,再从中选择一个进行调用。&/p&&p&那么选哪个调用好呢?这时候就需要负载均衡了,于是你又得考虑如何实现复杂均衡,比如Dubbo就提供了好几种负载均衡策略。&/p&&p&这还没完,总不能每次调用时都去注册中心查询实例列表吧,这样效率多低呀,于是又有了缓存,有了缓存,就要考虑缓存的更新问题,blablabla……&/p&&p&你以为就这样结束了,没呢,还有这些:&/p&&ul&&li&客户端总不能每次调用完都干等着服务端返回数据吧,于是就要支持异步调用;&/li&&li&服务端的接口修改了,老的接口还有人在用,怎么办?总不能让他们都改了吧?这就需要版本控制了;&/li&&li&服务端总不能每次接到请求都马上启动一个线程去处理吧?于是就需要线程池;&/li&&li&服务端关闭时,还没处理完的请求怎么办?是直接结束呢,还是等全部请求处理完再关闭呢?&/li&&li&……&/li&&/ul&&p&如此种种,都是一个优秀的RPC框架需要考虑的问题。&/p&&p&当然,接下来我们还是先实现一个简单的RPC,再在上面一步步优化!&/p&&a href=&https://zhuanlan.zhihu.com/p/& data-draft-node=&block& data-draft-type=&link-card& data-image=&https://pic3.zhimg.com/v2-d357cc02_180x120.jpg& data-image-width=&1024& data-image-height=&578& class=&internal&&Javdroider Hong:如何实现一个简单的RPC&/a&&h2&参考&/h2&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Remote_procedure_call& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&wikipedia - RPC&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//sites.google.com/site/wagingguerillasoftware/rest-series/what-is-restful-rest-vs-rpc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&what-is-restful-rest-vs-rpc&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//techdifferences.com/difference-between-rpc-and-rmi.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&difference-between-rpc-and-rmi.html&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//stackoverflow.com/questions/2728495/what-is-the-difference-between-java-rmi-and-rpc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&what-is-the-difference-between-java-rmi-and-rpc&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=http%3A//dubbo.apache.org/books/dubbo-user-book/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dubbo 使用文档&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=http%3A//dubbo.apache.org/books/dubbo-dev-book/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Dubbo 源码开发手册&/a&&/li&&li&一本很棒的分布式书籍:《大型网站系统与Java中间件实践》&/li&&/ul&&p&&br&&/p&&p&对了,微信公众号已经开通:&b&Bridge4You&/b&,欢迎关注!&/p&&p&有些话只能在那里跟你说 (〃'▽'〃)&/p&
一个阳光明媚的早晨,老婆又在翻看我订阅的技术杂志。“老公,什么是RPC呀,为什么你们程序员那么多黑话!”,老婆还是一如既往的好奇。 “RPC,就是Remote Procedure Call的简称呀,翻译成中文就是远程过程调用嘛”,我一边看着书,一边漫不经心的回答着。…
&figure&&img src=&https://pic4.zhimg.com/v2-693ec47f60dff583c0f08a9f5c43c6d7_b.jpg& data-rawwidth=&960& data-rawheight=&600& class=&origin_image zh-lightbox-thumb& width=&960& data-original=&https://pic4.zhimg.com/v2-693ec47f60dff583c0f08a9f5c43c6d7_r.jpg&&&/figure&&p&这些年来,我已经写了许多关于 DevOps 工具的文章,也培训了这方面的人员。尽管这些工具很棒,但很明显,大多数都是按照开发人员的思路设计出来的。这也没有什么问题,因为以编程的方式接近配置管理是重点。不过,直到我开始接触 Ansible,我才觉得这才是系统管理员喜欢的东西。&/p&&p&喜欢的一部分原因是 Ansible 与客户端计算机通信的方式,是通过 SSH 的。作为系统管理员,你们都非常熟悉通过 SSH 连接到计算机,所以从单词“去”的角度来看,相对于其它选择,你更容易理解 Ansible。&/p&&p&考虑到这一点,我打算写一些文章,探讨如何使用 Ansible。这是一个很好的系统,但是当我第一次接触到这个系统的时候,不知道如何开始。这并不是学习曲线陡峭。事实上,问题是在开始使用 Ansible 之前,我并没有太多的东西要学,这才是让人感到困惑的。例如,如果您不必安装客户端程序(Ansible 没有在客户端计算机上安装任何软件),那么您将如何启动?&/p&&h2&&b&踏出第一步&/b&&/h2&&p&起初 Ansible 对我来说非常困难的原因在于配置服务器/客户端的关系是非常灵活的,我不知道我该从何入手。事实是,Ansible 并不关心你如何设置 SSH 系统。它会利用你现有的任何配置。需要考虑以下几件事情:&/p&&ol&&li&Ansible 需要通过 SSH 连接到客户端计算机。&/li&&li&连接后,Ansible 需要提升权限才能配置系统,安装软件包等等。&/li&&/ol&&p&不幸的是,这两个考虑真的带来了一堆蠕虫。连接到远程计算机并提升权限是一件可怕的事情。当您在远程计算机上安装代理并使用 Chef 或 Puppet 处理特权升级问题时,似乎感觉就没那么可怕了。 Ansible 并非不安全,而是安全的决定权在你手中。&/p&&p&接下来,我将列出一系列潜在的配置,以及每个配置的优缺点。这不是一个详尽的清单,但是你会受到正确的启发,去思考在你自己的环境中什么是理想的配置。也需要注意,我不会提到像 Vagrant 这样的系统,因为尽管 Vagrant 在构建测试和开发的敏捷架构时非常棒,但是和一堆服务器是非常不同的,因此考虑因素是极不相似的。&/p&&h2&&b&一些 SSH 场景&/b&&/h2&&h2&&code&1)在 Ansible 配置中,root 用户以密码进入远程计算机。&/code&&/h2&&p&拥有这个想法是一个非常可怕的开始。这个设置的“优点”是它消除了对特权提升的需要,并且远程服务器上不需要其他用户帐户。 但是,这种便利的成本是不值得的。 首先,大多数系统不会让你在不改变默认配置的情况下以 root 身份进行 SSH 登录。默认的配置之所以如此,坦率地说,是因为允许 root 用户远程连接是一个不好的主意。 其次,将 root 密码放在 Ansible 机器上的纯文本配置文件中是不合适的。 真的,我提到了这种可能性,因为这是可以的,但这是应该避免的。 请记住,Ansible 允许你自己配置连接,它可以让你做真正愚蠢的事情。 但是请不要这么做。&/p&&h2&&code&2)使用存储在 Ansible 配置中的密码,以普通用户的身份进入远程计算机。&/code&&/h2&&p&这种情况的一个优点是它不需要太多的客户端配置。 大多数用户默认情况下都可以使用 SSH,因此 Ansible 应该能够使用用户凭据并且能够正常登录。 我个人不喜欢在配置文件中以纯文本形式存储密码,但至少它不是 root 密码。 如果您使用此方法,请务必考虑远程服务器上的权限提升方式。 我知道我还没有谈到权限提升,但是如果你在配置文件中配置了一个密码,这个密码可能会被用来获得 sudo 访问权限。 因此,一旦发生泄露,您不仅已经泄露了远程用户的帐户,还可能泄露整个系统。&/p&&h2&&code&3)使用具有空密码的密钥对进行身份验证,以普通用户身份进入远程计算机。&/code&&/h2&&p&这消除了将密码存储在配置文件中的弊端,至少在登录的过程中消除了。 没有密码的密钥对并不理想,但这是我经常做的事情。 在我的个人内部网络中,我通常使用没有密码的密钥对来自动执行许多事情,如需要身份验证的定时任务。 这不是最安全的选择,因为私钥泄露意味着可以无限制地访问远程用户的帐户,但是相对于在配置文件中存储密码我更喜欢这种方式。&/p&&h2&&code&4)使用通过密码保护的密钥对进行身份验证,以普通用户的身份通过 SSH 连接到远程计算机。&/code&&/h2&&p&这是处理远程访问的一种非常安全的方式,因为它需要两种不同的身份验证因素来解密:私钥和密码。 如果你只是以交互方式运行 Ansible,这可能是理想的设置。 当你运行命令时,Ansible 会提示你输入私钥的密码,然后使用密钥对登录到远程系统。 是的,只需使用标准密码登录并且不用在配置文件中指定密码即可完成,但是如果不管怎样都要在命令行上输入密码,那为什么不在保护层添加密钥对呢?&/p&&h2&&code&5)使用密码保护密钥对进行 SSH 连接,但是使用 ssh-agent “解锁”私钥。&/code&&/h2&&p&这并不能完美地解决无人值守、自动化的 Ansible 命令的问题,但是它确实也使安全设置变得相当方便。 ssh-agent 程序一次验证密码,然后使用该验证进行后续连接。当我使用 Ansible 时,这是我想要做的事情。如果我是完全值得信任的,我通常仍然使用没有密码的密钥对,但是这通常是因为我在我的家庭服务器上工作,是不是容易受到攻击的。&/p&&p&在配置 SSH 环境时还要记住一些其他注意事项。 也许你可以限制 Ansible 用户(通常是你的本地用户),以便它只能从一个特定的 IP 地址登录。 也许您的 Ansible 服务器可以位于不同的子网中,位于强大的防火墙之后,因此其私钥更难以远程访问。 也许 Ansible 服务器本身没有安装 SSH 服务器,所以根本没法访问。 同样,Ansible 的优势之一是它使用 SSH 协议进行通信,而且这是一个你用了多年的协议,你已经把你的系统调整到最适合你的环境了。 我不是宣传“最佳实践”的忠实粉丝,因为实际上最好的做法是考虑你的环境,并选择最适合你情况的设置。&/p&&h2&&b&权限提升&/b&&/h2&&p&一旦您的 Ansible 服务器通过 SSH 连接到它的客户端,就需要能够提升特权。 如果你选择了上面的选项 1,那么你已经是 root 了,这是一个有争议的问题。 但是由于没有人选择选项 1(对吧?),您需要考虑客户端计算机上的普通用户如何获得访问权限。 Ansible 支持各种权限提升的系统,但在 Linux 中,最常用的选项是 &code&sudo&/code& 和 &code&su&/code&。 和 SSH 一样,有几种情况需要考虑,虽然肯定还有其他选择。&/p&&h2&&code&1)使用 su 提升权限。&/code&&/h2&&p&对于 RedHat/CentOS 用户来说,可能默认是使用 &code&su&/code& 来获得系统访问权限。 默认情况下,这些系统在安装过程中配置了 root 密码,要想获得特殊访问权限,您需要输入该密码。使用 &code&su&/code& 的问题在于,虽说它可以给了您完全访问远程系统,而您确实也可以完全访问远程系统。 (是的,这是讽刺。)另外,&code&su&/code&程序没有使用密钥对进行身份验证的能力,所以密码必须以交互方式输入或存储在配置文件中。 由于它实际上是 root 密码,因此将其存储在配置文件中听起来像、也确实是一个可怕的想法。&/p&&h2&&code&2)使用 sudo 提升权限。&/code&&/h2&&p&这就是 Debian/Ubuntu 系统的配置方式。 正常用户组中的用户可以使用 &code&sudo&/code& 命令并使用 root 权限执行该命令。 随之而来的是,这仍然存在密码存储或交互式输入的问题。 由于在配置文件中存储用户的密码看起来不太可怕,我猜这是使用 &code&su&/code& 的一个进步,但是如果密码被泄露,仍然可以完全访问系统。 (毕竟,输入 &code&sudo&/code& 和 &code&su -&/code& 都将允许用户成为 root 用户,就像拥有 root 密码一样。)&/p&&h2&&code&3) 使用 sudo 提升权限,并在 sudoers 文件中配置 NOPASSWD。&/code&&/h2&&p&再次,在我的本地环境中,我就是这么做的。 这并不完美,因为它给予用户帐户无限制的 root 权限,并且不需要任何密码。 但是,当我这样做并且使用没有密码短语的 SSH 密钥对时,我可以让 Ansible 命令更轻松的自动化。 再次提示,虽然这很方便,但这不是一个非常安全的想法。&/p&&h2&&code&4)使用 sudo 提升权限,并在特定的可执行文件上配置 NOPASSWD。&/code&&/h2&&p&这个想法可能是安全性和便利性的最佳折衷。 基本上,如果你知道你打算用 Ansible 做什么,那么你可以为远程用户使用的那些应用程序提供 NOPASSWD 权限。 这可能会让人有些困惑,因为 Ansible 使用 Python 来处理很多事情,但是经过足够的尝试和错误,你应该能够弄清原理。 这是额外的工作,但确实消除了一些明显的安全漏洞。&/p&&h2&&b&计划实施&/b&&/h2&&p&一旦你决定如何处理 Ansible 认证和权限提升,就需要设置它。 在熟悉 Ansible 之后,您可能会使用该工具来帮助“引导”新客户端,但首先手动配置客户端非常重要,以便您知道发生了什么事情。 将你熟悉的事情变得自动化比从头开始自动化要好。&/p&&p&我已经写过关于 SSH 密钥对的文章,网上有无数的设置类的文章。 来自 Ansible 服务器的简短版本看起来像这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# ssh-keygen
# ssh-copy-id -i .ssh/id_dsa.pub puter.ip
# ssh puter.ip
&/code&&/pre&&/div&&p&如果您在创建密钥对时选择不使用密码,最后一步您应该可以直接进入远程计算机,而不用输入密码或密钥串。&/p&&p&为了在 &code&sudo&/code& 中设置权限提升,您需要编辑 &code&sudoers&/code& 文件。 你不应该直接编辑文件,而是使用:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# sudo visudo
&/code&&/pre&&/div&&p&这将打开 &code&sudoers&/code& 文件并允许您安全地进行更改(保存时会进行错误检查,所以您不会意外地因为输入错误将自己锁住)。 这个文件中有一些例子,所以你应该能够弄清楚如何分配你想要的确切的权限。&/p&&p&一旦配置完成,您应该在使用 Ansible 之前进行手动测试。 尝试 SSH 到远程客户端,然后尝试使用您选择的任何方法提升权限。 一旦你确认配置的方式可以连接,就可以安装 Ansible 了。&/p&&h2&&b&安装 Ansible&/b&&/h2&&p&由于 Ansible 程序仅安装在一台计算机上,因此开始并不是一件繁重的工作。 Red Hat/Ubuntu 系统的软件包安装有点不同,但都不是很困难。&/p&&p&在 Red Hat/CentOS 中,首先启用 EPEL 库:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&sudo yum install epel-release
&/code&&/pre&&/div&&p&然后安装 Ansible:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&sudo yum install ansible
&/code&&/pre&&/div&&p&在 Ubuntu 中,首先启用 Ansible PPA:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&sudo apt-add-repository spa:ansible/ansible
(press ENTER to access the key and add the repo)
&/code&&/pre&&/div&&p&然后安装 Ansible:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&sudo apt-get update
sudo apt-get install ansible
&/code&&/pre&&/div&&h2&&b&Ansible 主机文件配置&/b&&/h2&&p&Ansible 系统无法知道您希望它控制哪个客户端,除非您给它一个计算机列表。 该列表非常简单,看起来像这样:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# file /etc/ansible/hosts
[webservers]
blogserver ansible_host=192.168.1.5
wikiserver ansible_host=192.168.1.10
[dbservers]
mysql_1 ansible_host=192.168.1.22
pgsql_1 ansible_host=192.168.1.23
&/code&&/pre&&/div&&p&方括号内的部分是指定的组。 单个主机可以列在多个组中,而 Ansible 可以指向单个主机或组。 这也是配置文件,比如纯文本密码的东西将被存储,如果这是你计划的那种设置。 配置文件中的每一行配置一个主机地址,并且可以在 &code&ansible_host&/code& 语句之后添加多个声明。 一些有用的选项是:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ansible_ssh_pass
ansible_become
ansible_become_method
ansible_become_user
ansible_become_pass
&/code&&/pre&&/div&&h2&&b&Ansible&/b& &b&&i&保险库(Vault)&/i&&/b&&/h2&&p&(LCTT 译注:Vault 作为 ansible 的一项新功能可将例如密码、密钥等敏感数据文件进行加密,而非明文存放)&/p&&p&我也应该注意到,尽管安装程序比较复杂,而且这不是在您首次进入 Ansible 世界时可能会做的事情,但该程序确实提供了一种加密保险库中的密码的方法。 一旦您熟悉 Ansible,并且希望将其投入生产,将这些密码存储在加密的 Ansible 保险库中是非常理想的。 但是本着先学会爬再学会走的精神,我建议首先在非生产环境下使用无密码方法。&/p&&h2&&b&系统测试&/b&&/h2&&p&最后,你应该测试你的系统,以确保客户端可以正常连接。 &code&ping&/code& 测试将确保 Ansible 计算机可以 &code&ping&/code& 每个主机:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ansible -m ping all
&/code&&/pre&&/div&&p&运行后,如果 &code&ping&/code& 成功,您应该看到每个定义的主机显示 &code&ping&/code& 的消息:&code&pong&/code&。 这实际上并没有测试认证,只是测试网络连接。 试试这个来测试你的认证:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ansible -m shell -a 'uptime' webservers
&/code&&/pre&&/div&&p&您应该可以看到 webservers 组中每个主机的运行时间命令的结果。&/p&&p&在后续文章中,我计划开始深入 Ansible 管理远程计算机的功能。 我将介绍各种模块,以及如何使用 ad-hoc 模式来完成一些按键操作,这些操作在命令行上单独处理都需要很长时间。 如果您没有从上面的示例 Ansible 命令中获得预期的结果,请花些时间确保身份验证可以工作。 如果遇到困难,请查阅 &a href=&https://link.zhihu.com/?target=http%3A//docs.ansible.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Ansible 文档&/a&获取更多帮助。&/p&&hr&&p&via: &a href=&https://link.zhihu.com/?target=http%3A//www.linuxjo

我要回帖

更多关于 timezone是什么意思 的文章

 

随机推荐