diff --git a/README.md b/README.md
index 162fc8441c..1d4b14a734 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,8 @@ CURVE是网易自主设计研发的高性能、高可用、高可靠分布式存
- [Snapshotcloneserver](docs/cn/snapshotcloneserver.md)
- [CURVE质量体系介绍](docs/cn/quality.md)
- [CURVE监控体系介绍](docs/cn/monitor.md)
+ - [Client](docs/cn/curve-client.md)
+ - [Client Python API](docs/cn/curve-client-python-api.md)
- CURVE上层应用
- [对接k8s文档](docs/cn/k8s_csi_interface.md)
diff --git a/docs/cn/curve-client-python-api.md b/docs/cn/curve-client-python-api.md
new file mode 100644
index 0000000000..b730ad24a2
--- /dev/null
+++ b/docs/cn/curve-client-python-api.md
@@ -0,0 +1,304 @@
+#### 获取一个与curve集群交互的CBDClient对象
+
+```python
+import curvefs
+
+# 获取一个与后端集群交互的CBDClient对象,不同的CBDClient对象可以与不同的集群建立连接
+cbd1 = curvefs.CBDClient()
+cbd2 = curvefs.CBDClient()
+```
+
+#### 初始化CBDClient
+
+```python
+import curvefs
+cbd = curvefs.CBDClient()
+
+# 参数:curve-client配置文件的绝对路径
+# 返回值:返回0表示初始化成功,-1表示初始化失败
+cbd.Init("/etc/curve/client.conf")
+```
+
+#### 创建文件
+
+```python
+import curvefs
+cbd = curvefs.CBDClient()
+cbd.Init("/etc/curve/client.conf") # 后续示例省略初始化过程
+
+# 参数:三个参数分别为
+# 文件全路径
+# 文件所属用户信息
+# 文件大小
+# 返回值:返回0表示创建成功,否则返回错误码
+
+# 首先初始化user信息(curvefs的控制面接口都有用户信息验证,都需要传入用户信息)
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+user.password = "" # 密码为空时,可以省略
+
+# 调用Create接口创建文件
+cbd.Create("/curve", user, 10*1024*1024*1024)
+
+# UserInfo定义如下
+typedef struct UserInfo {
+ char owner[256]; # 用户名
+ char password[256]; # 用户密码
+} UserInfo_t;
+```
+
+#### 查看文件信息
+
+```python
+# 参数:三个参数分别为
+# 文件名
+# 用户信息
+# 文件信息[出参]
+# 返回值:返回0表示获取成功,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+
+# 构造file信息
+finfo = curvefs.FileInfo_t()
+
+# 查看文件信息
+cbd.StatFile("/curve", user, finfo)
+print finfo.filetype
+print finfo.length
+print finfo.ctime
+
+# FileInfo定义如下
+typedef struct FileInfo {
+ uint64_t id;
+ uint64_t parentid;
+ int filetype; # 卷类型
+ uint64_t length; # 卷大小
+ uint64_t ctime; # 卷创建时间
+ char filename[256]; # 卷名
+ char owner[256]; # 卷所属用户
+ int fileStatus; # 卷状态
+} FileInfo_t;
+
+# 文件状态
+#define CURVE_FILE_CREATED 0
+#define CURVE_FILE_DELETING 1
+#define CURVE_FILE_CLONING 2
+#define CURVE_FILE_CLONEMETAINSTALLED 3
+#define CURVE_FILE_CLONED 4
+#define CURVE_FILE_BEINGCLONED 5
+```
+
+#### 扩容文件
+
+```python
+# 参数:三个参数分别为
+# 文件名
+# 用户信息
+# 扩容后文件大小
+# 返回值:返回0表示扩容成功,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+
+# 扩容
+cbd.Extend("/curve", user, 20*1024*1024*1024)
+
+# 查看扩容后的文件信息
+finfo = curvefs.FileInfo_t()
+cbd.StatFile("/curve", user, finfo)
+print finfo.length
+```
+
+#### 打开/关闭文件
+
+```python
+# 打开文件
+# 参数:两个参数分别为
+# 文件名
+# 用户信息
+# 返回值:打开成功返回文件fd,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "user1"
+
+# 打开文件,返回fd
+fd = cbd.Open("/tmp1", user)
+
+# 关闭文件
+# 参数:打开文件时返回的fd
+# 返回值:关闭成功返回0,否则返回错误码
+cbd.Close(fd)
+```
+
+#### 读写文件
+
+```python
+# 写文件
+# 参数:四个参数分别为
+# 文件fd
+# 待写入数据
+# 偏移量
+# 写入数据长度
+# 返回值:写入成功返回写入字节数,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "user1"
+
+# 打开文件,返回fd
+fd = cbd.Open("/tmp1", user)
+
+# 写文件(目前读写都需要4k对齐)
+cbd.Write(fd, "aaaaaaaa"*512, 0, 4096)
+cbd.Write(fd, "bbbbbbbb"*512, 4096, 4096)
+
+# 读文件
+# 参数:四个参数分别为
+# 文件fd
+# 空字符串
+# 偏移量
+# 读取数据长度
+# 返回值:读取成功返回读取数据,否则返回错误码
+
+# 读取的内容通过返回值返回,buf在此没有意义,可以传入一个空串
+cbd.Read(fd,"", 0, 4096)
+
+# 关闭文件
+cbd.Close(fd)
+```
+
+备注:当前python api接口,不支持异步读写
+
+#### 删除文件
+
+```python
+# 参数:两个参数分别为
+# 文件名
+# 用户信息
+# 返回值:删除成功返回0,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+
+# 删除文件
+cbd.Unlink("/curve", user)
+```
+
+#### 重命名文件
+
+```python
+# 参数:三个参数分别为
+# 用户信息
+# 旧文件名
+# 新文件名
+# 返回值:成功返回0,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+
+# 重命名
+cbd.Rename(user, "/curve", "/curve-new")
+```
+
+#### 创建目录
+
+```python
+# 参数:两个参数分别为
+# 目录路径
+# 用户信息
+# 返回值:成功返回0,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+# 创建目录
+cbd.Mkdir("/curvedir", user)
+```
+
+#### 删除目录
+
+```python
+# 参数:两个参数分别为
+# 目录路径
+# 用户信息
+# 返回值:成功返回0,否则返回错误码
+
+# 构造user信息
+user = curvefs.UserInfo_t()
+user.owner = "curve"
+
+# 删除目录
+cbd.Rmdir("/curvedir", user)
+```
+
+#### 获取目录下的文件
+
+```python
+# 参数:两个参数分别为
+# 目录路径
+# 用户信息
+# 返回值:当前目录下的文件列表(只包括文件名)
+files = cbd.Listdir("/test", user)
+for f in files:
+ print f
+```
+
+#### 获取集群ID
+
+```python
+# 通过返回值判断是否获取成功
+# 成功返回集群id字符串
+# 失败返回空字符串
+clusterId = cbd.GetClusterId()
+print clusterId
+# c355675a-f4d2-4729-b80a-5a7bcc749d1c
+```
+
+#### 清理CBDClient对象
+
+```python
+cbd.UnInit()
+```
+
+### 错误码
+
+| Code | Message | 描述 |
+| :--: | :-------------------------- | ------------------------ |
+| 0 | OK | 操作成功 |
+| -1 | EXISTS | 文件或目录已存存在 |
+| -2 | FAILED | 操作失败 |
+| -3 | DISABLEDIO | 禁止IO |
+| -4 | AUTHFAIL | 认证失败 |
+| -5 | DELETING | 正在删除 |
+| -6 | NOTEXIST | 文件不存在 |
+| -7 | UNDER_SNAPSHOT | 快照中 |
+| -8 | NOT_UNDERSNAPSHOT | 非快照状态 |
+| -9 | DELETE_ERROR | 删除错误 |
+| -10 | NOT_ALLOCATE | Segment未分配 |
+| -11 | NOT_SUPPORT | 操作不支持 |
+| -12 | NOT_EMPTY | 目录非空 |
+| -13 | NO_SHRINK_BIGGER_FILE | 禁止缩容 |
+| -14 | SESSION_NOTEXISTS | Session不存在 |
+| -15 | FILE_OCCUPIED | 文件被占用 |
+| -16 | PARAM_ERROR | 参数错误 |
+| -17 | INTERNAL_ERROR | 内部错误 |
+| -18 | CRC_ERROR | CRC检查错误 |
+| -19 | INVALID_REQUEST | 请求参数存在异常 |
+| -20 | DISK_FAIL | 磁盘异常 |
+| -21 | NO_SPACE | 空间不足 |
+| -22 | NOT_ALIGNED | IO未对齐 |
+| -23 | BAD_FD | 文件正在被关闭,fd不可用 |
+| -24 | LENGTH_NOT_SUPPORT | 文件长度不满足要求 |
+| -25 | SESSION_NOT_EXIST | Session不存在(与-14重复) |
+| -26 | STATUS_NOT_MATCH | 状态异常 |
+| -27 | DELETE_BEING_CLONED | 删除文件正在被克隆 |
+| -28 | CLIENT_NOT_SUPPORT_SNAPSHOT | Client版本不支持快照 |
+| -29 | SNAPSHOT_FROZEN | Snapshot功能禁用中 |
+| -100 | UNKNOWN | 未知错误 |
+
diff --git a/docs/cn/curve-client.md b/docs/cn/curve-client.md
new file mode 100644
index 0000000000..476a293286
--- /dev/null
+++ b/docs/cn/curve-client.md
@@ -0,0 +1,139 @@
+## 1 概要
+
+curve作为中心化的分布式存储系统主要组件分为前端驱动Client模块、底层存储Chunkserver模块、元数据服务器MDS模块,以及快照系统。
+
+所谓前端驱动client模块即为curve client,它以动态库libcurve的方式向上提供服务,外部服务进程如Qemu、Curve-Nbd通过链接该库来使用curve提供的存储服务。(热升级后,curve client不再直接对接Qemu和Curve-Nbd等上层服务。)
+
+所以,curve client可以理解为用户行为入口。
+
+## 2 curve client功能点
+
+Curve Client存在的目的就是通过提供接口的方式向上提供用户数据存储服务,curve系统以分布式文件系统作为底层存储向上提供块存储服务。从用户角度来看,curve为其提供的就是一个可以进行随机读写的块设备,这个块设备对应的就是底层curvefs的一个文件。
+
+这个curvefs文件的底层存储方式是分布在多个底层集群节点上的,举个例子:
+
+用户创建一个1T的块设备,这个块设备在底层curvefs上就是一个1T大小的文件。如下图:
+
+> 注意:这个所谓的1T大小的文件只是一个逻辑概念,这个文件只有curve client和mds两个模块感知,底层存储集群chunksevrer节点不感知这个文件。
+
+
+
+用户一侧创建一个1T的块设备,对其而言是一个连续的0-1T的连续地址空间,其可以在这个空间内进行随机读写。但是从curve角度来看,这个1T大小的块设备就是一个由一批chunk组成的地址空间,每个chunk有唯一的ID编号,这些chunk会对应到底层chunkserver上一段真实的物理存储空间。
+
+curve client与底层存储集群以rpc方式通信,因此curve client的功能点也就呼之欲出。
+
+### 2.1 提供接口
+
+用户创建块设备及读写块设备都是通过curve client提供的接口,这些接口包括创建块设备、打开块设备等等,以及读写该块设备,为了追求极致的性能,curve向上提供异步读写接口。
+
+### 2.2 IO拆分
+
+从上图可以看到,用户的块设备其实在底层物理存储中是以chunk为单位打散在底层多个存储节点上的,这一方面可以提供处理的并发度,同时也能够提高数据的可靠性。
+
+用户写数据到curve client,client能够拿到用户IO的offset、length、data,这个offset + length在curve的文件上有可能会覆盖多个chunk,因为底层chunk是分布在不同的chunkserver上的,所以curve client需要把用户对块设备的的IO请求,转换为对底层不同chunkserver的chunk请求,并分别下发。
+
+### 2.3 IO跟踪
+
+IO拆分会将用户的IO根据offset和length拆分,比如一个用户的IO `offset = 0, length = 2*chunksize`,那么这个请求到client后,会被至少拆分成两个请求,因为这个IO正好横跨两个chunk,这两个chunk分布在不同的chunkserver上,因此一个大IO被拆分成了两个小IO,由于client的IO接口是异步的,而且client写chunk也是异步的,所以需要跟踪一个大IO的每个子IO,记录其返回状态,只有所有的子IO都返回这个IO才能算完成,然后才能向上返回给用户。
+
+### 2.4 元数据获取及缓存
+
+curve client本身是一个无状态的组件,不会保存文件的任何元数据信息,上面提到的IO拆分,是需要依据的,client需要知道chunk对应到具体chunkserver上的某一个物理chunk。这些信息都是通过mds获取的,mds会持久化文件的路由信息,当用户写某个块设备时,client需要从mds获取这个文件的元数据信息,然后保存在内存,供后续使用。
+
+一个用户IO下发需要的元信息:
+
+1. 上层文件与底层chunk的对应关系,即上层文件的逻辑chunk,与底层物理chunk的对应关系
+2. 底层物理chunk所属的raft group
+3. raft group所在的chunkserver列表
+
+
+### 2.5 mds failover 支持
+
+mds提供元数据存储服务,为了提高可用性,mds以集群方式服务,同一时刻只有一个mds提供服务,其他mds节点通过etcd进行监听,随时准备替代leader,成为新leader提供服务。
+
+curve client在IO下发及控制面调用时会与mds进行通信,通信以RPC方式进行,通信时需要指定对应的mds的地址,所以如果mds集群中服务节点切换时还需要client进行地址切换。
+
+### 2.6 Chunkserver failover 支持
+
+与mds高可用设计类似,chunkserver存储节点通过使用raft算法,实现多节点数据复制及高可用保证,在curve client一侧下发请求时需要先获取当前raft group的leader,然后将请求发往leader所在的节点。
+
+### 2.7 IO流控
+
+所谓IO流控就是curve client在感知底层集群负载过高时进行一定的流量控制,防止底层负载恶性循环。从本质上讲,client一侧的IO流控只是一种缓解方式,并非一种根本解决方案。
+
+## 3 curve client架构
+
+上节大致描述了client的功能点,本节分析client的架构,主要从模块架构和线程模型两方面。
+
+### 3.1 模块架构
+
+curve client的基本模块架构如下,其中client qos目前暂未实现
+
+
+
+### 3.2 线程模型
+
+
+
+这里以异步IO请求为例,client一侧共涉及到4类线程:
+
+1. 用户线程:用户发起异步IO请求,会调用client的AioWrite接口,AioWrite会将用户请求封装成task放入任务队列中,此时用户调用就返回了。
+2. 任务队列线程:任务队列线程会监听任务队列,只要有任务进来,就从队列中取出,进行IO拆分,拆分成的Sub-IO请求会放入IO分发队列中。
+3. IO分发线程:根据Sub-IO的信息,调用RPC发送异步请求到对应的chunkserver节点。
+4. BRPC线程:RPC的发送以及请求的返回都是在BRPC线程中处理的,rpc返回后还会调用异步请求的Closure回调。如果所有的Sub-IO都返回成功,则会找到对应的上层IO请求,并调用异步IO的回调(回调的操作也是在BRPC线程中执行)。
+
+## 4 关键点
+
+### 4.1 MetaCache
+
+IO拆分过程中,需要依赖文件的元数据信息,这些元数据信息在client一侧并不持久化,只是在需要的时候从mds获取。
+
+为了避免频繁与mds通信,client会对获取到的元数据进行缓存。
+
+缓存的元数据在2.4节已经提到,主要是以下几点:
+
+1. file chunk -> chunk id:上层文件与底层chunk的对应关系,即上层文件的逻辑chunk,与底层物理chunk的对应关系
+2. chunk id -> copyset id(raft group):底层物理chunk所属的raft group
+3. copyset id -> serverlist:raft group所在的chunkserver列表
+
+#### 4.1.1 元数据缓存更新
+
+通常文件一旦分配了对应的chunkid和copysetid,这些信息就不会变化。
+
+上述三种元数据会出现更新的就是copysetid到serverlist的映射关系。因为底层如果出现节点宕机、负载不均衡等情况会触发配置变更,这种情况下会导致copyset的chunkserver列表发生变更。
+
+client触发元数据更新都是通过RPC失败。
+
+更新的元数据信息包括
+
+1. raft group的leader信息
+
+ client发送请求是发送到raft group leader节点,在每次发送请求之前都会获取当前raft group的leader信息(metacache进行缓存)。
+
+ 请求发送到chunkserver之后,如果这个chunkserver已经不是leader了,那么**client会发起GetLeader请求到当前raft group里的其他chunkserver节点**。因为如果底层重新选举出了leader,节点肯定知道当前leader是谁,然后会把这个信息返回给client,client更新完metacache中的leader信息之后将请求转发到新leader。
+
+2. raft group的peer信息
+
+ 极端状况下,某个raft group因为底层节点宕机等原因,其group peer全部变更了。这种情况下,通过GetLeader是无法获取真正的leader信息,所以在重试多次之后client会向mds拉取当前raft group的最新信息。
+
+### 4.2 IO请求重试
+
+IO分发线程获取IO任务后会发送异步RPC请求,RPC请求返回后,会调用异步请求的回调。在回调中,会根据RPC请求的返回值,判断请求成功与否。如果请求失败,而且需要进行重试,那么会在回调中再次发起rpc请求。
+
+> 对于读写请求,重试次数设置很大,目的在于让IO尽可能成功返回。因为对于块设备而言,如果用户写入返回错误会造成上层认为块设备错误,硬盘损坏。
+
+RPC请求重试时,会进行预处理,分为两种情况:
+
+1. chunkserver overload
+
+ 这种情况下,对应的RPC Response中返回的错误码是OVERLOAD,说明底层chunkserver目前负载较高。
+
+ 此时,如果直接发送重试请求,大概率的情况下还是会返回OVERLOAD。所以这种情况下,应该让client在下发重试请求前,一段时间的sleep。
+
+ 在client一侧,针对这种情况,加入了睡眠重试时间指数退避,并加入了睡眠时间随机抖动,避免大量请求同时被返回OVERLOAD后,又同时重试。
+
+2. RPC Timeout
+
+ 出现这种情况的原因比较多,但是常见的原因是,底层chunkserver处理请求较多,压力较大,导致请求的返回时间超过了预期的RPC超时时间。
+
+ 这种情况下,如果重试请求的RPC超时时间不发生变化,那么很可能会重复上述流程,导致用户IO请求迟迟未能返回。所以,在这种情况下,重试请求会将RPC超时时间进行增加。
\ No newline at end of file
diff --git a/docs/images/curve-client-arch.png b/docs/images/curve-client-arch.png
new file mode 100644
index 0000000000..9ce137922b
Binary files /dev/null and b/docs/images/curve-client-arch.png differ
diff --git a/docs/images/curve-client-thread-model.png b/docs/images/curve-client-thread-model.png
new file mode 100644
index 0000000000..8e5b6277a5
Binary files /dev/null and b/docs/images/curve-client-thread-model.png differ
diff --git a/docs/images/curve-file.png b/docs/images/curve-file.png
new file mode 100644
index 0000000000..99dcda4132
Binary files /dev/null and b/docs/images/curve-file.png differ