许多工程师都有很乐观的想法: 让服务完美进行他们在一开始就考虑好最终情况, 不去想一些可能引起灾难的变化或不可预测的事件, 也就无法从这些变化和不可预测性中获利, 使服务变得更好
那么问题来了, 我们如何才能利用好不稳定性, 随机性和无序性?
有很多抗脆弱性相关的博客, 但其中少有涉及现有技术的这里我们把所有东西打包一下
抗脆弱性
抗脆弱性这个词最先由 Nassim Nicholas Taleb 在他的书 Antifragile: Things That Gain from Disorder 中首次引入
有些事物从冲击中受益, 当面对不稳定性随机性无序性和压力源的时候, 它们能生长繁荣; 它们热爱冒险风险和不确定性然而, 尽管这种现象很普遍, 却没有一个说法能准确描述脆弱的反面我们就管它叫抗脆弱性吧抗脆弱性不仅仅是指弹性和稳健性, 有弹性的事物能抵抗冲击保持原样, 而抗脆弱的事物却能利用冲击变得更好
如何量化服务的脆弱性? 服务失败了会发生什么? Kubernetes 能起到什么作用?
这些问题都关系到抗脆弱性的几个关键概念
简易性
复杂的系统难以监测和维护系统越大, 变更起来就越难, 任何突发事件都可能引起难以追踪和调试的不良后果甚至连锁故障
Kubernetes 提供名为 Pod 的部署单元 Pod 是运行在同一节点上有相同生命周期的容器集合我们可以假设一个容器负责一个特定事件
- __Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__apiVersion: v1
- kind: Pod
- metadata:
- name: web-app
- spec:
- containers:
- - name: web
- image: nginx
- ports:
- - name: web
- containerPort: 80
- protocol: TCP
- - name: database
- image: postgres
- ports:
- - name: psql
- containerPort: 5432
- protocol: TCP__Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__
显然, 还有其他种类的 Kubernetes 资源, 比如: 部署, DaemonSet,StatefulSet 等
可观察性
监测和日志记录是理解服务运行和表现的关键机制, 尤其是在类似 Kubernetes 的动态分布式环境中
Kubernetes 上运行的所有容器都应当在 stdout 或 stderr 上记录应用程序输出日志这能帮助形成独立的存储, 并在容器崩溃时能让你及时了解情况
- __Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__I0221 00:40:02.060314 version: 1.14.8
- I0221 00:40:02.133217 Using configuration read from directory: /kube-dns-config with period 10s
- I0221 00:40:02.133299 FLAG: --alsologtostderr="false"
- I0221 00:40:02.133312 FLAG: --config-dir="/kube-dns-config"
- I0221 00:40:02.133320 FLAG: --config-map=""I0221 00:40:02.133325 FLAG: --config-map-namespace="kube-system"I0221 00:40:02.133331 FLAG: --config-period="10s"I0221 00:40:02.133338 FLAG: --dns-bind-address="0.0.0.0"I0221 00:40:02.133344 FLAG: --dns-port="10053"I0221 00:40:02.133353 FLAG: --domain="cluster.local."I0221 00:40:02.133361 FLAG: --federations=""
- I0221 00:40:02.133368 FLAG: --healthz-port="8081"
- I0221 00:40:02.133373 FLAG: --initial-sync-timeout="1m0s"
- I0221 00:40:02.133378 FLAG: --kube-master-url=""I0221 00:40:02.133385 FLAG: --kubecfg-file=""
- I0221 00:40:02.133390 FLAG: --log-backtrace-at=":0"
- I0221 00:40:02.133400 FLAG: --log-dir=""I0221 00:40:02.133406 FLAG: --log-flush-frequency="5s"I0221 00:40:02.133411 FLAG: --logtostderr="true"I0221 00:40:02.133416 FLAG: --nameservers=""
- I0221 00:40:02.133421 FLAG: --stderrthreshold="2"
- I0221 00:40:02.133426 FLAG: --v="2"
- I0221 00:40:02.133431 FLAG: --version="false"
- I0221 00:40:02.133440 FLAG: --vmodule=""
- I0221 00:40:02.133520 Starting SkyDNS server (0.0.0.0:10053)
- I0221 00:40:02.133827 Skydns metrics enabled (/metrics:10055)
- I0221 00:40:02.133836 Starting endpointsController
- I0221 00:40:02.133841 Starting serviceController__Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__
Prometheus 是 SoundCloud 研发的开源监控报警系统它能和 Grafana 一起让你完全了解 Kubernetes 集群的健康状况
容忍性和错误
想想自然母亲也没有那么安全, 她可以肆意摧毁, 替换, 选择和重组考虑到完全的稳健性几乎不可能达到, 我们需要这样一种机制: 它可以从随机事件不可预测的冲击压力源以及不稳定性中不断自我更新, 而非从中受损
同样的原则也适用于 Kubernetes 的环境当由于某些原因节点死亡, 所有的容器都将通过平衡资源利用重新分配到其他健康节点上
关于容器还有 liveness 和 readiness 探针 Liveliness 在应用程序进程无法继续时启动重启, Readiness 则用来判断一个容器何时可以开始接受流量
- __Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__apiVersion: v1
- kind: Pod
- metadata:
- labels:
- test: liveness
- name: liveness-exec
- spec:
- containers:
- - name: liveness
- image: k8s.gcr.io/busybox
- args:
- - /bin/sh
- - -c
- - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
- livenessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 5
- periodSeconds: 5
- readinessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 5
- periodSeconds: 5__Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__
另外一个重要技巧是故障注入, 有时也是混沌工程学方法的一部分, 能让系统不断演进, 避免混沌状态
混沌工程学这门学科在分布式系统上进行实验, 以提升系统容量, 在生产中应对混乱状态
PRINCIPLES OF CHAOS ENGINEERING
kube-monkey 是 Netflix Chaos Monkey 在 Kubernetes 集群中的一个实现它在鼓励和验证故障恢复服务开发的集群中随机删除 Kubernetes 的 Pod
去中心化和隔离
分布式系统和生物体很像心理学上有一种过度补偿机制, 指个体不仅要弥补某一方面的不足, 实现正常的补偿, 还要努力使自己补偿的结果超越普通人, 形成一种优势如果分布式系统也存在过度补偿机制, 显然能对突发事件作出更好的响应, 再结合适当的隔离, 就能限制爆炸半径
Kubernetes 提供命名空间的概念可以认为它们是有访问控制策略 (基于属性的访问控制(ABAC) 或更颗粒化的基于角色的访问控制 (RBAC)) 的区域虚拟集群
- __Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__kind: Role
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- namespace: default
- name: pod-reader
- rules:
- - apiGroups: [""] #"" indicates the core API group
- resources: ["pods"]
- verbs: ["get", "watch", "list"]__Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__
具体命名空间也可以通过网络策略 (说明哪些 Pod 集合可以相互交流以及和其他网络端点交流) 限制在网络层
- __Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__apiVersion: networking.k8s.io/v1
- kind: NetworkPolicy
- metadata:
- name: test-network-policy
- namespace: default
- spec:
- podSelector:
- matchLabels:
- role: db
- policyTypes:
- - Ingress
- - Egress
- ingress:
- - from:
- - ipBlock:
- cidr: 172.17.0.0/16
- except:
- - 172.17.1.0/24
- - namespaceSelector:
- matchLabels:
- project: myproject
- - podSelector:
- matchLabels:
- role: frontend
- ports:
- - protocol: TCP
- port: 6379
- egress:
- - to:
- - ipBlock:
- cidr: 10.0.0.0/24
- ports:
- - protocol: TCP
- port: 5978__Wed Mar 21 2018 10:53:06 GMT+0800 (CST)____Wed Mar 21 2018 10:53:06 GMT+0800 (CST)__
非预期
有时在不确定的情况下很难做决定, 比如, 为了应对出乎意料的高流量, 我们应该分配多少资源? 我们需要多少在云中运行的实例? 但很遗憾我们无法预测稀少事件的发生
Kubernetes 的一个优点是根据特定情况实现按比例缩放, 比如在资源利用中, 通过 cluster-autoscaler 调整节点数量, 包括删除没有被充分利用的节点
关于应用层的比例缩放, 可以使用 Horizontal Pod Autoscaler, 它能够根据资源利用或自定义指标自动调整 Pod 的个数
总结
最后我们还是诚实一点: 完全不脆弱是不可能实现的, 但是频繁快速的出现故障能使系统对错误有更强的抵抗力
为了降低脆弱性, 应该不断给部署过程以及在 Kubernetes 上运行的服务施以压力
来源: https://juejin.im/entry/5ab1c351f265da239e4df34c