代码的艺术

作者简介:章淼,章博士,清华大学计算机博士,百度云前端技术负责人,百度 Golang & Python 技术委员会成员。 笔记对比Google的工程师,国内的工程师写代码的占用时间显然过多了,而不太注重提前设计 ;Google 工程师们在开始实现某一模...
继续阅读 »

作者简介:章淼,章博士,清华大学计算机博士,百度云前端技术负责人,百度 Golang & Python 技术委员会成员。


笔记

对比Google的工程师,国内的工程师写代码的占用时间显然过多了,而不太注重提前设计 ;Google 工程师们在开始实现某一模块或功能时,会事先在代码库中搜索是否已经有可重用的代码,并且代码库中的代码具有完整的注释和文档。


提前设计的重要性

尽可能地提前完成两个文档


  • 需求分析文档
  • 系统设计文档

原因:在未启动实现细节代码之前构思设计时发现问题的修改,对比后期真正已经开始Coding的时候,对比发现问题进行修改,成本要低很多。文档一般只写主要逻辑,而代码涉及更多细节。


笔者备注:但这不是绝对的,修改是正常的,不要惧怕修改,反复尝试积累经验。


  • 需求分析文档:主要是在定义黑盒状态,描述外在,描述WHAT要做什么?
  • 系统设计文档:主要实在定义白盒状态,描述内在,描述HOW怎么做?

两者要有区分,不要混淆 ,也不要混在一起写!


需求分析文档的误区:
不要过早提前构想实现细节,我们的大脑会下意识地在我们构想如何实现时遇到的各种难题,而将原本的需求分析的思考挂起;举例:导弹 vs 炸弹,两者都有摧毁目标的能力,但是很明显导弹的价值更高,重要的是制导的功能,而不是爆炸本身。

系统设计文档的误区:
主要要写定义系统的架构、模块、接口、数据、关键算法、设计思路等等得过程记录。

系统架构要写什么以及方法

概念、模型、视图等等。


  • 静:系统静态的样子,功能模块如何划分等
  • 动:系统运转起来,各模块联动起来的样子
  • 细:不同角度,不同层次去描述
  • 每一个组件(模块、函数)保证单一性, Single purpose. 只做一件事!
  • 轻耦合,低内聚(避免全局变量(多处操作难以控制))
  • 当前系统设计所受到的约束(当前设计的瓶颈在哪?比如网络、吞吐量、占用 CPU 或文件位置资源等)
  • 需求分析是系统设计的来源
  • 模型和抽象的思维能力很重要(涉及概念:模型、数据结构、算法等等)

设计接口(Interface)要注意什么?

  • 接口定义系统外在的功能
  • 接口定义当前系统与外部系统之间的关系

接口Interface定义了系统对外的接口,往往比系统实现内部细节代码更重要,不要过于草率,因为一旦定义了接口,提供出去给调用方使用,想修改就太难了。所以设计接口有重要原则,站在使用者的角度考虑问题!


两点细节:


  • 向前兼容(尽量不要接口已升级,老接口全不能用,那就不是好的接口设计)
  • 使用方便(让调用者可以一目了然知道接口的作用,简化传参,说明返回值等等)

如何写代码?

代码是一种表达的方式。是写给人看的,要有编程规范
拥有编程规范的理想状态:

  1. 看别人代码就像看自己代码一样易懂;
  2. 看代码主要看逻辑,不要过多注重细节;
  3. 代码尽可能地不要让人去多想。

Don’t make me think!


Moudle模块

紧内聚,低耦合。单一功能。反例,定义一个 utils.py 内部包含诸多方法,不易懂。


模块一般可以分为两类:


  • 数据类的模块(1. 主要完成对数据的封装; 2. 对外提供的数据接口)
  • 过程类的模块(1. 不要包含数据,可以是调用数据类的模块或者调用其他过程类模块; 2. 具备操作性质的模块)

模块的重要性:


  1. 降低维护成本;
  2. 更好地复用

Class类和Function函数

两者是不同的模型,各自有各自适用的范围。


推荐方法: 和类的成员无关的函数,尽量独立出去单独一个函数,不建议作为类的成员函数。


面向对象思想的讨论:多态和继承,需要谨慎适用,作为Python的工程师,不太推崇Java中继承和多态,因为系统是逐渐长起来的,并不是从一开始就是一个成熟的样子,所以很难凭空去设计一个继承的关系。


模块的构成

文件头(注释)


  • 模块的说明,简要功能
  • 修改历史(时间、修改人,修改的内容)
  • 其他特殊细节的说明

函数(重要性仅次于模块)


  • 描述功能
  • 传入参数的描述(含义、类型、限制条件等等)
  • 返回值得描述(有足够明确的语义说明)


    逻辑判断型 check is XXX
    操作型(成功 or 失败)
    数据获取型(状态 + 数据)

  • 异常如何处理(是抛出?还是内部catch?要明确)


  • 明确单入口和单出口(多线程开发时尤为重要)

函数要尽可能的规模小,足够短(BUG 往往出现在非常长的一个函数里)


代码块的分段也很重要,分段背后是划分和逻辑表达。


代码是一种表达能力的体现,也算是文科的范畴! 注释不是补出来的!


命名的重要性:要准确、易懂、可读性强,尽量做到 望名生义 。


互联网时代的系统是运营出来的。


可检测性也是尤其重要的。(埋点、监控等等)


没有数据的收集,等于系统没有上线。


监控不单单只有传统意义上的内存、CPU、网络、崩溃率的监控,还应有线上真实数据监控,需要有足够多的状态记录。


日志是很有限的一种监控手段,并且采集日志也是一种资源耗费。推荐的手段:可以使用埋点,对外提供接口,有单独的系统调用接口进行有针对性的采集。


修身

好的程序员,与工作年限无关,与学历无关


学习-思考-实践

学习:主观意愿地学习,途径也有很多,例如书籍、开源代码、社区。忌讳夜郎自大、井底之蛙。注重培养自己学习吸收的能力,多读多看但是数量不是最终目的。


Stay Hungry, Stay Foolish. – Steve Jobs


思考:学习需要经过思考,形成自己的思维。


实践:《卓有成效的时间管理者 - 德鲁克》推荐阅读


知识-方法-精神

知识过时会非常快!


方法:分析问题、解决问题的能力尤其重要(定义问题、识别问题、定义关键问题)


精神:决定型,要做就要坚持做


前进的道路上不能永远都是鲜花和掌声。


基础乃治学之根本。


数据结构、软件工程、逻辑思维能力、研究能力,需要5-8年时间磨炼。

收起阅读 »

kvm虚拟机启动报错Unable to find security driver for model selinux

Kvm
好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误: [root@kvm-labs kvm]# virsh start centos7-lab-node1 error: Failed to ...
继续阅读 »

好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误:


[root@kvm-labs kvm]# virsh start centos7-lab-node1
error: Failed to start domain centos7-lab-node1
error: unsupported configuration: Unable to find security driver for model selinux

根据错误提示,怀疑是系统selinux的问题,但是发现selinux是disabled,难道要强制用selinux,不合理啊。重新梳理逻辑,kvm虚拟机是可被定义的,是不是定义的配置文件中有selinux相关定义,那是不是可以去掉,经过实验还真ok,解决步骤如下。


1. 进入虚拟机配置文件目录

cd /etc/libvirt/qemu/
# 如果你构建环境修改过默认路径,根据实际情况进入

2. 编辑虚拟机配置文件

vim  centos7-lab-node1.xml

.....................
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</rng>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'/>
</domain>

如上,删除<seclabel type='dynamic' model='selinux' relabel='yes'/> , 然后保存退出。


3. 重新定义配置文件

virsh define ./centos7-lab-node1.xml

然后重新执行virsh start centos7-lab-node1 就可以了。


如果想迁移虚拟机的存储路径也可以关机,修改配置文件下的存储路径,并将.qcow2文件移动到相应的目录下即可.


<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/data/kvmdata/centos7-lab-node1.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>

修改完成后,然后重新定义配置文件,重启虚拟机即可。

收起阅读 »

Centos系统进入单用户修改root用户密码

1. 重启系统,在选择进入系统界面按字母e2. 在rhgb前添加’rw’ ,在行末添加 ‘init=/bin/sh’ ,按 ‘Ctrl+x’ 进入系统进入系统后,修改密码echo "www.baidu.com | passwd --stdin root tou...
继续阅读 »

1. 重启系统,在选择进入系统界面按字母e

2. 在rhgb前添加’rw’ ,在行末添加 ‘init=/bin/sh’ ,按 ‘Ctrl+x’ 进入系统

进入系统后,修改密码

echo "www.baidu.com | passwd --stdin root
touch /.autorelabel
exec /sbin/init

等待一会,点击回车,进入重启。

收起阅读 »

MySQL的三种复制模式

MySQL支持的三种复制模式分别为: asynchronous 异步复制fully synchronous 全同步复制semi synchronous 半同步复制异步复制 (asynchronous replication)原理:在异步复制中,master写数...
继续阅读 »

MySQL支持的三种复制模式分别为:


  1. asynchronous 异步复制
  2. fully synchronous 全同步复制
  3. semi synchronous 半同步复制

异步复制 (asynchronous replication)

原理:在异步复制中,master写数据到binlog且sync,slave request binlog后写入relay-log并flush disk
优点:复制的性能最好
缺点: master挂掉后,slave可能会丢失事务
代表:MySQL原生的复制

全同步复制 (fully synchronous replication)

原理:在全同步复制中,master写数据到binlog且sync,所有slave request binlog后写入relay-log并flush disk,并且回放完日志且commit
优点:数据不会丢失
缺点:会阻塞master session,性能太差,非常依赖网络
代表:MySQL Cluster

半同步复制 (semi synchronous replication)

1. 普通的半同步复制

原理: 在半同步复制中,master写数据到binlog且sync,且commit,然后一直等待ACK。当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack(不需要回放完日志)
优点:会有数据丢失风险(低)
缺点:会阻塞master session,性能差,非常依赖网络,
代表:after commit, 原生的半同步



重点:由于master是在三段提交的最后commit阶段完成后才等待,所以master的其他session是可以看到这个提交事务的,所以这时候master上的数据和slave不一致,master crash后,slave数据丢失



2. 增强版的半同步复制(lossless replication)

原理: 在半同步复制中,master写数据到binlog且sync,然后一直等待ACK. 当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack(不需要回放完日志)
优点:数据零丢失(前提是让其一直是lossless replication),性能好
缺点:会阻塞master session,非常依赖网络
代表:after sync, 原生的半同步



重点:由于master是在三段提交的第二阶段sync binlog完成后才等待, 所以master的其他session是看不见这个提交事务的,所以这时候master上的数据和slave一致,master crash后,slave没有丢失数据



重要参数:
































参数 评论 默认值 推荐值 是否动态
rpl_semi_sync_master_wait_for_slave_count 至少有N个slave接收到日志 1 1 dynamic
rpl_semi_sync_master_wait_point 等待的point AFTER_SYNC AFTER_SYNC dynamic
rpl_semi_sync_master_timeout 切换复制的timeout 1000(10s) 1000 (1s) dynamic
rpl_semi_sync_master_enabled 是否开启半同步 OFF ON dynamic
rpl_semi_sync_slave_enabled 是否开启半同步 OFF ON dynamic

如何开启lossless replication:


########semi sync replication settings########
plugin_dir=/usr/local/mysql/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 1000

实践是检验真理的唯一标准

如何检验上述after_syncafter_commit, 如何检验上述原理的正确性。


InnoDB commit: 三阶段提交过程
A阶段: wite prepare log 写入Xid
B阶段: write binlog
C阶段: write commit log

测试点:master上当一个事务Waiting for semi-sync ACK from slave的时候,后来的事务是在A,B,C哪个阶段卡住呢?


0,RC模式

1. semi-sync C阶段等待

假设设置time-out=100000s,当事务一提交了一个大事务,在write commit log(C阶段)时候等待,
那么第二个事务在敲commit命令的时候,是卡在哪个阶段呢?是卡在 wite prepare log(A阶段)?还是write binlog(B阶段)?还是write commit log(C阶段)

测试:semi-sync vs loss-less semi-sync

【semi-sync】 C阶段等待
0, 开启事务1,然后在slave上执行stop slave,制造timeout的情况,让其阻塞。(Waiting for semi-sync ACK from slave)
1,在开启一个事务2,事务2插入一条特殊记录(XXXXX)。 (Waiting for semi-sync ACK from slave)
2,在开启一个事务3。
2.1,测试案例:这个时候,kill -9 mysqld,造成人为的mysql crash
3,假设卡在A阶段,那么事务3,肯定是看不到事务1,2写入的记录(XXXXX),且重启mysql后,事务2不会提交。
4,假设卡在C阶段,那么事务3,肯定是可以看见事务1,2写入的记录(XXXXX)。

经过测试:
1,是卡在C阶段,也就是说事务3是可以看见事务1,事务2的。
2,MySQL crash重启后,事务1,事务2的dml都已经提交成功,说明不是卡在A阶段

【loss-less semi-sync】B阶段等待

0, 开启事务1,然后在slave上执行stop slave,制造timeout的情况,让其阻塞。(Waiting for semi-sync ACK from slave)
1,在开启一个事务2,事务2插入一条特殊记录(XXXXX)。(Waiting for semi-sync ACK from slave)
2,在开启一个事务3
3,假设卡在A阶段,那么事务3,肯定是看不到事务1,2写入的记录(XXXXX),且重启mysql后,事务2不会提交。。
4,假设卡在B阶段,那么事务3,肯定是可以看见事务1,2写入的记录(XXXXX),且重启mysql后,事务1,2都会提交。。
5, 假设卡在C阶段,那么事务3,肯定是可以看见事务3写入的记录(XXXXX)。

经过测试:
1,是卡在B阶段,也就是说事务3,既看不见事务1的提交内容,也看不见事务2的提交内容,且重启mysql后,事务1,2都已经提交。。
2,MySQL crash重启后,事务1,事务2的dml都已经提交成功,说明不是卡在A阶段。

性能
semi-sync vs lossless semi-sync 的性能对比


根据以上的测试,可以得知,lossless只卡在B阶段,普通的semi-sync是卡在C阶段。
lossless的性能远远好于普通的semi-sync,即(after_sync 优于 after_commit)
因为lossless 卡在B阶段的时候可以堆积事务,可以在C阶段进行group commit。
普通的semi-sync,卡在C阶段,事务都已经commit了,并没有堆积的过程。


CAP理论:



一致性【C】
可用性【A】
分区容忍性【P】
理论:CAP 三者不可兼得,必须要牺牲一个


分区,是一定存在的,不是你想不要就不要的。所以,这里只剩下两种组合


CP 牺牲可用性



这种做法,就是保留强一致性,牺牲可用性
案例:可以将rpl_semi_sync_master_timeout设置成一个无限大的值,比如:100天,那么master和slave就强一致了,但是可用性就大打折扣


AP 牺牲一致性



这种做法,就是保留高可用性,牺牲一致性
案例:比如原生的异步复制就是这样咯。可以快速做到切换,但是一致性就没有保障


阅读分享:https://henduan.com/FJHU5

收起阅读 »

Kubernetes中的容器编排和应用编排

众所周知,Kubernetes 是一个容器编排平台,它有非常丰富的原始的 API 来支持容器编排,但是对于用户来说更加关心的是一个应用的编排,包含多容器和服务的组合,管理它们之间的依赖关系,以及如何管理存储。 在这个领域,Kubernetes 用 Helm 的...
继续阅读 »

众所周知,Kubernetes 是一个容器编排平台,它有非常丰富的原始的 API 来支持容器编排,但是对于用户来说更加关心的是一个应用的编排,包含多容器和服务的组合,管理它们之间的依赖关系,以及如何管理存储。


在这个领域,Kubernetes 用 Helm 的来管理和打包应用,但是 Helm 并不是十全十美的,在使用过程中我们发现它并不能完全满足我们的需求,所以在 Helm 的基础上,我们自己研发了一套编排组件……


什么是编排

不知道大家有没仔细思考过编排到底是什么意思? 我查阅了 Wiki 百科,了解到我们常说的编排的英文单词为 “Orchestration”,它常被解释为:


  • 本意:为管弦乐中的配器法,主要是研究各种管弦乐器的运用和配合方法,通过各种乐器的不同音色,以便充分表现乐曲的内容和风格。
  • 计算机领域:引申为描述复杂计算机系统、中间件 (middleware) 和业务的自动化的安排、协调和管理。

有趣的是 “Orchestration” 的标准翻译应该为“编配”,而“编排”则是另外一个单词 “Choreography”,为了方便大家理解, 符合平时的习惯,我们还是使用编排 (Orchestration) 来描述下面的问题。至于“编配 (Orchestration)” 和 “编排(Choreography)” 之争,这里有一篇文章,有兴趣可以看一下 。http://www.infoq.com/cn/news/2008/09/Orchestration


Kubernetes 容器编排技术

当我们在说容器编排的时候,我们在说什么?


在传统的单体式架构的应用中,我们开发、测试、交付、部署等都是针对单个组件,我们很少听到编排这个概念。而在云的时代,微服务和容器大行其道,除了为我们显示出了它们在敏捷性,可移植性等方面的巨大优势以外,也为我们的交付和运维带来了新的挑战:我们将单体式的架构拆分成越来越多细小的服务,运行在各自的容器中,那么该如何解决它们之间的依赖管理,服务发现,资源管理,高可用等问题呢?


在容器环境中,编排通常涉及到三个方面:


  • 资源编排 - 负责资源的分配,如限制 namespace 的可用资源,scheduler 针对资源的不同调度策略;
  • 工作负载编排 - 负责在资源之间共享工作负载,如 Kubernetes 通过不同的 controller 将 Pod 调度到合适的 node 上,并且负责管理它们的生命周期;
  • 服务编排 - 负责服务发现和高可用等,如 Kubernetes 中可用通过 Service 来对内暴露服务,通过 Ingress 来对外暴露服务。

在 Kubernetes 中有 5 种经常会用到的控制器来帮助我们进行容器编排,分别是 Deployment, StatefulSet, DaemonSet, CronJob, Job


在这 5 种常见资源中,Deployment 经常被作为无状态实例控制器使用; StatefulSet 是一个有状态实例控制器; DaemonSet 可以指定在选定的 Node 上跑,每个Node 上会跑一个副本,它有一个特点是它的Pod的调度不经过调度器,在Pod 创建的时候就直接绑定NodeName;最后一个是定时任务,它是一个上级控制器,和 Deployment 有些类似,当一个定时任务触发的时候,它会去创建一个 Job,具体的任务实际上是由 Job 来负责执行的。他们之间的关系如下图:

一个简单的例子
我们来考虑这么一个简单的例子,一个需要使用到数据库的 API 服务在 Kubernetes 中应该如何表示:

客户端程序通过 Ingress 来访问到内部的 API Service, API Service 将流量导流到 API Server Deployment 管理的其中一个 Pod 中,这个 Server 还需要访问数据库服务,它通过 DB Service 来访问 DataBase StatefulSet 的有状态副本。由定时任务 CronJob 来定期备份数据库,通过 DaemonSet 的 Logging 来采集日志,Monitoring 来负责收集监控指标。

容器编排的困境

Kubernetes 为我们带来了什么?
通过上面的例子,我们发现 Kubernetes 已经为我们对大量常用的基础资源进行了抽象和封装,我们可以非常灵活地组合、使用这些资源来解决问题,同时它还提供了一系列自动化运维的机制:如 HPA, VPA, Rollback, Rolling Update 等帮助我们进行弹性伸缩和滚动更新,而且上述所有的功能都可以用 YAML 声明式进行部署。

困境
但是这些抽象还是在容器层面的,对于一个大型的应用而言,需要组合大量的 Kubernetes 原生资源,需要非常多的 Services, Deployments, StatefulSets 等,这里面用起来就会比较繁琐,而且其中服务之间的依赖关系需要用户自己解决,缺乏统一的依赖管理机制。

应用编排

什么是应用?
一个对外提供服务的应用,首先它需要一个能够与外部通讯的网络,其次还需要能运行这个服务的载体 (Pods),如果这个应用需要存储数据,这还需要配套的存储,所以我们可以认为:

应用单元 = 网络 + 服务载体 +存储

那么我们很容易地可以将 Kubernetes 的资源联系起来,然后将他们划分为 4 种类型的应用:

  • 无状态应用 = Services + Volumes + Deployment
  • 有状态应用 = Services + Volumes + StatefulSet
  • 守护型应用 = Services + Volumes + DaemonSet
  • 批处理应用 = Services + Volumes + CronJob/Job

我们来重新审视一下之前的例子:

应用层面的四个问题
通过前面的探索,我们可以引出应用层面的四个问题:

  • 应用包的定义
  • 应用依赖管理
  • 包存储
  • 运行时管理

在社区中,这四个方面的问题分别由三个组件或者项目来解决:


  • Helm Charts: 定义了应用包的结构以及依赖关系;
  • Helm Registry: 解决了包存储;
  • HelmTiller: 负责将包运行在 Kubernetes 集群中。

Helm Charts
Charts 在本质上是一个 tar 包,包含了一些 yaml 的 template 以及解析 template 需要的 values, 如下图:templates 是 Golang 的 template 模板,values.yaml 里面包含了这个 Charts 需要的值。

Helm Registry
用来负责存储和管理用户的 Charts, 并提供简单的版本管理,与容器领域的镜像仓库类似这个项目是开源的。( https://github.com/caicloud/helm-registry)


Tiller


  • 负责将 Chart 部署到指定的集群当中,并管理生成的 Release (应用);
  • 支持对 Release 的更新,删除,回滚操作;
  • 支持对 Release 的资源进行增量更新;
  • Release 的状态管理;
  • Kubernetes下属子项目(https://github.com/kubernetes/helm) 。


Tiller 的缺陷


  1. 没有内建的认知授权机制,Tiller 跑在 kube-system 分区下,拥有整个集群的权限;
  2. Tiller 将 Release 安装到 Kubernetes 集群中后并不会继续追踪他们的状态;
  3. Helm+Tiller的架构并不符合 Kubernetes 的设计模式,这就导致它的拓展性比较差;
  4. Tiller 创建的 Release 是全局的并不是在某一个分区下,这就导致多用户/租户下,不能进行隔离;
  5. Tiller 的回滚机制是基于更新的,每次回滚会使版本号增加,这不符合用户的直觉。

Release Controller

为了解决上述的问题,我们基于 Kubernetes 的 Custom Resource Definition 设计并实现了我们自己的运行时管理系统 – Release Controller, 为此我们设计了两个新的 CRD – Release 和 Release History。


Release 创建
当 Release CRD 被创建出来,controller 为它创建一个新的 Release History, 然后将 Release 中的 Chart 和 Configuration 解析成 Kubernetes 的资源,然后将这些资源在集群中创建出来,同时会监听这些资源的变化,将它们的状态反映在 Release CRD 的 status 中。

Release 更新
当用户更新 Release 的时候,controller 计算出更新后的资源与集群中现有资源的 diff, 然后删除一部分,更新一部分,创建一部分,来使得集群中的资源与 Release 描述的一致,同时为旧的 Release 创建一份 Release History。

Release 回滚和删除
用户希望回滚到某一个版本的 Release, controller 从 Release History 中找到对应的版本,然后将 Release 的 Spec 覆盖,同时去更新集群中对应的资源。当 Release 被删除后,controller 将它关联的 Release History 删除,同时将集群中的其他资源一并删除。

架构图

这样的设计有什么好处?


  • 隔离性:资源使用 Namespace 隔离,适应多用户/租户;
  • 可读性:Release Controller 会追踪每个 Release 的子资源的状态;
  • 版本控制:你可以很容易地会退到某一个版本;
  • 拓展性:整个架构是遵循 Kubernetes 的 controller pattern,具有良好的可扩展性,可以在上面进行二次开发;
  • 安全性:因为所有的操作都是基于 Kubernetes 的 Resource,可以充分利用 Kubernetes 内建的认证鉴权模块,如 ABAC, RBAC 。

总而言之,编排不仅仅是一门技术也是一门艺术!谢谢!
分享阅读原文链接:https://mp.weixin.qq.com/s/zHlS2cQEHzRea_bqKpNA9A

收起阅读 »

漏洞风险评估CVSS介绍

什么是CVSS通用弱点评价体系(CVSS)是由NIAC开发、FIRST维护的一个开放并且能够被产品厂商免费采用的标准。利用该标准,可以对弱点进行评分,进而帮助我们判断修复不同弱点的优先等级。 CVSS(Common Vulnerability Scoring ...
继续阅读 »

什么是CVSS

通用弱点评价体系(CVSS)是由NIAC开发、FIRST维护的一个开放并且能够被产品厂商免费采用的标准。利用该标准,可以对弱点进行评分,进而帮助我们判断修复不同弱点的优先等级。


CVSS(Common Vulnerability Scoring System),即”通用漏洞评分系统”,是一个”行业公开标准,其被设计用来评测漏洞的严重程度,并帮助确定所需反应的紧急度和重要度”。


它的主要目的是帮助人们建立衡量漏洞严重程度的标准,使得人们可以比较漏洞的严重程度,从而确定处理它们的优先级。CVSS得分基于一系列维度上的测量结果,这些测量维度被称为量度(Metrics)。漏洞的最终得分最大为10,最小为0。


得分7~10的漏洞通常被认为比较严重,得分在4~6.9之间的是中级漏洞,0~3.9的则是低级漏洞。


CVSS系统包括三种类型的分数:基本分数、暂时分和环境分。


基本得分临时得分通常由安全产品卖主、供应商给出,因为他们能够更加清楚的了解漏洞的详细信息;


环境得分通常由用户给出,因为他们能够在自己的使用环境下更好的评价该漏洞存在的潜在影响。


所以应该是基于漏洞库的扫描, 需要预先知道该漏洞的威胁值?


就是说漏洞应该预先有脆弱性等级,系统的安全性评估是综合各个漏洞来进行的?


CVSS 2.0 计算方法: 通用漏洞评估方法CVSS 3.0 计算公式及说明 - caya - 博客园 (cnblogs.com)


一些指标具有不确定性和复杂性,会导致完全的定量分析困难。3个客观性指标和11个主观性指标。下一步:指标量化(客观性指标量化和主观性指标量化)。


CVSS评分计算方法

A. 基本评价(Base Metric)

基本评价指的是该漏洞本身固有的一些特点及这些特点可能造成的影响的评价分值


































序号 要素 可选值 评分
1 攻击途径 (AccessVector) 本地/远程 0.7/1.0
2 攻击复杂度(AccessComplexity) 高/中/低 0.6/0.8/1.0
3 认证(Authentication) 需要/不需要 0.6/1.0
4 机密性(Conflmpact) 不受影响/部分/完全 0/0.7/1
5 完整性(integlmpact) 不受影响/部分/完全 0/0.7/1
6 可用性(Availlmpact) 不受影响/部分/完全 0/0.7/1
7 权值倾向 平均/机密性/完整性/可用性 各0.333/权值倾向要素0.5另两个0.25

基础评价 = 四舍五入(10 * 攻击途径 攻击复杂度 认证 ((机密性 机密性权重) + (完整性 完整性权重) + (可用性 可用性权重)))


B.生命周期评价(Temporal Metric)

是针对最新类型漏洞(如: 0day漏洞)设置的评分项,因此SQL注入漏洞不用考虑


因此这里也列举出三个与时间紧密关联的要素如下:


















序号 要素 可选值 评分
1 可利用性 未证明/概念证明/功能性/完全代码 0.85/0.9/0.95/1.0
2 修复措施 官方补丁/临时补丁/临时解决方案/无 0.87/0.90/0.95/1.0
3 确认程度 不确认/未经确认/已确认 0.9/0.95/1.0

生命周期评价 =四舍五入(基础评价 可利用性 修复措施 * 未经确认)


C.环境评价(Environmental Metric)

每个漏洞会造成的影响大小都与用户自身的实际环境密不可分,因此可选项中也包括了环境评价,这可以由用户自评。(用户扫描配置时填写)














序号 要素 可选值 评分
1 危害影响程度 无/低/中/高 0/0.1/0.3/0.5
2 目标分布范围 无/低/中/高(0/1-15%/16-49%/50-100%) 0/0.25/0.75/1.0

环境评价 = 四舍五入<(生命周期评价 + [(10 -生命周期评价) *危害影响程度]) *目标分布范围>


评分与危险等级













序号 评分 危险等级
1 [0,4]
2 [4,7]
3 [7,10]
收起阅读 »

使用kubekey部署kubernetes集群

kubekey简介kubeykey是KubeSphere基于Go 语言开发的kubernetes集群部署工具,使用 KubeKey,您可以轻松、高效、灵活地单独或整体安装 Kubernetes 和 KubeSphere。 KubeKey可以用于以下三种安装场景...
继续阅读 »

kubekey简介

kubeykey是KubeSphere基于Go 语言开发的kubernetes集群部署工具,使用 KubeKey,您可以轻松、高效、灵活地单独或整体安装 Kubernetes 和 KubeSphere。


KubeKey可以用于以下三种安装场景:


  • 仅安装 Kubernetes集群
  • 使用一个命令安装 Kubernetes 和 KubeSphere
  • 已有Kubernetes集群,使用ks-installer 在其上部署 KubeSphere

项目地址:https://github.com/kubesphere/kubekey 开源公司:青云


kubekey安装

下载kk二进制部署命令,您可以在任意节点下载该工具,比如准备一个部署节点,或者复用集群中已有节点:


wget https://github.com/kubesphere/kubekey/releases/download/v1.2.0-alpha.2/kubekey-v1.2.0-alpha.2-linux-amd64.tar.gz
tar -zxvf kubekey-v1.2.0-alpha.2-linux-amd64.tar.gz
mv kk /usr/local/bin/

脚本下载安装:


export KKZONE=cn
curl -sfL | VERSION=v1.1.0 sh -
mv kk /usr/local/bin/

查看版本:


kk version

在所有节点上安装相关依赖


yum install -y socat conntrack ebtables ipset

所有节点关闭selinux和firewalld


setenforce 0 && sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
systemctl disable --now firewalld

所有节点时间同步


yum install -y chrony
systemctl enable --now chronyd
timedatectl set-timezone Asia/Shanghai

节点无需配置主机名,kubekey会自动纠正主机名。


部署单节点集群

部署单节点kubernetes


kk create cluster

同时部署kubernetes和kubesphere,可指定kubernetes版本或kubesphere版本


kk create cluster --with-kubernetes v1.20.4 --with-kubesphere v3.1.0

当指定安装KubeSphere时,要求集群中有可用的持久化存储。默认使用localVolume,如果需要使用其他持久化存储,请参阅addons配置。


部署多节点集群

准备6个节点,部署高可用kubernetes集群,kubekey的高可用实现目前是基于haproxy的本地负载均衡模式。


创建示例配置文件:


kk create config

根据您的环境修改配置文件config-sample.yaml,以下示例以部署3个master节点和3个node节点为例(不执行kubesphere部署,仅搭建kubernetes集群):


cat > config-sample.yaml <

使用配置文件创建集群

export KKZONE=cn
kk create cluster -f config-sample.yaml | tee kk.log

创建完成后查看节点状态

[root@kube-master1 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kube-master1 Ready control-plane,master 4m58s v1.20.6 192.168.93.60 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64
kube-master2 Ready control-plane,master 3m58s v1.20.6 192.168.93.61 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64
kube-master3 Ready control-plane,master 3m58s v1.20.6 192.168.93.62 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64
kube-node1 Ready worker 4m13s v1.20.6 192.168.93.63 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64
kube-node2 Ready worker 3m59s v1.20.6 192.168.93.64 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64
kube-node3 Ready worker 3m59s v1.20.6 192.168.93.65 CentOS Linux 7 (Core) 3.10.0-1127.el7.x86_64

查看所有pod状态

[root@kube-master1 ~]# kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-8545b68dd4-rbshc 1/1 Running 2 3m48s
kube-system calico-node-5k7b5 1/1 Running 1 3m48s
kube-system calico-node-6cv8z 1/1 Running 1 3m48s
kube-system calico-node-8rbjs 1/1 Running 0 3m48s
kube-system calico-node-d6wkc 1/1 Running 0 3m48s
kube-system calico-node-q8qp8 1/1 Running 0 3m48s
kube-system calico-node-rvqpj 1/1 Running 0 3m48s
kube-system coredns-7f87749d6c-66wqb 1/1 Running 0 4m58s
kube-system coredns-7f87749d6c-htqww 1/1 Running 0 4m58s
kube-system haproxy-kube-node1 1/1 Running 0 4m3s
kube-system haproxy-kube-node2 1/1 Running 0 4m3s
kube-system haproxy-kube-node3 1/1 Running 0 2m47s
kube-system kube-apiserver-kube-master1 1/1 Running 0 5m13s
kube-system kube-apiserver-kube-master2 1/1 Running 0 4m10s
kube-system kube-apiserver-kube-master3 1/1 Running 0 4m16s
kube-system kube-controller-manager-kube-master1 1/1 Running 0 5m13s
kube-system kube-controller-manager-kube-master2 1/1 Running 0 4m10s
kube-system kube-controller-manager-kube-master3 1/1 Running 0 4m16s
kube-system kube-proxy-2t5l6 1/1 Running 0 3m55s
kube-system kube-proxy-b8q6g 1/1 Running 0 3m56s
kube-system kube-proxy-dsz5g 1/1 Running 0 3m55s
kube-system kube-proxy-g2gxz 1/1 Running 0 3m55s
kube-system kube-proxy-p6gb7 1/1 Running 0 3m57s
kube-system kube-proxy-q44jp 1/1 Running 0 3m56s
kube-system kube-scheduler-kube-master1 1/1 Running 0 5m13s
kube-system kube-scheduler-kube-master2 1/1 Running 0 4m10s
kube-system kube-scheduler-kube-master3 1/1 Running 0 4m16s
kube-system nodelocaldns-l958t 1/1 Running 0 4m19s
kube-system nodelocaldns-n7vkn 1/1 Running 0 4m18s
kube-system nodelocaldns-q6wjc 1/1 Running 0 4m33s
kube-system nodelocaldns-sfmcc 1/1 Running 0 4m58s
kube-system nodelocaldns-tvdbh 1/1 Running 0 4m18s
kube-system nodelocaldns-vg5t7 1/1 Running 0 4m19s

kubekey集群维护

添加节点

kk add nodes -f config-sample.yaml

删除节点

kk delete node  -f config-sample.yaml

删除集群

kk delete cluster
kk delete cluster [-f config-sample.yaml]

集群升级

kk upgrade [--with-kubernetes version] [--with-kubesphere version]
kk upgrade [--with-kubernetes version] [--with-kubesphere version] [(-f | --file) path]
收起阅读 »

什么是PDCA模型和SMART原则

什么是 PDCA 模型?PDCA 循环是提高工作质量的理论方法,广泛应用在企业管理和个人工作中。P-D-C-A 这四个字母,分别代表:Plan(计划),Do(行动),Check(检查),Act(处理)。美国的质量管理大师戴明认为,高质量,不是来自基于结果的产品...
继续阅读 »

什么是 PDCA 模型?

PDCA 循环是提高工作质量的理论方法,广泛应用在企业管理和个人工作中。P-D-C-A 这四个字母,分别代表:Plan(计划),Do(行动),Check(检查),Act(处理)。美国的质量管理大师戴明认为,高质量,不是来自基于结果的产品检验,而是来自于基于过程的不断改善。


PDCA循环的四个过程


第一,Plan(计划)
一个 PDCA 循环式的「计划」,一定要有「Who do what by when」,也就是:「谁在什么时间之前做什么」,发给大家,而不是口头布置。

第二,Do(行动)


行动,是最占用时间,也是最重要的部分。因为有了计划,以及基于计划分解的,分配到每个人任务栏里的,有时间限制的具体任务,执行就变得责任明确、优先级清晰。


第三,Check(检查)
每一件交代出去的任务,就像一个扔出去的回行镖,最终必须回到你的手上。这是 PDCA 的关键。

第四,Act(处理)
处理不是行动,而是总结成功经验,制定相应标准,或者把未解决或新出现的问题转入下一个 PDCA 循环。

什么是 SMART 原则?

SMART原则是一套制定目标的原则。S-M-A-R-T这5个字母,代表Specific(具体的),Measurable(可衡量的),Attainable(可实现的),Relevant(相关的),和Time-Based(有时间限制的)。


它的本质,是砍掉模棱两可,砍掉标准争议,砍掉不切实际,砍掉无关目标,砍掉无限拖延,让目标从“一千个人心中的一千个哈姆雷特”,变成同一个。


五个字母的含义


第一,Specific(具体的)
绩效考核要切中特定的工作指标,不能笼统。

第二,Measurable(可衡量的)
绩效指标是数量化或者行为化的,验证这些绩效指标的数据或者信息是可以获得的。

第三,Attainable(可实现的)
绩效指标在付出努力的情况下可以实现,避免设立过高或过低的目标。

第四,Relevant(相关性的)
绩效指标是与工作的其它目标是相关联的;绩效指标是与本职工作相关联的。

第五,Time-bound(有时间限制的)
注重完成绩效指标的特定期限。

收起阅读 »

Python的发展趋势

一、Python发展历史Python是一种计算机程序设计语言。你可能在之前听说过很多编程语言,比如难学的C语言(语法和实现难度),非常流行的JAVA语言(尤其是现在分布式存储和服务),非常有争议的PHP(常见 WordPress 大多网站),前端HTML、Ja...
继续阅读 »

一、Python发展历史

Python是一种计算机程序设计语言。你可能在之前听说过很多编程语言,比如难学的C语言(语法和实现难度),非常流行的JAVA语言(尤其是现在分布式存储和服务),非常有争议的PHP(常见 WordPress 大多网站),前端HTML、JavaScripts、Node.JS、还有最近随着容器风行的Golang等等。那Python是What?


  • 1989年,Python的创始人为吉多·范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承。
  • 1991年,第一个Python编译器诞生。它是用C语言实现的,并能够调用C语言的库文件。从一出生,Python已经具有了:类,函数,异常处理,包含表和词典在内的核心数据类型,以及模块为基础的拓展系统。
  • 1992年,Python之父发布了Python的web框架Zope1.
  • Python 1.0 - January 1994 增加了 lambda, map, filter and reduce.
  • Python 2.0 - October 16, 2000,加入了内存回收机制,构成了现在Python语言框架的基础
  • Python 2.4 - November 30, 2004, 同年目前最流行的WEB框架Django 诞生
  • Python 2.5 - September 19, 2006
  • Python 2.6 - October 1, 2008
  • Python 2.7 - July 3, 2010
  • In November 2014, it was announced that Python 2.7 would be supported until 2020, and reaffirmed that there would be no 2.8 release as users were expected to move to Python 3.4+ as soon as possible
  • Python 3.0 - December 3, 2008
  • Python 3.1 - June 27, 2009
  • Python 3.2 - February 20, 2011
  • Python 3.3 - September 29, 2012
  • Python 3.4 - March 16, 2014
  • Python 3.5 - September 13, 2015

最新参考:https://www.python.org/downloads/release


二、Python的前景

最新的TIOBE( https://www.tiobe.com/tiobe-index/ )排行榜,Python赶超JAVA占据第二名了, Python崇尚优美、清晰、简单,是一个优秀并广泛使用的语言。

我们看看17年Python的排名:


由上图17年预测可见,Python整体呈上升趋势,反映出Python应用越来越广泛并且也逐渐得到大家的认知和认可,影响度也越来越大,在国内Python开发招聘的岗位也越来越多,我们来看看2017年100offer统计情况:

从上图我们可以看出Python的人均面邀数为6,整体年薪在34w左右,在职位招聘排行榜前十名,应该还算不错的表现哦。


三、Python的应用领域

Python可以应用于众多领域,如:数据分析、组件集成、网络服务、图像处理、数值计算和科学计算等众多领域。


目前业内几乎所有大中型互联网企业都在使用Python,如:Youtube、Dropbox、BT、Quora(中国知乎)、豆瓣、知乎、Google、Yahoo!、Facebook、NASA、阿里、百度、腾讯、汽车之家、美团等。


目前Python主要的应用领域

  • 云计算: 在云计算领域Python可谓有一席之地, 典型应用OpenStack这个大体量的开源云计算产品就是居于Python开发的。


  • WEB开发: 已有众多大型网站均为Python开发,Youtube, Dropbox, 豆瓣, 知乎等…., Python也有许多Web开发框架,典型WEB框架有Django、Pylons,还有Tornado、Bottle、Flask等。


  • 系统运维: 从国内的趋势来看,掌握一门编程语言已经成为了必然的结果,Python在国内已经成为了首选,不管是做自动化运维还是业务运维现在Python在运维领域已经应用极广。


  • 金融:量化交易,金融分析,在金融工程领域,Python不但在用,且用的最多,而且重要性逐年提高。原因:作为动态语言的Python,语言结构清晰简单,库丰富,成熟稳定,科学计算和统计分析都很牛逼,生产效率远远高于c,c++,java,尤其擅长策略回测


  • 图形GUI: PyQT, WxPython, TkInter, PySide等在图形用户接口领域都有广泛被应用。


哪些公司在用Python

  • 谷歌:Google App Engine 、code.google.com 、Google earth 、谷歌爬虫、Google广告等项目都在大量使用Python开发。


  • CIA: 美国中情局网站就是用Python开发的。


  • NASA: 美国航天局(NASA)大量使用Python进行数据分析和运算。


  • YouTube:世界上最大的视频网站YouTube就是用Python开发的。


  • Dropbox:美国最大的在线云存储网站,全部用Python实现,每天网站处理10亿个文件的上传和下载。


  • Instagram:美国最大的图片分享社交网站,每天超过3千万张照片被分享,全部用python开发。


  • Facebook:大量的基础库均通过Python实现的


  • Redhat: 世界上最流行的Linux发行版本中的yum包管理工具就是用python开发的


  • 豆瓣: 公司几乎所有的业务均是通过Python开发完成的。


  • 知乎: 国内最大的问答社区,通过Python开发(国外Quora)


  • 春雨医生:国内知名的在线医疗网站是用Python开发的


除上面之外,还有搜狐、金山、腾讯、盛大、网易、百度、阿里、淘宝 、土豆、新浪、果壳等公司都在使用Python完成各种各样的任务, 互联网公司广泛使用Python来做的事一般有:自动化运维、自动化测试、大数据分析、爬虫、Web 等


为什么是Python而不是其他语言呢?

C 和 Python、Java、C#等

C语言: 代码编译得到 机器码 ,机器码在处理器上直接执行,每一条指令控制CPU工作


其他语言: 代码编译得到 字节码 ,虚拟机执行字节码并转换成机器码再后在处理器上执行


Python和C Python这门语言是由C开发而来 

对于使用:Python的类库齐全并且使用简洁,如果要实现同样的功能,Python 10行代码可以解决,C可能就需要100行甚至更多.
对于速度:Python的运行速度相较与C,绝逼是慢了


Python 和 Java、C#等

对于使用:Linux原装Python,其他语言没有;以上几门语言都有非常丰富的类库支持


对于速度:Python在速度上可能稍显逊色


Python和PHP相比

Python提供了丰富的数据结构,非常容易和c集成。相比较而言,php集中专注在web上。 php大多只提供了系统api的简单封装,但是python标准包却直接提供了很多实用的工具。python的适用性更为广泛,php在web更加专业,php的简单数据类型,完全是为web量身定做。


所以,Python和其他语言没有什么本质区别,其他区别在于:擅长某领域、人才丰富、先入为主。语言是死的,每个语言的诞生都有它的道理,所以选择你喜欢的,开心的玩起来。

收起阅读 »

yum和apt-get命令对比

说明 Redhat系 Debian系 更新缓存 yum makecache apt-get update 更新包 yum update apt-get upgrade 检索包 yum search apt-cache search 检索包内文件 yum pro...
继续阅读 »






















































说明 Redhat Debian
更新缓存 yum makecache apt-get update
更新包 yum update apt-get upgrade
检索包 yum search apt-cache search
检索包内文件 yum provides apt-file search
安装指定的包 yum install apt-get install
删除指定的包 yum remove apt-get remove
显示指定包的信息 yum info apt-cache show
显示包所在组的一览 yum grouplist -
显示指定包所在组的信息 yum groupinfo -
安装指定的包组 yum groupinstall -
删除指定的包组 yum groupremove -
参考库的设定文件 /etc/yum.repos.d/* /etc/apt/sources.list
安装完的包的列表 rpm -qa dpkg-query -l
显示安装完的指定包的信息 rpm -qi apt-cache show
安装完的指定包内的文件列表 rpm -ql dpkg-query -L
安装完的包的信赖包的列表 rpm -qR apt-cache depends
安装完的文件信赖的包 rpm -qf dpkg -S
收起阅读 »