Linux 集群

时间:2024-04-06 17:04:41

p:first-child, #write > ul:first-child, #write > ol:first-child, #write > pre:first-child, #write > blockquote:first-child, #write > div:first-child, #write > table:first-child { margin-top: 30px; }
img { max-width: 100%; }
input, button, select, textarea { color: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
::before, ::after, * { box-sizing: border-box; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write div, #write pre { width: inherit; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6 { position: relative; }
h1 { font-size: 2rem; }
p { -webkit-margin-before: 1rem; -webkit-margin-after: 1rem; -webkit-margin-start: 0px; -webkit-margin-end: 0px; }
.mathjax-block { margin-top: 0px; margin-bottom: 0px; -webkit-margin-before: 0rem; -webkit-margin-after: 0rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: bold; font-style: italic; }
a { cursor: pointer; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; margin: 4px 0px 0px; }
tr { page-break-inside: avoid; page-break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; page-break-inside: auto; text-align: left; }
table.md-table td { min-width: 80px; }
.CodeMirror-gutters { border-right-width: 0px; background-color: inherit; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
pre { white-space: pre-wrap; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences, pre.md-fences { font-size: 0.9rem; display: block; page-break-inside: avoid; text-align: left; overflow: visible; white-space: pre; position: relative !important; background: inherit; }
.md-fences .CodeMirror.CodeMirror-wrap { top: -1.6em; margin-bottom: -1.6em; }
.md-fences.mock-cm { white-space: pre-wrap; }
.show-fences-line-number pre.md-fences { padding-left: 0px; }
.show-fences-line-number pre.md-fences.mock-cm { padding-left: 40px; }
.footnotes { color: rgb(136, 136, 136); font-size: 0.9rem; padding-top: 1em; padding-bottom: 1em; }
.footnotes + .footnotes { margin-top: -1em; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; text-decoration: none; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 1rem; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: normal; text-align: left; box-sizing: content-box; direction: ltr; background: transparent; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li p, li .mathjax-block { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; }
@media print {
html, body { height: 100%; }
.typora-export * { -webkit-print-color-adjust: exact; }
h1, h2, h3, h4, h5, h6 { page-break-after: avoid; orphans: 2; }
p { orphans: 4; }
html.blink-to-pdf { font-size: 13px; }
.typora-export #write { padding-left: 1cm; padding-right: 1cm; }
.typora-export #write::after { height: 0px; }
@page { margin: 20mm 0mm; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
#write pre.md-meta-block { font-size: 0.8rem; min-height: 2.86rem; white-space: pre-wrap; display: block; background: rgb(204, 204, 204); }
p > .md-image:only-child { display: inline-block; width: 100%; text-align: center; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.mathjax-block { white-space: pre; overflow: hidden; width: 100%; }
p + .mathjax-block { margin-top: -1.143rem; }
.mathjax-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: none; box-shadow: none; }
.task-list { list-style-type: none; }
.task-list-item { position: relative; padding-left: 1em; }
.task-list-item input { position: absolute; top: 0px; left: 0px; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc::after, .md-toc-content::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: bold; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
.md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
.md-toc-h4 .md-toc-inner { margin-left: 5em; }
.md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
.md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { color: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; text-decoration: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
.md-tag { opacity: 0.5; }
code { text-align: left; }
h1 .md-tag, h2 .md-tag, h3 .md-tag, h4 .md-tag, h5 .md-tag, h6 .md-tag { font-weight: initial; opacity: 0.35; }
a.md-header-anchor.md-print-anchor { border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: none !important; text-decoration: initial !important; text-shadow: initial !important; background: transparent !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.mathjax-block .MathJax_SVG_Display { text-align: center; margin: 1em 0em; position: relative; text-indent: 0px; max-width: none; max-height: none; min-width: 0px; min-height: 0px; width: 100%; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: monospace; }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: normal; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none; }

@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: normal; src: local("Open Sans Regular"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/github/400.woff") format("woff"); }
@font-face { font-family: 'Open Sans'; font-style: italic; font-weight: normal; src: local("Open Sans Italic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/github/400i.woff") format("woff"); }
@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: bold; src: local("Open Sans Bold"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/github/700.woff") format("woff"); }
@font-face { font-family: 'Open Sans'; font-style: italic; font-weight: bold; src: local("Open Sans Bold Italic"), url("file:///C:/Users/Administrator/AppData/Roaming/Typora/themes/github/700i.woff") format("woff"); }
html { font-size: 16px; }
body { font-family: 'Open Sans', 'Clear Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; color: rgb(51, 51, 51); line-height: 1.6; }
#write { max-width: 860px; margin: 0px auto; padding: 20px 30px 100px; }
#write > ul:first-child, #write > ol:first-child { margin-top: 30px; }
body > :first-child { margin-top: 0px !important; }
body > :last-child { margin-bottom: 0px !important; }
a { color: rgb(65, 131, 196); }
h1, h2, h3, h4, h5, h6 { position: relative; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; }
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { text-decoration: none; }
h1 tt, h1 code { font-size: inherit; }
h2 tt, h2 code { font-size: inherit; }
h3 tt, h3 code { font-size: inherit; }
h4 tt, h4 code { font-size: inherit; }
h5 tt, h5 code { font-size: inherit; }
h6 tt, h6 code { font-size: inherit; }
h1 { padding-bottom: 0.3em; font-size: 2.25em; line-height: 1.2; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); }
h2 { padding-bottom: 0.3em; font-size: 1.75em; line-height: 1.225; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); }
h3 { font-size: 1.5em; line-height: 1.43; }
h4 { font-size: 1.25em; }
h5 { font-size: 1em; }
h6 { font-size: 1em; color: rgb(119, 119, 119); }
p, blockquote, ul, ol, dl, table { margin: 0.8em 0px; }
li > ol, li > ul { margin: 0px; }
hr { height: 4px; padding: 0px; margin: 16px 0px; border-width: 0px 0px 1px; border-style: none none solid; overflow: hidden; box-sizing: content-box; border-bottom-color: rgb(221, 221, 221); background-color: rgb(231, 231, 231); }
body > h2:first-child { margin-top: 0px; padding-top: 0px; }
body > h1:first-child { margin-top: 0px; padding-top: 0px; }
body > h1:first-child + h2 { margin-top: 0px; padding-top: 0px; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { margin-top: 0px; padding-top: 0px; }
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { margin-top: 0px; padding-top: 0px; }
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { margin-top: 0px; }
li p.first { display: inline-block; }
ul, ol { padding-left: 30px; }
ul:first-child, ol:first-child { margin-top: 0px; }
ul:last-child, ol:last-child { margin-bottom: 0px; }
blockquote { border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); }
blockquote blockquote { padding-right: 0px; }
table { padding: 0px; word-break: initial; }
#write { overflow-x: auto; }
table tr { border-top-width: 1px; border-top-style: solid; border-top-color: rgb(204, 204, 204); margin: 0px; padding: 0px; background-color: white; }
table tr:nth-child(2n) { background-color: rgb(248, 248, 248); }
table tr th { font-weight: bold; border: 1px solid rgb(204, 204, 204); text-align: left; margin: 0px; padding: 6px 13px; }
table tr td { border: 1px solid rgb(204, 204, 204); text-align: left; margin: 0px; padding: 6px 13px; }
table tr th:first-child, table tr td:first-child { margin-top: 0px; }
table tr th:last-child, table tr td:last-child { margin-bottom: 0px; }
.CodeMirror-gutters { border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); }
.md-fences, code, tt { border: 1px solid rgb(221, 221, 221); border-radius: 3px; font-family: Consolas, 'Liberation Mono', Courier, monospace; padding: 2px 4px 0px; font-size: 0.9em; background-color: rgb(248, 248, 248); }
.md-fences { margin-bottom: 15px; margin-top: 15px; padding: 8px 1em 6px; }
.task-list { padding-left: 0px; }
.task-list-item { padding-left: 32px; }
.task-list-item input { top: 3px; left: 8px; }
@media screen and (min-width: 914px) {
}
@media print {
html { font-size: 13px; }
table, pre { page-break-inside: avoid; }
pre { word-wrap: break-word; }
}
.md-fences { background-color: rgb(248, 248, 248); }
#write pre.md-meta-block { padding: 1rem; font-size: 85%; line-height: 1.45; border: 0px; border-radius: 3px; color: rgb(119, 119, 119); margin-top: 0px !important; background-color: rgb(247, 247, 247); }
.mathjax-block > .code-tooltip { bottom: 0.375rem; }
#write > h3.md-focus::before { left: -1.5625rem; top: 0.375rem; }
#write > h4.md-focus::before { left: -1.5625rem; top: 0.285714rem; }
#write > h5.md-focus::before { left: -1.5625rem; top: 0.285714rem; }
#write > h6.md-focus::before { left: -1.5625rem; top: 0.285714rem; }
.md-image > .md-meta { border: 1px solid rgb(221, 221, 221); border-radius: 3px; font-family: Consolas, 'Liberation Mono', Courier, monospace; padding: 2px 4px 0px; font-size: 0.9em; color: inherit; background-color: rgb(248, 248, 248); }
.md-tag { color: inherit; }
.md-toc { margin-top: 20px; padding-bottom: 20px; }
#typora-quick-open { border: 1px solid rgb(221, 221, 221); background-color: rgb(248, 248, 248); }
#typora-quick-open-item { border-color: rgb(254, 254, 254) rgb(229, 229, 229) rgb(229, 229, 229) rgb(238, 238, 238); border-style: solid; border-width: 1px; background-color: rgb(250, 250, 250); }
#md-notification::before { top: 10px; }
.on-focus-mode blockquote { border-left-color: rgba(85, 85, 85, 0.117647); }
header, .context-menu, .megamenu-content, footer { font-family: 'Segoe UI', Arial, sans-serif; }
-->

Linux_Cluster

Linux_ClusterOverviewLBIntroductionLVS的调度方法:10种ipvsadm查看lvs状态VS/NATARP问题LVS my testing持久连接HA概述Cluster 选项顺序约束属性排列约束CRMRARHEL OR CentOS高可用集群解决方案资源争用安装配置高可用集群heartbeatHA集群的工作模型:资源粘性与约束资源释放资源类型Heartbeat V2资源脚本:安装配置HeartbeatAnsible安装配置YAMLCorosync && PacemakerBackground配置实例Crmsh监测资源功能配置资源粘性定义资源约束部署corosync && pacemaker 案例PCSDFS概率分布式事务的模型和规范分布式应用分布式存储MogileFS特性安装配置mogilefs应用示例存储DRBDDRBD ProtocolBrain Split配置DRBDDRBD&&Pacemakermysql+drbd+corosyncDRBD 工作在双主模型结合RHCS时资源定义示例多节点同时启动一个IPISCSI配置iscsitgtadmiSCSI配置示例分享ISCSI步骤删除ISCSI设备tgtd configurationISCSI配置CHAP用户认证RHCS and CongaHA解决方案(终极)部署RHCS的方法RHCS基于命令行的实现GFS集群文件系统集群逻辑卷lvm2-clusterDevice Mapper 简析DM与MDDMSetupKeepAlivedKeepAlived配置Keepalived功能补充组播IP地址特殊网卡类型配置故障切换域

注册用户>在线数>并发数

Overview

扩展类型: Scale up: 向上扩展 Scale out: 向外扩展 HA: 服务可用性 平均无故障时间/(平均无故障时间+平均修复时间) 将调度与生产分离 RAS 1、负载均衡集群(LB):load balance 扩展容量,伸缩性 tcp: lvs,haproxy 应用层:nginx, haproxy, ats 缓存:varnish,squid 2、高可用集群(HA):High Availiablity 实现服务可用性 heartbeat, corosync, keepalived iscsi, gfs2, drbd

  • heartbeat
  • corosync + pacemaker
  • cman + rgmanager
  • cman + pacemaker
  • keepalived
  • ultramonkey

分布式图片存储:MogileFS NoSQL: MongoDB 3、高性能集群 HP:High Performance Hadoop 向量机 并行处理集群

LB

Introduction

硬件解决方案: F5 公司产品 BIG-IP 思杰Ctrix Netscaler A10 A10 Array Redware

Linux: LVS Linux Virtual Server 章文嵩,国人研发 IPVS:框架,需要依赖于规则完成转发.不属于netfilter的INPUT链

libnet下载地址: http://search.cpan.org/dist/libnet/ ipvsadm下载地址: http://www.linuxvirtualserver.org/software/ipvs.html#kernel-2.6

从Linux内核版本2.6起,ip_vs code已经被整合进了内核中,因此,只要在编译内核的时候选择了ipvs的功能,您的Linux即能支持LVS。Linux 2.4.23以后的内核版本也整合了ip_vs code,但如果是更旧的内核版本,您得自己手动将ip_vs code整合进内核原码中,并重新编译内核方可使用lvs。 ipvsadmin/ipvs = LVS

关于ipvsadm:

ipvsadm是运行于用户空间、用来与ipvs交互的命令行工具,它的作用表现在: 1、定义在Director上进行dispatching的服务(service),以及哪此服务器(server)用来提供此服务; 2、为每台同时提供某一种服务的服务器定义其权重(即概据服务器性能确定的其承担负载的能力) 注:权重用整数来表示,有时候也可以将其设置为atomic_t;其有效表示值范围为24bit整数空间,即(2^24-1);

因此,ipvsadm命令的主要作用表现在以下方面: 1、添加服务(通过设定其权重>0); 2、关闭服务(通过设定其权重>0);此应用场景中,已经连接的用户将可以继续使用此服务,直到其退出或超时;新的连接请求将被拒绝; 3、保存ipvs设置,通过使用“ipvsadm-sav > ipvsadm.sav”命令实现; 4、恢复ipvs设置,通过使用“ipvsadm-sav < ipvsadm.sav”命令实现; 5、显示ip_vs的版本号,下面的命令显示ipvs的hash表的大小为4k;

// ipvsadm

IP Virtual Server version 1.2.1 (size=4096)

6、显示ipvsadm的版本号 ipvsadm --version ipvsadm v1.24 2003/06/07 (compiled with popt and IPVS v1.2.0)

ipvsadm使用中应注意的问题

默认情况下,ipvsadm在输出主机信息时使用其主机名而非IP地址,因此,Director需要使用名称解析服务。如果没有设置名称解析服务、服务不可用或设置错误,ipvsadm将会一直等到名称解析超时后才返回。当然,ipvsadm需要解析的名称仅限于RealServer,考虑到DNS提供名称解析服务效率不高的情况,建议将所有RealServer的名称解析通过/etc/hosts文件来实现LVS根据套接字进行转发,所以通常称LVS为四层交换或者四层路由

CIP --- VIP --- DIP --- RIP

LVS类型:

  • NAT
  • DR
  • TUN
  • FULLNAT

LVS的NAT特征:

1、RS应该使用私有地址 2、 RS的网关必须指向DIP 3、 RIP和DIP必须在同一网段内 4、 请求和响应的报文都得经过Director,在高负载运行场景中,Director很可能成为系统性能瓶颈 5、支持端口映射: 6、RS可以使用任意支持集群服务的OS

LVS DR类型:

1、让前端路由将请求发往VIP时,只能是Director上的VIP: 解决方案: 1、静态地址绑定 未必有路由器的配置权限; Director调用时静态地址绑定将难以适用; 2、arptables 3、修改Linux参数,将RS上的VIP配置在lo接口的别名,限制Linux仅对对应接口的APR请求做相应;

LVS DR类型的特性: 1、RS可以使用私有地址,但也可以使用公网地址,此时可以直接通过互联网连入RS以实现配置、监控等; 2、RS的网关一定不能指向DIP; 3、RS跟Directory要在同一物理网络内(不能由路由器分割); 4、请求报文经过Directory,但响应报文一定不经过Directory; 5、不支持端口映射; 6、RS可以使用大多数的操作系统;

LVS TUN类型:IP隧道

1、RIP,DIP,VIP都得是公网地址; 2、RS的网关不会指向也不可能指向RIP; 3、请求报文经过Directory,但响应报文一定不经过Director; 4、不支持端口映射; 5、RS的OS必须得支持隧道功能;

LVS的调度方法:10种

Schedule method:调度算法 静态方法:仅根据算法本身进行调度

rr: Round Robin
wrr: Weighted RR
sh: source hashing
dh: destination hashing

动态方法:根据算法及RS当前的负载状况

lc: Least Connection
Overhead=Active*256+Inactive
结果中,最小者胜出;
wlc: Weighted LC
Overhead=(Active*256+Inactive)/weight
sed: Shortest Expect Delay
Overhead=(Active+1)*256/weight
nq: Nerver Queue
lblc: Locality-based Least Connection
dh+lc
lblcr: Replicated and Locality-based Least Connection

Session持久机制:

1、session绑定:始终将同一个请求者的连接定向至同一个RS(第一次请求时仍由调度方法选择);没有容错能力,有损均衡效果;
2、session复制:在RS之间同步session,因此,每个RS持集群中所有的session;对于大规模集群环境不适用;
3、session服务器:利用单独部署的服务器来统一管理session;

调度算法解析

1、轮询(round robin, rr),加权轮询(Weighted round robin, wrr)――新的连接请求被轮流分配至各RealServer;算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。轮叫调度算法假设所有服务器处理性能均相同,不管服务器的当前连接数和响应速度。该算法相对简单,不适用于服务器组中处理性能不一的情况,而且当请求服务时间变化比较大时,轮叫调度算法容易导致服务器间的负载不平衡。 2、最少连接(least connected, lc), 加权最少连接(weighted least connection, wlc)――新的连接请求将被分配至当前连接数最少的RealServer;最小连接调度是一种动态调度算法,它通过服务器当前所活跃的连接数来估计服务器的负载情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中止或超时,其连接数减一。 3、基于局部性的最少链接调度(Locality-Based Least Connections Scheduling,lblc)――针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和主存Cache命中率,从而整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于其一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。 4、带复制的基于局部性最少链接调度(Locality-Based Least Connections with Replication Scheduling,lblcr)――也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而 LBLC算法维护从一个目标IP地址到一台服务器的映射。对于一个“热门”站点的服务请求,一台Cache 服务器可能会忙不过来处理这些请求。这时,LBLC调度算法会从所有的Cache服务器中按“最小连接”原则选出一台Cache服务器,映射该“热门”站点到这台Cache服务器,很快这台Cache服务器也会超载,就会重复上述过程选出新的Cache服务器。这样,可能会导致该“热门”站点的映像会出现在所有的Cache服务器上,降低了Cache服务器的使用效率。LBLCR调度算法将“热门”站点映射到一组Cache服务器(服务器集合),当该“热门”站点的请求负载增加时,会增加集合里的Cache服务器,来处理不断增长的负载;当该“热门”站点的请求负载降低时,会减少集合里的Cache服务器数目。这样,该“热门”站点的映像不太可能出现在所有的Cache服务器上,从而提供Cache集群系统的使用效率。LBLCR算法先根据请求的目标IP地址找出该目标IP地址对应的服务器组;按“最小连接”原则从该服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载;则按“最小连接”原则从整个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。 5、目标地址散列调度(Destination Hashing,dh)算法也是针对目标IP地址的负载均衡,但它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。 6、源地址散列调度(Source Hashing,sh)算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。除了将请求的目标IP地址换成请求的源IP地址外,它的算法流程与目标地址散列调度算法的基本相似。在实际应用中,源地址散列调度和目标地址散列调度可以结合使用在防火墙集群中,它们可以保证整个系统的唯一出入口。

LVS追踪标记fwmark:

如果LVS放置于多防火墙的网络中,并且每个防火墙都用到了状态追踪的机制,那么在回应一个针对于LVS的连接请求时必须经过此请求连接进来时的防火墙,否则,这个响应的数据包将会被丢弃。 LVS-fullnat: Director将CIP|VIP 转变为DIP|RIP Session持久机制: 1、Session绑定:始终将同一个请求者的连接定向至同一个RS(第一次请求时仍由调度方法选择),没有容错能力,有损均衡效果(反均衡); 2、Session复制:在RS之间同步session,因此每个RS持集群中所有的session,对于大规模集群环境并不适用; 3、Session服务器:利用单独部署的服务器来统一管理Session。此共享的Session服务器要实现高可用;

LVS的集群服务:根据请求目标套接字(包括端口的协议类型tcp,udp)来实现转发

查看内核中的关于ipvs的编译

 grep -i -E 'ipvs|ip_vs' /boot/config-2.6.32-573.el6.x86_64

ipvsadm

ipvsadm
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask]
ipvsadm -D -t|u|f service-address
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address]

集群服务相关选项

-A: 添加一个集群服务
-t: tcp
-u: udp
-f: firewall mark, 通常用于将两个或以上的服务绑定为一个服务进行处理时使用;
service-address:
-t IP:port
-u IP:port
-f firewall_mark
-s 调度方法,默认为wlc
-p timeout: persistent connection
-E: 修改定义过的集群服务
-D -t|u|f service-address:删除指定的集群服务

RS相关选项

-a: 向指定的Cluster中添加RS
-t|-u|-f service-address: 指明将RS添加至哪个Cluster Server中
-r: 指定RS,可以包含{IP:port},只有支持端口映射的LVS类型才允许此处使用跟集群服务中不同的端口
LVS类型:
-g:Gateway---> DR
-i:IPIP ---> TUN
-m:masquerade --->NAT
指定RS权重:
-w: weight
指定服务器可接受的连接数
-x: upper
-y: lower
-e:修改指定RS属性
-d -u|u|f service-address -r service-address:从指定的集群服务中删除某RS

其他参数

-C:清除所有集群服务
-S: ipvsadm-save 保存规则(使用输出重定向)
-R: ipvsadm-restore 载入指定的规则(使用输入重定向)
—L: 查看ipvs规则
-n:不使用反向解析
-c:显示RS活动连接数和非活动连接数
--stats: 显示统计数据
--rate: 报文传输数据
--timeouts: 显示ipvs限定的tcp,tcpfin,udp的超时时长
--exact: 对输出结果不做换算而显示精确值
-Z: 计数器清零

查看lvs状态

查看LVS上当前的所有连接

ipvsadm -Lcn
或者
cat /proc/net/ip_vs_conn

查看虚拟服务和RealServer上当前的连接数,数据包数和自己数的统计值,则可以使用:

ipvsadm -l --stats

查看包传递速率的近似精确值,可以使用:

ipvsadm -l --rate

VS/NAT

LVS-NAT基于cisco的LocalDirector。VS/NAT不需要在RealServer上做任何设置,其只要能提供一个tcp/ip的协议栈即可,甚至其无论基于什么OS。基于VS/NAT,所有的入站数据包均由Director进行目标地址转换后转发至内部的RealServer,RealServer响应的数据包再由Director转换源地址后发回客户端。 VS/NAT模式不能与netfilter兼容,因此,不能将VS/NAT模式的Director运行在netfilter的保护范围之中。现在已经有补丁可以解决此问题,但尚未被整合进ip_vs code。

    ____________
| |
| client |
|____________|
CIP=192.168.0.253 (eth0)
|
|
VIP=192.168.0.220 (eth0)
____________
| |
| director |
|____________|
DIP=192.168.10.10 (eth1)
|
(switch)------------------------
| |
RIP=192.168.10.2 (eth0) RIP=192.168.10.3 (eth0)
_____________ _____________
| | | |
| realserver1 | | realserver2 |
|_____________| |_____________|

设置VS/NAT模式的LVS(以Web服务为例)

Director:

建立服务

ipvsadm -A -t VIP:PORT -s rr
ipvsadm -A -t 192.168.0.220:80 -s rr

设置转发

ipvsadm -a -t VIP:PORT -r RIP_N:PORT -m -w N
ipvsadm -a -t 192.168.0.220:80 -r 192.168.10.2 -m -w 1
ipvsadm -a -t 192.168.0.220:80 -r 192.168.10.3 -m -w 1

打开路由转发功能

echo 1 > /proc/sys/net/ipv4/ip_forward

服务控制脚本

#!/bin/bash
#
# chkconfig: - 88 12
# description: LVS script for VS/NAT
#
. /etc/rc.d/init.d/functions
#
VIP=192.168.0.219
DIP=192.168.10.10
RIP1=192.168.10.11
RIP2=192.168.10.12
#
case "$1" in
start) /sbin/ifconfig eth0:1 $VIP netmask 255.255.255.0 up # Since this is the Director we must be able to forward packets
echo 1 > /proc/sys/net/ipv4/ip_forward # Clear all iptables rules.
/sbin/iptables -F # Reset iptables counters.
/sbin/iptables -Z # Clear all ipvsadm rules/services.
/sbin/ipvsadm -C # Add an IP virtual service for VIP 192.168.0.219 port 80
# In this recipe, we will use the round-robin scheduling method.
# In production, however, you should use a weighted, dynamic scheduling method.
/sbin/ipvsadm -A -t $VIP:80 -s rr # Now direct packets for this VIP to
# the real server IP (RIP) inside the cluster
/sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m
/sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m /bin/touch /var/lock/subsys/ipvsadm.lock
;; stop)
# Stop forwarding packets
echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm
/sbin/ipvsadm -C # Bring down the VIP interface
ifconfig eth0:1 down rm -rf /var/lock/subsys/ipvsadm.lock
;; status)
[ -e /var/lock/subsys/ipvsadm.lock ] && echo "ipvs is running..." || echo "ipvsadm is stopped..."
;;
*)
echo "Usage: $0 {start|stop}"
;;
esac

ARP问题

                     __________
| |
| client |
|________|
|
(router)
|
|
| __________
| DIP | |
|------| director |
| VIP |__________|
|
|
|
------------------------------------
| | |
| | |
RIP1, VIP RIP2, VIP RIP3, VIP
______________ ______________ ______________
| | | | | |
| realserver1 | | realserver2 | | realserver3 |
|______________| |______________| |______________|

在如上图的VS/DR或VS/TUN应用的一种模型中(所有机器都在同一个物理网络),所有机器(包括Director和RealServer)都使用了一个额外的IP地址,即VIP。当一个客户端向VIP发出一个连接请求时,此请求必须要连接至Director的VIP,而不能是RealServer的。因为,LVS的主要目标就是要Director负责调度这些连接请求至RealServer的。 因此,在Client发出至VIP的连接请求后,只能由Director将其MAC地址响应给客户端(也可能是直接与Director连接的路由设备),而Director则会相应的更新其ipvsadm table以追踪此连接,而后将其转发至后端的RealServer之一。 如果Client在请求建立至VIP的连接时由某RealServer响应了其请求,则Client会在其MAC table中建立起一个VIP至RealServer的对就关系,并以至进行后面的通信。此时,在Client看来只有一个RealServer而无法意识到其它服务器的存在。 为了解决此问题,可以通过在路由器上设置其转发规则来实现。当然,如果没有权限访问路由器并做出相应的设置,则只能通过传统的本地方式来解决此问题了。这些方法包括: 1、禁止RealServer响应对VIP的ARP请求; 2、在RealServer上隐藏VIP,以使得它们无法获知网络上的ARP请求; 3、基于“透明代理(Transparent Proxy)”或者“fwmark (firewall mark)”; 4、禁止ARP请求发往RealServers;

传统认为,解决ARP问题可以基于网络接口,也可以基于主机来实现。Linux采用了基于主机的方式,因为其可以在大多场景中工作良好,但LVS却并不属于这些场景之一,因此,过去实现此功能相当麻烦。现在可以通过设置arp_ignore和arp_announce,这变得相对简单的多了。 Linux 2.2和2.4(2.4.26之前的版本)的内核解决“ARP问题”的方法各不相同,且比较麻烦。幸运的是,2.4.26和2.6的内核中引入了两个新的调整ARP栈的标志(device flags):arp_announce和arp_ignore。基于此,在DR/TUN的环境中,所有IPVS相关的设定均可使用arp_announce=2和arp_ignore=1/2/3来解决“ARP问题”了。 arp_annouce:Define different restriction levels for announcing the local source IP address from IP packets in ARP requests sent on interface;

0 - (default) Use any local address, configured on any interface.
1 - Try to avoid local addresses that are not in the target's subnet for this interface.
2 - Always use the best local address for this target.

arp_ignore: Define different modes for sending replies in response to received ARP requests that resolve local target IP address.

0 - (default): reply for any local target IP address, configured on any interface.
1 - reply only if the target IP address is local address configured on the incoming interface.
2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface.
3 - do not reply for local address configured with scope host, only resolutions for golbal and link addresses are replied.
4-7 - reserved
8 - do not reply for all local addresses

在RealServers上,VIP配置在本地回环接口lo上。如果回应给Client的数据包路由到了eth0接口上,则arp通告或请应该通过eth0实现,因此,需要在sysctl.conf文件中定义如下配置:

//vim /etc/sysctl.conf
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

以上选项需要在启用VIP之前进行,否则,则需要在Drector上清空arp表才能正常使用LVS。

到达Director的数据包首先会经过PREROUTING,而后经过路由发现其目标地址为本地某接口的地址,因此,接着就会将数据包发往INPUT(LOCAL_IN HOOK)。此时,正在运行内核中的ipvs(始终监控着LOCAL_IN HOOK)进程会发现此数据包请求的是一个集群服务,因为其目标地址是VIP。于是,此数据包的本来到达本机(Director)目标行程被改变为经由POSTROUTING HOOK发往RealServer。这种改变数据包正常行程的过程是根据IPVS表(由管理员通过ipvsadm定义)来实现的。

如果有多台Realserver,在某些应用场景中,Director还需要基于“连接追踪”实现将由同一个客户机的请求始终发往其第一次被分配至的Realserver,以保证其请求的完整性等。其连接追踪的功能由Hash table实现。Hash table的大小等属性可通过下面的命令查看: // ipvsadm -lcn

为了保证其时效性,Hash table中“连接追踪”信息被定义了“生存时间”。LVS为记录“连接超时”定义了三个计时器:

1、空闲TCP会话;
2、客户端正常断开连接后的TCP会话;
3、无连接的UDP数据包(记录其两次发送数据包的时间间隔);

上面三个计时器的默认值可以由类似下面的命令修改,其后面的值依次对应于上述的三个计时器: // ipvsadm --set 28800 30 600

数据包在由Direcotr发往Realserver时,只有目标MAC地址发生了改变(变成了Realserver的MAC地址)。Realserver在接收到数据包后会根据本地路由表将数据包路由至本地回环设备,接着,监听于本地回环设备VIP上的服务则对进来的数据库进行相应的处理,而后将处理结果回应至RIP,但数据包的原地址依然是VIP。

LVS my testing

准备工作

关闭iptables的规则

iptables -F; iptables -t filter;service iptables save

开启IP Forward

vi /etc/systl.conf
#change net.ipv4.ip_forward = 0 to
net.ipv4.ip_forward = 1

DR模式RS修改网卡对APR行为的参数

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

arp_announce级别:

0:默认值,不管哪块网卡接收到了ARP请求,只要发现本机有这个MAC都给与响应 1:尽量避免响应ARP请求中MAC不是本网卡的,一个主机有多块网卡,其中一块网卡接收到了ARP请求,发现所请求的MAC是本机另一块网卡的,这个时候接收到ARP请求的这块网卡就尽量避免响应 2:总是使用最合适的网卡来响应,一个主机有多块网卡,其中一块网卡接收到了ARP请求,发现所请求的MAC是本机另一块网卡的,这个时候接收到ARP请求的这块网卡就一定不响应,只有发现请求的MAC是自己的才给与响应(只通告同一网络中的请求)

arp_ignore级别:

0:默认值,不管哪块网卡接收到了ARP请求,只要发现本机有这个MAC都给与响应 1:总是使用最合适的网卡来响应,一个主机有多块网卡,其中一块网卡接收到了ARP请求,发现所请求的MAC是本机另一块网卡的,这个时候接收到ARP请求的这块网卡就一定不响应,只有发现请求的MAC是自己的才给与响应

修改Director:

iptables -t filter -F
ifconfig eth0:0 VIP up
route add -host VIP dev eth0:0

RS指定VIP到网卡lo:0

ifconfig lo:0 VIP netmask 255.255.255.255 broadcast VIP
route add -host VIP dev lo:0 (使得包进入eth0以后必须经过lo网卡)

配置director

ipvsadm -A -t IP:PORT -s SCHEDULER
ipvsadm -a -t IP:PORT -r RS1 -g -w WEIGHT

持久连接

无论基于什么样的算法,只要期望源于同一个客户端的请求都由同一台Realserver响应时,就需要用到持久连接。比如,某一用户连续打开了三个telnet连接请求时,根据RR算法,其请求很可能会被分配至不同的Realserver,这通常不符合使用要求。 -p N 指定持久连接时间,默认为300s 每次默认延长2min LVS持久连接类型

1 . 持久客户端连接(PCC):将来自同一个客户端发往VIP的所有请求通通定向至同一个RS

    ipvsadm -A -t VIP:0 -s rr -p 600
ipvsadm -a -t VIP:0 -r RS1 -g
ipvsadm -a -t VIP:0 -r RS2 -g

2 . 持久端口连接(PPC):将来自于一个客户端发往某VIP的某端口的所有请求通通定向至同一个RS

   ipvsadm -A -t VIP:80 -s rr -p 120
ipvsadm -a -t VIP:80 -r RS1 -g
ipvsadm -a -t VIP:80 -r RS2 -g

3 . 持久防火墙标记连接(PFMC):端口绑定,port affinity.能够实现基于防火墙标记,将两个或以上的端口绑定为同一个服务

iptables -t mangle -A PREROUTING -d VIP -p tcp --dport 443 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -d VIP -p tcp --dport 80 -j MARK --set-mark 10
防火墙标记要指定0~99的整数
ipvsadm -A -f 10 -s rr
ipvsadm -a -f 10 -r RS1 -g
ipvsadm -a -f 10 -r RS1 -g

查看持久连接

ipvsadm -L -n --persistent-conn
cat /proc/net/ip_vs
cat /proc/net/ip_vs_conn

ipvs集群两个问题:

  • 后端RSs的健康状态检测如何实现

    • 脚本监测

      #!/bin/bash
      VIP=10.10.10.100
      PORT=80
      CS=${VIP}:${PORT}
      CS1='-f 10'
      RS1=192.168.48.135
      RS2=192.168.48.136
      RS1_STATE=1
      RS2_STATE=1
      checkRS(){
      curl -s http://${1}/.health.html|grep 'ok' &>/dev/null
      RetVal=$?
      if [ $RetVal -ne 0 ] && ipvsadm -L -n|grep "$1" &>/dev/null;then
      ipvsadm -d ${CS1} -r $1
      fi
      if [ $RetVal -eq 0 ] && ! ipvsadm -L -n|grep "$1" &>/dev/null;then
      ipvsadm -a ${CS1} -r $1 -g
      fi
      }
      while true;do
      checkRS $RS1
      checkRS $RS2
      sleep 3
      done
      1、某RS故障时,要监测至少三次才让其下线;而重新上线时,只需要检测一次
      2、如何让脚本有更好的适应性;
    • keepalived, ldirectord

  • Director自身的可用性如何得到保证

    • ldirectored(heartbeat, corosync)
    • keepalived

Director sysV配置文件

#!/bin/bash
#
# LVS script for VS/DR
#
. /etc/rc.d/init.d/functions
#
VIP=192.168.0.210
RIP1=192.168.0.221
RIP2=192.168.0.222
PORT=80 #
case "$1" in
start) /sbin/ifconfig eth0:1 $VIP broadcast $VIP netmask 255.255.255.255 up
/sbin/route add -host $VIP dev eth0:1 # Since this is the Director we must be able to forward packets
echo 1 > /proc/sys/net/ipv4/ip_forward # Clear all iptables rules.
/sbin/iptables -F # Reset iptables counters.
/sbin/iptables -Z # Clear all ipvsadm rules/services.
/sbin/ipvsadm -C # Add an IP virtual service for VIP 192.168.0.219 port 80
# In this recipe, we will use the round-robin scheduling method.
# In production, however, you should use a weighted, dynamic scheduling method.
/sbin/ipvsadm -A -t $VIP:80 -s wlc # Now direct packets for this VIP to
# the real server IP (RIP) inside the cluster
/sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -g -w 1
/sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -g -w 2 /bin/touch /var/lock/subsys/ipvsadm &> /dev/null
;; stop)
# Stop forwarding packets
echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm
/sbin/ipvsadm -C # Bring down the VIP interface
/sbin/ifconfig eth0:1 down
/sbin/route del $VIP /bin/rm -f /var/lock/subsys/ipvsadm echo "ipvs is stopped..."
;; status)
if [ ! -e /var/lock/subsys/ipvsadm ]; then
echo "ipvsadm is stopped ..."
else
echo "ipvs is running ..."
ipvsadm -L -n
fi
;;
*)
echo "Usage: $0 {start|stop|status}"
;;
esac

RealServer sysV配置文件

#!/bin/bash
#
# Script to start LVS DR real server.
# description: LVS DR real server
#
. /etc/rc.d/init.d/functions VIP=192.168.0.219
host=`/bin/hostname` case "$1" in
start)
# Start LVS-DR real server on this machine.
/sbin/ifconfig lo down
/sbin/ifconfig lo up
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up
/sbin/route add -host $VIP dev lo:0 ;;
stop) # Stop LVS-DR real server loopback device(s).
/sbin/ifconfig lo:0 down
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce ;;
status) # Status of LVS-DR real server.
islothere=`/sbin/ifconfig lo:0 | grep $VIP`
isrothere=`netstat -rn | grep "lo:0" | grep $VIP`
if [ ! "$islothere" -o ! "isrothere" ];then
# Either the route or the lo:0 device
# not found.
echo "LVS-DR real server Stopped."
else
echo "LVS-DR real server Running."
fi
;;
*)
# Invalid entry.
echo "$0: Usage: $0 {start|status|stop}"
exit 1
;;
esac

HA

概述

什么是高可用 常用的HA: heartbeat ha_resources crm pacemaker corosync(openais) cman rgmanager keepalived: ipvs() MTBF = mean time between failures MTTR = mean time to repair

A= MTBF/(MTBF+MTTR)

Hardware Failure Causes:

  • Design failure
  • Random failure
  • Infant Mortality
  • Wear Out

Cluster 选项

Option Default Description
batch-limit 30 The number of jobs that the TE is allowed to execute in parallel.
no-quorum-policy stop What to do when the cluster does not have quorum: 1. Ignore 2. Freeze 3 . Stop 4. suicde
Symmetric-cluster Ture Call all resources run on any node by default
stonith-enabled Ture If enable stonith function
cluster-delay 60s Round trip delay over the ne
stonith-action reboot Action to send to STONITH device

顺序约束属性

Field Description
id A unique name for constraint
first 在then的资源前开启
then 在first之后启动的资源
score 资源得分
symmetrical 启动次序与关闭次序reverse

排列约束

Field Description
id A unique name for the constraint
rsc The colocation source. If the constraint cannot be satisfied, the cluster may decide not to allow the resource to run at it
with-rsc The colocation target. From 'rsc to 'with-rsc'
score 资源得分

Primitive Resource

Field Description
id The resouce name
class Heartbeat; lsb; ocf; stonith
type RA名字 eg: IPaddr or FIlesystem
provider ocf:heartbeat 给不同的vendor提供相同的RA

资源属性

Field Default Description
priority 0 如果所有资源无法都启动,则根据优先级来启动资源
target-role Started 集群中保持资源的状态 1. Started 2. Stopped 3. Master
is-managed TRUE 集群是否允许管理资源
resource-stickiness Inherited rsc_defaults section中可以设置资源粘性
migration-threshold 0(disabled) 迁移失败尝试门限
failure-timeout 0(disabled) 发生错误的超时时间

资源操作(Resource Operations)

Field Description
Interval 执行时间间隔
timeout 超时间隔
requires 资源满足条件才能运行 1. nothing 2. quorum 3. fencing
on-fail 资源发生错误时 1. ignore 2. block 3. stop 4. fence 5. standby default is fence

Linux HA Cluster: ha_aware: 非ha_aware: 三个层次:

  • Messaging Infrastructure
  • Resource Allocation
  • Resource

DC: Designated Coordinator CRM: Cluster Resources Manager LRM: Local Resources Manager CIB: Cluster Information Base (XML 文件) PE: Policy Engine 高可用集群中,任何资源都不应该自行启用,而是由CRM管理启动与否 RA:resource agent {start|stop|restart|status} status: running: 运行 stopped: 停止 failover: 失效转移,故障转移 failback: 失效转回,故障转回 Messaging Layer: 信息层 heartbeat v1,v2,v3 OpenAIS: 定义开放的HA组织架构 corosync: 底层心跳信息传递的层次 cman: cluster manager 集群管理器

CRM

heartbeat v1: haresources (配置接口:配置文件,文件名也叫作haresources) heartbeat v2: crm(各节点均运行进程crmd,客户端crm(shell),heartbeat-GUI) heartbeat v3: heartbeat + pacemaker+ cluster-glue: pacemaker: 配置接口: CLI: crm(SuSE开发), pcs(红帽) GUI: hawk, LCMC, pacemaker-mgmt cman + rgmanager: resource group manager: Failover Domain 配置接口:clusteradmin cmanadmin RHCS: Redhat Cluster Suite 配置接口:Conga(完全生命命令周期的配置接口) RHEL 6.5 use CMAN+PaceMaker+Corosync. To config CMAN use ccs, and use ricci for replicate settings of file cluster.conf to all nodes; and use pcs to config resource on pacemaker RHEL 7 uses PaceMaker+Corosync with pcs config cluster and resource, and pcsd to replicate setting nodes. Conga:集群的全生命周期管理工具。依赖ricci+luci

RA

RA类型: 1、heartbeat legacy: heartbeat的传统类型 2、LSB: /etc/rc.d/init.d/* Linux standard base 3、OCF: Open Cluster Framework 开放集群框架 provider:pacemaker linbit 4、STONITH: shoot the other node in the head keepalived: vrrp keepalived + ipvs keepalived + haproxy

RHEL OR CentOS高可用集群解决方案

RHEL5: 自带: RHCS(cman + rgmanager) 选用第三方:corosync + pacemaker, heartbeat v1/v2, keepalived RHEL6: 自带:RHCS(cman + rgmanager) corosync + rgmanager cman + pacemaker heartbeat v3 + pacemaker keepalived 应用方式: 做前端负载均衡器的高可用:keepalived 做大规模的高用集群:corosync(cman) + pacemaker gracious ARP: 欺骗式的ARP,通过广播报文自问自答通知广播域中的主机更新arp表

资源争用

votes; total; qurom(满足合法人数) 资源隔离: 节点级别: STONITH eg. 电源交换机,通过网线连接控制服务器重启.很多专业的服务器都有控制芯片可以控制服务器关机重启 HA节点数:大于2,且总数为奇数。放置Brain-split 若两节点的HA场景,应设置gw作为ping node(仲裁设备), 使二者ping gw node来判定。多个ping节点称为ping group 红帽使用共享存储的方式来作为仲裁设备(仲裁盘) qdisk

安装配置高可用集群heartbeat

1、节点名称:集群每个节点的名称都得能够互相解析 hosts中主机名的正反解析结果必须跟“uname -n"的结果保持一致 2、时间必须同步 使用网络时间服务器同步时间 3、各节点间能基于ssh密钥认证(最好) 多节点集群,自动化运维工具 ansible fabric puppet 安装heartbeat v1

yum install perl-TimeDate PyXML libnet libtool-ltdl-devel net-snmp-libs
rpm -ivh heartbeat-2.1.4-12.el6.x86_64.rpm heartbeat-pils-2.1.4-12.el6.x86_64.rpm heartbeat-stonith-2.1.4-12.el6.x86_64.rpm

HMAC:使用消息认证码进行消息传递 crc md5 sha1

heartbeat: 监听在udp的694端口 配置样本在/usr/share/doc/heartbeat-xx-xx/ha.cf

cp /usr/share/doc/heartbeat-xx-xx/ha.cf authkeys haresources /etc/ha.d/

/usr/share/heartbeat/ 存有一些有用的脚本

产生随机密码并配置authkeys

openssl rand -hex 8
in authkeys:
auth 2
2 sha1 df67e71df88aa222
chmod 600 /etc/ha.d/authkeys

ha.cf配置文件

logfile	/var/log/ha-log
keepalive 1000ms
deadtime 8
warntime 4
initdead 60
udpport 694
mcast eth0 225.0.100.1 694 1 0
auto_failback on
node mysql.example.com
node mysql2.example.com
ping 192.168.48.130
compression bz2
compression_threshold 2

haresource定义资源,会首先查看/etc/ha.d/resource.d/如果没有找到会其次查找/etc/rc.d/init.d/

mysql.example.com 192.168.48.135/24/eth0 Filesystem::192.168.48.133:/www/htdocs::/var/www/html::nfs httpd

发布配置到从节点

/usr/lib64/heartbeat/ha_propagate

配置共享存储 nfs

配置/etc/exports
/www/htdocs 192.168.48.0/24(rw)
/mydata 192.168.48.0/24(rw,no_root_squash)
##no_root_squash 不压缩root权限,使得root有写权限
安装nfs
yum install portmap nfs-utils
开启nfs服务
service rpcbind start
service nfs start
查看nfs共享
showmount -e Server_IP
exportfs

重新分享nfs服务资源

exportfs -rav

Fencing:

  • 外部fence设备

    • 电源交换机
    • SAN交换机
  • 内部fence设备

  • IBM RSAII

  • HP iLO

HA集群的工作模型:

A/P:主备模型,two nodes N-M: N > M,N各节点,M个服务:活动节点为N,备用N-M个 N-N: N各节点N各服务 A/A: 双主模型,各自运行不同的服务,互为彼此冗余 资源转移的方式: rgmanager: failover domain 故障转移域,priority

资源粘性与约束

资源黏性:如果所有节点的位置约束都一样,若黏性为正值则更倾向于留在当前节点,如果黏性为负值,则更倾向于离开 资源约束(3种类型): 1、位置约束:资源更倾向于哪个节点上; inf: 无穷大 n: 数值倾向性 -n: 离开倾向性 -inf: 负无穷 2、 排列约束:资源运行于同一节点的倾向性 inf: 相濡以沫 -inf: 相忘于江湖 3、 顺序约束:明确定义资源的启动次序及关闭次序,一般而言先启动的后关闭 案例:如何让web service中的三个资源:vip、httpd及filessystem运行于同一节点上? 1、排列约束: 2、资源组(resource group)

资源释放

如果节点不再是集群节点成员时,如何处理运行在当前节点的资源? stopped:将节点停掉 ignore:忽略当前节点是否为节点成员 freeze:已经连接进来的请求将继续处理,但是新的请求不予以处理 suicide:将节点kill掉 一个资源刚配置完成时,是否启动? target-role: 目标角色来指定是否启动

资源类型

1、primitive, native: 主资源,只能运行于一个节点 2、resource group: 组资源 3、clone: 克隆资源: 总克隆数:每个节点罪过可运行的克隆数 4、master/slave: 主从资源

Heartbeat V2

运行于备用主机上的Heartbeat可以通过以太网连接检测主服务器的运行状态,一旦其无法检测到主服务器的“心跳”则自动接管主服务器的资源。通常情况下,主、备服务器间的心跳连接是一个独立的物理连接,这个连接可以是串行线缆、一个由“交叉线”实现的以太网连接。Heartbeat甚至可同时通过多个物理连接检测主服务器的工作状态,而其只要能通过其中一个连接收到主服务器处于活动状态的信息,就会认为主服务器处于正常状态。从实践经验的角度来说,建议为Heartbeat配置多条独立的物理连接,以避免Heartbeat通信线路本身存在单点故障。

1、串行电缆:被认为是比以太网连接安全性稍好些的连接方式,因为hacker无法通过串行连接运行诸如telnet、ssh或rsh类的程序,从而可以降低其通过已劫持的服务器再次侵入备份服务器的几率。但串行线缆受限于可用长度,因此主、备服务器的距离必须非常短。 2、以太网连接:使用此方式可以消除串行线缆的在长度方面限制,并且可以通过此连接在主备服务器间同步文件系统,从而减少了从正常通信连接带宽的占用。

基于冗余的角度考虑,应该在主、备服务器使用两个物理连接传输heartbeat的控制信息;这样可以避免在一个网络或线缆故障时导致两个节点同时认为自已是唯一处于活动状态的服务器从而出现争用资源的情况,这种争用资源的场景即是所谓的“脑裂”(split-brain)或“partitioned cluster”。在两个节点共享同一个物理设备资源的情况下,脑裂会产生相当可怕的后果。 为了避免出现脑裂,可采用下面的预防措施: 1、如前所述,在主、备节点间建立一个冗余的、可靠的物理连接来同时传送控制信息; 2、一旦发生脑裂时,借助额外设备强制性地关闭其中一个节点;

第二种方式即是俗称的“将其它节点‘爆头’(shoot the other node in the head)”,简称为STONITH。基于能够通过软件指令关闭某节点特殊的硬件设备,Heartbeat即可实现可配置的Stonith。但当主、备服务器是基于WAN进行通信时,则很难避免“脑裂”情景的出现。因此,当构建异地“容灾”的应用时,应尽量避免主、备节点共享物理资源。

Heartbeat的控制信息: “心跳”信息: (也称为状态信息)仅150 bytes大小的广播、组播或多播数据包。可为以每个节点配置其向其它节点通报“心跳”信息的频率,以及其它节点上的heartbeat进程为了确认主节点出节点出现了运行等错误之前的等待时间。

集群变动事务(transition)信息:ip-request和ip-request-rest是相对较常见的两种集群变动信息,它们在节点间需要进行资源迁移时为不同节点上heartbeat进程间会话传递信息。比如,当修复了主节点并且使其重新“上线”后,主节点会使用ip-request要求备用节点释放其此前从因主节点故障而从主节点那里接管的资源。此时,备用节点则关闭服务并使用ip-request-resp通知主节点其已经不再占用此前接管的资源。主接点收到ip-request-resp后就会重新启动服务。

重传请求:在某集群节点发现其从其它节点接收到的heartbeat控制信息“失序”(heartbeat进程使用序列号来确保数据包在传输过程中没有被丢弃或出现错误)时,会要求对方重新传送此控制信息。 Heartbeat一般每一秒发送一次重传请求,以避免洪泛。

上面三种控制信息均基于UDP协议进行传送,可以在/etc/ha.d/ha.cf中指定其使用的UDP端口或者多播地址(使用以太网连接的情况下)。

此外,除了使用“序列号/确认”机制来确保控制信息的可靠传输外,Heartbeat还会使用MD5或SHA1为每个数据包进行签名以确保传输中的控制信息的安全性。

资源脚本:

资源脚本(resource scripts)即Heartbeat控制下的脚本。这些脚本可以添加或移除IP别名(IP alias)或从属IP地址(secondary IP address),或者包含了可以启动/停止服务能力之外数据包的处理功能等。通常,Heartbeat会到/etc/init.d/或/etc/ha.d/resource.d/目录中读取脚本文件。Heartbeat需要一直明确了解“资源”归哪个节点拥有或由哪个节点提供。在编写一个脚本来启动或停止某个资源时,一定在要脚本中明确判断出相关服务是否由当前系统所提供。

Heartbeat的配置文件: /etc/ha.d/ha.cf 定义位于不同节点上的heartbeat进程间如何进行通信; /etc/ha.d/haresources 定义对某个资源来说哪个服务器是主节点,以及哪个节点应该拥有客户端访问资源时的目标IP地址。 /etc/ha.d/authkeys 定义Heartbeat包在通信过程中如何进行加密。

当ha.cf或authkeys文件发生改变时,需要重新加载它们就可以使用之生效;而如果haresource文件发生了改变,则只能重启heartbeat服务方可使之生效。

Heartbeat当前也不监控其所控制的资源的状态,比如它们是否正在运行,是否运行良好以及是否可供客户端访问等。要想监控这些资源,冉要使用额外的Mon软件包来实现。

haresources配置文件介绍: 主从节点上的/etc/ra.d/raresource文件必须完全相同。文件每行通常包含以下组成部分: 1、服务器名字:指正常情况下资源运行的那个节点(即主节点),后跟一个空格或tab;这里指定的名字必须跟某个节点上的命令"uname -n"的返回值相同; 2、IP别名(即额外的IP地址,可选):在启动资源之前添加至系统的附加IP地址,后跟空格或tab;IP地址后面通常会跟一个子网掩码和广播地址,彼此间用“/”隔开; 3、资源脚本:即用来启动或停止资源的脚本,位于/etc/init.d/或/etc/ha.d/resourcd.d目录中;如果需要传递参数给资源脚本,脚本和参数之间需要用两个冒号分隔,多个参数时彼此间也需要用两个冒号分隔;如果有多个资源脚本,彼此间也需要使用空格隔开;

格式:

primary-server [IPaddress[/mask/interface/broadcast]]  resource1[::arg1::arg2]  resource2[::arg1::arg2]
eg.
primary-server 221.67.132.195 sendmail httpd

安装配置Heartbeat

 yum install

cp /usr/share/doc/heartbeat-2*/authkeys, ha.cf, haresources

( echo -ne "auth 1\n1 sha1 "; \
dd if=/dev/urandom bs=512 count=1 | openssl md5 ) \
> /etc/ha.d/authkeys
chmod 0600 /etc/ha.d/authkeys /usr/lib/heartbeat/ha_propagate

HA的LVS集群有两台Director,在启动时,主节点占有集群负载均衡资源(VIP和LVS的转发及高度规则),备用节点监听主节点的“心跳”信息并在主节点出现异常时进行“故障转移”而取得资源使用权,这包括如下步骤:

1、添加VIP至其网络接口;
2、广播GARP信息,通知网络内的其它主机目前本Director其占有VIP;
3、创建IPVS表以实现入站请求连接的负载均衡;
4、Stonith;

弃用resource脚本,改用ldirecotord来控制LVS: ldirectord用来实现LVS负载均衡资源的在主、备节点间的故障转移。在首次启动时,ldirectord可以自动创建IPVS表。此外,它还可以监控各Realserver的运行状态,一旦发现某Realserver运行异常时,还可以将其从IPVS表中移除。 ldirectord进程通过向Realserver的RIP发送资源访问请求并通过由Realserver返回的响应信息来确定Realserver的运行状态。在Director上,每一个VIP需要一个单独的ldirector进程。如果Realserver不能正常响应Directord上ldirectord的请求,ldirectord进程将通过ipvsadm命令将此Realserver从IPVS表中移除。而一旦Realserver再次上线,ldirectord会使用正确的ipvsadm命令将其信息重新添加至IPVS表中。 例如,为了监控一组提供web服务的Realserver,ldirectord进程使用HTTP协议请求访问每台Realserver上的某个特定网页。ldirectord进程根据自己的配置文件中事先定义了的Realserver的正常响应结果来判断当前的返回结果是否正常。比如,在每台web服务器的网站目录中存放一个页面".ldirector.html",其内容为"GOOD",ldirectord进程每隔一段时间就访问一次此网页,并根据获取到的响应信息来判断Realserver的运行状态是否正常。如果其返回的信息不是"GOOD",则表明服务不正常。 ldirectord需要从/etc/ha.d/目录中读取配置文件,文件名可以任意,但建议最好见名知义。 实现过程:

创建/etc/ha.d/ldirectord-192.168.0.219.cf,添加如下内容: // Global Directives checktimeout=20
// ldirectord等待Realserver健康检查完成的时间,单位为秒;
// 任何原因的检查错误或超过此时间限制,ldirector将会将此Realserver从IPVS表中移除;
checkinterval=5
// 每次检查的时间间隔,即检查的频率;
autoreload=yes
// 此项用来定义ldirectord是否定期每隔一段时间检查此配置文件是否发生改变并自动重新加载此文件;
logfile="/var/log/ldirectord.log"
// 定义日志文件存放位置;
quiescent=yes
// 当某台Realserver出现异常,此项可将其设置为静默状态(即其权重为“0”)从而不再响应客户端的访问请求;

// For an http virtual service
virtual=192.168.0.219:80
// 此项用来定义LVS服务及其使用的VIP和PORT

real=192.168.0.221:80 gate 100
# 定义Realserver,语法:real=RIP:port gate|masq|ipip [weight]
real=192.168.0.223:80 gate 300
fallback=127.0.0.1:80 gate
# 当IPVS表没有任何可用的Realserver时,此“地址:端口”作为最后响应的服务;
# 一般指向127.0.0.1,并可以通过一个包含错误信息的页面通知用户服务发生了异常;
service=http
# 定义基于什么服务来测试Realserver;
request=".ldirectord.html"
receive="GOOD"
scheduler=wlc
#persistent=600
#netmask=255.255.255.255
protocol=tcp
# 定义此虚拟服务用到的协议;
checktype=negotiate
# ldirectord进程用于监控Realserver的方法;{negotiate|connect|A number|off}
checkport=80

在/etc/hd.d/haresources中添加类似如下行:

node1.example.com 192.168.0.219
ldirectord::ldirectord-192.168.0.219.cf

使用/usr/lib64/heartbeat/haresource2cib.py 文件来转换haresource文件格式到cib的形式(xml) 开启crm功能

crm respawn/crm on 				#ha.cf文件

安装heartbeat-gui

yum install pygtk2-libglade
开启X11需要安装
yum install xorg-x11-xauth

防止xmanager显示乱码,需要安装xorg库

yum install xorg-x11-font*

CRM用于实现管理来接受用户的连接命令并实现当前集群配置的API服务接口就是mgmtd,于是我们将获得一些CRM命令

查看集群状态

crm_mon

with quorum:满足法定票数

without quorum: 不满足法定票数

防止active/standby模型中有节点离线导致without quorum的场景出现,可以做如下配置

crm configure property no-quorum-policy=ignore

实验:

web server: VIP 192.168.48.140 httpd nfs: /www/htdocs, /var/www/html

ipvs: director vip ipvsadm

heartbeat为director专门提供了组件ldirectord

安装Idirectord

yum install heartbeat-ldirectord-2.1.4-12.el6.x86_64.rpm
cp /usr/share/doc/heartbeat-ldirectord-2.1.4/ldirectord.cf /etc/ha.d/

配置HA服务

服务组成:vip, service, store

服务内的素有资源应该同时运行同一个节点:

​ 资源组

​ 排列约束

Ansible

Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine. OS Provisioning PXE, cobbler OS config cfengine, puppet, saltstack, chef Deployment func(SSL) Fabric(ssh) ansible YAML: Yet another Markable Language

安装

编译安装

yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible

rpm安装

配置

因为ansible是基于ssh的集群配置,首先要对所有主机进行ssh-key交换

ssh-keygen -t rsa -P ''
ssh-copy-id -i .ssh/id_rsa.pub root@mysql

执行ansible

syntax:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
eg.
ansible all -m ping
默认模块是command,命令模块
ansible all -a 'date'

查看ansible所有支持模块

ansible-doc -l

查看指定模块可以使用的参数

ansible-doc -s [module_name]
eg.
ansible-doc -s COPY
ansible webservers -m copy -a "src=~/shell_script/showsum.sh dest=/tmp/"

定义crontab任务

ansible webservers -m cron -a 'name="custom job" minute=*/3 hour=* day=* month=* weekday=* job="/usr/sbin/utpdate 192.168.48.130"'

执行yum安装

ansible all -m yum -a "state=present name=corosync" 

使用shell解析

ansible all -m shell -a "date;echo hello"

执行service脚本

ansible all -m service -a 'state=started name=httpd enabled=yes' 

YAML

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。

特点:

  • YAML的可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现
  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

语法

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。下面是一个示例

更多语法参考规范http://www.yaml.org

name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age 13
gender: Female

YAML文件扩展名通常为.yaml

playbook 示例

- hosts: webnodes
vars:
http_port: 80
max_clients: 256
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted

Tasks,任务列表和action

定义task的时候可以使用“action: module options" 或者 ”modules: options"的格式,推荐使用后者以实现向后兼容。

name: make sure apache is running
service: name=httpd state=running

在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如:

tasks:
- name: disable selinux
command: /sbin/setenforce 0

如果命令或脚本的退出码不为零,可以使用如下方式替代:

tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true

或者使用ignore_errors来忽略错误信息:

tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True

Handler:

用于当关注的资源发生变化时采取一定的操作。

“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache

handler是task列表,这些task与前述的task并没有本质上的不同。

handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted

配置示例

- hosts: all
remote_user: root
tasks:
- name: ensure apache latest version
yum: state=latest name=httpd
- name: apache configure file
copy: src=/etc/ansible/httpd.conf dest=/etc/httpd/conf/httpd.conf force=yes
notify:
- restart httpd
handlers:
- name: restart httpd
service: name=httpd state=restarted

Heartbeat的任务清单

- hosts: hbhosts
remote_user: root
tasks:
- name: ensure heartbeat latest version
yum: name=heartbeat state=present
- name: authkeys configure file
copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
- name: authkeys modes 600
file: path=/etc/ha.d/authkeys mode=600
notify:
- restart heartbeat
- name: ha.cf configure file
copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
notify:
- restart heartbeat
handlers:
- name: restart heartbeat
service: name=heartbeat state=restarted

Corosync && Pacemaker

Background

AIS: 应用接口规范,定义应用接口(API) AIS 就是一个通用的应用程序编程接口,OpenAIS是AIS的子项目,标准的集群框架的应用程序接口规范,而corosync是OpenAIS是具体实现 Pacemaker是从heartbeatv3分离出来的子项目, 单独作为作为资源管理器。 Pacemaker 接口工具:

CLI: crmsh pcs (pcs+pcsd) GUI: haw LCMC pyGUI Conga

RHCS: cman, rgmanager, conga corosync目前维护两个版本。1版本和2版本。 1版本本身不提供投票功能votes 2版本之后提供了votequorum子系统,具备了votes能力 cman+rgmanager, cman+pacemaker, corosync+pacemaker 趋势是使用pacemaker作为资源管理器,底层使用cman还是corosync可根据需求来提供

配置实例

前提: 1)本配置共有两个测试节点,分别node1.example.com和node2.example.com,相的IP地址分别为192.168.48.137和192.168.48.138; 2)集群服务为apache的httpd服务; 3)提供web服务的地址为192.168.48.141,即vip; 4)系统为CentOS 6.4 64bits

配置主机名称

#node1
sed -i 's@\(HOSTNAME=\).*@\1node1.example.com@g' /etc/sysconfig/network
hostname node1.example.com
#node2
sed -i 's@\(HOSTNAME=\).*@\1node2.example.com@g' /etc/sysconfig/network
hostname node2.example.com

配置corosync

安装corosync和pacemaker

yum install corosync pacemaker

编辑corosync.conf 添加如下内容: note: version 0是以插件的形式启动pacemaker,centos6.7中这种形式就有很大的问题,所以我使用version 1,之后再单独启动pacemaker服务

service {
ver: 1
name: pacemaker
}
aisexec {
user: root
group: root
}

bindnetaddr后面的IP地址是网卡所在的网络地址 mcastaddr: 定义组播IP

安装crmsh

由于RHEL6以后就已经不提供crmsh,需要寻找其他途径来进行安装

wget http://download.opensuse.org/repositories/network:/ha-clustering:/Stable/CentOS_CentOS-6/noarch/crmsh-2.2.1-1.2.noarch.rpm
wget http://download.opensuse.org/repositories/network:/ha-clustering:/Stable/CentOS_CentOS-6/x86_64/pssh-2.3.1-4.2.x86_64.rpm
wget http://download.opensuse.org/repositories/network:/ha-clustering:/Stable/CentOS_CentOS-6/noarch/crmsh-scripts-2.2.1-1.2.noarch.rpm
wget http://download.opensuse.org/repositories/network:/ha-clustering:/Stable/CentOS_CentOS-6/noarch/python-parallax-1.0.1-14.1.noarch.rpm rpm -ivh crmsh-scripts-2.2.1-1.2.noarch.rpm
rpm -ivh python-parallax-1.0.1-14.1.noarch.rpm
rpm -Uvh crmsh-2.2.1-1.2.noarch.rpm

the other way...

cd /etc/yum.repos.d/
wget http://download.opensuse.org/repositories/network:/ha-clustering:/Stable/CentOS_CentOS-6/network:ha-clustering:Stable.repo
yum -y install crmsh
yum -y install pssh

产生authkey

corosync-keygen
自动在/etc/corosync/下生成

开启corosync服务

servcie corosync start

查看corosync引擎是否正常启动

grep -e "Corosync Cluster Engine" -e "configuration file" /var/log/cluster/corosync.log 

查看初始化成员通知是否正常发出:

grep TOTEM /var/log/cluster/corosync.log

检查启动过程中是否有错误产生。下面的错误信息表示packmaker不久之后将不再作为corosync的插件运行,因此,建议使用cman作为集群基础架构服务;此处可安全忽略。

查看ERROR

grep ERROR: /var/log/cluster/corosync.log | grep -v unpack_resources

查看pacemaker是否正常启动

grep pcmk_startup /var/log/cluster/corosync.log

Crmsh

查看集群状态

crm status

配置全局属性来禁用stonith

corosync默认开启了stonith,但是测试环境集群没有响应的stonith设备,因此此默认配置目前尚不可用。

crm configure property stonith-enabled=false

property 保存全局属性

配置模式

crm configure
//查看配置信息
crm confiugre show
//查看详细cib资源配置
crm configure show xml
//验证配置语法
crm configure verify
//提交配置
commit
//直接修改配置文件
edit

pacemaker命令行管理查询

如果开启了stonith信息,则可以看到相关报错

crm_verify -L -V

查看RA,定义资源

查看可支持的RA类型

crm ra classes

查看某种类别下的所有资源代理列表

crm ra list lsb
crm ra list ocf heartbeat
crm ra list ocf pacemaker
crm ra list stonith

查看资源参数

crm ra info [class:[provider:]] resource_agent
crm ra meta ocf:heartbeat:IPaddr
#带星号表示必须配置的参数,[]表示可选参数
crm ra info ocf:heartbeat:Filesystem

定义RA

定义WebIP

Syntax:
primitive <rsc> [<class>:[<provider>:]]<type>
[params attr_list]
[operations id_spec]
[op op_type [<attribute>=<value>...] ...]
op_type :: start | stop | monitor
eg.
crm configure primitive webip ocf:heartbeat:IPaddr params ip=192.168.48.140
eg.
primitive apcfence stonith:apcsmart \
params ttydev=/dev/ttyS0 hostlist="node1 node2" \
op start timeout=60s \
op monitor interval=30m timeout=60s

定义WebServer

crm configure primitive webserver lsb:httpd

定义WebService Group

crm configure group webservice webip webserver

Node Active/Standby

crm node standby node1.example.com
crm node online node1.example.com

停止/开启资源

crm resource stop webservice
crm resource status webservice

删除资源

crm configure delete webservice 

定义排列约束

syntax:
colocation <id> <score>: <rsc>[:<role>] <with-rsc>[:<role>]
eg:
crm configure colocation webserver_with_webip inf: webserver webip

定义顺序约束

syntax:
order <id> [{kind|<score>}:] first then [symmetrical=<bool>] order <id> [{kind|<score>}:] resource_sets [symmetrical=<bool>]
kind类型:Mandatory | Optional | Serialize
eg:
crm configure order webip_before_webserver Mandatory: webip webserver

定义位置约束

Syntax:
location <id> <rsc> [<attributes>] {<node_pref>|<rules>}
crm configure location webserver_on_node1 webserver 200: node1.example.com

Note: 如果有多个服务且有顺序约束,则倾向性是各个resource之和 Note: 默认情况下pacemaker不会对资源进行监控,比如程序异常关闭(kill), 在crm监控中的状态仍然是active。CRM只会监测节点状态 如果资源异常关闭,应当清理资源信息,以防止其后续出问题

crm resource cleanup [RA_name]

监测资源功能

Syntax:
monitor <rsc>[:<role>] <interval>[:<timeout>]
eg:
crm configure monitor webserver 10s:5s

也可以在定义资源的时候直接定义monitor

primitive vip ocf:heartbeat:IPaddr params ip=192.168.48.141 op monitor interval=30s timeout=20s op start timeout=20s 
配置资源粘性

如果primary的server 从down的状态返回到正常状态,有可能会产生服务从secondary的转移到primary.资源的这种在节点上每一次的来回流动都会造成那段时间内其无法被访问。所以,我们有时候需要在资源因为节点故障转移到其它节点后,即便原来的节点恢复正常也禁止资源再次流转回来。这可以通过定义资源的黏性(stickiness)来实现。在创建资源时或在创建资源后,都可以指定指定资源黏性

资源黏性值范围及其作用: 0:这是默认选项。资源放置在系统中的最适合位置。这意味着当负载能力“较好”或较差的节点变得可用时才转移资源。此选项的作用基本等同于自动故障回复,只是资源可能会转移到非之前活动的节点上; 大于0:资源更愿意留在当前位置,但是如果有更合适的节点可用时会移动。值越高表示资源越愿意留在当前位置; 小于0:资源更愿意移离当前位置。绝对值越高表示资源越愿意离开当前位置; INFINITY:如果不是因节点不适合运行资源(节点关机、节点待机、达到migration-threshold 或配置更改)而强制资源转移,资源总是留在当前位置。此选项的作用几乎等同于完全禁用自动故障回复; -INFINITY:资源总是移离当前位置

crm configure rsc_defaults resource-stickiness=100
定义资源约束

资源约束则用以指定在哪些群集节点上运行资源,以何种顺序装载资源,以及特定资源依赖于哪些其它资源。pacemaker共给我们提供了三种资源约束方法: 1)Resource Location(资源位置):定义资源可以、不可以或尽可能在哪些节点上运行; 2)Resource Collocation(资源排列):排列约束用以定义集群资源可以或不可以在某个节点上同时运行; 3)Resource Order(资源顺序):顺序约束定义集群资源在节点上启动的顺序;

1)任何值 + 无穷大 = 无穷大 2)任何值 - 无穷大 = -无穷大 3)无穷大 - 无穷大 = -无穷大 定义约束时,还需要指定分数。各种分数是集群工作方式的重要组成部分。其实,从迁移资源到决定在已降级集群中停止哪些资源的整个过程是通过以某种方式修改分数来实现的。分数按每个资源来计算,资源分数为负的任何节点都无法运行该资源。在计算出资源分数后,集群选择分数最高的节点。INFINITY(无穷大)目前定义为 1,000,000。加减无穷大遵循以下3个基本规则:

定义资源约束时,也可以指定每个约束的分数。分数表示指派给此资源约束的值。分数较高的约束先应用,分数较低的约束后应用。通过使用不同的分数为既定资源创建更多位置约束,可以指定资源要故障转移至的目标节点的顺序。

colocation This constraint expresses the placement relation between two or more resources. If there are more than two resources, then the constraint is called a resource set. Collocation resource sets have an extra attribute to allow for sets of resources which don’t depend on each other in terms of state. The shell syntax for such sets is to put resources in parentheses.

Usage:
colocation <id> <score>: <rsc>[:<role>] <rsc>[:<role>] ...
Example: colocation dummy_and_apache -inf: apache dummy
colocation c1 inf: A ( B C )

order

This constraint expresses the order of actions on two resources or more resources. If there are more than two resources, then the constraint is called a resource set. Ordered resource sets have an extra attribute to allow for sets of resources whose actions may run in parallel. The shell syntax for such sets is to put resources in parentheses.

Usage:
order <id> score-type: <rsc>[:<action>] <rsc>[:<action>] ...
[symmetrical=<bool>] score-type :: advisory | mandatory | <score>
Example: order c_apache_1 mandatory: apache:start ip_1
order o1 inf: A ( B C )

配置副本

xxxxxxxxxx
node node1.example.com \                                        
    attributes standby=off                                      
node node2.example.com                                          
primitive vip IPaddr \                                          
    params ip=192.168.48.141 \                                  
    op monitor interval=30s timeout=20s \                       
    op start timeout=20s interval=0                             
primitive webip IPaddr \                                        
    params ip=192.168.48.140                                    
primitive webserver lsb:httpd \                                 
    op monitor interval=20s timeout=15s                         
order webip_before_webserver Mandatory: webip webserver         
location webip_on_node2 webip 200: node2.example.com            
colocation webserver_with_webip inf: webserver webip            
property cib-bootstrap-options: \                               
    dc-version=1.1.11-97629de \                                 
    cluster-infrastructure="classic openais (with plugin)" \    
    expected-quorum-votes=2 \                                   
    stonith-enabled=false \                                     
    no-quorum-policy=ignore                                     
rsc_defaults rsc-options: \                                     
    resource-stickiness=100                                     

部署corosync && pacemaker 案例

使用ansible剧本安装,定义HA节点为hanodes

- hosts: hanodes			 #HA group
remote_user: root
vars: #define varibles
crmsh: crmsh-1.2.6-4.el6.x86_64.rpm
pssh: pssh-2.3.1-2.el6.x86_64.rpm
tasks:
- name: corosync installing
yum: name=corosync state=present
- name: pacemaker installing
yum: name=pacemaker state=present
- name: crmsh rpm packages
copy: src=/ansible/corosync/packages/{{ crmsh }} dest=/tmp/{{ crmsh }} #定义变量,并用双括号扩上,括号两边要留空格
- name: pssh rpm packages
copy: src=/ansible/corosync/packages/{{ pssh }} dest=/tmp/{{ pssh }}
- name: crmsh installing
command: yum -y install /tmp/{{ crmsh }} /tmp/{{ pssh }}
- name: authkey configure file
copy: src=/ansible/corosync/conf/authkey dest=/etc/corosync/authkey
- name: authkey mode 400
file: path=/etc/corosync/authkey mode=400
notify:
- restart corosync
- name: corosync.conf configure file
copy: src=/ansible/corosync/conf/corosync.conf dest=/etc/corosync/corosync.conf
tags: #打标签,可以使用直接调用标签来使用
- conf
notify:
- restart corosync
- name: ensure the corosync service startup on boot
service: name=corosync state=started enabled=yes
handlers:
- name: restart corosync
service: name=corosync state=restarted

执行剧本

ansible-playbook corsync.yaml

定义资源组及其约束

primitive webip ocf:heartbeat:IPaddr params ip=192.168.48.140 op monitor interval=30s timeout=20s on-fail=restart
primitive webstore ocf:heartbeat:Filesystem params device="192.168.48.133:/www/htdocs" directory="/var/www/html" fstype="nfs" op monitor interval=20s timeout=40s op start timeout=60s op stop timeout=60s on-fail=restart
primitive webserver lsb:httpd op monitor interval=30s timeout=20s on-fail=restart
group webservice webip webstore webserver
order webip_webstore_webserver mandatory: webip webstore webserver

PCS

查看集群状态

pcs status
property
pcs property set [--force] <property>=[<value>]
unset <property>
list|show [property] [--all | --defaults]
eg:
pcs property list --all

查看当前的配置信息

pcs cluster cib
pcs config

修改stonith-enabled

pcs property set stonith-enabled=false

修改不具备法定票数的规则

pcs property set no-quorum-policy=ignore

修改默认粘性

pcs resource defaults resource-stickness=100

显示RA类别

pcs resource standards

显示OCF的providers

pcs resource providers

显示某类别下的所有RA

pcs resource agents [stantard[:provider]]
pcs resource agents ocf:heartbeat

查看某个resource的属性信息

pcs resource describe <class:provider:type|type>
pcs resource describe ocf:heartbeat:IPaddr

查看资源

pcs resource show

定义资源

定义webip

pcs resource create webip ocf:heartbeat:IPaddr ip=192.168.48.140 op monitor interval=30s timeout=20s

定义webstore

pcs resource create webstore ocf:heartbeat:Filesystem device="192.168.48.130:/www/htdocs" directory="/var/www/html" fstype="nfs" op monitor interval=30s timeout=20s op start timeout=60s op stop timeout=60s 

定义webserver

pcs resource create webserver lsb:httpd op monitor interval=30s timeout=20s on-fail=restart

定义组

pcs resource group add webservice webip webstore webserver 

Standby Active node

pcs cluster standby node1.example.com 

查看约束

pcs constraint list --full 

顺序约束

pcs constraint order set webip webstore webserver 

位置约束

pcs constraint location add webservice_on_node1 webservice node1.example.com 500  

排列约束

pcs constraint colocation set webip webstore webservice 

删除资源

pcs resource delete webservice 

资源迁移

pcs resource move webip 

DFS

概率

数据采集, 数据存储, 数据搜索, 数据共享, 数据传输, 数据分析, 数据可视化 纵向扩展受阵列空间限制, 横向扩展受交换设备限制 节点受文件系统限制 多线程与进程的执行模式 互不通信的多线程模式 基于共享容器协同的多线程模式 通过事件协同的多线程模型 A: 1-->2-->3 B: 1-->2-->3 输入设备的变化 控制器的变化: 透明代理 旁路代理 名称服务 规则服务器 运算器的变化: 存储器的变化: 代理模型 名称服务 规则服务器 Master 分布式系统的难点: 缺乏全局时钟 面对故障的独立性 处理单点故障 冗余 降低单点故障的影响范围 事物的挑战 ACID 2PC(两段式提交), 最终一致, BASE法则, CAP理论, Paxos算法

分布式文件系统设计目标

  • 访问透明
  • 位置透明
  • 并发透明
  • 失效透明
  • 硬件透明
  • 可扩展性
  • 复制透明
  • 迁移透明

Scalable: Looking at storage and serving infrastructures Reliable: Looking at redundancy, failure rates, on the fly changes Cheap: Looking at upfront costs, TCO and lifetimes

分布式事务的模型和规范

X/Open: XA DTP: Distributed Transaction Process Reference Module 定义了三个组件: AP: Application Program, 应用程序 RM: Resource Manager, 资源管理器 TM: Transaction Manager, 事务管理器 事务管理器注册管理资源管理器 两段式提交

  1. Prepare 2. Commit

CAP理论

C: Consistency A: Availability P: Tolerance of network Partition

三者不可能同时达成 关注一致性, 就需要处理因为系统不可用而导致的写操作失败的情况 关注可用性, 就应该知道系统的read操作可能不能精确的读取到write操作写入的最新值 CA: 传统关系型数据库 AP: key-value数据库

BASE

BA: Basically Available, 基本可用 S: Soft state, 软状态, 接受一段时间内的状态不同步 E: Eventually consistent: 最终一致性 强一致性: ACID在单机场景可以使用数据库事务来保证, 在分布式事务中很难实现 弱一致性: 延迟一致性,

Paxos协议

作者花了十年时间...拜占庭将军问题: 通信条件不安全 比2PC提交更轻量级的分布式协调方式

集群内数据一致性算法实施过程案例:

Quorum, Vector Clock Quorum: N: 数据复制的节点量 R: 成功读操作所依赖的最少节点数 W: 成功写操作所以来的最少节点数 W+R >N: 强一致性

分布式应用

分布式计算: MapReduce: 分布式运算框架 开源实现: MapReduce(Java实现) 分布式存储: GFS, Google File System 元数据放在服务器的内存中, 适合存储少量大文件的数据, 不适合海量小数据 开源实现: HDFS(Java实现) KV BigTable: 利用GFS的存储机制, 实现了列式数据库, 底层是GFS. NoSQL的表现之一 HBase: 开源组织clone HADOOP: MapReduce + GFS (山寨的google产品, 基于google提供的论文)

分布式存储

分布式存储和分布式文件系统区别 分布式存储不可mount, 基于API进行存储 文件系统可mount, 基于VFS接口, 直接读写数据 适合存储少量大文件: GFS HDFS TFS: 在名称节点上将元数据存储于关系型数据库中, 文件数量不再受限于名称节点的内存空间, 可以存储海量小文件 Lustre: 企业级应用, 非常重量级 GlusterFS: 适合存储PB级别企业数据 MooseFS: 基于FUSE的方式, 可以实现挂载, 轻量级的分布式存储文件系统 MogileFS: 使用Perl语言开发. 非常适合存储海量小图片, 元数据存储在MySQL中. 早期没有FUSE接口. 可以基于插件实现挂载, 豆瓣, 一号店,大众点评 FastDFS: MogileFS C语言实现的clone版

MogileFS

特性

应用层: 无单点: (tracker, mogstore, database(MySQL)) 自动文件复制: 复制的最小单位不是文件, 而是class 传输中立, 无特殊协议: 可以通过NFS或HTTP进行通信 简单的命名空间: 没有文件目录, 通过域(domain)来区分存储来源 不共享任何数据 Tracker: 负责存储元数据, MogilFS的核心, 是一个调度器: 服务进程为mogilefsd; 职责: 删除, 复制, 监控, 查询等. 查询基于HTTP. 工作在旁路模型 Database: mogstored: 数据存储的位置, 通常是一个HTT(WebDAV)服务器, 用来数据的创建, 删除, 获取 fid: fileID, 通常为文件名. /a/b/filename.000000.fid(value) /a/a/1.jpg 键

CPAN

Perl 综合典藏网. Perl编译安装:

1 . make Makefile.PL
2 . make
3 . make test
4 . make install

安装

准备

yum -y install make gcc unzip perl-DBD-MySQL perl perl-CPAN perl-YAML perl-Time-HiRes

cpan App::cpanminus MogileFS::Server MogileFS::Utils IO::AIO IO::WrapTie Danga::Socket

初始化数据库

授权访问

GRANT ALL ON mogilefs.* TO 'moguser'@'HOSTNAME' IDENTIFIED BY 'mogpass'

创建数据库

mogdbsetup --dbhost=localhost --dbport=3306 --dbname=mogilefs --type=MySQL --dbrootuser=ro
ot --dbrootpass=nsadm --dbuser=moguser --dbpass=mogpass

创建目录

mkdir /var/run/mogilefsd/
chown -R mogilefs.mogilefs /var/run.mogilefsd

安装mogstored

- hosts: rhcs
remote_user: root tasks:
- name: copy the mogiles rpm
copy: src=/etc/ansible/mogileFS/ dest=~/mogileFS/ force=yes
- name: install the packages
shell: chdir=~/mogileFS yum install -y *
- name: create mkdir /dfs/mogdata
shell: mkdir /dfs/mogdata -pv
- name: change right
shell: chown -R mogilefs.mogilefs /dfs/mogdata
- name: change mogestored.conf
shell: sed -i 's@docroot = \/var\/mogdata@docroot=/dfs/mogdata/@' /etc/mogilefs/mogstored.c
onf
- name: yum install perl-IO-AIO
yum: state=present name=perl-IO-AIO
- name: start mogstored service
service: state=started name=mogstored enabled=yes

配置mogilefs

mogadm --trackers=192.168.48.131:7001 check

查看主机

mogadm --trackers=192.168.48.131:7001 host list

添加主机

mogadm --trackers=192.168.48.131:7001 host add node2 --ip=192.168.48.132 --status=alive

查看设备

mogadm --trackers=192.168.48.131:7001 device list

添加设备

mogadm --trackers=192.168.48.131:7001 device add node2 001

查看domain

mogadm --trackers=192.168.48.131:7001 domain list

上传文件

mogupload --trackers=192.168.48.131:7001 --domain=files -key="/fstab.html" --file="/etc/fstab"

查看文件内容

moglistkeys --trackers=192.168.48.131:7001 --domain=files

查看文件的访问路径

mogfileinfo --trackers=192.168.48.131:7001 --domain=files --key='/fstab.html'

手动使某host下线

mogadm --trackers=192.168.48.131:7001 host mark node3 down

应用示例

http://grid.net.ru/nginx/mogilefs.en.html

node1: reverse proxy node2-node4: mogileFS mysql: mysqlserver

安装nginx

./configure \
--prefix=/usr \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
--http-uwsgi-temp-path=/var/tmp/nginx/uwgi \
--http-scgi-temp-path=/var/tmp/nginx/scgi \
--with-pcre \
--with-debug \
--add-module=../nginx_mogilefs_module-1.0.4

nginx.conf

upstream mogcluster {
server 192.168.48.132:7001;
server 192.168.48.138:7001;
server 192.168.48.137:7001;
}
server ....
location /images/ {
mogilefs_tracker mogcluster;
mogilefs_domain images;
mogilefs_noverify on;
mogilefs_methods GET PUT DELETE;
# mogilefs_class default class0 class1 class2 class3
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}

mogilefs会使用uri的basename来进行key值匹配. 如果想以路径为匹配条件则可以使用括号扩起匹配的内容(分组匹配) 然后在mogilefs_pass $1 中引用即可

mogstats

mogstats --config=/etc/mogilefs/mogilefsd.conf

存储

存储类型

DAS: 直接附加存储 Direct Attached Storage.

​ 直连主机的总线上来的设备

硬盘接口:

  • IDE(ATA) 并行接口
  • SATA 串行接口
  • SCSI 并行接口 (small computer system interface)
  • SAS 串行接口
  • USB
Device Interface Rate
IDE(ATA) 133MB/s
SATA SATA2: 300MB/s SATA3: 600MB/s
SAS 6Gbps
SCSI 640MB/s
USB USB3.0 480MB/s

HBA: 主机适配器,Adapter NAS:Network Attached Storage 文件服务器:文件系统级别 文件共享服务器,共享级别为file,而非filesystem 对于本机而言,直接附加存储看起来是块设备文件,但是NAS本身就是文件系统,访问接口是文件API SAN: Storage Area Network 存储区域网络 把SCSI协议借助于其他网络协议实现传送 窄总线SCSI设备有一个控制器可以连7块硬盘。 最后一个块硬盘要使用终结器终结 8,7 一般第七个作为终结器 宽总线SCSI设备 16,7 一般也是第七个作为终结器 管理的总线称为 initiator, 目标的存储设备为Target 借助Internet传输SCSI传输机制

  • FC
  • FCoE(Cisco)
  • iSCSI

Target并非需要是SCSI设备。但是对于主机而言,SAN设备是块设备

DRBD

Distributed Replicated Block Device 这种解决方案能够让本身不具备复制能力的数据直接在内核级别就能够完成数据的传输复制,不再依赖于应用程序自身就能够完成 2.6.33之后就被收纳进入内核的源代码树,drbd是内核的一种功能 Disk Scheduler: 磁盘调度器:将多个写操作合并成一起处理,并从新排序。可以减少磁盘中的磁头移动,提高操作效率

  • CFQ 完全公平队列
  • Deadline 最后期限
  • 期望
  • No OP 不做任何操作(固态硬盘没有寻道损耗)

Buffer Cache ----> DRBD ----> Disk Scheduler

支持三种模式

  • 异步

    数据只需要发送给本地TCP/IP协议栈并发送给本地的发送队列中则返回

  • 半同步 数据已经发送到对方的TCP/IP协议栈并返回

  • 同步 必须要将数据写入磁盘并返回

DRBD用户空间管理工具 drbdadm /etc/drbd.conf /etc/drbd.d/ drbdsetup drbdmeta

DRBD Resources

resource name: 可以使用除空白字符外的任意ASCII表中的字符

  • DRBD Device:drbd设备的访问路径,设备文件 /dev/drbd[n]
  • Disk Configuration: 各节点为组成此drbd设备所提供的块设备
  • Network configuration: 节点间为了实现跨主机磁盘镜像而使用网络配置

只有在使用drbdadm工具时才会读取配置文件,对多个资源的公共配置,可以提取出来只配置一次,通常保存在common中。此外,还有global配置,通常跟资源本身没有关系。 Resource Role: Primary: 主节点,可读写 Secondary: 从节点,不能挂载 Promote可以提升为主 DRBD一般只能用于一主一从的场景,如果使用一主多从需要使用drbd代理,原理非常复杂。 DRBD使用双主模型,只可以使用GFS2和OCFS2文件系统

DRBD Protocol

A: Asynchronous replication protocol B: Memory Synchronous (semi-synchronous) replication C: Synchronous replication protol

Brain Split

Split brain notification and automatic revovery

  • Discarding moifications made on "youger" primary
  • DIscarding mofications made on the "older" primary
  • Dicarding modications on the primary with fewer changes
  • Graceful recovery from split brain if one host has had no intermediate changes

In my lab cases

# on standby
drbdadm secondary mystore
drbdadm --discard-my-data connect mystore
# on active
drbdadm connect mydrbd

配置DRBD

drbd的主配置文件为/etc/drbd.conf;为了管理的便捷性,目前通常会将些配置文件分成多个部分,且都保存至/etc/drbd.d/目录中,主配置文件中仅使用"include"指令将这些配置文件片断整合起来。通常,/etc/drbd.d目录中的配置文件为global_common.conf和所有以.res结尾的文件。其中global_common.conf中主要定义global段和common段,而每一个.res的文件用于定义一个资源。

在配置文件中,global段仅能出现一次,且如果所有的配置信息都保存至同一个配置文件中而不分开为多个文件的话,global段必须位于配置文件的最开始处。目前global段中可以定义的参数仅有minor-count, dialog-refresh, disable-ip-verification和usage-count。

common段则用于定义被每一个资源默认继承的参数,可以在资源定义中使用的参数都可以在common段中定义。实际应用中,common段并非必须,但建议将多个资源共享的参数定义为common段中的参数以降低配置文件的复杂度。

resource段则用于定义drbd资源,每个资源通常定义在一个单独的位于/etc/drbd.d目录中的以.res结尾的文件中。资源在定义时必须为其命名,名字可以由非空白的ASCII字符组成。每一个资源段的定义中至少要包含两个host子段,以定义此资源关联至的节点,其它参数均可以从common段或drbd的默认中进行继承而无须定义。

drbd的组成部分:用户空间工具,内核模块(2.6.33及以后版本的内核) 用户空间工具:跟内核版本关系松散,只要能适用于Centos 6及对应硬件平台的就ok 内核模块:必须与当前内核版本严格对应 note: 用户空间工具与drbd内核中使用的模块的版本要保持一致

DRBD版本

drbd共有两部分组成:内核模块和用户空间的管理工具。其中drbd内核模块代码已经整合进Linux内核2.6.33以后的版本中,因此,如果您的内核版本高于此版本的话,你只需要安装管理工具即可;否则,您需要同时安装内核模块和管理工具两个软件包,并且此两者的版本号一定要保持对应。

目前支持的主要三个版本8.0, 8.2, 8.3

目前适用CentOS 5的drbd版本主要有8.0、8.2、8.3三个版本,其对应的rpm包的名字分别为drbd, drbd82和drbd83,对应的内核模块的名字分别为kmod-drbd, kmod-drbd82和kmod-drbd83。而适用于CentOS 6的版本为8.4,其对应的rpm包为drbd和drbd-kmdl,但在实际选用时,要切记两点:drbd和drbd-kmdl的版本要对应;另一个是drbd-kmdl的版本要与当前系统的内容版本相对应。各版本的功能和配置等略有差异;我们实验所用的平台为x8664且系统为CentOS 6.5,因此需要同时安装内核模块和管理工具。我们这里选用最新的8.4的版本(drbd-8.4.3-33.el6.x8664.rpm和drbd-kmdl-2.6.32-431.el6-8.4.3-33.el6.x86_64.rpm),下载地址为ftp://rpmfind.net/linux/atrpms/

配置

global {
usage-count no;
# minor-count dialog-refresh disable-ip-verification
}
common {
protocol C;
handlers {
pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f";
# fence-peer "/usr/lib/drbd/crm-fence-peer.sh";
# split-brain "/usr/lib/drbd/notify-split-brain.sh root";
# out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root";
# before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh -p 15 -- -c 16k";
# after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh;
}
startup {
wfc-timeout 120;
degr-wfc-timeout 120;
}
disk {
on-io-error detach;
#fencing resource-only;
}
net {
cram-hmac-alg "sha1";
shared-secret "mydrbdlab";
}
syncer {
rate 1000M;
}
}

如果drbd变成单个,则称为降级的drbd 定义一个资源/etc/drbd.d/web.res, drbd 侦听在7789端口

resource web {
on node3.example.com {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.48.131:7789;
meta-disk internal;
}
on node4.example.com {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.48.132:7789;
meta-disk internal;
}
}

复制配置到从节点

初始化资源

drbdadm create-md web

查看drbd状态

drbd-overview
cat /proc/drbd

定义主从节点

drbdadm primary --force [resource]
降级
drbadm secondary [resource]

DRBD自身不会做角色切换,在手动做角色切换时要对原主节点做降级,再对从节点升级。从节点甚至不允许挂载drbd磁盘

DRBD&&Pacemaker

创建drbd 资源

crm configure primitive mysqlstore ocf:linbit:drbd params drbd_resource=mystore op monitor role=Master interval=3os timeout=20s op monitor role=Slave interval=60s timeout=20s op start timeout=240s op stop timeout=100s 

制作主从资源模式

crm configure ms ms_mysqlstore mysqlstore meta master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify="True" 

约束fs与主节点在一起

crm configure colocation mysqlfs_with_ms_myslstore_master inf: mysqlfs ms_mysqlstore:Master 

顺序约束master与挂载顺序

 order mysqlfs_after_ms_mysqlstore_master mandatory: ms_mysqlstore:promotemysqlfs:start 
mysql+drbd+corosync
node node1.example.com \
attributes standby="off"
node node2.example.com \
attributes standby="off"
primitive myip ocf:heartbeat:IPaddr \
params ip="172.16.100.101" \
op monitor interval="20" timeout="20" on-fail="restart"
primitive myserver lsb:mysqld \
op monitor interval="20" timeout="20" on-fail="restart"
primitive mysql_drbd ocf:linbit:drbd \
params drbd_resource="mydata" \
op monitor role="Master" interval="10" timeout="20" \
op monitor role="Slave" interval="20" timeout="20" \
op start timeout="240" interval="0" \
op stop timeout="100" interval="0"
primitive mystore ocf:heartbeat:Filesystem \
params device="/dev/drbd0" directory="/mydata" fstype="ext4" \
op monitor interval="40" timeout="40" \
op start timeout="60" interval="0" \
op stop timeout="60" interval="0"
ms ms_mysql_drbd mysql_drbd \
meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true"
colocation myip_with_myserver inf: myip myserver
colocation myserver_with_mystore inf: myserver mystore
colocation mystore_with_ms_mysql_drbd_master inf: mystore ms_mysql_drbd:Master
order ms_mysql_drbd_before_mystore inf: ms_mysql_drbd:promote mystore:start
order myip_before_myserver inf: myip myserver
order mystore_before_myserver inf: mystore:start myserver:start
property $id="cib-bootstrap-options" \
dc-version="1.1.8-7.el6-394e906" \
cluster-infrastructure="classic openais (with plugin)" \
expected-quorum-votes="2" \
stonith-enabled="false" \
last-lrm-refresh="1379316850" \
no-quorum-policy="ignore"
DRBD 工作在双主模型
resource <resource> {
startup {
become-primary-on both;
...
}
net {
allow-two-primaries yes;
after-sb-0pri discard-zero-changes;
after-sb-1pri discard-secondary;
after-sb-2pri disconnect;
...
}
...
}

同时,包括双主drbd模型中的任何集群文件系统都需要fencing功能,且要求其不仅要在资源级别实现,也要在节点级别实现STONITH功能

disk {
fencing resource-and-stonith;
}
handlers {
outdate-peer "/sbin/make-sure-the-other-node-is-confirmed-dead.sh"
}
结合RHCS时资源定义示例
<rm>
<resources />
<service autostart="1" name="mysql">
<drbd name="drbd-mysql" resource="mydrbd">
<fs device="/dev/drbd0"
mountpoint="/var/lib/mysql"
fstype="ext3"
name="mydrbd"
options="noatime"/>
</drbd>
<ip address="172.16.100.8" monitor_link="1"/>
<mysql config_file="/etc/my.cnf"
listen_address="172.16.100.8"
name="mysqld"/>
</service>
</rm>
多节点同时启动一个IP
node node1.example.com \
attributes standby="off"
node node2.example.com
node node3.example.com \
attributes standby="off"
primitive DLM ocf:pacemaker:controld \
params daemon="/usr/sbin/dlm_controld" \
op start interval="0" timeout="90" \
op stop interval="0" timeout="100"
primitive clusterip ocf:heartbeat:IPaddr2 \
params ip="172.16.200.7" cidr_netmask="32" clusterip_hash="sourceip"
clone WebIP clusterip \
meta globally-unique="true" clone-max="3" clone-node-max="3" target-role="Stopped"
clone dlm_clone DLM \
meta clone-max="3" clone-node-max="1" target-role="Started"
property $id="cib-bootstrap-options" \
dc-version="1.1.7-6.el6-148fccfd5985c5590cc601123c6c16e966b85d14" \
cluster-infrastructure="openais" \
expected-quorum-votes="3" \
stonith-enabled="false" \
last-lrm-refresh="1354024090"
primitive mysql_drbd ocf:linbit:drbd params drbd_resource="mydata" op monitor role=Master interval=10 timeout=20 op monitor role=Slave interval=20 timeout=20 op start timeout=240 op stop timeout=100

ISCSI

外频:CPU与内存协调的内存功率 PCI-e就是直接连接在北桥的扩展插槽接口 ISA bus:十六位总线,低速总线 SCSI控制器可以替代CPU工作,降低CPU的使用率 SCSI 工作模型 Initiator:
Target:
LUN: Logical Unit Number 逻辑单元号,最多32个
CHAP:Challenge handshake authentication Protocol
并行接口:
IDE,SCSI
串行:
SATA, SAS, USB

Target管理工具

tgtadm

ISCSI配置工具

iSCSI Server:scsi-target-utils
iSCSI Initiator: iscsi-initiator-utils

配置iscsi

tgtadm常用于管理三类对象:
target:创建、查看、删除
lun: 创建、查看、删除
认证:用户创建、绑定、解绑定、删除、查看
常用选项

-L --lld <driver>
<drvier> iscsi
-m --mode <mode>
<mode>: target, logicalunit等
-o --op <operation>
<operation>: new,show,delete,bind,unbind
-t --tid<id>: 指定target的ID (iscsi通常0使用本身)
-T --targetname<targetname>: 指定target的名称
target的命名机制:为了保证全局以唯一,命名要遵循iqn规范
iqn: iqn.yyyy-mm.reverse_domain.STRING[:substring]
eg. iqn.2016-05.com.example.node3:webserver
-l --lun<lun>: 指定LUN的号码
-b --backing-store<path>:关联到某指定LUN上的后端存储设备,可以是分区,也可以是磁盘。建议使用后者
-I --initiator-address<address>: 指定授权访问某target的IP地址来源

tgtadm

tgtadm --lld [driver] --op [operation] --mode [mode] [OPTION]...

(1)、添加一个新的 target 且其ID为 [id], 名字为 [name]. --lld [driver] --op new --mode target --tid=[id] --targetname [name]

(2)、显示所有或某个特定的target: --lld [driver] --op show --mode target [--tid=[id]]

(3)、向某ID为[id]的设备上添加一个新的LUN,其号码为[lun],且此设备提供给initiator使用。[path]是某“块设备”的路径,此块设备也可以是raid或lvm设备。lun0已经被系统预留。 --lld [driver] --op new --mode=logicalunit --tid=[id] --lun=[lun] --backing-store [path]

(4)、删除ID为[id]的target: --lld [driver] --op delete --mode target --tid=[id]

(5)、删除target [id]中的LUN [lun]: -lld [driver] --op delete --mode=logicalunit --tid=[id] --lun=[lun]

(6)、定义某target的基于主机的访问控制列表,其中,[address]表示允许访问此target的initiator客户端的列表: --lld [driver] --op bind --mode=target --tid=[id] --initiator-address=[address]

(7)、解除target [id]的访问控制列表中[address]的访问控制权限: --lld [driver] --op unbind --mode=target --tid=[id] --initiator-address=[address]

iSCSI配置示例

(1)创建一个target: tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.2013-05.com.magedu:tsan.disk1

(2)显示所有: tgtadm --lld iscsi --op show --mode target

(3)显示刚创建的target: tgtadm --lld iscsi --op show --mode target --tid 1

(4)创建LUN,号码为1: tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun 1 -b /dev/sda5

(5)开放给192.168.0.0/24网络中的主机访问: tgtadm --lld iscsi --op bind --mode target --tid 1 -I 172.16.0.0/16 其中的-I相当于--initiator-address

(6)Create a new account: tgtadm --lld iscsi --op new --mode account --user christina --password 123456 tgtadm --lld iscsi --op show --mode account

Assign this account to a target:

tgtadm --lld iscsi --op bind --mode account --tid 1 --user christina tgtadm --lld iscsi --op show --mode target

(7)Set up an outgoing account. First, you need to create a new account like the previous example

tgtadm --lld iscsi --op new --mode account --user clyde --password 123456 tgtadm --lld iscsi --op show --mode account

tgtadm --lld iscsi --op bind --mode account --tid 1 --user clyde --outgoing tgtadm --lld iscsi --op show --mode target

分享ISCSI步骤

Server端

service tgtd start 

1、创建target

tgtadm -L iscsi -o new -m target -t 1 -T iqn.2016-05.com.example.node3:1 

2、指定LUN到target

tgtadm -L iscsi -o new -m logicalunit -t 1 -l 1 -b /dev/sdb2
tgtadm -L iscsi -o new -m logicalunit -t 1 -l 2 -b /dev/sdb5

3、创建LUN与target Binding关系

tgtadm -L iscsi -o bind -t 1 -I 192.168.48.0/24 -m target 

Client端

1、创建initiatorname和别名

echo "InitiatorName=`iscsi-iname -p iqn.2016-05.com.example`" > /etc/iscsi/initiatorname.iscsi
echo "InitiatorAlias=initiator1" >> /etc/iscsi/initiatorname.iscsi

2、启动客户端iscsi服务,下次开机时可以自动发现iscsi target

service iscsi start; service iscsid start

iscsiadm工具

iscsiadm是个模式化的工具,其模式可通过-m或--mode选项指定,常见的模式有discovery、node、fw、session、host、iface几个,如果没有额外指定其它选项,则discovery和node会显示其相关的所有记录;session用于显示所有的活动会话和连接,fw显示所有的启动固件值,host显示所有的iSCSI主机,iface显示/var/lib/iscsi/ifaces目录中的所有ifaces设定

iscsiadm -m discovery [ -d debug_level ] [ -P printlevel ] [ -I iface -t type -p ip:port [ -l ] ]
iscsiadm -m node [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ [ -T tar-getname -p ip:port -I iface ] [ -l | -u | -R | -s] ] [ [ -o operation ] -d, --debug=debug_level 显示debug信息,级别为0-8;
-l, --login
-t, --type=type 这里可以使用的类型为sendtargets(可简写为st)、slp、fw和 isns,此选项仅用于discovery模式,且目前仅支持st、fw和isns;其中st表示允许每个iSCSI target发送一个可用target列表给initiator;
-p, --portal=ip[:port] 指定target服务的IP和端口;
-m, --mode op 可用的mode有discovery, node, fw, host iface 和 session
-T, --targetname=targetname 用于指定target的名字
-u, --logout
-o, --op=OPEARTION:指定针对discoverydb数据库的操作,其仅能为new、delete、update、show和nonpersistent其中之一;
-I, --interface=[iface]:指定执行操作的iSCSI接口,这些接口定义在/var/lib/iscsi/ifaces中;

1、Discovery ISCSI设备

iscsiadm -m discovery -t st -p 192.168.48.131:3260 

2、登录ISCSI设备

iscsiadm -m node -T iqn.2016-05.com.example.node3:1 -p 192.168.48.131:3260 -l

删除ISCSI设备

登出ISCSI设备

iscsiadm -m node -T iqn.2016-06.com.example.node3:1 -p 192.168.48.131:3260 -u

登陆过的信息都会保存在/var/lib/iscsi/send_targets/下 ISCSI连接时,本地接口等信息会保存在/var/lib/iscsi/ifaces/目录下 /var/lib/iscsi/nodes/下保存着可以自动登录的设备信息

删除iSCSI设备及元数据

iscsiadm -m node -T iqn.2016-06.com.example.node3:1 -p 192.168.48.131:3260 -o delete

在服务器端解绑定

tgtadm -L iscsi -o unbind -m target -t 1 -I 192.168.48.0/24

删除LUN

tgtadm -L iscsi -o delete -m logicalunit -t 1 -l 2

删除Target

tgtadm -L iscsi -o delete -m target -t 1

tgtd configuration

在/etc/tgt/targets.conf

default-driver iscsi
<target iqn.2016-05.com.example.node3:1>
backing-store /dev/sdb5
incominguser iscsiuser mypass
outgoinguser myuser mypass
initiator-address 192.168.0.0/24
</target>

3、分区格式化并创建文件系统.. 4、开机挂载 如果出现了无法挂载的情况,则

dmsetup status
dmsetup remove_all

Note: 使用共享存储上的挂载一定不要同时挂载和使用

ISCSI配置CHAP用户认证

1、在target端创建账号esunyig,并为其授予访问某tid的权限

tgtadm -L iscsi -o new -m account --user esunyig --password 123456

2、将用户与某target绑定

tgtadm -L iscsi -o bind -m account --tid 1 --user esunyig

3、修改initiator端的主配置文件/etc/iscsi/iscsid.conf

node.session.auth.authmethod = CHAP
node.session.auth.username = esunyig
node.session.auth.password = 123456

4、如果initiator端已经登录过此target,此时还需要先注销登录后重启iscsid服务,并在删除此前生成的database后重新发现target并登录

RHCS and Conga

如果要在企业中自建一个共享存储,可以有如下选择

Openfiler WebGUI FreeNas: NAS4free freebsd
Nexenstor:
solaris
ZFS Windows, iSCSI(target, initiator)
RHCS: Redhat Cluster Suite
lvs, piraha(为lvs提供高可用功能)
cman+rgmanager
DLM: distributed lock manager 分布式锁管理器
GFS:
Global File System (redhat)
Google FIle System: GFS(google),分布式文件系统
TFS:
Taobao File System
Tencent File System
OCFS2: oracle Filesystem

HA解决方案(终极)

HA方案
Heartbeat v1 + haresources
Heartbeat v2 + crm
Heartbeat v3 + cluster-glue + pacemaker
Corosync + pacemaker
Corosync + cman + rgmanager
Corosync + cman + pacemaker

红帽管理方案:
conga: luci + ricci
luci: work station
ricii: cluster nodes

部署RHCS的方法

RHCS的核心组件为cman和rgmanager,其中cman为基于openais的“集群基础架构层”,rgmanager为资源管理器。RHCS的集群中资源的配置需要修改其主配置文件/etc/cluster/cluster.xml实现,这对于很多用户来说是比较有挑战性的,因此,RHEL提供了system-config-cluster这个GUI工具,其仅安装在集群中的某一节点上即可,而cman和rgmanager需要分别安装在集群中的每个节点上。这里选择将此三个rpm包分别安装在了集群中的每个节点上,这可以在跳板机上执行如下命令实现
conga:部署、资源管理等功能
手动安装:corosync + cman + rgmanager
GFS一般集群文件系统一般不能多于16个
分布式存储:名称节点能够将用户数据分割成多个块,而后分散存储在多个数据节点上

集群文件系统

GFS2
OCFS2

分布式文件系统
GFS (google filesystem)
HDFS (hadoop) (单个大文件)
TFS (Taobao)
MooseFS
MogileFS (适用于存储海量小文件) 无法挂载,有API
GlusterFS
Swift (Openstack)
ceph
对于数据库而言,存储从内容上分类有两类,一类是关系型数据库中的表内容,一部分是图片,数据之类的文件

Conga:
管理主机:可以非为集群中的节点,luci
集群节点:安装ricci
两节点集群:qdisk(仲裁磁盘)

1、配置hosts主机解析

ansible rhcs -m shell -a 'rm /etc/hosts'
ansible rhcs -m shell -a 'echo "127.0.0.1 localhost localhost.localdomain localhost4
localhost4.localdomain4" /etc/hosts'
ansible rhcs -m shell -a 'echo "::1 localhost localhost.localdomain localhost6
localhost6.localdomain6" >>/etc/hosts'
ansible rhcs -m shell -a 'echo "192.168.48.131 node1.exmaple.com node1" >>/etc/hosts'
ansible rhcs -m shell -a 'echo "192.168.48.132 node2.exmaple.com node2" >>/etc/hosts'
ansible rhcs -m shell -a 'echo "192.168.48.137 node3.exmaple.com node3" >>/etc/hosts'
ansible rhcs -m shell -a 'echo "192.168.48.138 node4.exmaple.com node4" >>/etc/hosts'

2、安装ricci在客户机上 note: 在安装rhcs时,要禁用epel源

ansible rhcs -m yum -a "name=ricci state=present disablerepo=epel"

启动服务

ansible rhcs -m service -a "name=ricci state=started enabled=yes"

ricci侦听在111端口上 给cluster集群中的ricci用户添加密码

ansible rhcs -m shell -a "echo nsadm|passwd --stdin ricci"

3、在本机上安装lucci 同样也要禁用epel源

yum -y install luci --disablerepo=epel
service luci start

luci侦听在8084端口上

查看cluster状态

clustat

使用clusvcadm转移资源

clusvcadm -r webservice -m node3.example.com

使用cman_tool管理集群

查看集群状态

cman_tool status

查看集群服务

cman_tool services

查看集群节点

cman_tool nodes

/etc/cluster/cluster.conf

<?xml version="1.0"?>
<cluster config_version="5" name="my_cluster">
<clusternodes>
<clusternode name="node1.example.com" nodeid="1"/>
<clusternode name="node2.example.com" nodeid="2"/>
<clusternode name="node3.example.com" nodeid="3"/>
</clusternodes>
<rm>
<failoverdomains>
<failoverdomain name="webdomain" nofailback="1" ordered="1">
<failoverdomainnode name="node1.example.com" priority="1"/>
<failoverdomainnode name="node2.example.com" priority="2"/>
<failoverdomainnode name="node3.example.com" priority="3"/>
</failoverdomain>
</failoverdomains>
<resources>
<ip address="192.168.48.140/24" sleeptime="10"/>
</resources>
<service domain="webdomain" name="webservice" recovery="relocate">
<ip ref="192.168.48.140/24"/>
<script file="/etc/init.d/httpd" name="webserver"/>
</service>
</rm>
</cluster>

RHCS基于命令行的实现

rhcs跟NetworkManager服务冲突,确保NetworkManager处于关闭状态 配置过程:找集群中某一个节点

准备环境

ansible rhcs -m yum -a "name=corosync state=present"
ansible rhcs -m yum -a "name=cman state=present"
ansible rhcs -m yum -a "name=rgmanager state=present"
ansible rhcs -m service -a "name=corosync state=started enabled=yes"
ansible rhcs -m service -a "name=cman state=started enabled=yes"
###我的环境可以简化。。
ansible rhcs -m copy -a "src=/etc/ansible/cluster.conf dest=/etc/cluster/cluster.conf"

1、创建集群配置文件的框架

ccs_tool create mycluster

2、定义集群节点

ccs_tool addnode node1.example.com -n 1 -v 1
ccs_tool addnode node2.example.com -n 2 -v 1
ccs_tool addnode node3.example.com -n 3 -v 1

生成cluster.conf文件

<?xml version="1.0"?>
<cluster name="mycluster" config_version="4"> <clusternodes>
<clusternode name="node1.example.com" votes="1" nodeid="1"/><clusternode name="node2.example.
com" votes="1" nodeid="2"/><clusternode name="node3.example.com" votes="1" nodeid="3"/></cluste
rnodes> <fencedevices>
</fencedevices> <rm>
<failoverdomains/>
<resources/>
</rm>
</cluster>
ansible rhcs -m copy -a "src=/etc/ansible/cluster.conf dest=/etc/cluster/cluster.conf"
ansible rhcs -m service -a "name=cman state=started enabled=yes"

创建fence设备

一个RHCS集群至少需要一个fence设备,正常环境中,可以选择将其配置到集群中来。这里为演示环境,没有可用的fence设备,因此,选择使用“manual fence”,即手动fence。创建fence设备也需要使用ccs_tool命令进行,其需要在集群中的某节点上执行,而且需要与前面创建集群配置文件时所执行的命令在同一个节点上进行。

查看fence代理的名称,可以通过查看cman安装生成文件来实现。

rpm -ql cman | grep /sbin/fence

这里为tcluster添加名为meatware的fence设备,其fence代理为fence-manual

ccs_tool addfence meatware fence-manaualxxxxxxxxxx 

接着可以使用ccs_tool lsfence查看fence设备

ccs_tool lsfence

RHCS集群需要配置好各节点及相关的fence设备后才能启动,因此,这里需要事先将各节点添加进集群配置文件。每个节点在添加进集群时,需要至少为其配置node id(每个节点的id必须惟一)及相关的fence设备两个属性。ccs_tool的addnode子命令可以完成节点添加。例如将前面规划的三个集群节点添加至集群中,可以使用如下命令实现。

ccs_tool addnode -n 1 -f meatware node1.magedu.com
ccs_tool addnode -n 2 -f meatware node2.magedu.com
ccs_tool addnode -n 3 -f meatware node3.magedu.com

GFS集群文件系统

  GFS 文件系统是Linux操作系统上唯一针对企业应用的Native64位集群文件系统,支持x86、AMD64/EM64T和Itanium等处理器平台。它还是Linux系统上扩展能力最强的企业集群文件系统,支持多达300个结点。

  由于多个集群节点同时访问/读写同一分区/数据,就必顺通过一个或多个管理服务器来保证数据的一致性,在GFS中,管理服务器叫DLM(distributed lock manager),通过DLM 可以与每个集群节点心跳通讯,以确保数据完整性,及节点健康性,一旦发现某个节点通讯有问题,它会把该节点从集群中隔离出来,直到该节点重新恢复,才能再加入集群节点中。考虑到DLM服务器的高可用性,GFS 可以通过设置多个DLM的备份,一旦主DLM发生故障,备份的DLM就可以接管作为主DLM来管理整个GFS。所以从节点到DLM,都可以实现HA的功能,就不存在单点故障的问题,可以确保GFS 最高程度的高可用性。GFS文件系统支持三种锁管理机制DLM、GULM、nolock。DLM是默认最优的锁管理器。

1)DLM 锁管理器

DLM(Distributed Lock Manager)是最优的锁管理器,它避免了GULM 锁管理方式中必须提供GULM 锁管理服务器的缺点,不再需要设定锁管理服务器,而是采用对等的锁管理方式,大大提供处理性能,DLM 避免了当单个节点失败需要整个恢复的性能瓶颈,DLM 的请求是本地的,不需要网络请求,立即生效,通锁分层机制,DLM 实现多个锁空间,并行锁模式。

2)GULM 锁管理器

GULM 是GFS6.1 以前的锁管理器,它必须要设置一个锁管理服务器,是一种client/Server 的锁管理方式,显示易见,所有的锁请求必须要与锁管理服务器通讯。而且当节点增大的一定数量的时候,可能会出现磁盘的交换,降低了整个GFS 系统的性能。

3)nolock锁管理器

nolock实际并不是一个集群管理锁机制,它只能用于单个节点的GFS 系统。一般用来测试和实验用。GFS 6.1与GFS 6.0对比GFS 6.1是一个成熟的、高可扩展的、高性能的集群文件系统,支持分布式锁管理,成熟的LVM2卷管理系统,而且与Red Hat Enterprise Linux紧密集成的系统。GFS 6.1与GFS 6.0相比尤其在性能上得到很大提升,包括快速的磁盘扫描、避免Kernel Panic,并且与Red Hat Cluster Suite 紧密结合,而且其DLM的锁管理技术已经被Linux Kernel社区接纳。

GFS可以在同一时间内多台服务器同时访问共享磁盘上的同一个磁盘分区,甚至同一个文件。GFS 不仅提供了HA 功能,还同时允许多台服务器同时访问同一个磁盘分区和文件

1、配置共享存储iscsi设备

 yum -y install scsi-target-utils

配置/etc/tgt/targets.conf

default-driver iscsi
<target iqn.2016-05.com.example.testsan:1>
backing-store /dev/sda5
backing-store /dev/sda6
initiator-address 192.168.48.0/24
</target>

2、配置iscsi客户端

ansible rhcs -m yum -a "name=iscsi-initiator-utils state=present"
echo InitiatorName=`iscsi-iname -p iqn.2016-05.com.example` >/etc/iscsi/initiator
rname.iscsi

3、登录iscsi设备

ansible rhcs -m shell -a 'iscsiadm -m node -T iqn.2016-05.com.example.testsan:1 -p 192.168
.48.138:3260 -l'

4、安装gfs

ansible rhcs -m yum -a "name=gfs2-utils state=present"

GFS文件系统

Syntax:
mkfs.gfs2 [options] <device> [ block-count ]
Options:
-b <bytes> Filesystem block size
-c <MB> Size of quota change file
-D Enable debugging code
-h Print this help, then exit
-J <MB> Size of journals
-j <num> Number of journals
如果指定的日志区域不够用,可以使用gfs2_jadd天假新的日志区域
-K Don't try to discard unused blocks
-O Don't ask for confirmation
-p <name> Name of the locking protocol
lock_dlm
-q Don't print anything
-r <MB> Resource Group Size
-t <name> Name of the lock table
clustername:fname
-u <MB> Size of unlinked file
-V Print program version information, then exit
-b BlockSize:指定文件系统块大小,最小为512,默认为4096;
-J MegaBytes:指定gfs2日志区域大小,默认为128MB,最小值为8MB;
-j Number:指定创建gfs2文件系统时所创建的日志区域个数,一般需要为每个挂载的客户端指定一个日志区域;
-p LockProtoName:所使用的锁协议名称,通常为lock_dlm或lock_nolock之一;
-t LockTableName:锁表名称,一般来说一个集群文件系统需一个锁表名以便让集群节点在施加文件锁时得悉其所关联到的集群文件系统,锁表名称为clustername:fsname,其中的clustername必须跟集群配置文件中的集群名称保持一致,因此,也仅有此集群内的节点可访问此集群文件系统;此外,同一个集群内,每个文件系统的名称必须惟一;

gfs2,日志文件系统 配置示例

mkfs.gfs2 -j 3 -t mycluster:webstore -p lock_dlm /dev/sdb1

集群文件系统中没有lost+found 集群文件系统通过集群文件系统锁dlm来实现文件的实时显示修改

gfs2_tool工具

冻结/解冻某文件系统
gfs2_tool freeze /mnt
gfs2_tool unfreeze /mnt
获取参数
gfs2_tool gettune /mnt
设置参数
gfs2_tool settune /mnt log_flush_secs 120
查看文件系统日志区域
gfs2_tool journals /mnt

让gfs文件系统在开机后自动启动

需要启动gfs2的服务,fstab的配置如下

/dev/sdb1        /gfs          gfs2    defaults        0 0

集群逻辑卷lvm2-cluster

安装集群逻辑卷

ansible rhcs -m yum -a "name=lvm2-cluster state=present"

修改集群逻辑卷锁类型

ansible rhcs -m shell -a 'sed -i "s@^\([[:space:]]*locking_type\).*@\1 = 3@g" /etc/lvm/lvm.conf'
也可以
ansible rhcs -m shell -a 'lvmconf --enable-cluster' # Type of locking to use. Defaults to local file-based locking (1).
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
# if LVM2 commands get run concurrently).
# Type 2 uses the external shared library locking_library.
# Type 3 uses built-in clustered locking.
# Type 4 uses read-only locking which forbids any operations that might
# change metadata.
# Type 5 offers dummy locking for tools that do not need any locks.

启动llvm2服务

ansible rhcs -m service -a "name=clvmd state=started enabled=yes"

在任意cluster节点中创建逻辑卷并创建集群逻辑卷文件系统

mkfs.gfs2 -p lock_dlm -j 3 -t mycluster:clvm /dev/cluster_vg/cluster_lv

扩展lvm2逻辑卷大小

lvextend -L +2G /dev/cluster_vg/cluster_lv
gfs2_grow /dev/cluster_vg/cluster_lv

扩展:如何实现双主模型的drbd

gfs_lvm只能在cman管理下使用。RHEL6 下corosync并不支持corosync

Device Mapper 简析

DM与MD

Device Mapper(DM)是Linux 2.6全面引入的块设备新构架,通过DM可以灵活地管理系统中所有的真实或虚拟的块设备。

DM以块设备的形式注册到Linux内核中,凡是挂载(或者说“映射”)于DM结构下的块设备,不管他们是如何组织,如何通讯,在Linux看来都是一个完整的DM块设备。因此DM让不同组织形式的块设备或者块设备集群在Linux内核面前有一个完整统一的DM表示。

在Linux内核代码中(本文以2.6.33内核代码为参照),DM指的是整个Device Mapper的设计框架。MD(Mapped Device)是框架所虚拟出来的各种设备。简而言之DM就是不同种类的MD经过特定的关系连接到块设备管理器上的大构架。

DM的内核代码集中在drivers/md目录中。DM构架相关的代码在dm.c和dm-io.c文件中,各种抽象的MD虚拟设备代码分散在同目录的其他文件中,除了dm-ioctl.c是dm设置接口设备。

DMSetup

dmsetup可以用来组装,解散,监视我们自己的虚拟存储结构。 dmsetup的子命令中,create、load、reload子命令都带有 --table

参数 table字串有如下形式:

<start><lenght><type><arguments>

在DM架构中MD只是一个对外的统一接口,不同target driver的对外接口可以都是一样的,因此无需为不同的虚拟方式编写不同的MD,只需要提供不同的target driver即可 mapped-driver简称为md,target device简称为target。target driver简称为driver Target类型: linear; mirror;snapshot;multipath

dmsetup ls
dmsetup info
dmsetup status
dmsetup deps
dmsetup table

创建一个linear设备

起始扇区  扇区个数  线性映射  目标设备 目标设备上的起始扇区
0 1025 linear /dev/sdb2 0

查看IO读写状态

iostat

KeepAlived

DFS: Distributed Filesystem CFS: Cluster Filesystem; GFS2 cLVM: lvm2-cluster keepalived核心: vrrp的实现 virtual server vrrp_script vrrp: virtual redundancy routing protocal 数字越大,优先级越高 http://www.keepalived.org

vrrp虚拟mac地址 00-00-5E-00-01-{VRID} LAN客户端判定哪个路由器应该为其到达目标主机的下一跳网关的方式有动态及静态决策两种方式,其中,常见的动态路由发现方式有如下几种: 1、Proxy ARP —— 客户端使用ARP协议获取其想要到达的目标,而后,由某路由以其MAC地址响应此ARP请求; 2、Routing Protocol —— 客户端监听动态路由更新(如通过RIP或OSPF协议)并以之重建自己的路由表; 3、ICMP IRDP (Router Discovery Protocol) 客户端 —— 客户端主机运行一个ICMP路由发现客户端程序;

动态路由发现协议的不足之处在于它会导致在客户端引起一定的配置和处理方面的开销,并且,如果路由器故障,切换至其它路由器的过程会比较慢。解决此类问题的一个方案是为客户端静态配置默认路由设备,这大大简化了客户端的处理过程,但也会带来单点故障类的问题。默认网关故障时,LAN客户端仅能实现本地通信。 VRRP可以通过在一组路由器(一个VRRP组)之间共享一个虚拟IP(VIP)解决静态配置的问题,此时仅需要客户端以VIP作为其默认网关即可。

VRRP是一个“选举”协议,它能够动态地将一个虚拟路由器的责任指定至同一个VRRP组中的其它路由器上,从而消除了静态路由配置的单点故障。

VRRP的优势: 冗余:可以使用多个路由器设备作为LAN客户端的默认网关,大大降低了默认网关成为单点故障的可能性; 负载共享:允许来自LAN客户端的流量由多个路由器设备所共享; 多VRRP组:在一个路由器物理接口上可配置多达255个VRRP组; 多IP地址:基于接口别名在同一个物理接口上配置多个IP地址,从而支持在同一个物理接口上接入多个子网; 抢占:在master故障时允许优先级更高的backup成为master; 通告协议:使用IANA所指定的组播地址224.0.0.18进行VRRP通告; VRRP追踪:基于接口状态来改变其VRRP优先级来确定最佳的VRRP路由器成为master;

IP地址拥有者(IP Address Owner):如果一个VRRP设备将虚拟路由器IP地址作为真实的接口地址,则该设备被称为IP地址拥有者。如果IP地址拥有者是可用的,通常它将成为Master。

KeepAlived配置

Global Configuration Global definitions Static routes

VRRPD Configuration VRRP Synchronization Group String, name of group of IPs that failover together VRRP instance(s) Describes the moveable IP for each instance of a group in vrrp_sync_group

LVS Configuration Virtual Server Group Vritual Server virtual_ipaddrss:

<IPADDR>/<MASK> brd <IPADDR> DEV <STRING> scope <SCOPE> label <LABEL>

virtual_routes:

#src <IPADDR> [to] <IPADDR>/<MASK> via|gw <IPADDR> [or <IPADDR>] dev <STRING> scope <SCOPE> tab

man keepalived.conf 查看配置 配置script监测脚本

vrrp_script chk_maintenance {
script "[[ -e /etc/keepalived/down ]] && exit 1 || exit 0"
interval 1
weight -2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.48.150
}
track_script {
chk_maintenance
}
}

Keepalived功能

1 . 如何在状态转换时进行通知? notify_master "/path/script.sh" notify_backup notify_fault

MASTER:
#!/bin/bash
vip=192.168.48.150
thisip=`ifconfig eth0|awk '/inet addr:/{print $2}|awk -F: '{print $2}'`
contact='root@localhost'
notify(){
mailbody="vrrp transaction, $vip floated to $thisip."
subject="$thisip is to be $vip master"
echo $mailbody|mail -s $subject $contact
}
notify $1

vrrp_sync_group{} vrrp_instance{}

2 . 如何配置ipvs?

vritual server realserver health check 配置内容 virtual_server IP port virtual_server fwmak int virtual_server group string lb_algo rr|wrr|lc|wlc|blc|sh|dh lb_kind NAT|DR|TUN persistence_timeout protocol TCP sorry_server

real_server <IPADDR> <PORT> {
weight <INT>
notify_up <STRING>|<QUOTED-STRING>
notify_down <STRING>|<QUOTED-STRING>
#HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
}
virtual_server 192.168.48.150 80 {
# delay_loop 6
lb_algo rr
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP real_server 192.168.48.137 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.48.138 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}

TCP_CHECK

{
connect_port <PORT>
bindto <IPADDR>
connect_timeout <INT>
}

HTTP_GET|SSL_GET

{
url{
path <STRING>
digest <STRING> ##get from genhash eg. genhash -s 192.168.48.137 -p 80 --url "/"
status_code <INT>
}
connect_port <PORT>
bindto <IPADDR>
connect_timeout <INT>
nb_get_retry <INT>
delay_before_retry <INT>
}

3 . 如何对某特定服务实现高可用 对nginx实现高可用

vrrp_scrip chk_nginx{
script "killall -0 nginx &>/dev/null"
interval 1
fall 2
rise 2
weight -5
}
对nginx进行脚本测试

4 . 如何实现基于多虚拟路由的master/master模型 设置多路虚拟路由, 并将各自fallback节点指向彼此即可

补充

组播IP地址

组播IP地址用于标识一个IP组播组。IANA(internet assigned number authority)把D类地址空间分配给IP组播,其范围是从224.0.0.0到239.255.255.255。 XXXX XXXXXXXX XXXXXXXX XXXXXXXX组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。

224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用。
224.0.1.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效。
239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。常用的预留组播地址列表如下:
224.0.0.0 基准地址(保留)
224.0.0.1 所有主机的地址
224.0.0.2 所有组播路由器的地址
224.0.0.3 不分配
224.0.0.4 dvmrp(Distance Vector Multicast Routing Protocol,距离矢量组播路由协议)路由器
224.0.0.5 ospf(Open Shortest Path First,开放最短路径优先)路由器
224.0.0.6 ospf dr(Designated Router,指定路由器)
224.0.0.7 st (Shared Tree,共享树)路由器
224.0.0.8 st主机
224.0.0.9 rip-2路由器
224.0.0.10 Eigrp(Enhanced Interior Gateway Routing Protocol,增强网关内部路由线路协议)路由器 224.0.0.11 活动代理
224.0.0.12 dhcp服务器/中继代理
224.0.0.13 所有pim (Protocol Independent Multicast,协议无关组播)路由器
224.0.0.14 rsvp (Resource Reservation Protocol,资源预留协议)封装
224.0.0.15 所有cbt 路由器
224.0.0.16 指定sbm(Subnetwork Bandwidth Management,子网带宽管理)
224.0.0.17 所有sbms
224.0.0.18 vrrp(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)
239.255.255.255 SSDP协议使用

特殊网卡类型

  • 普通的以太网卡
  • TOE网卡:TCP offload Engine. 在硬件层面完成TCP/IP报文封装,无需CPU内核参与
  • HBA: Host Bus Adapter。 采用内建SCSI指令及TOE引擎的ASIC芯片的适配卡。可以参与ISCSI的协议层的封装解封装

配置故障切换域

故障切换域是一个命名的集群节点子集,它可在节点失败事件中运行集群服务。故障切换域有以下特征: 无限制 — 允许您为在子集指定首选成员子集,但分配给这个域名的集群服务可在任意可用成员中运行。 限制 — 允许您限制可运行具体集群服务的成员。如果在限制故障切换域中没有可用成员,则无法启动集群服务(手动或者使用集群软件均不可行)。 无序 — 当将一个集群服务分配给一个无序故障切换域时,则可从可用故障切换域成员中随机选择运行集群服务的成员,没有优先顺序。 有序的 — 可让您在故障切换域的成员间指定顺序。该列表顶端的成员是首选成员,接下来是列表中的第二个成员,依此类推。 故障恢复 — 允许您指定在故障切换域中的服务是否应该恢复到节点失败前最初运行的节点。配置这个特性在作为有序故障切换域一部分节点重复失败的环境中很有帮助。在那种情况下,如果某个节点是故障切换域中的首选节点,在可能在首选节点和其它节点间重复切换和恢复某个服务,从而不会对性能产生严重影响。