apisix ingress controller使用指南

1.ingress.class示例

通過ingress.class方式暴露服務

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apisix-dashboard
  annotations:
    kubernetes.io/ingress.class: apisix
spec:
  rules:
  - host: apisix-dashboard.example.com
    http:
      paths:
      - backend:
          serviceName: apisix-dashboard
          servicePort: 80
        path: /*
        pathType: Prefix

首先確定apifix-ingress-controller配置文件中ingress_class的值绣版, 默認為apisix

注意如果要匹配跟下面的所有路徑,需要將path配置為/*, 也可以配置pathType: Prefix會創(chuàng)建/ /* 兩個路徑 其它的用法完全符合ingress的默認配置碉纺,annotation可配置參數(shù)參考官方文檔

2.crd基礎示例

2.1.ApisixRoute基本用法

先在集群中部署httpbin服務

kubectl run httpbin --image kennethreitz/httpbin --port 80
kubectl expose pod httpbin --port 80

創(chuàng)建httpbin-route.yaml文件挽拂,內(nèi)容如下:

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - httpbin.example.com
      paths:
      - /*
    backends:
       - serviceName: httpbin
         servicePort: 80

可以使用兩種路徑類型prefix驹暑、exact,默認為exact,如果prefix需要,只需附加一個扒腕,例如擂达,/id/匹配前綴為 的所有路徑/id/土铺。

測試過程如下:

?  ~ curl -H "Host: httpbin.example.com" http://internal/headers/ -v
*   Trying internal...
* TCP_NODELAY set
* Connected to internal (internal) port 80 (#0)
> GET / HTTP/1.1
> Host: httpbin.example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 9593
< Connection: keep-alive
< Date: Tue, 16 Aug 2022 09:07:36 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Server: APISIX/2.15.0

2.2.ApisixTls基本用法

ApisixTls主要用來維護https證書

需要先創(chuàng)建tls secret

kubectl -n kube-system create secret tls traefik-ui-tls-cert --key=tls.key --cert=tls.crt

創(chuàng)建httpbin-tls.yaml文件,內(nèi)容如下:

apiVersion: apisix.apache.org/v2
kind: ApisixTls
metadata:
  name: wildcard.example.com-ApisixTls
spec:
  hosts:
  - "*.example.com"
  secret:
    name: wildcard.example.com-tls-secret
    namespace: ingress-apisix

通過該方式創(chuàng)建的ssl證書板鬓,對apisix全局服務都有效悲敷,apisix會根據(jù)請求域名動態(tài)選擇

2.3.ApisixUpstream基本用法

ApisixUpstream 需要配置成和Kubernetes Service相同的名字,通過添加負載均衡俭令、健康檢查后德、重試、超時參數(shù)等使 Kubernetes Service 更加豐富抄腔。

如果不使用ApisixUpstream探遵,則loadbalancer的類型為roundrobin

apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  name: httpbin
spec:
  loadbalancer:
    type: ewma
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
spec:
  selector:
    app: httpbin
  ports:
  - name: http
    port: 80
    targetPort: 8080

其中l(wèi)oadbalancer支持如下四種類型

Round robin: 輪詢,配置為type: roundrobin

Least loaded: 最小鏈接,配置為type: least_conn

Peak EWMA: 維護每個副本往返時間的移動平均值妓柜,按未完成請求的數(shù)量加權箱季,并將流量分配到成本函數(shù)最小的副本。配置為type: ewma

chash: 一致性哈希 配置為type: chash

3.ApisixRoute使用進階

3.1.ApisixRoute配置多個域名和路徑

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - local.example.com
      - local01.example.com
      paths:
      - /*
      - /api
    backends:
       - serviceName: httpbin
         servicePort: 80

3.2.路徑/api特殊配制棍掐,路徑/無特殊配制

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /api*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"]
  - name: default-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000

apisix中會創(chuàng)建兩個route藏雏,分別是httpserver-route 和 default-route

3.3.ApisixRoute添加插件

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpbin-route
spec:
  http:
    - name: httpbin
      match:
        hosts:
        - local.httpbin.org
        paths:
          - /*
      backends:
      - serviceName: foo
        servicePort: 80
      plugins:
        - name: gzip
          enable: true

3.4.HTTP強跳HTTPS

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        http_to_https: true

3.5.域名跳轉

local.example.com跳轉到local01.example.com

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        uri: "https://local01.example.com$request_uri"

3.6.rewrite路徑跳轉

3.6.1./api/header 轉/header

方法一: 使用redirect插件,頁面會發(fā)生302跳轉

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"] 

方法二: 使用proxy-rewrite 插件,頁面不會302跳轉

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"] 

3.6.2./header轉/api/header

使用proxy-rewrite 插件掘殴,頁面不會302跳轉

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        uri: /api/$uri

3.7.基于用戶名和密碼的認證**

basix-auth插件需要與 Consumer 一起使用才能實現(xiàn)該功能赚瘦。 開啟認證的apisixroute會自動匹配用戶名

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth
spec:
  authParameter:
    basicAuth:
      value:
        username: admin
        password: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    authentication:
      enable: true 
      type: basicAuth

測試:

curl -i -uadmin:admin https://local.example.com/

3.8.基于apikey的認證

key-auth插件需要與 Consumer 一起使用才能實現(xiàn)該功能。 開啟認證的apisixroute會自動匹配key

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth
spec:
  authParameter:
    keyAuth:
      value:
        key: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    authentication:
      enable: true 
      type: keyAuth

測試:

curl -H 'apikey:admin' https://local.example.com/ 

3.9.限制站點的用戶名和密碼

通過3.6.基于用戶名和密碼的認證和3.7.基于apikey的說法奏寨,有沒有辦法用戶名和密碼只針對一個站點生效, 創(chuàng)建兩個consumer起意,分別是admin01和宮秀德,只允許admin可以進行認證病瞳。

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth-admin
spec:
  authParameter:
    basicAuth:
      value:
        username: admin
        password: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth-admin01
spec:
  authParameter:
    basicAuth:
      value:
        username: admin01
        password: admin01
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: consumer-restriction
      enable: true
      config:
        whitelist: 
        - ingress_apisix_httpserver_basicauth_admin 
    authentication:
      enable: true 
      type: basicAuth

httpserver-basicauth-admin需要添加ingress-controller添加的默認前綴ingress_apisix揽咕,否則會報403,所以全名為ingress_apisix_httpserver_basicauth_admin

測試admin01訪問

> curl -i -uadmin01:admin01 https://local.example.com/
HTTP/2 403
date: Tue, 30 Aug 2022 08:00:04 GMT
content-type: text/plain; charset=utf-8
server: APISIX/2.15.0

{"message":"The consumer_name is forbidden."}

測試admin訪問

curl -i -uadmin:admin https://local.example.com/
HTTP/2 200
content-type: text/html; charset=utf-8
content-length: 615
date: Tue, 30 Aug 2022 07:55:55 GMT
last-modified: Wed, 25 May 2022 10:01:40 GMT
etag: "628dfe84-267"
accept-ranges: bytes
server: APISIX/2.15.0
.........

3.10.基于IP的白名單配置

ip-restriction插件實現(xiàn)該功能, 只允許10.10.50.207 10.0.0.0/16 訪問站點

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: ip-restriction
      enable: true
      config:
        whitelist: 
        - 10.10.50.207
        - 10.0.0.0/16

白名單中地址測試正常打開頁面

非白名單地址測試

> curl  https://local.example.com/
{"message":"Your IP address is not allowed"}

3.11.基于IP的黑名單限制

ip-restriction插件實現(xiàn)該功能, 不允許10.10.50.207 訪問站點

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: ip-restriction
      enable: true
      config:
        blacklist: 
        - 10.10.50.207

測試

> curl  https://local.example.com/
{"message":"Your IP address is not allowed"}

3.12.添加自定義配置

4.灰度發(fā)布

4.1.準備環(huán)境

4.1.1.stable版本

# vim s1-stable.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-stable-service
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http-port
  selector:
    app: myapp
    version: stable
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-stable
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      version: stable
  template:
    metadata:
      labels:
        app: myapp
        version: stable
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/public-registry-fzh/myapp:v1
        imagePullPolicy: IfNotPresent
        name: myapp-stable
        ports:
        - name: http-port
          containerPort: 80
        env:
        - name: APP_ENV
          value: stable

4.1.2.canary版本

# vim s2-canary.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-canary-service
  namespace: canary
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http-port
  selector:
    app: myapp
    version: canary
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-canary
  namespace: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      version: canary
  template:
    metadata:
      labels:
        app: myapp
        version: canary
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/public-registry-fzh/myapp:v2
        imagePullPolicy: IfNotPresent
        name: myapp-canary
        ports:
        - name: http-port
          containerPort: 80
        env:
        - name: APP_ENV
          value: canary

4.2.基于weight分流

# vim s3-apisixroute-weight.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute
  namespace: canary 
spec:
  http:
  - name: myapp-canary-rule
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
      weight: 10
    - serviceName: myapp-canary-service
      servicePort: 80
      weight: 1

創(chuàng)建服務和路由等

?  kubectl apply -f ./
service/myapp-stable-service unchanged
deployment.apps/myapp-stable unchanged
service/myapp-canary-service unchanged
deployment.apps/myapp-canary unchanged
apisixroute.apisix.apache.org/myapp-canary-apisixroute unchanged
?  kubectl get pods -n canary
NAME                           READY   STATUS    RESTARTS   AGE
myapp-canary-9ff4c55f9-ndjrs   1/1     Running   0          15s
myapp-stable-5fdf6bd75-sq8df   1/1     Running   0          75s
?  kubectl get apisixroute -n canary
NAME                       HOSTS                   URIS   AGE
myapp-canary-apisixroute   [myapp.example.com]   [/]    97s

測試weight灰度

Stable和 Canary 的比例約為10:1

  ~ for i in `seq 30`;do curl https://myapp.example.com;done
myapp:v1
myapp:v1
.......
myapp:v2
myapp:v1
myapp:v1
myapp:v2
myapp:v1
myapp:v1
myapp:v1
.......
myapp:v1
myapp:v1
myapp:v2
myapp:v1
myapp:v1
myapp:v2

4.3.基于優(yōu)先級分流

# vim s4-priority.yaml
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute2
  namespace: canary
spec:
  http:
  - name: myapp-stable-rule2
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule2
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

測試套菜,流量會優(yōu)先打入優(yōu)先級高的pod

?  ~ for i in `seq 30`;do curl https://myapp.example.com;done
myapp:v2
myapp:v2
........
myapp:v2
myapp:v2
myapp:v2
myapp:v2

4.4.基于header分流

# vim  canary-header.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute3
  namespace: canary 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Header
          name: canary
        op: RegexMatch
        value: ".*myapp.*"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

測試

?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com -X GET -H "canary: 124myapp"
myapp:v2
?  ~ curl https://myapp.example.com -X GET -H "canary: myapp"
myapp:v2
?  ~ curl https://myapp.example.com -X GET -H "canary: xiamyapp"
myapp:v2
?  ~ curl https://myapp.example.com -X GET -H "stable: xiamyapp"
myapp:v1
?  ~ curl https://myapp.example.com -X GET -H "stable: myapp"
myapp:v1

4.5.基于參數(shù)的分流

# cat vars.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute3
  namespace: canary 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Query
          name: id
        op: In
        set:
        - "12"
        - "23"
        - "45"
        - "67"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

測試

?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com
myapp:v1
?  ~ curl https://myapp.example.com/\?id\=12
myapp:v2
?  ~ curl https://myapp.example.com/\?id\=23
myapp:v2
?  ~ curl https://myapp.example.com/\?id\=45
myapp:v2
?  ~ curl https://myapp.example.com/\?id\=67
myapp:v2
?  ~ curl https://myapp.example.com/\?id\=89
myapp:v1
?  ~ curl https://myapp.example.com/\?id\=143
myapp:v1

4.6.基于cookie分流

apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute
  namespace: default 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Cookie
          name: canary_v5
        op: Equal
        value: "always"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

測試攜帶cookie:

?  ~ curl --cookie "canary_v5=always" "http://myapp.example.com"
myapp:v2

測試不攜帶cookie

?  ~ curl  "http://myapp.example.com"
myapp:v1
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亲善,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子逗柴,更是在濱河造成了極大的恐慌蛹头,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戏溺,死亡現(xiàn)場離奇詭異渣蜗,居然都是意外死亡,警方通過查閱死者的電腦和手機旷祸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門耕拷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肋僧,你說我怎么就攤上這事斑胜】氐” “怎么了嫌吠?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掺炭。 經(jīng)常有香客問我辫诅,道長,這世上最難降的妖魔是什么涧狮? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任炕矮,我火速辦了婚禮,結果婚禮上者冤,老公的妹妹穿的比我還像新娘肤视。我一直安慰自己,他們只是感情好涉枫,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布邢滑。 她就那樣靜靜地躺著,像睡著了一般愿汰。 火紅的嫁衣襯著肌膚如雪困后。 梳的紋絲不亂的頭發(fā)上乐纸,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音摇予,去河邊找鬼汽绢。 笑死,一個胖子當著我的面吹牛侧戴,可吹牛的內(nèi)容都是我干的宁昭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼救鲤,長吁一口氣:“原來是場噩夢啊……” “哼久窟!你這毒婦竟也來了?” 一聲冷哼從身側響起本缠,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤斥扛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丹锹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稀颁,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年楣黍,在試婚紗的時候發(fā)現(xiàn)自己被綠了匾灶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡租漂,死狀恐怖阶女,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哩治,我是刑警寧澤秃踩,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站业筏,受9級特大地震影響憔杨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蒜胖,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一消别、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧台谢,春花似錦寻狂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春怀读,著一層夾襖步出監(jiān)牢的瞬間诉位,已是汗流浹背记靡。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工约计, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稠鼻。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓啤誊,卻偏偏與公主長得像岳瞭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蚊锹,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345