CentOS远程重装系统

公司内网的一台Linux弱口令机器让扫出来了,数据洗劫一空,悲剧啊
还好不是什么重要的东西,赶紧重装系统。

人不在公司,只能使用远程重装,方案如下:

Fedora 14需要下载的文件在http://nas1.itc.virginia.edu/fedora/releases/14/Fedora/x86_64/os/images/…
64位Centos需要下载的文件在 http://mirror.centos.org/centos-5/5/os/x86_64/images/pxeboot/

修改服务器的/boot/grub/grub.conf文件,在这个配置文件中,添加如下启动项:

title CentOS Reinstall
root (hd0,0)
kernel /vmlinuz vnc vncpassword=12345678 headless ip=10.36.64.238 netmask=255.255.255.0 gateway=10.36.64.254 dns=10.36.10.8 hostname=0map238 ksdevice=eth0 method=http://mirrors.163.com/centos/6/os/x86_64/ lang=
en_US keymap=us
initrd /initrd.img

在"hiddenmenu" 和 "title CentOS..." 增加一项:
method中的url为安装centos的源

重启后使用vnc软件连接服务器 IP:1 ,并输入刚刚设置的vnc密码即可进行centos的重装。这个过程中机器需要下载一些镜像,大约要等待15分钟,VNC才可以访问。

使用OneApm CI SDK实现业务响应速度监控

目前负责的业务处于急速扩张期,每周会增加几台服务器,业务日访问量在5000万左右。

目前的监控需求在可用性和响应速度。运营的需求要求每次接口响应控制在0.1-0.5s内。

在现在的基础监控中,可以分析出http业务的可用性,但没法监控具体的响应时间。
最开始使用的方法为在后端添加serverId和处理时间并放到http header中,通过curl去获得后端信息和处理时间,采样后生成报表。
听起来就比较复杂。
再后来,改成通过nginx记录upstream的response time,采样生成可视化。
由于nginx日志分布于不同的机器中,收集数据相对来讲还是比较麻烦的。

后来将一部分监控迁到OneAPM上,折腾一段时间以后,无意中发现了CI有一个SDK,学习了一下,发现可以实现一些业务层的监控。
经过一段时间的试验,发现CI SDK使用起来非常方便,能方便的接入丰富的业务数据。

其实现的原理为隔一段时间采样一个数据,上报给CI,CI会根据输入的数值,生成线性报表。
下面是一些使用的经验,分享给大家。

以下是抄了OneApm的官方介绍,供参考。

==============================

OneApm CI是什么
http://docs-ci.oneapm.com/

Cloud Insight SDK For Python
http://docs-ci.oneapm.com/api/python.html

Cloud Insight 集成了数十种互联网流行基础组件的监控,开箱即用,您只需要进行最小化的配置就可以实现复杂的基础组件监控, 免除了传统基础组件监控中的复杂流程。Cloud Insight 采集这些基础组件的权威指标,所有指标都是标准化的格式,您再也不需要 自己定义各种指标,以及思考如何进行各种指标的组合展示,一切就只有两步,安装探针,查看仪表盘,如果您使用的是阿里云、UCloud 等云厂商,甚至不需要安装探针,Cloud Insight 会直接通过这些云厂商提供的 API 收集服务器以及基础组件的性能和健康情况的 指标,并友好的展示在定义好的仪表盘中。

OneApm CI还提供了SDK,可以实现自定义的业务数据监控,比如业务的订单趋势,响应速度曲线等。配合CI的丰富报表功能,非常轻松的实现自定义业务监控。

==============================

按照文档,安装CI, 及CI SDK,这里不再赘述。
step 1, OneAPM CI Agent 安装
step 2, OneApm CI SDK For Python安装
step 3, 编写一段简单的python 代码

#!/usr/bin/env python
# -*- coding:utf8 -*-

import commands
import socket
from oneapm_ci_sdk import statsd

hostname = socket.gethostname()
error, result = commands.getstatusoutput(""" tail /opt/dataroot/nginx/access.log |grep "download" | awk -F '" "' '{print $7}' """)
if ( error == 0 ):
        code = result.split("\n")
        statsd.gauge('php_response_time.download.%s' % hostname, float( max(code) ) )
        print 'php_response_time.%s : %04f' % ( hostname, float(max(code)) )

上述代码实现的逻辑为调用系统命令,获取nginx中,php的responsetime,从几个响应时间中取最大值。

step 4, 部署收集数据

#获取Nginx Upstream response time
* * * * * for i in $(seq 3); do sleep 15; python /opt/ci_check_php_response_time.py; done

添加上述计划任务,每秒统计三次响应最慢的请求。由于默认的系统计划任务无法实现按秒制定任务,通过sleep间接实现。

step 5, 查看报表

进入 https://cloud.oneapm.com/dashboard#/,在最右下角找到自定义仪表盘,
效果如下:

QQ20160318-0

根据官方文档的说明,未来还会开放不需要SDK的API,非常适合做一些私有业务的监控和告警,非常期待。

Cloud Insight API

API 提供了更加强大的功能,您可以不受任何约束的发送符合Cloud Insight数据格式标准的任意数据,无论本机是否安装了Cloud Insight Agent。目前API正在开发之中。

在几个月的使用中,OneApm CI和AI,给我们提供了非常多的帮助,慢慢的使用才发现OneApm的强大,感谢 OneApm 志利在使用过程中给我们的帮助,不管是晚上还是周末,响应速度非常快,非常感动。
下次分享一下在使用AI的过程中,通过AI定位ThinkPHP中Redis连接异常的一个故障处理。

Update:

CI在这个月发布了新版,也提供了新的PHPSDK,可以愉快的从之前的python sdk切过来了。同时,也增加了仪表盘分享功能。

aws ami 执行yum出现"Protected multilib versions: openssl-1.0.1e-42.el6_7.2.x86_64 != openssl-1.0.1e-42.el6.i686"

[txtplain]
--> Finished Dependency Resolution
Error: Multilib version problems found. This often means that the root
cause is something else and multilib version checking is just
pointing out that there is a problem. Eg.:

1. You have an upgrade for openssl which is missing some
dependency that another package requires. Yum is trying to
solve this by installing an older version of openssl of the
different architecture. If you exclude the bad architecture
yum will tell you what the root cause is (which package
requires what). You can try redoing the upgrade with
--exclude openssl.otherarch ... this should give you an error
message showing the root cause of the problem.

2. You have multiple architectures of openssl installed, but
yum can only see an upgrade for one of those arcitectures.
If you don't want/need both architectures anymore then you
can remove the one with the missing update and everything
will work.

3. You have duplicate versions of openssl installed already.
You can use "yum check" to get yum show these errors.

...you can also use --setopt=protected_multilib=false to remove
this checking, however this is almost never the correct thing to
do as something else is very likely to go wrong (often causing
much more problems).

Protected multilib versions: openssl-1.0.1e-42.el6_7.2.x86_64 != openssl-1.0.1e-42.el6.i686
[/txtplain]

原因未知,卸载掉openssl-1.0.1e-42.el6.i686即可

php版本的文件夹合并

#!/bin/env php
<?php
error_reporting(7);

$dir1 = $argv[1];
$dir2 = $argv[2];

if(empty($dir1) || empty($dir2))
{
    echo "php {$argv[0]} dir_merged dir_merge_save\n";
    exit(0);
}

if(! is_dir($dir1))
{
    echo "{$dir1} is not a dir\n";
    exit(0);
}
if(! is_dir($dir2))
{
    echo "{$dir2} is not a dir\n";
    exit(0);
}

merge_dir($dir1, $dir2);

function merge_dir($from, $to)
{
    $from  = rtrim($from, "/")."/";
    $to    = rtrim($to, "/")."/";
    echo "search file from {$from}";
    $files = glob($from."*");
    echo "\t\tdone\n";

    foreach($files as $f)
    {
        $relative_path = substr_replace($f, "", 0, strlen($from));
        $ff = $to . $relative_path;

        //目录不存在则直接复制目录
        if(is_dir($f))
        {
            if(!is_dir($ff))
            {
                $cmd = "cp -r '{$f}' '{$ff}'";
                `$cmd`;
                logs($relative_path);
            } else {
                merge_dir($f, $ff);
            }
        }else{
            if(!is_file($ff))
            {
                copy($f, $ff);
                logs($relative_path);
                continue;
            }

            //对特殊文件进行检查
            $ext = substr($relative_path, strrpos($relative_path, ".")+1);
            if($ext == "apk" && filesize($f) != filesize($ff))
            {
                $compare = apk_version_compare($f, $ff);
                if($compare)
                {
                    copy($f, $ff);
                    logs($relative_path);
                }
            }
        }
    }
}

function apk_version_compare($apk1, $apk2)
{
    return aapt($apk1) > aapt($apk2);
}

function aapt($apk)
{
    $apk = realpath($apk);
    $aapt = "aapt d badging {$apk} | grep versionCode | awk '{print $3}'";
    $aapt = `$aapt`;

    return substr($aapt, 13, -2);
}

function logs($file)
{
    printf("%s\n", $file);
}

基于CloudFlare + Conoha搭建的企业级廉价CDN

中国的流量很贵,流量越大越贵。

目前我负责的业务一半国内,一半海外。目前日均请求过千万,流量过10T,总成本不超过500元/天。跟传统的CDN服务相比,便宜到可以忽略。

CDN介绍
在项目早期,为了业务简单,直接使用传统CDN提供商网宿,在CDN宽带超过 5G 的时候,CDN的成本开始显现出来。
一般国内的CDN(网宿、帝联、蓝汛,还有一些如七牛、又拍这样的二手贩子)均有宽带和流量计费,新起的云平台(阿里、腾讯、uCloud)基本上使用流量计费。

国内的CDN价格,网宿的95峰值计费,一般价格在45-55元/M,根据宽带高值、公司背景、销售人员关系等等因素,合同的价格可以签到30-40元左右,其它二线的CDN可以签到25-30元左右。

其它的云服务平台,价格相对固定,业务购买一般是自助服务,价格基本上没得可谈,普遍价格在0.9元-1.2元/G。

国内服务商运营的国外CDN价格比国内高出几个数量级,网宿的报价为150元/M,其海外节点为少数自建加akamai代理。其它几家传统的CDN服务商完全代理甚至没有海外业务。

海外的CDN服务商,计费一般是按流量计费,常见的如MaxCDN, KeyCDN,价格一般为0.04-0.1美元/G。

业务介绍
我们的业务早期使用网宿,业务从0M跑到3G,业务一直比较稳定。后来业务推到海外,直到CDN的成本越来越高,CDN成本差不多占了利润的一半。

网宿现在有市场优势,价格一直砍不下来。经过跟几家CDN服务咨询、测试,从最初的七牛,MaxCDN,KeyCDN,到最后的CloudFlare+Conoha,终于实现成本与速度的平衡。

在第一次使用CloudFlare和Conoha的时候,都被其极低的价格吓得不敢相信,企业级项目中总觉得低价的服务肯定会出问题(事实上确实是这样,毕竟价格高的也会出问题)。


cloudflare.com

和国内的安全宝、百度云加速的业务类似,CloudFlare提供的安全服务是帮助网站阻止来自网络的黑客攻击、垃圾邮件等,并提升网页的浏览速度,这和一般的安全软件往往会影响网页的运行速度大相径庭。目前CloudFlare在全球拥有23个数据中心,如果用户使用了其服务,那么网络流量将通过CloudFlare的全球网络智能路由。CloudFlare会自动优化用户的网页交付,以期达到最快的页面加载时间以及最佳性能。 CloudFlare提供包括CDN、优化工具、安全、分析以及应用等服务。

2015年9月,CloudFlare正式宣布与百度合作改善外国网站在中国的可访问性。双方早在去年7月就签署了合作协议,CloudFlare将其技术转让给百度(CEO称此举是为了增加信任),而采用CloudFlare技术的百度云加速服务于去年12月开始运作。

CloudFlare称,百度在中国大陆的17个中心地区节点与 CloudFlare 全球的45个节点结合起来,提升中国国内外的访问体验,当客户激活中国网络服务后,他们的中国访问者将会访问百度节点,而CloudFlare节点则继续服务海外访问者,可将中国流量的响应时间缩短超过200毫秒。
但外国客户如果要激活中国网络服务将需要ICP备案。网站备案是中国工信部要求所有在中国大陆使用主机或CDN服务的许可证书。

via:http://www.cnbeta.com/articles/429815.htm

conoha.jp

ConoHa日本gmo.jp旗下的一个VPS主机商,成立于2014年。ConoHa提供日本、新加坡及美国机房云VPS服务。

ConoHa的业务跟国内的云服务平台类似。说是云服务器,个人感觉跟vps差不多,跟常见的Linode和digitalocean基本上相同。
ConoHa的官网支持中文,支持信用卡和支付宝,支持扩容支持按时间收费,可以按小时按月计费。

ConoHa的价格非常廉价,常见的配置如1GB、2Core、SSD50GB,每个月50元人民币。

最重要的是,ConoHa不限流量,100M宽带,可扩容,可加IP。

ConoHa有激励政策,通过我的邀请链接注册,你可以获取1000日元,相当于免费赠送一台主机,
https://www.conoha.jp/referral/?token=V3xoVa5812CYk15rhJkKiiNc5E340f3uNaNjQCiaBmnWZdA30Zk-0VJ

业务实现
在CloudFlare中,添加一个免费(我们使用付费方案是200美元/月)的域名,主要使用其提供的IP隐藏、文件缓存来实现防DDOS和CDN需求。

在我们的单个项目中,CloudFlare每天可以缓存数百万次的请求,差不多8-12TB左右的流量。按最低4美分的价格,每天的CDN成本应该在3000元左右,一个月10万元,一年超过100百万元。
采用了CloudFlare以后,只需要1200元一个月,一年只需要1万元,CloudFlare实实再再的帮老板省了一大笔钱。
老板是不是该奖励我一台特斯拉了哎?

QQ20160110-1

经过我们跟数家CDN服务商的对比和测速,给CloudFlare的节点和速度5个星,稳定性和速度让我们非常意外,点赞。
但作为一个非专业的CDN解决方案,CloudFlare目前还没有完善的数据报表。不能分析请求的URL列表,不能按常见维度分析用户和行为,对运营人员来讲是个缺憾。
同时,CloudFlare默认只对一些基本的文本、图片文件进行缓存,有特殊的文件,比如apk、exe等文件,则颇费周折。

via:https://support.cloudflare.com/hc/en-us/articles/200172516

CloudFlare中非默认缓存的文件,比如apk文件,如果需要缓存,则不能携带任何参数,否则会回源,无法缓存。
CloudFlare另外一个巨坑便是其缓存重建只能通过pull方式。回源pull方式存在严重的风险。我们这边出现过一个50M的文件清理缓存以后,源站瞬间出现近千个请求。这包括CloudFlare的全球节点的缓存请求,也有用户的的真实请求。
CloudFlare无法设置限速,所有请求全落到源站,源站的流量瞬间飙上500M。放在云上的整个路由器下的所有业务全部卡死。

源站的流量可以通过扩容的方式提升上限,为了解决巨大的回源请求,我们曾差不多把宽带提高了到1G。
云平台1.2元/G的流量价格也是贵到滴血,逼得我们必须要为回源的请求再构建一个廉价的中转服务器。

在测试过Linode和digitalocean以后,我们选中了ConoHa。主要看中其极低的价格、无限流量、多节点等优势。
我们把文件rsync到ConoHa的多台主机以后,再将CloudFlare的回源请求重定向到不同的ConoHa服务器。
虽然业务架构越来越复杂,但比起源站业务被中断,以及宽带扩容的成本,ConoHa上一个月不到一千块钱的成本实再便宜得让人心疼。

其它
在目前的架构中,所采用的方案均为比较新的服务商,稳定性存在非常大的风险,如果有一天CloudFlare或者ConoHa倒闭,则会对现在的业务造成致命的影响。

为了降低风险,我们也在采用了一些优化手段,也在积极寻找备用方案。
比如,为了避免单个域名流量太大,被CloudFlare封掉,或者要求我们使用更高的付费方案,我们把CDN拆到多个域名下,减少单个域名的请求和流量。我们也在寻找与CloudFlare相同的的平台,比如Incapsula。甚至有人建议直接购买廉价vps自建CDN。考虑到现在云计算基础服务相对完善,自建一个全球性的CDN平台也不是太大难事。

为了避免ConoHa出故障,我们也在其它几个廉价的vps服务商购买了几个备用服务器,定期将文件同步过去进行灾备。

同时,我们发现CloudFlare中添加一个在国内备案的域名,其节点尚不能确认是否已经使用了百度云加速的节点,有没有知晓内幕的朋友。

最后
经过项目的实践和数月的运营,这个廉价的CDN实现,节点数可以达到成熟商用CDN节点数的30%-80%(海外优势尤其明显)。跟同行业的一些朋友交流时发现,也有其它同行业的业务使用CloudFlare+Digitalocean实现,稳定支撑月流水数百万美元的业务,而其成本非常低廉。

云服务越来越成熟,成本越来越低廉,对于我们这样的创业公司来讲,是一大福音。而对于那些传统的基础服务商来讲,又是什么呢?

简单获取并验证client ip

function get_ip_address()
{
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key)
    {
        if (array_key_exists($key, $_SERVER) === true)
        {
            foreach (explode(',', $_SERVER[$key]) as $ip)
            {
                $ip = trim($ip);

                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                {
                    return $ip;
                }
            }
        }
    }
}