Ansible自动福运来平台制作化运维的安装及常用模块解释

(一)前言:

Ansible是今年来越来越火福运来平台制作Q> 1279829431【源码链接】dashengba.com 的一款开源运维自动化工具,通过Ansible可以实现运维自动化,提高运维工程师的工作效率,减少人为失误。Ansible通过本身集成的非常丰富的模块可以实现各种管理任务,其自带模块超过上千个。更为重要的是,它操作简单,但提供的功能又非常丰富,在运维领域,几乎可以做任何事。

Ansible自2012年发布以来,很快在全球流行,其特点如下:

Ansible基于Python开发,运维工程师对其二次开发相对比较容易;

Ansible丰富的内置模块,几乎可以满足一切要求;

管理模式非常简单,一条命令可以影响上千台主机;

无客户端模式,底层通过SSH通信;

我们可以通过四种方式和Ansible交互,我这里只研究了其中两种方式,应付日常工作足够了。分别如下:

Ad-Hoc命令集:user直接通过Ad-Hoc命令集调用Ansible工具集来完成任务。

playbooks:user预先编写好ansible playbooks,通过执行playbooks中预先编排好的任务集,按序执行任务。

1、Ansible工作集:

Ansible工作集包含inventory、Modules、Plugins和API,其中,inventory(清单)用来管理设备列表,可以通过分组实现,对组的调用直接影响组内的所有主机;modules是各种执行模块,几乎所有的管理任务都是通过模块执行的;plugins提供了各种附加功能;API为编程人员提供一个接口,可以基于此做Ansible的二次开发。

Ansible可以通过单条命令或者配置文件来对多台主机进行控制及更改,下面将从安装及配置依次写出来。

2、playbook配置文件

playbook配置文件使用YAML语法,具有简洁明了、结构清晰等特点。playbook配置文件类似于shell脚本,是一个YAML格式的文件,用于保存针对特定需求的任务列表。上面介绍的ansible命令虽然可以完成各种任务,但是当配置一些复杂任务时,逐条输入就显得效率非常低下了。更有效的方案是在playbook配置文件中放置所有的任务代码,利用ansible-playbook命令执行该文件,可以实现自动化运维。YAML文件的扩展名通常为.yaml或.yml。

(二)Ansible的安装及配置

通过一个简单的环境把Ansible的配置及安装写下来,环境如下:

最终效果:可以通过Ansible server来控制server 1和server 2。

一、部署前工作:

1、若采用本地yum仓库安装,请下载我提供的本地yum仓库,提取码:buqy ,我提供的是Ansible 2.3.1.0版本。

2、若本机可上网,也可以直接将yum仓库指向互联网,可以安装Ansible 2.4.x.x版本。

3、默认采用TCP 22进行与客户机进行通信,若有更改,需自行设置防火墙,我这里为了方便,直接关闭了防火墙。

二、安装Ansible(二选一即可):

1、采用互联网yum仓库的安装方式:

[root@ansible ~]# yum clean all        #清除yum缓存[root@ansible ~]# yum -y install ansible            #安装Ansible[root@ansible ~]# ansible --version                  #可以查看到此信息,说明安装成功ansible2.4.2.0config file = /etc/ansible/ansible.cfg        .............................

2、采用我提供的本地yum仓库安装方式:

[root@ansible yum.repos.d]# mount /dev/cdrom /media        #挂载我提供的ISO文件mount: /dev/sr0 写保护,将以只读方式挂载[root@ansible yum.repos.d]# cat /etc/yum.repos.d/a.repo      #删除或移动原有yum配置文件,并编写本地yum文件:[fd]baseurl=file:///mediagpgcheck=0[root@ansible yum.repos.d]# yum clean all          #清除yum缓存[root@ansibleyum.repos.d]# yum -y install ansible            #安装Ansible[root@ansible yum.repos.d]# ansible --version              #可以查看到此信息,说明安装成功ansible 2.3.1.0  config file = /etc/ansible/ansible.cfg          .....................

我这里采用了互联网yum仓库进行安装,即ansible 2.4.2.0。

安装已经完成,但是若要正常的使用Ansible,还需要解决一个问题,就是在控制多台主机时,若要每执行一次命令或脚本都要输入一次对端密码的话,显得就很鸡肋,所以还需要创建SSH免交互登录,如下:

以下操作都在Ansible服务器进行:

[root@ansible ~]# ssh-keygen -t rsa            #在Ansible服务器生成密钥对,执行后默认一直按回车即可Generating public/privatersa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):#默认按回车Enter passphrase (empty for no passphrase):#默认按回车Enter same passphrase again:#默认按回车Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:#默认按回车SHA256:zhd2++KvByxFPE4ZKmDdmTHp6cjsuIEz5M26QrkBfes root@ansibleThe key's randomart image is:#默认按回车+---[RSA 2048]----+|      o. .o*.o  ||    . .. =o*    || .      ...= .  ||. . .    .o o    || . o.. oSooo.    ||  +o.+ o+.ooo.  || . += +oo ....  ||  o E+....  ...  ||  .o...  .o=o  |+----[SHA256]-----+#至此密钥对已经生成了,隐藏存在当前用户的宿主目录下。[root@ansible ~]# ls -a | grep ssh        #查看.ssh[root@ansible ~]# cd .ssh[root@ansible .ssh]# ls      #查看.ssh目录下的文件,有公钥和私钥id_rsa  id_rsa.pub  known_hosts[root@ansible ~]# ssh-copy-id root@192.168.1.2            #复制公钥到主机192.168.1.2root@192.168.1.2's password:#输入主机1.2的root用户密码[root@ansible ~]# ssh-copy-id root@192.168.1.3            #复制公钥到主机192.168.1.3root@192.168.1.3's password:#输入主机1.3的root用户密码#在实际生产环境中,不会使用root身份,更改一下复制公钥时指定的用户即可。[root@ansible ~]# ssh 192.168.1.2          #测试是否可以免密码登录Last login: Tue Jul 23 08:11:39 2019 from 192.168.1.88[root@server1 ~]# exit              #退出192.168.1.2的shell环境[root@ansible ~]# ssh 192.168.1.3                #测试是否可以免密码登录Last login: Tue Jul 23 08:43:16 2019 from 192.168.1.88[root@server 2 ~]# exit          #退出192.168.1.3的shell环境

三、Ansible配置:

inventory是Ansible管理主机信息的配置文件,相当于系统的hosts文件功能,默认存放在/etc/ansible/hosts,在hosts文件中,通过分组来组织设备,Ansible通过inventory来定义主机和分组,若不使用默认的/etc/ansible/hosts,可以通过ansible -i 新的inventory路径 来指定inventory,我这里直接采用默认的路径。

1、以分组的方式添加需要管理的主机:

正是管理之前,首先要编写hosts文件,因为Ansible通过将设备列表以分组的方式添加hosts文件来实现对设备的管理。hosts文件中,[ ]包含的是组名,设备列表支持域名及IP地址,默认情况下,通过访问22端口(SSH)来管理设备,若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号标明,以行为分隔单位,也支持通配符。

[root@ansible ~]# vim /etc/ansible/hosts            #编辑清单文件,在文件末尾写入以下内容.....................#省略部分内容  [web]#定义一个名为web的分组,下面是web组中的主机192.168.1.2192.168.1.3[test01]#定义一个名为test01的分组,下面是test01组中的主机www.warrent.com:222#若目标主机使用了非默认的SSH端口,可以在域名后面加端口号来指定ljz[2:5].test.com#[2:5]表示2~5之间的所有数字,如ljz2.test.com、ljz3.test.com .......的所有主机192.168.1.4:66#IP地址后面也可以指定非默认的端口号#将需要管理的主机写入后,保存退出即可。注意,该文件中包含一个隐含的分组“all”,表示所有主机。

配置完成后,可以针对hosts定义的组进行远程操作,也可以针对组中所指定的某一个或者多个主机操作,如下:

[root@ansible ~]# ansible web -m command -a "systemctl status httpd" --limit "192.168.1.2"#查看web组中的192.168.1.2主机httpd服务的状态192.168.1.2| FAILED | rc=3>>● httpd.service - The Apache HTTP Server  Loaded: loaded (/usr/lib/systemd/system/httpd. preset: disabled)  Active: inactive (dead)    Docs: man:httpd(8)          man:apachectl(8)non-zeroreturncode#也可以这样:[root@ansible ~]# ansible 192.168.1.2 -m command -a "systemctl status httpd"192.168.1.2| FAILED | rc=3>>● httpd.service - The Apache HTTP Server  Loaded: loaded (/usr/lib/systemd/system/httpd. preset: disabled)  Active: inactive (dead)    Docs: man:httpd(8)          man:apachectl(8)non-zeroreturncode[root@ansible ~]# ansible 192.168.1.* -m command -a "systemctl status httpd"#查询192.168.1.0这个网段所有主机的httpd服务状态192.168.1.2| FAILED | rc=3>>    .................192.168.1.3| FAILED | rc=3>>    .................

四、Ansible命令:

[root@ansible ~]#ansible#输入ansible后,连续按两下tab键,可以查看ansible所有相关命令ansibleansible-docansible-playbook-2ansible-2ansible-doc-2ansible-playbook-2.7ansible-2.7ansible-doc-2.7ansible-pull..........................

命令1、ansible:

ansible是生产环境中使用非常频繁的命令之一,主要应用在以下场景:

临时性的维护,没有规律,临时需要做的任务,也称为非固化需求。

临时一次性操作。

二次开发接口调用。

ansible可用的选项如下:

-v:输出详细的执行过程信息,可以得到执行过程所有的信息。

-i PATH:指定inventory信息,默认为/etc/ansible/hosts。

-f:并发线程数,默认为5个线程。

--private-key=PRIVATE_KEY_FILE:指定密钥文件。

-m:指定执行使用的模块。

-M:指定模块的存放路径,默认为/usr/share/ansible,也可以通过ANSIBLE_LIBRARY来设定默认路径。

-a:指定模块参数。

-u:指定远程主机以哪个用户运行命令。

-l:限制运行主机,等同于“--limit”。

--list-hosts:列出符合条件的主机列表,不执行任何命令。

用法示例1(需要提前在/etc/ansible/hosts文件中定义web组):

[root@ansible ~]# ansible all -f 5 -m ping<!--检查所有主机是否存活-->192.168.1.3 | SUCCESS => {    "changed": false,    "ping": "pong"}192.168.1.2 | SUCCESS => {    "changed": false,    "ping": "pong"}<!--其中192.168.1.3和1.2是执行主机,SUCCESS表示命令执行成功,“=> {”表示返回的

结果。“changed”:false表示没有对主机做出更改,“ping”:“pong”表示执行了ping命令的

返回结果。命令中“all”关键字在前面提到过,代表了/etc/ansible/hosts文件中的所有主机,

不需要在hosts文件中定义,系统中默认存在的-->

用法示例2:

[root@ansible ~]#ansibleweb--list#列出web组所有的主机列表hosts(2):    192.168.1.2192.168.1.3#以上表示web中包含两个主机,分别是1.2和1.3

用法示例3:

[root@ansible ~]# ansible web -m command -a "df -hT"        #显示web组中主机的磁盘使用情况192.168.1.2| SUCCESS | rc=0>>文件系统                类型      容量  已用  可用 已用% 挂载点/dev/mapper/centos-root xfs        50G  5.8G  45G  12% /devtmpfs                devtmpfs895M0895M0% /dev                          ............................#省略部分192.168.1.3| SUCCESS | rc=0>>文件系统            类型      容量  已用  可用 已用% 挂载点/dev/mapper/cl-root xfs        17G  5.5G  12G  33% /devtmpfs            devtmpfs897M0897M0% /devtmpfs              tmpfs912M84K912M1% /dev/shm                          ............................#省略部分

ansible的返回结果非常友好,一般会用三种颜色来表示执行结果:红色、绿色和橘yellow(那个颜色被和谐了)。其中红色代表执行过程中有异常;橘yellow表示命令执行后目标有状态变化;绿色表示执行成功且没有对目标主机做修改。

命令2、ansible-doc:

ansible-doc用来查询ansible模块文档的说明,类似于man命令,针对每个模块都有详细的用法说明及应用案例介绍。

[root@ansible ~]# ansible-doc -l | wc -l                  #列出支持的模块1378#支持的模块有1378个[root@ansible ~]# ansible-doc ping            #查询ping模块的说明信息> PING    (/usr/lib/python2.7/site-packages/ansible/modules/system/ping.py)        A trivial testmodule,thismodulealwaysreturns`pong'onsuccessful contact. It doesnotmake senseinplaybooks, but        it is useful from /usr/bin/ansible' to verify the ability to

                            ................#省略部分内容

命令3、ansible-playbook:

ansible-playbook是日常应用中使用率最高的命令,类似于Linux中的sh或source命令,用来执行系列任务。其工作机制是:通过读取预先编写好的playbook文件实现集中处理任务。ansible-playbook命令后跟yml格式的playbook文件,playbook文件存放了要执行的任务代码,命令使用方式如下(playbook.yml文件需要提前编写好,最好指定playbook.yml的绝对路径):

[root@ansible ~]# ansible-playbook playbook.yml

命令4、ansible-console:

ansible-console是ansible为我们提供的一款交互式工具,类似于Windows中的cmd及Linux中的shell。可以在ansible-console虚拟出来的终端上像shell一样使用ansible内置的各种命令,这为习惯于shell交互方式的用户提供了良好的使用体验,所有的操作与shell类似,而且支持tab键补全。具体操作如下:

[root@ansible ~]# ansible-console          #连接交互式工具Vaultpassword:#ansible 2.4.2.0会提示输入一个密码,随便输入后按回车即可,不允许空值Welcome to the ansible console.Type helpor? to list commands.root@all (2)[f:5]$ cd web#切换到web组root@web (2)[f:5]$ list#列出组中主机192.168.1.2192.168.1.3root@web (2)[f:5]$ ifconfig ens33#查询每个主机的网卡信息root@web (2)[f:5]$ exit#退出ansible-console环境

五、Ansible中自带的模块介绍:

1、command模块:

command模块在远程主机执行命令,不支持管道,重定向等shell特性,其余和shell类似,常用参数如下:

chdir:在远程主机上运行命令前需要提前进入的目录。

creates:在命令运行时创建一个文件,如果文件已经存在,则不会执行创建任务。

removes:在命令运行时移除一个文件,如果文件不存在,则不会执行移除任务。

executeble:指明运行命令的shell程序。

[root@ansible ~]# ansible all -m command -a "chdir=/home ls ./"#在所有主机上运行“ls ./”命令,运行前切换至/home目录下。

2、shell模块(相当于万能模块,可以执行大多数命令):

shell模块在远程主机执行命令,相当于调用远程主机的shell进程,然后在shell下打开一个子shell运行命令。和command模块的区别是它支持shell特性,如管道符、重定向等。

[root@ansible ~]# ansible web -m shell -a 'echo "hello world" >> /tmp/hello.txt'#在web组的主机上编写一个txt文件192.168.1.2 | SUCCESS | rc=0 >>192.168.1.3| SUCCESS |rc=0>>[root@ansible ~]# ansible web -m shell -a ' cat /tmp/hello.txt'        #查看编写的文件192.168.1.3 | SUCCESS | rc=0 >>hello world192.168.1.2 | SUCCESS | rc=0 >>hello world

3、copy模块:

copy模块用于复制指定主机文件到远程主机的位置,常见参数如下:

src:指出源文件路径,可以使用相对路径和绝对路径。支持直接指定目录,如果源是目录,则目标也要是目录。

dest:指出复制文件的目标目录位置,使用绝对路径,支持直接指定目录。如果源是目录,则目标也要是目录,如果目标已经存在,则会覆盖原有内容。

mode:指出复制时,目标文件的权限,可选。

owner:指出复制时,目标文件的属主,可选。

group:指出复制时,目标文件的属组,可选。

content:指出复制到目标主机上的内容,不能与src一起使用,相当于复制content指明的数据到目标文件中。

[root@ansible ~]# ansible web -m copy -a "src=/etc/hosts dest=/tmp/ mode=777 owner=nobody group=root"#将本机的/etc/hosts文件复制到web组中的主机,并指定权限为777,属主为nobody,属组为root。

4、hostname模块:

hostname模块用于管理主机名,常用参数如下:

name:指明主机名。

[root@ansible ~]# ansible 192.168.1.2 -m hostname -a "name=web1"#将主机192.168.1.2的主机名改为web1192.168.1.2 | SUCCESS =>{ansible_facts:{ansible_domain:,ansible_fqdn:web1,        ansible_hostname web1ansible_nodename:web1    },changed:truename:web1}[root@server1 ~]# hostname      #在192.168.1.2主机上查看web1[root@server1 ~]# cat /etc/hostname                  #在192.168.1.2主机上查看web1#更改主机名后需重启才可使新的主机名生效。

5、yum模块:

yum模块基于yum机制,对远程主机管理程序包,常用参数如下:

name:程序包的名称,可以带上版本号。若不指明版本,则默认安装最新版本。

state=present | latest | absent:指明对程序包执行的操作,present表示安装程序包,latest表示安装最新版本的程序包,absent表示卸载程序包。

disablerepo:在用yum安装时,临时禁用某个仓库的ID。

enablerepo:在用yum安装时,临时启用某个仓库的ID。

conf_file:yum运行时的配置文件,而不是使用默认的配置文件。

diable_gpg_check=yes | no:是否启用完整性校验功能。

[root@ansible ~]# ansible web -m yum -a "name=httpd state=present"<!--

在web组中的主机上安装httpd服务,需要注意的是,管理端只是发送yum指令到被

管理端,被管理端要存在可用的yum仓库才可以成功安装。

        -->

6、Service模块:

Service模块用来管理远程主机上的服务的模块,常见参数如下:

name:被管理的服务名称。

state=started | stopped | restarted | reloaded:动作包含启动、关闭、重启及重新加载配置文件。

enabled=yes | no:表示是否设置该服务开机自启动。

runlevel:如果设定了enabled开机自启动,则要定义在那些运行目标下自动启动,如2/3/4/5。

[root@ansible ~]# ansible web -m service -a "name=httpd state=started enabled=yes"#启动httpd服务,并设置为开机自启动。

7、user模块:

user模块用于管理远程主机上的用户账号,常见参数如下:

name:必须参数,账号名称。

state=present | absent:创建或删除账号,present表示创建,absent表示删除。

system=yes | no:是否为系统账户。

uid:用户UID。

group:用户的基本组。

groups:用户的附加组。

shell:默认使用的shell。

home:用户的家目录。

move_home=yes | no:如果设置的家目录已经存在,是否将已存在的家目录进行移动。

password:用户的密码。

comment:用户的注释信息。

remove=yes | no:当state=absent时,是否要删除用户的家目录。

[root@ansible ~]# ansible web -m user -a 'name=user1 system=yes uid=501 group=root groups=sshd shell=/sbin/nologin home=/home/user1 password=user1 comment="test user"'#创建一个名为user1的用户[root@ansible ~]# ansible web -m user -a "name=user1 remove=yes state=absent"#删除刚才创建的user1用户

8、group模块:

group模块用于管理组,用于新建或删除组,常用参数如下:

gid:指定组的gid

name:指定组的name

state=present | absent:创建或删除

system=yes | no:是否为系统组

[root@ansible ~]#  ansible web -m group -a 'name=test gid=300 state=present system=yes'#创建gid为300,组名为test的系统组。[root@ansible ~]#  ansible web -m group -a 'name=test gid=300 state=absent system=yes'#删除刚刚创建的组。

9、mount模块:

mount模块用于挂载文件系统,常用参数如下:

src:要挂载的设备或文件系统

name:指定挂载点

fstype:指定文件系统类型

ots=w | r | o :设置文件读写类型,可组合使用。

state=present | absent | mounted | unmounted:present表示只修改fstab文件中的配置,不自动创建挂载点,而且不挂载;absent表示删除挂载点,修改fstab文件;mounted:自动创建挂载点并挂载,添加自动挂载(fstab);unmounted:只卸载,不删除挂载点,不修改fstab文件。

[root@an..~]# ansible web -m mount -a 'name=/warrent src=/dev/cdrom fstype=iso9660 state=mounted'#挂载iso镜像到/warrent目录下,并设置开机自动挂载。[root@ansible ~]#  ansible web -m mount -a 'name=/warrent state=absent'#卸载ISO镜像,并删除挂载点,删除开机自动挂载。[root@an..~]# ansible web -m mount -a "path=/mnt/data src=/dev/sdb1 fstype=xfs ots=wr state=mounted"#注:mount已经使用path代替了原来的name参数,但是name参数还是可以使用的。

10、cron模块:

cron模块用来管理计划任务,常用参数如下:

name:指定计划任务描述,必填

job:要执行的任务

user:运行计划任务的用户

执行时间:

minute:0-59,默认为 *

hour:0-23,默认为 *

day:1-31,默认为 *

month:1-12,默认为 *

weekday:1-7,默认为 *

state=present | absent:present表示添加计划任务;absent表示删除计划任务。

[root@ansible ~]# ansible web -m cron -a 'name=test user=root minute=*/2 job="echo test >> /tmp/warrent.txt" state=present'#添加一个计划任务测试一下[root@ansible ~]# ansible web -m shell -a "crontab -l"                #查看创建的任务计划192.168.1.2 | SUCCESS | rc=0 >>#Ansible: test*/2 * * * *echotest>> /tmp/warrent.txt192.168.1.3 | SUCCESS | rc=0 >>#Ansible: test*/2 * * * *echotest>> /tmp/warrent.txt

11、 script模块:

功能:在远程主机上执行主控端的脚本,相当于scp+shell组合。

用法如下:

[root@ansible ~]#ansible web -m script -a "/home/test.sh"

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容