Ansible專業(yè)教程

一米间、簡介

Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine.

Design Principles

Have a dead simple setup process and a minimal learning curve
Be super fast & parallel by default
Require no server or client daemons; use existing SSHd
Use a language that is both machine and human friendly
Focus on security and easy auditability/review/rewriting of content
Manage remote machines instantly, without bootstrapping
Allow module development in any dynamic language, not just Python
Be usable as non-root
Be the easiest IT automation system to use, ever.

二崖面、安裝

ansible依賴于Python 2.6或更高的版本掌唾、paramiko能颁、PyYAML及Jinja2。

2.1 編譯安裝

解決依賴關系

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

2.2 rpm包安裝
# yum install ansible

注意:不同版本的ansible的功能差異可能較大。

三、簡單應用

ansible通過ssh實現(xiàn)配置管理薄榛、應用部署、任務執(zhí)行等功能让歼,因此敞恋,需要事先配置ansible端能基于密鑰認證的方式聯(lián)系各被管理節(jié)點。

ansible <host-pattern> [-f forks] [-m module_name] [-a args]
-m module:默認為command

ansible-doc: Show Ansible module documentation
-l, --list List available modules
-s, --snippet Show playbook snippet for specified module(s)

四谋右、YAML

4.1 YAML介紹

YAML是一個可讀性高的用來表達資料序列的格式硬猫。YAML參考了其他多種語言,包括:XML改执、C語言啸蜜、 Python、Perl以及電子郵件格式RFC2822等辈挂。Clark Evans在2001年在首次發(fā)表了這種語言衬横,另外 Ingy d?t Net與Oren Ben-Kiki也是這語言的共同設計者。

YAML Ain't Markup Language终蒂,即YAML不是XML蜂林。不過遥诉,在開發(fā)的這種語言時,YAML的意思其實 是:"Yet Another Markup Language"(仍是一種標記語言)噪叙。其特性:

YAML的可讀性好
YAML和腳本語言的交互性好
YAML使用實現(xiàn)語言的數據類型
YAML有一個一致的信息模型
YAML易于實現(xiàn)
YAML可以基于流來處理
YAML表達能力強矮锈,擴展性好

更多的內容及規(guī)范參見http://www.yaml.org

4.2 YAML語法

YAML的語法和其他高階語言類似构眯,并且可以簡單表達清單愕难、散列表、標量等數據結構惫霸。其結構 (Structure)通過空格來展示猫缭,序列(Sequence)里的項用"-"來代表,Map里的鍵值對用":"分隔壹店。 下面是一個示例猜丹。

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,如example.yaml硅卢。

4.2.1 list

列表的所有元素均使用“-”打頭射窒,例如:

\# A list of tasty fruits  
- Apple  
- Orange    
- Strawberry  
- Mango  

4.2.2 dictionary

字典通過key與value進行標識,例如:

---
\# An employee record
name: Example Developer
job: Developer
skill: Elite

也可以將key:value放置于{}中進行表示将塑,例如:
---
\# An employee record
{name: Example Developer, job: Developer, skill: Elite}

五脉顿、Ansible基礎元素

5.1 變量

5.1.1 變量命名

變量名僅能由字母、數字和下劃線組成点寥,且只能以字母開頭艾疟。

5.1.2 facts

facts是由正在通信的遠程目標主機發(fā)回的信息,這些信息被保存在ansible變量中敢辩。要獲取指定的遠程主機所支持的所有facts蔽莱,可使用如下命令進行:

\# ansible hostname -m setup

5.1.3 register

把任務的輸出定義為變量,然后用于其他任務戚长,示例如下:

  tasks:
     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

5.1.4 通過命令行傳遞變量

在運行playbook的時候也可以傳遞一些變量供playbook使用盗冷,示例如下:

    ansible-playbook test.yml --extra-vars "hosts=www user=mageedu"

5.1.5 通過roles傳遞變量

當給一個主機應用角色的時候可以傳遞變量,然后在角色內使用這些變量同廉,示例如下:

- hosts: webservers
  roles:
    - common
    - { role: foo_app_instance, dir: '/web/htdocs/a.com',  port: 8080 }

5.2 Inventory

ansible的主要功用在于批量主機操作仪糖,為了便捷地使用其中的部分主機,可以在inventory file中將其分組命名恤溶。默認的inventory file為/etc/ansible/hosts乓诽。

inventory file可以有多個,且也可以通過Dynamic Inventory來動態(tài)生成咒程。

5.2.1 inventory文件格式

inventory文件遵循INI文件風格鸠天,中括號中的字符為組名≌室觯可以將同一個主機同時歸并到多個不同的組中稠集;此外奶段,當如若目標主機使用了非默認的SSH端口,還可以在主機名稱之后使用冒號加端口號來標明剥纷。

ntp.magedu.com

[webservers]
www1.magedu.com:2222
www2.magedu.com

[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com

如果主機名稱遵循相似的命名模式痹籍,還可以使用列表的方式標識各主機,例如:

[webservers]
www[01:50].example.com

[databases]
db-[a:f].example.com

5.2.2 主機變量

可以在inventory中定義主機時為其添加主機變量以便于在playbook中使用晦鞋。例如:

[webservers]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=8080 maxRequestsPerChild=909

5.2.3 組變量

組變量是指賦予給指定組內所有主機上的在playboo中可用的變量蹲缠。例如:

[webservers]        
www1.magedu.com         
www2.magedu.com

[webservers:vars]
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com

5.2.4 組嵌套

inventory中,組還可以包含其它的組悠垛,并且也可以向組中的主機指定變量线定。不過,這些變量只能在ansible-playbook中使用确买,而ansible不支持斤讥。例如:

[apache]
httpd1.magedu.com
httpd2.magedu.com

[nginx]
ngx1.magedu.com
ngx2.magedu.com

[webservers:children]
apache
nginx

[webservers:vars]
ntp_server=ntp.magedu.com

5.2.5 inventory參數

ansible基于ssh連接inventory中指定的遠程主機時,還可以通過參數指定其交互方式湾趾;這些參數如下所示:

ansible_ssh_host
  The name of the host to connect to, if different from the alias you wish to give to it.
ansible_ssh_port
  The ssh port number, if not 22
ansible_ssh_user
  The default ssh user name to use.
ansible_ssh_pass
  The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_sudo_pass
  The sudo password to use (this is insecure, we strongly recommend using --ask-sudo-pass)
ansible_connection
Connection type of the host. Candidates are local, ssh or paramiko.  The default is paramiko before Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on whether ControlPersist is supported.
ansible_ssh_private_key_file
Private key file used by ssh.  Useful if using multiple keys and you don't want to use SSH agent.
ansible_shell_type
The shell type of the target system. By default commands are formatted using 'sh'-style syntax by default. Setting this to 'csh' or 'fish' will cause commands executed on target systems to follow those shell's syntax instead.
ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at "/usr/bin/python" such as \*BSD, or where /usr/bin/python
is not a 2.X series Python.  We do not use the "/usr/bin/env" mechanism as that requires the remote user's
path to be set right and also assumes the "python" executable is named python, where the executable might
be named something like "python26".
ansible\_\*\_interpreter
Works for anything such as ruby or perl and works just like ansible_python_interpreter.
This replaces shebang of modules which will run on that host.

5.3 條件測試

如果需要根據變量芭商、facts或此前任務的執(zhí)行結果來做為某task執(zhí)行與否的前提時要用到條件測試。

5.3.1 when語句

在task后添加when子句即可使用條件測試搀缠;when語句支持Jinja2表達式語法铛楣。例如:

tasks:
 - name: "shutdown Debian flavored systems"
    command: /sbin/shutdown -h now
 when: ansible_os_family == "Debian"

when語句中還可以使用Jinja2的大多“filter”,例如要忽略此前某語句的錯誤并基于其結果(failed或者sucess)運行后面指定的語句艺普,可使用類似如下形式:

tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

此外蛉艾,when語句中還可以使用facts或playbook中定義的變量。

5.4 迭代

當有需要重復性執(zhí)行的任務時衷敌,可以使用迭代機制。其使用格式為將需要迭代的內容定義為item變量引用拓瞪,并通過with_items語句來指明迭代的元素列表即可缴罗。例如:

- name: add several users
  user: name={{ item }} state=present groups=wheel
  with_items:
     - testuser1
     - testuser2

上面語句的功能等同于下面的語句:

- name: add user testuser1
  user: name=testuser1 state=present groups=wheel
- name: add user testuser2
  user: name=testuser2 state=present groups=wheel

事實上,with_items中可以使用元素還可為hashes祭埂,例如:

- name: add several users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

ansible的循環(huán)機制還有更多的高級功能面氓,具體請參見官方文檔(http://docs.ansible.com/playbooks_loops.html)。

七蛆橡、ansible playbooks

playbook是由一個或多個“play”組成的列表舌界。play的主要功能在于將事先歸并為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講泰演,所謂task無非是調用ansible的一個module呻拌。將多個play組織在一個playbook中,即可以讓它們聯(lián)同起來按事先編排的機制同唱一臺大戲睦焕。下面是一個簡單示例藐握。

    - 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

7.1 playbook基礎組件

7.1.1 Hosts和Users

playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執(zhí)行任務靴拱。hosts用于指定要執(zhí)行指定任務的主機,其可以是一個或多個由冒號分隔主機組猾普;remote_user則用于指定遠程主機上的執(zhí)行任務的用戶袜炕。如上面示例中的

    -hosts: webnodes
     remote_user: root

不過,remote_user也可用于各task中初家。也可以通過指定其通過sudo的方式在遠程主機上執(zhí)行任務偎窘,其可用于play全局或某任務;此外溜在,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶陌知。

    - hosts: webnodes
      remote_user: mageedu
      tasks:
        - name: test connection
          ping:
          remote_user: mageedu
          sudo: yes

7.1.2 任務列表和action

play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的所有主機上執(zhí)行炕泳,即在所有主機上完成第一個任務后再開始第二個纵诞。在運行自下而下某playbook時,如果中途發(fā)生錯誤培遵,所有已執(zhí)行任務都將回滾浙芙,因此,在更正playbook后重新執(zhí)行一次即可籽腕。

task的目的是使用指定的參數執(zhí)行模塊嗡呼,而在模塊參數中可以使用變量。模塊執(zhí)行是冪等的皇耗,這意味著多次執(zhí)行是安全的南窗,因為其結果均一致。

每個task都應該有其name郎楼,用于playbook的執(zhí)行結果輸出万伤,建議其內容盡可能清晰地描述任務執(zhí)行步驟。如果未提供name呜袁,則action的結果將用于輸出敌买。

定義task的可以使用“action: module options”或“module: options”的格式,推薦使用后者以實現(xiàn)向后兼容阶界。如果action一行的內容過多虹钮,也中使用在行首使用幾個空白字符進行換行。

    tasks:
      - 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     

7.1.3 handlers

用于當關注的資源發(fā)生變化時采取一定的操作氧映。

“notify”這個action可用于在每個play的最后被觸發(fā)春畔,這樣可以避免多次有改變發(fā)生時每次都執(zhí)行指定的操作,取而代之,僅在所有的變化發(fā)生完成后一次性地執(zhí)行指定操作拐迁。在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

案例:

heartbeat.yaml
- 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 mode 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

八、roles

ansilbe自1.2版本引入的新特性缓淹,用于層次性哈打、結構化地組織playbook。roles能夠根據層次型結構自動裝載變量文件讯壶、tasks以及handlers等料仗。要使用roles只需要在playbook中使用include指令即可。簡單來講伏蚊,roles就是通過分別將變量立轧、文件、任務躏吊、模板及處理器放置于單獨的目錄中氛改,并可以便捷地include它們的一種機制。角色一般用于基于主機構建服務的場景中比伏,但也可以是用于構建守護進程等場景中胜卤。

一個roles的案例如下所示:
    site.yml
    webservers.yml
    dbservers.yml
    roles/
       common/
         files/
         templates/
         tasks/
         handlers/
         vars/
         meta/
       webservers/
         files/
         templates/
         tasks/
         handlers/
         vars/
         meta/

而在playbook中,可以這樣使用roles:

---
- hosts: webservers
  roles:
     - common
     - webservers

也可以向roles傳遞參數赁项,例如:

---

- hosts: webservers
  roles:
    - common
    - { role: foo_app_instance, dir: '/opt/a',  port: 5000 }
    - { role: foo_app_instance, dir: '/opt/b',  port: 5001 }

甚至也可以條件式地使用roles葛躏,例如:

---

- hosts: webservers
  roles:
    - { role: some_role, when: "ansible_os_family == 'RedHat'" }

8.1 創(chuàng)建role的步驟

(1) 創(chuàng)建以roles命名的目錄;
(2) 在roles目錄中分別創(chuàng)建以各角色名稱命名的目錄悠菜,如webservers等舰攒;
(3) 在每個角色命名的目錄中分別創(chuàng)建files、handlers悔醋、meta芒率、tasks、templates和vars目錄篙顺;用不到的目錄可以創(chuàng)建為空目錄,也可以不創(chuàng)建充择;
(4) 在playbook文件中德玫,調用各角色;

8.2 role內各目錄中可用的文件

tasks目錄:至少應該包含一個名為main.yml的文件椎麦,其定義了此角色的任務列表宰僧;此文件可以使用 include包含其它的位于此目錄中的task文件;
files目錄:存放由copy或script等模塊調用的文件观挎;
templates目錄:template模塊會自動在此目錄中尋找Jinja2模板文件琴儿;
handlers目錄:此目錄中應當包含一個main.yml文件段化,用于定義此角色用到的各handler;在handler中使用include包含的其它的handler文件也應該位于此目錄中造成;
vars目錄:應當包含一個main.yml文件显熏,用于定義此角色用到的變量;
meta目錄:應當包含一個main.yml文件晒屎,用于定義此角色的特殊設定及其依賴關系喘蟆;ansible 1.3及其以后的版本才支持;
default目錄:為當前角色設定默認變量時使用此目錄鼓鲁;應當包含一個main.yml文件蕴轨;

九、Tags

tags用于讓用戶選擇運行playbook中的部分代碼骇吭。ansible具有冪等性橙弱,因此會自動跳過沒有變化的部分溃槐,即便如此胡控,有些代碼為測試其確實沒有發(fā)生變化的時間依然會非常地長产镐。此時绘搞,如果確信其沒有變化宜狐,就可以通過tags跳過此些代碼片斷蛇尚。

十啼肩、Jinja2相關

10.1 字面量
表達式最簡單的形式就是字面量亿笤。字面量表示諸如字符串和數值的 Python 對象净当。下面 的字面量是可用的:

“Hello World”:
雙引號或單引號中間的一切都是字符串内斯。無論何時你需要在模板中使用一個字 符串(比如函數調用、過濾器或只是包含或繼承一個模板的參數)像啼,它們都是 有用的俘闯。

42 / 42.23:
直接寫下數值就可以創(chuàng)建整數和浮點數。如果有小數點忽冻,則為浮點數真朗,否則為 整數。記住在 Python 里僧诚, 42 和 42.0 是不一樣的遮婶。

[‘list’, ‘of’, ‘objects’]:
一對中括號括起來的東西是一個列表。列表用于存儲和迭代序列化的數據湖笨。例如 你可以容易地在 for 循環(huán)中用列表和元組創(chuàng)建一個鏈接的列表:

<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
                         ('downloads.html', 'Downloads')] %}
    <li><a href="{{ href }}">{{ caption }}</a></li>
{% endfor %}
</ul>

(‘tuple’, ‘of’, ‘values’):
元組與列表類似旗扑,只是你不能修改元組。如果元組中只有一個項慈省,你需要以逗號 結尾它臀防。元組通常用于表示兩個或更多元素的項。更多細節(jié)見上面的例子。

{‘dict’: ‘of’, ‘key’: ‘and’, ‘value’: ‘pairs’}:
Python 中的字典是一種關聯(lián)鍵和值的結構袱衷。鍵必須是唯一的捎废,并且鍵必須只有一個 值。字典在模板中很少使用致燥,罕用于諸如 xmlattr() 過濾器之類登疗。

true / false:
true 永遠是 true ,而 false 始終是 false 篡悟。

10.2 算術運算

Jinja 允許你用計算值谜叹。這在模板中很少用到,但是為了完整性允許其存在搬葬。支持下面的 運算符:

+
    把兩個對象加到一起荷腊。通常對象是素質,但是如果兩者是字符串或列表急凰,你可以用這 種方式來銜接它們女仰。無論如何這不是首選的連接字符串的方式!連接字符串見 ~ 運算符抡锈。 {{ 1 + 1 }} 等于 2 疾忍。
-
    用第一個數減去第二個數。 {{ 3 - 2 }} 等于 1 床三。
/
    對兩個數做除法一罩。返回值會是一個浮點數。 {{ 1 / 2 }} 等于 {{ 0.5 }} 撇簿。
//
    對兩個數做除法聂渊,返回整數商。 {{ 20 // 7 }} 等于 2 四瘫。
%
    計算整數除法的余數汉嗽。 {{ 11 % 7 }} 等于 4 。
*
    用右邊的數乘左邊的操作數找蜜。 {{ 2 * 2 }} 會返回 4 饼暑。也可以用于重 復一個字符串多次。 {{ ‘=’ * 80 }} 會打印 80 個等號的橫條洗做。
**
    取左操作數的右操作數次冪弓叛。 {{ 2**3 }} 會返回 8 。

10.3 比較操作符

==
    比較兩個對象是否相等诚纸。
!=
    比較兩個對象是否不等邪码。
>
    如果左邊大于右邊,返回 true 咬清。
>=
    如果左邊大于等于右邊,返回 true 。
<
    如果左邊小于右邊旧烧,返回 true 影钉。
<=
    如果左邊小于等于右邊,返回 true 掘剪。

10.4 邏輯運算符

對于 if 語句平委,在 for 過濾或 if 表達式中,它可以用于聯(lián)合多個表達式:

and
    如果左操作數和右操作數同為真夺谁,返回 true 廉赔。
or
    如果左操作數和右操作數有一個為真,返回 true 匾鸥。
not
    對一個表達式取反(見下)蜡塌。
(expr)
    表達式組。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末勿负,一起剝皮案震驚了整個濱河市馏艾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奴愉,老刑警劉巖琅摩,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锭硼,居然都是意外死亡房资,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門檀头,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轰异,“玉大人,你說我怎么就攤上這事鳖擒「日悖” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵蒋荚,是天一觀的道長戳稽。 經常有香客問我,道長期升,這世上最難降的妖魔是什么惊奇? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮播赁,結果婚禮上颂郎,老公的妹妹穿的比我還像新娘。我一直安慰自己容为,他們只是感情好乓序,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布寺酪。 她就那樣靜靜地躺著,像睡著了一般替劈。 火紅的嫁衣襯著肌膚如雪寄雀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天陨献,我揣著相機與錄音盒犹,去河邊找鬼。 笑死眨业,一個胖子當著我的面吹牛急膀,可吹牛的內容都是我干的。 我是一名探鬼主播龄捡,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼卓嫂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了墅茉?” 一聲冷哼從身側響起命黔,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎就斤,沒想到半個月后悍募,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡洋机,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年坠宴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绷旗。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡喜鼓,死狀恐怖,靈堂內的尸體忽然破棺而出衔肢,到底是詐尸還是另有隱情庄岖,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布角骤,位于F島的核電站隅忿,受9級特大地震影響,放射性物質發(fā)生泄漏邦尊。R本人自食惡果不足惜背桐,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝉揍。 院中可真熱鬧链峭,春花似錦、人聲如沸又沾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至励饵,卻和暖如春再膳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背曲横。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留不瓶,地道東北人禾嫉。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蚊丐,于是被迫代替她去往敵國和親熙参。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容