美文网首页
读《金刚经》,品云计算

读《金刚经》,品云计算

作者: vaping | 来源:发表于2018-12-08 00:01 被阅读0次

Page1:缘起

《金刚经》第一品:法会因由分
如是我闻:一时,佛在舍卫国祇树给孤独园,与大比丘众千二百五十人俱。尔时,世尊食时,著衣持钵,入舍卫大城乞食。于其城中,次第乞已,还至本处。饭食讫,收衣钵,洗足已,敷座而坐。

标题有点儿唬人,其实是稍微整理一下自己最近对AWS的一些体会。跨入IT这个行当也超过10年了,感觉始终都有学不完的新东西冒出来。这是这个行业从业者的挑战,也是乐趣所在。

但不管冒出什么新技术,有一个感觉是始终不变的:学习不能停留在pdf、ppt上,一定要动手实践。

尔时,世尊食时,著衣持钵,入舍卫大城乞食。于其城中,次第乞已,还至本处。

当年佛祖带着1250位比丘的时候尚且亲自乞食,更何况我们了。在自己的领域里面,动手实践和理论学习都是不可或缺的。再简单的demo都能帮带给你比文字更直观的体会。

Page2:一个传统IT架构示例

《金刚经》第二十六品:法身非相分
……尔时,世尊而说偈言:“若以色见我,以音声求我,是人行邪道,不能见如来。”

在云计算环境下部署应用的时候,很多人的第一反应是将原有的应用架构直接搬到云环境中,区别只是将原来的物理服务器替换成虚拟机,并基于这样的需求,反过来要求云环境应该提供什么样的能力。大概2年前的一个私有云的项目,应用厂商提出云平台一定要支持“一盘双挂”(就是一块硬盘或LUN能挂给两台虚机),原因是他们的应用需要做A-S的HA。

传统的HA(尤其是Active-Standby)架构示意图如下:

HA架构示意图

为了实现这一架构,部署过程中至少需要做到:

  • 网络设置:
    • 两台服务器各有1个persist ip,用于本机管理,不会随着故障切换而迁移
    • 1个service ip,用于对外提供服务,随着故障切换而迁移
  • 存储设置: 需要有一个LUN同时mapping到两台服务器上,写权限随故障切换而迁移
  • 心跳设置: 两台服务器间有一个心跳网络,用于传递心跳,判断状态
  • 软件设置: 需要专门的双机软件(比如当年的IBM HACMP、HP Serviceguard等)来处理心跳监测、应用切换、存储锁等事务

如果在云上实现类似A-S的HA保障时仍然延续上图这样的思路,必然就会要求云平台具备“一盘双挂”的能力。但这样做显然没有走出传统IT的窠臼,无疑是对云计算的一种误解和浪费。

或者可以这样说:以传统的架构思维在云端进行应用部署,无异于“以色见我、以音声求我”,不能发挥出云计算最大的优势。说得再直白一点儿,不改变驾驶模式和驾驶思维,你开辆法拉利说它不如大公共有劲儿,究竟是车的问题还是驾驶员的问题呢?

Page3:云中实现 - 基础设施操作的代码化

**《金刚经》第三品:大乘正宗分
……所有一切众生之类:若卵生、若胎生、若湿生、若化生;若有色、若无色;若有想、若无想,若非有想非无想,我皆令入无余涅盘而灭度之……

但是改变架构说起来轻巧,做起来则需要花费相当的时间和精力,需要有一个循序渐进的过程。下面的demo做个非常简单的对比说明。(这个Page会比较长……)

云计算提供的不仅仅是资源(计算、存储、网络),它还提供了各种各样的服务和API。正是基于后者,才能让我们用代码控制基础设施、做自动化,才能用有限的人力管理运维海量的资源。《金刚经》说“一切众生之类,皆令入无余涅槃”,那么云计算中可能就应该是“一切操作,皆令用代码实现”了。

公有云环境下,可以将Page2中的架构示意图调整如下:

云中HA架构示意图

和传统HA的架构项目,上图有这样几处变化:

  • 虚拟机实例(Instance)替代了服务器
  • 使用Elastic Network Interface替代了IP
  • 主备实例之间不再需要专门的心跳线/心跳网络
  • 共享存储无需同时映射给两个主机(服务器/实例)

资源的切换可以用自定义的代码来实现。简要流程如下:


判断流程

以下代码全部部署在Standby Instance中。各部分的脚本代码如下展开。

HB Checking

传统的心跳监测(HB Checking)可以用这段代码实现(就是持续去ping那台Active Instance):

ping $ACT_INSTANCE_IP -c 1 &> /dev/null
RESULT=$?
while [ $RESULT -eq 0 ]; do
    ping $ACT_INSTANCE_IP -c 1 &> /dev/null
    RESULT=$?
    sleep 1s
done

其中变量ACT_INSTANCE_IP是Serivce ENI当前所在的实例IP。获取这个IP可以通过查询Service ENI(即代码中的eni-xxxxxxxxxx)的属性获得:

ENI_ID=eni-xxxxxxxxxx  
ACT_INSTANCE_ID=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID | grep InstanceId | awk -F\\\" '{print $4}')  
ACT_INSTANC_IP=$(aws ec2 describe-instances --instance-id $ACT_INSTANCE_ID | grep PrivateIpAddress | awk -F\\\" 'NR==1 {print $4}')  

这里使用到了公有云为云中服务所提供的cli命令(例如aws ec2 describe-network-interfaces),这些操作有对应的api提供,便于使用不同的语言实现。

Detach ENI and Volume

一旦Standby Instance发现无法ping通对方就认定对方已死(实际上不能这么武断),将会进行切换。首先将Service ENI和Shared Volume从原来的Active Instance上detach下来(demo所用的公有云中,ENI可以从实例上detach下来、并attach给同一AZ内的其它实例)。

aws ec2 detach-network-interface --attachment-id $ATTACHMENT_ID
aws ec2 detach-volume --volume-id $VOLUME_ID

代码中的VOLUME_ID指Shared Volume的ID,需要手工指定。ATTACHMENT_ID同样可以通过查询查询Service ENI的属性获得:

ATTACHMENT_ID=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID | grep AttachmentId | sed 's/"/\n/g' | grep eni-attach-*)

Attach ENI and Volume

当Service ENI和Shared Volume均detach下来后,同样可以通过命令将这两类资源attache给Standby Instance:

aws ec2 attach-network-interface --instance-id $STA_INSTANCE_ID --network-interface-id $ENI_ID --device-index 1 &> /dev/null
RESULT=$?
while [ $RESULT -ne 0 ]; do
    aws ec2 attach-network-interface --instance-id $STA_INSTANCE_ID --network-interface-id $ENI_ID --device-index 1 &> /dev/null
    RESULT=$?
done

aws ec2 attach-volume --instance-id $STA_INSTANCE_ID --volume-id $VOLUME_ID --device /dev/xvdf &> /dev/null
RESULT=$?
while [ $RESULT -ne 0 ]; do
    aws ec2 attach-volume --instance-id $STA_INSTANCE_ID --volume-id $VOLUME_ID --device /dev/xvdf &> /dev/null 
    RESULT=$?
done

STA_INSTANCE_ID是Standy Instance自己的ID。这个ID不必hard code写入,通过查询自己的metadata(这也是公有云提供的服务之一)即可获得:

STA_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)

Mount filesystem and Start application

当资源完成切换之后,只需要重新mount文件系统、拉起应用即可。这里选择了mariadb作为作为A-S所使用的应用:

# Mount filesystem
sudo mount /dev/xvdf1 /home/mysql &> /dev/null
RESULT=$?
while [ $RESULT -ne 0 ]; do
    sudo mount /dev/xvdf1 /home/mysql &> /dev/null
    RESULT=$?
done

# Start databse
sudo systemctl start mariadb
RESULT=$?
while [ $RESULT -ne 0 ]; do
    sudo systemctl start mariadb &> /dev/null
    RESULT=$?
    sleep 1s
done

借助一段公有云厂商官方提供前端代码(参见AWS RDS UserGuide中“教程-创建Web服务器”部分)能够验证上述代码可以成功实现切换。此处因文字局限,不再描述。

补充一个关于ENI的好处。在公有云中,允许针对ENI指定安全策略规则。在这个实验室,可以为persist ENI创建规则,只允许特定源访问22端口;为Service ENI创建规则,只允许特定源访问3306端口、放行ICMP。这种允许为单个网口指定安全规则的功能提升了安全设置中的灵活性。

(最长的page结束)

Page4:初级优化 - 利用云平台的监控能力

《金刚经》第七品:无德无说分
……如我解佛所说义,无有定法,名阿耨多罗三藐三菩提;亦无有定法,如来可说。……

Page3虽然说明了如何借助代码改变传统IT部署架构以实现相同需求,但基本上还是通过Guest OS来完成所有工作。

以监控Active Instance健康状态的那段代码来说,不但加重了Standby Instance的负担(需要持续ping),还很容易造成状态误判(网络都抖动也可能产生ping不通的现象)。

既然“无有定法”,说明同一功能会有多种实现方式。那么不妨看看还能如何优化。一个思路就是进一步利用公有云提供的服务。

公有云平台本身就可以实现Instance状态监控的功能。由此,Standby Instance就可以直接去查询公有云平台提供的Active Instance状态,当状态不处于running时即可确认Active Instance发生故障,这就避免了误切换的问题。

将最初ping的代码可以修改如下:

ACT_INSTANCE_STATE=$(aws ec2 describe-instances --instance-id $ACT_INSTANCE_ID | grep "\"Name\"\:" | awk -F\\\" '{print $4}')
STATE_TARGET="running"  

while [ $ACT_INSTANCE_STATE == $STATE_TARGET ]; do
    ACT_INSTANCE_STATE=$(aws ec2 describe-instances --instance-id $ACT_INSTANCE_ID | grep "\"Name\"\:" | awk -F\\\" '{print $4}')
    sleep 1s
done

同理,对ENI、Volume的操作也可以将云平台提供的状态作为依据,并根据状态改变的情况执行后续操作。原理和方法相同,此处不再展开。

Page5:进阶优化 - 云中的高级服务

《金刚经》第十四品:离相寂灭分
……无我相,无人相,无众生相,无寿者相。是故须菩提,菩萨应离一切相……

Page4中虽然利用了云平台的监控信息,但判断状态信息的改变、触发切换动作仍然需要Standby Instance完成。也就是说,这么一个占资源的功能仍然需要服务器去实现。“住于相”了,还在传统IT思维中打转。而IT领域里,“无我相,无人相,无众生相,无寿者相”的最高境界可能就是“无服务器”了吧。

下面的示例图利用更多的云中高级服务,进一步改变了Page2中的HA架构。


Lambda
  • 状态监控:CloudWatch
    利用云中服务CloudWatch监控Instance状态,当Active Instance状态发生改变时(不再是running状态),产生一个CloudWatch Events,用于触发一个Lambda函数。

  • 代码执行:Lambda
    Lambda是一项Serverless的服务,可以由多种服务来触发,触发后执行实现定义好的函数(代码)。

此时,Active Instance的状态判断流程就变成了这样:
Active Instance状态改变 -> 产生一个CloudWatch Event -> 触发Lambda函数 -> 完成状态判断

此时Lambda要做的工作非常简单,就是触发切换动作。切换动作可以写在lamnbda中,也可以重复利用Page3中切换部分的代码。以重复利用Page3代码为基础,lambda代码可以最简化为(使用python3.x):

import boto3
import botocore

# General Resource Definition
REGION = boto3.Session(region_name='xxxxxxxx')      #setup region
EC2 = REGION.resource('ec2')
SSM = boto3.client('ssm')
STA_INSTANCE_ID = 'i-xxxxxxxx'   

# Run command in the standby instance
SSM.send_command(InstanceIds=[STA_INSTANCE_ID], DocumentName='AWS-RunShellScript', Parameters={'commands': ['sh ~/xxxx.sh']})

xxxx.sh是保存在Standby Instance中的脚本,包括Page3中提及的ENI、Volume的detach/attach,以及mount文件系统、拉起DB应用的代码。

仅在运行时存在(付费),无需过多考虑底层资源(甚至是OS),这就是serverless。也许未来IT的发展也会是这样:无我相,无人相,无众生相,无寿者相……

Page6:结语

《金刚经》第六品:正信希有分
……知我说法,如筏喻者;法尚应舍,何况非法。
《金刚经》第三十二品:应化非真分
……一切有为法,如梦幻泡影,如露亦如电 应作如是观……

这个demo的说明到此就结束了。它是我最近一些感受的总结,也希望它能够帮助别人从不同的角度去理解云计算。但它本身并不代表着云计算,甚至不能说是一个云计算应用的demo。它只是一个工具,一个应该在进一步学习过程中应该丢弃的工具。

我们的学习过程也像是乘着竹筏过河,会利用各种个样的工具、他人的心得体会。而过河之后没人会背着竹筏继续前进,佛祖说正法都可以舍弃(法尚应舍),更何况这篇短文了(何况非法)。希望我们都能不断前进。

最后感慨一句:技术发展真快。

不说云计算、容器什么的,就说写东西这事儿吧。两三年前是用word写,word里面贴图片,然后发blog、长微博。今天呢?用markdown写……

有意思……

相关文章

网友评论

      本文标题:读《金刚经》,品云计算

      本文链接:https://www.haomeiwen.com/subject/ehjfhqtx.html