puppet

Puppet
理论
定义: Puppet 是一个跨平台的集中化配置管理系统,它使用自有的描述语言,可管理配置文件、用户、Cron、软件包、系统服务等,Puppet把这些统称为“资源”。
运维的三个层次,以及对应的软件产品
OS Provision:OS Provision:
bare metal:pxe, cobblervirutal machine:image file template

Configuration:
ansible(agentless)puppet(master/agent)(ruby)saltstack(python)

Command and Control:
ansible(playbook)fabric(fab)func...

puppet的工作模型:
分为两种
单机模型:手动应用清单;

master/agent:由agent周期性地向Master请求清单并自动应用于本地;

单机模型
程序环境:
配置文件:/etc/puppet/puppet.conf

主程序:/usr/bin/puppet


puppet程序: Usage: puppet <subcommand> [options] <action> [options] help Display Puppet help. apply Apply Puppet manifests locally describe Display help about resource types agent The puppet agent daemon master The puppet master daemon module Creates, installs and searches for modules on the Puppet Forge …… 'puppet help <subcommand>' for help on a specific subcommand. 'puppet help <subcommand> <action>' for help on a specific subcommand action. puppet apply: Applies a standalone Puppet manifest to the local system. puppet apply [-d|--debug] [-v|--verbose] [-e|--execute] [--noop] <file> 程序环境: 配置文件:/etc/puppet/ puppet.conf 主程序:/usr/bin/puppet puppet程序: Usage: puppet <subcommand> [options] <action> [options] help Display Puppet help. apply Apply Puppet manifests locally describe Display help about resource types agent The puppet agent daemon master The puppet master daemon module Creates, installs and searches for modules on the Puppet Forge …… 'puppet help <subcommand>' for help on a specific subcommand. 'puppet help <subcommand> <action>' for help on a specific subcommand action. puppet apply: Applies a standalone Puppet manifest to the local system. puppet apply [-d|--debug] [-v|--verbose] [-e|--execute] [--noop] <file>
​ ​
puppet资源: 资源抽象的纬度(RAL如何抽象资源的?): 类型:具有类似属性的组件,例如package、service、file; 将资源的属性或状态与其实现方式分离; 仅描述资源的目标状态,也即期望其实现的结果状态,而不是具体过程; RAL由“类型”和提供者(provider); puppet describe: Prints help about Puppet resource types, providers, and metaparameters. puppet describe [-h|--help] [-s|--short] [-p|--providers] [-l|--list] [-m|--meta] [type] -l:列出所有资源类型; -s:显示指定类型的简要帮助信息; -m:显示指定类型的元参数,一般与-s一同使用; 资源定义:向资源类型的属性赋值来实现,可称为资源类型实例化; 定义了资源实例的文件即清单,manifest; 定义资源的语法: type {'title': attribute1 => value1, atrribute2 => value2, …… } 注意:type必须使用小写字符;title是一个字符串,在同一类型中必须惟一; 资源属性中的三个特殊属性: Namevar, 可简称为name; ensure:资源的目标状态; Provider:指明资源的管理接口; 资源类型: group: Manage groups. 属性: name:组名; gid:GID; system:是否为系统组,true OR false; ensure:目标状态,present/absent; members:成员用户; user: Manage users. 属性: name:用户名; uid: UID; gid:基本组ID; groups:附加组,不能包含基本组; comment:注释; expiry:过期时间 ; home:家目录; shell:默认shell类型; system:是否为系统用户 ; ensure:present/absent; password:加密后的密码串; 关系元参数:before/require A before B: B依赖于A,定义在A资源中; { ... before => Type['B'], ... } B require A: B依赖于A,定义在B资源中; { ... require => Type['A'], ... } package: Manage packages. 属性: ensure:installed, present, latest, absent name:包名; source:程序包来源,仅对不会自动下载相关程序包的provider有用,例如rpm或dpkg;
service: Manage running services. 属性: ensure:Whether a service should be running. Valid values are stopped (also called false), running (also called true). enable:Whether a service should be enabled to start at boot. Valid values are true, false, manual. name: path:The search path for finding init scripts. Multiple values should be separated by colons or provided as an array. 脚本的搜索路径,默认为/etc/init.d/; hasrestart: hasstatus: start:手动定义启动命令; stop: status: restart:Specify a restart command manually. If left unspecified, the service will be stopped and then started. 通常用于定义reload操作; 资源引用: Type['title'] 类型的首字母必须大写; 资源有特殊属性: 名称变量(namevar): name可省略,此时将由title表示; ensure: 定义资源的目标状态; 元参数:metaparameters 依赖关系: before require 通知关系:通知相关的其它资源进行“刷新”操作; notify A notify B:B依赖于A,且A发生改变后会通知B; { ... notify => Type['B'], ... } subscribe B subscribe A:B依赖于A,且B监控A资源的变化产生的事件; { ... subscribe => Type['A'], ... }​ file: Manages files, including their content, ownership, and permissions. ensure:Whether the file should exist, and if so what kind of file it should be. Possible values are present, absent, file, directory, and link. file:类型为普通文件,其内容由content属性生成或复制由source属性指向的文件路径来创建; link:类型为符号链接文件,必须由target属性指明其链接的目标文件; directory:类型为目录,可通过source指向的路径复制生成,recurse属性指明是否递归复制; path:文件路径; source:源文件; content:文件内容; target:符号链接的目标文件; owner:属主 group:属组 mode:权限; atime/ctime/mtime:时间戳; 通知元参数: A notify B:B依赖于A,接受由A触发refresh; B subscribe A:B依赖于A,接受由A触发refresh; 示例1: file{'test.txt': path => '/tmp/test.txt', ensure => file, source => '/etc/fstab', }​ file{'test.symlink': path => '/tmp/test.symlink', ensure => link, target => '/tmp/test.txt', require => File['test.txt'], }​ file{'test.dir': path => '/tmp/test.dir', ensure => directory, source => '/etc/yum.repos.d/', recurse => true, } 示例2: service{'httpd': ensure => running, enable => true, restart => 'systemctl restart httpd.service', # subscribe => File['httpd.conf'], }​ package{'httpd': ensure => installed, }​ file{'httpd.conf': path => '/etc/httpd/conf/httpd.conf', source => '/root/manifests/httpd.conf', ensure => file, notify => Service['httpd'], }​ Package['httpd'] -> File['httpd.conf'] -> Service['httpd']
回顾:
Bootstraping,Configuration, Command and Control;
puppet:Configuration apply:standalone master/agent: manifest: resource node 资源:resource type{'title': atrribute => value, ... } 关系元参数:before/require, notify/subscribe 特殊参数:NameVar 目标状态:ensure 资源类型:group, user, package, service, file;exec, cron, notify, ... puppet describe
​ Puppet(2)
资源类型: exec: Executes external commands. Any command in an exec resource must be able to run multiple times without causing harm --- that is, it must be idempotent. command (namevar):要运行的命令; cwd:The directory from which to run the command. creates:文件路径,仅此路径表示的文件不存在时,command方才执行; user/group:运行命令的用户身份; path:The search path used for command execution. Commands must be fully qualified if no path is specified. onlyif:此属性指定一个命令,此命令正常(退出码为0)运行时,当前command才会运行; unless:此属性指定一个命令,此命令非正常(退出码为非0)运行时,当前command才会运行; refresh:重新执行当前command的替代命令; refreshonly:仅接收到订阅的资源的通知时方才运行; cron: Installs and manages cron jobs. Every cron resource created by Puppet requires a command and at least one periodic attribute (hour, minute, month, monthday, weekday, or special). command:要执行的任务; ensure:present/absent; hour: minute: monthday: month: weekday: user:以哪个用户的身份运行命令 target:添加为哪个用户的任务 name:cron job的名称; 示例: cron{'timesync': command => '/usr/sbin/ntpdate 10.1.0.1 &> /dev/null', ensure => present, minute => '*/3', user => 'root', } notify: Sends an arbitrary message to the agent run-time log. 属性: message:信息内容 name:信息名称;​ 核心类型: group: 组 user:用户 packge:程序包 service:服务 file:文件 exec:执行自定义命令,要求幂等 cron:周期性任务计划 notify:通知 puppet variable:​ $variable_name=value 数据类型: 字符型:引号可有可无;但单引号为强引用,双引号为弱引用; 数值型:默认均识别为字符串,仅在数值上下文才以数值对待; 数组:[]中以逗号分隔元素列表; 布尔型值:true, false; hash:{}中以逗号分隔k/v数据列表; 键为字符型,值为任意puppet支持的类型;{ 'mon' => 'Monday', 'tue' => 'Tuesday', }; undef:未定义 ; 正则表达式: (?<ENABLED OPTION>:<PATTERN>) (?-<DISABLED OPTION>:<PATTERN>) OPTIONS: i:忽略字符大小写; m:把.当换行符; x:忽略<PATTERN>中的空白字符 (?i-mx:PATTERN) 不能赋值给变量 ,仅能用在接受=或!操作符的位置; puppet的变量类型: facts: 由facter提供;top scope; 内建变量: master端变量 agent端变量 parser变量 用户自定义变量: 变量有作用域,称为Scope; top scope: $::var_name node scope class scope
puppet流程控制语句: if语句: if CONDITION { ... } else { ... } CONDITION的给定方式: (1) 变量 (2) 比较表达式 (3) 有返回值的函数
if $osfamily =~ /(?i-mx:debian)/ { $webserver = 'apache2' } else { $webserver = 'httpd' }​ package{"$webserver": ensure => installed, before => [ File['httpd.conf'], Service['httpd'] ], }​ file{'httpd.conf': path => '/etc/httpd/conf/httpd.conf', source => '/root/manifests/httpd.conf', ensure => file, }​ service{'httpd': ensure => running, enable => true, restart => 'systemctl restart httpd.service', subscribe => File['httpd.conf'], }
case语句: case CONTROL_EXPRESSION { case1: { ... } case2: { ... } case3: { ... } ... default: { ... } } CONTROL_EXPRESSION: (1) 变量 (2) 表达式 (3) 有返回值的函数 各case的给定方式: (1) 直接字串; (2) 变量 (3) 有返回值的函数 (4) 正则表达式模式; (5) default ​ case $osfamily { "RedHat": { $webserver='httpd' } /(?i-mx:debian)/: { $webserver='apache2' } default: { $webserver='httpd' } }​ package{"$webserver": ensure => installed, before => [ File['httpd.conf'], Service['httpd'] ], }​ file{'httpd.conf': path => '/etc/httpd/conf/httpd.conf', source => '/root/manifests/httpd.conf', ensure => file, }​ service{'httpd': ensure => running, enable => true, restart => 'systemctl restart httpd.service', subscribe => File['httpd.conf'], } selector语句: CONTROL_VARIABLE ? { case1 => value1, case2 => value2, ... default => valueN, } CONTROL_VARIABLE的给定方法: (1) 变量 (2) 有返回值的函数 各case的给定方式: (1) 直接字串; (2) 变量 (3) 有返回值的函数 (4) 正则表达式模式; (5) default 注意:不能使用列表格式;但可以是其它的selecor; $pkgname = $operatingsystem ? { /(?i-mx:(ubuntu|debian))/ => 'apache2', /(?i-mx:(redhat|fedora|centos))/ => 'httpd', default => 'httpd', }​ package{"$pkgname": ensure => installed, } ​ 示例2: $webserver = $osfamily ? { "Redhat" => 'httpd', /(?i-mx:debian)/ => 'apache2', default => 'httpd', }
package{"$webserver": ensure => installed, before => [ File['httpd.conf'], Service['httpd'] ], }​ file{'httpd.conf': path => '/etc/httpd/conf/httpd.conf', source => '/root/manifests/httpd.conf', ensure => file, }​ service{'httpd': ensure => running, enable => true, restart => 'systemctl restart httpd.service', subscribe => File['httpd.conf'], } puppet的类: 类:puppet中命名的代码模块,常用于定义一组通用目标的资源,可在puppet全局调用; 类可以被继承,也可以包含子类; 语法格式: class NAME { ...puppet code... } class NAME(parameter1, parameter2) { ...puppet code... } 类代码只有声明后才会执行,调用方式: (1) include CLASS_NAME1, CLASS_NAME2, ... (2) class{'CLASS_NAME': attribute => value, } 示例1: class apache2 { $webpkg = $operatingsystem ? { /(?i-mx:(centos|redhat|fedora))/ => 'httpd', /(?i-mx:(ubuntu|debian))/ => 'apache2', default => 'httpd', }​ package{"$webpkg": ensure => installed, }​ file{'/etc/httpd/conf/httpd.conf': ensure => file, owner => root, group => root, source => '/tmp/httpd.conf', require => Package["$webpkg"], notify => Service['httpd'], }​ service{'httpd': ensure => running, enable => true, } }​ include apache2 示例2: class dbserver($pkgname) { package{"$pkgname": ensure => latest, }​ service{"$pkgname": ensure => running, enable => true, } }​ #include dbserver
if $operatingsystem == "CentOS" { $dbpkg = $operatingsystemmajrelease ? { 7 => 'mariadb-server', default => 'mysqld-server', } }​ class{'dbserver': pkgname => $dbpkg, } 类继承的方式: class SUB_CLASS_NAME inherits PARENT_CLASS_NAME { ...puppet code... } 示例: class nginx { package{'nginx': ensure => installed, }​ service{'nginx': ensure => running, enable => true, restart => '/usr/sbin/nginx -s reload', } }​ class nginx::web inherits nginx { Service['nginx'] { subscribe => File['ngx-web.conf'], }​ file{'ngx-web.conf': path => '/etc/nginx/conf.d/ngx-web.conf', ensure => file, source => '/root/manifests/ngx-web.conf', } }​ class nginx::proxy inherits nginx { Service['nginx'] { subscribe => File['ngx-proxy.conf'], }​ file{'ngx-proxy.conf': path => '/etc/nginx/conf.d/ngx-proxy.conf', ensure => file, source => '/root/manifests/ngx-proxy.conf', } }​ include nginx::proxy 在子类中为父类的资源新增属性或覆盖指定的属性的值: Type['title'] { attribute1 => value, ... } 在子类中为父类的资源的某属性增加新值: Type['title'] { attribute1 +> value, ... } puppet模板: erb:模板语言,embedded ruby; puppet兼容的erb语法: https://docs.puppet.com/puppet/latest/reference/lang_template_erb.html file{'title': ensure => file, content => template('/PATH/TO/ERB_FILE'), } 文本文件中内嵌变量替换机制: <%= @VARIABLE_NAME %> 示例: class nginx { package{'nginx': ensure => installed, }​ service{'nginx': ensure => running, enable => true, require => Package['nginx'], } }​ class nginx::web inherits nginx { file{'ngx-web.conf': path => '/etc/nginx/conf.d/ngx-web.conf', ensure => file, require => Package['nginx'], source => '/root/manifests/nginx/ngx-web.conf', }​ file{'nginx.conf': path => '/etc/nginx/nginx.conf', ensure => file, content => template('/root/manifests/nginx.conf.erb'), require => Package['nginx'], }​ Service['nginx'] { subscribe => [ File['ngx-web.conf'], File['nginx.conf'] ], } }​ include nginx::web puppet模块: 模块就是一个按约定的、预定义的结构存放了多个文件或子目录的目录,目录里的这些文件或子目录必须遵循一定格式的命名规范; puppet会在配置的路径下查找所需要的模块; MODULES_NAME: manifests/ init.pp files/ templates/ lib/ spec/ tests/ 模块名只能以小写字母开头,可以包含小写字母、数字和下划线;但不能使用”main"和"settings“; manifests/ init.pp:必须一个类定义,类名称必须与模块名称相同; files/:静态文件; puppet URL: puppet:///modules/MODULE_NAME/FILE_NAME templates/: tempate('MOD_NAME/TEMPLATE_FILE_NAME') lib/:插件目录,常用于存储自定义的facts以及自定义类型; spec/:类似于tests目录,存储lib/目录下插件的使用帮助和范例; tests/:当前模块的使用帮助或使用范例文件; 注意: 1、puppet 3.8及以后的版本中,资源清单文件的文件名要与文件听类名保持一致,例如某子类名为“base_class::child_class”,其文件名应该为child_class.pp; 2、无需再资源清单文件中使用import语句; 3、manifests目录下可存在多个清单文件,每个清单文件包含一个类,其文件名同类名;
puppet config命令: 获取或设定puppet配置参数; puppet config print [argument] puppet查找模块文件的路径:modulepath mariadb模块中的清单文件示例: class mariadb($datadir='/var/lib/mysql') { package{'mariadb-server': ensure => installed, }​ file{"$datadir": ensure => directory, owner => mysql, group => mysql, require => [ Package['mariadb-server'], Exec['createdir'], ], }​ exec{'createdir': command => "mkdir -pv $datadir", require => Package['mariadb-server'], path => '/bin:/sbin:/usr/bin:/usr/sbin', creates => “$datadir", }​ file{'my.cnf': path => '/etc/my.cnf', content => template('mariadb/my.cnf.erb'), require => Package['mariadb-server'], notify => Service['mariadb'], }​ service{'mariadb': ensure => running, enable => true, require => [ Exec['createdir'], File["$datadir"], ], } } 实践作业: 开发模块: memcached nginx(反代动态请求至httpd,work_process的值随主机CPU数量而变化) jdk(输出JAVA_HOME环境变量) tomcat mariadb httpd(反代请求至tomcat,ajp连接器;mpm允许用户通过参数指定)
回顾:
puppet核心资源类型:group, user, file, package, service, exec, cron, notify
puppet describe [-l] [type]

资源清单:manifests, *.pp
type{'title': attribute => value, ...}​引用:Type['title']

元参数:
before/requirenotify/subscribe->, ~>

数据类型:字符串、数值、布尔型、数组、hash、undef

正则表达式:
(?<enable_flag>-<disable_flag>:<PATTERN>)flag: i, m, x

变量:$variable,
FQN: $::scope1::scope2::variable $variable

编程元素:
流程控制:
if, case, selector, unless

类:
class class_name[($parameter1[=value1], $parameter2)] { ...puppet code...}class sub_class_name inherits class_name { ... puppet code ...} sub_class_name: base_class::sub_class_name

子类中引用父类的资源:
Type['title'] { attribute => value, atrribute +> value,}

声明类:
include class_nameclass{'class_name': attribute => value,}

模板:
erb:Embedded RuBy <%= erb code %> <% erb code %> <%# erb code %>

file类型的资源
content => template('/PATH/TO/ERB_FILE')

模块:
modulepath配置参数指定的目录路径下(puppet config print modulepath); manifests/ init.pp (至少得存在一个与模块名同名的类) sub_class_name.pp files/ puppet:///modules/MOD_NAME/FILE_NAME templates/ template('MOD_NAME/ERB_FILE') tests/ # 当前模块的帮助 spec/ # 帮助和示例模块

puppet(3)
standalone:puppet apply
standalone:
puppet apply -e 'include CLASS_NAME'

master/agent:agent每隔30分钟到master端请求与自己相关的catalog
master: site manifest
node 'node_name' { ...puppet code...}

相关网站
程序包下载路径:
https://yum.puppetlabs.com/

官方文档:
https://docs.puppet.com/puppet/3/reference/

内建函数:
https://docs.puppet.com/puppet/3/reference/function.html

配置参数列表:
https://docs.puppet.com/puppet/3/reference/configuration.html

安装部署 master/agent
部署master:
安装程序包:facter, puppet, puppet-server
初始化master:
puppet master --no-daemonize --verbose

生成一个完整的配置参数列表:可能不可用
puppet master --genconfig puppet agent --genconfig # 在agent端运行...

打印基于默认配置生效的各配置参数列表:
puppet config <action> [--section SECTION_NAME]puppet config print

基于命令行设定某参数的值:
puppet config set

可以直接启动
systemctl start puppetmaster.service

puppet 默认监听的端口:tcp/8140

master端管理证书签署:
puppet cert <action> " style="box-sizing: border-box; cursor: pointer; text-decoration: underline; outline: 0px; transition: all 0.2s ease-in-out; color: rgb(224, 224, 224);">--all
action: list sign revoke clean:吊销指定的客户端的证书,并删除与其相关的所有文件;

站点清单的定义:

主机名定义:
主机名(主机角色)#-机架-机房-运营商-区域.域名:www1-rack1-yz-unicom-bj.magedu.com
/etc/puppet/manifests/site.pp node 'base' { include ntp } node 'HOSTNAME' { ...puppet code... } node /PATTERN/ { ...puppet code... } node /node[0-9]+.magedu.com/ 节点定义的继承: node NODE inherits PAR_NODE_DEF { ...puppet code... } nodes/

清单配置信息可模块化组织:
databases.d/tomcatservers.d/nodes.d/:可通过多个pp文件分别定义各类站点的清单;而后统一导入site.pp,方法如下:
site.pp文件使用中如下配置:
import 'nodes/*.pp'

多环境配置
默认环境是production;

environmentpath =

puppet 3.4 之前的版本配置多环境的方法:
各环境配置:

/etc/puppet/environments/{production,development,testing}

master支持多环境:puppet.conf
[master]# modulepath=# manifest=environments = production, development, testing[production]modulepath=/etc/puppet/environments/production/modules/manifest=/etc/puppet/environments/production/manifests/site.pp[development]modulepath=/etc/puppet/environments/development/modules/manifest=/etc/puppet/environments/development/manifests/site.pp [testing]modulepath=/etc/puppet/environments/testing/modules/manifest=/etc/puppet/environments/testing/manifests/site.pp

puppet 3.6之后的版本配置多环境的方法:
master支持多环境:
(1) 配置文件puppet.conf

[master]environmentpath = $confdir/environments
(2) 在多环境配置目录下为每个环境准备一个子目录

ENVIRONMENT_NAME/ manifests/ site.pp modules/

agent端:
[agent]environment = { production|development | testing }

额外配置文件:
文件系统:fileserver.conf

认证(URL):auth.conf

puppet kick: agent: puppet.conf [agent] listen = true auth.conf path /run method save auth any allow master.magedu.com path / auth any master端: puppet kick puppet kick [--host <HOST>] [--all] GUI: dashboard foreman: 项目实践: haproxy(keepalived) cache --> varnish imgs--> nginx server app --> httpd+tomcat --> mariadb-server zabbix --> zabbix-server zabbix-agent
​ ​
生产环境案例:haproxy.pp
class haproxy { # init haproxy class init { file { '/etc/init.d/haproxy': ensure => present, source => "puppet:///modules/haproxy/haproxy/init.d/haproxy.init", group => "root", owner => "root", mode => "0755", } exec { 'init_haproxy_service': subscribe => File['/etc/init.d/haproxy'], refreshonly => true, command => "/sbin/chkconfig --add haproxy; /sbin/chkconfig --level 235 haproxy off;", } service { 'haproxy': ensure => running, enable => true, hasrestart => true, hasstatus => true, # restart => true, } } # init haproxy.cfg class conf { # file { '/usr/local/haproxy','/usr/local/haproxy/etc': file { ['/usr/local/haproxy','/usr/local/haproxy/etc']: ensure => directory, before => File['/usr/local/haproxy/etc/haproxy.cfg'], group => "root", owner => "root", mode => "0755", } class piccenter { file { '/usr/local/haproxy/etc/haproxy.cfg': ensure => present, source => "puppet:///modules/haproxy/haproxy/conf/haproxy_piccenter.cfg", group => "root", owner => "root", mode => "0644", } } } }

keepalived.pp
class keepalived { # init haproxy class init { file { '/etc/init.d/keepalived': ensure => present, source => "puppet:///modules/haproxy/keepalived/init.d/keepalived.init", group => "root", owner => "root", mode => "0755", } exec { 'init_keepalived_service': subscribe => File['/etc/init.d/keepalived'], refreshonly => true, command => "/sbin/chkconfig --add keepalived; /sbin/chkconfig --level 235 keepalived off;", } service { 'keepalived': ensure => running, enable => true, hasrestart => true, hasstatus => true, restart => true, } } }
​ ​ ​ ​ ​

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

推荐阅读更多精彩内容

  • 一.puppet介绍 (1)什么是puppetpuppet是一种重量级自动化运维工具,实现自动化运维以及能够帮助系...
    楠人帮阅读 1,045评论 0 3
  • 1.puppet 是什么 puppet是一个开源的软件自动化配置和部署工具,很多大型IT公司均在使用puppet对...
    milo_e1ce阅读 4,839评论 0 4
  • puppet简介 puppet是一套IT基础设施自动化管理工具,可以管理其整个生命周期,其官方网站:www.pup...
    魏镇坪阅读 3,895评论 0 5
  • Puppet部署与应用 前言:到目前为止,我们已经搭建了很多的服务器,每一台服务器都需要执行很多的命令,给我的感觉...
    李伟铭MIng阅读 2,680评论 0 3
  • 每次看别人的公众号 故事的开头一般都是这样的 我有一个朋友…… 妈蛋 别人的朋友可以三个一组凑齐一年的公众号推文 ...
    小小侠阅读 570评论 2 4