04 kubernetes 控制器

ReplicaSet

ReplicaSet 副本控制器容客。用 Deployments 控制 ReplicaSet 冀泻,用 ReplicaSet 控制 Pod 的副本數(shù)量桃序。

ReplicaSet 的作用是維護集群中 Pod 數(shù)量的穩(wěn)定棒假。

工作原理

ReplicaSet 是通過一組字段來定義的溯职,包括一個用來可識別可獲得的 Pod 集合的運算符,一個用來標明應(yīng)該維護的副本個數(shù)帽哑,一個用來指定應(yīng)該創(chuàng)建新 Pod 以滿足副本個數(shù)條件時要使用的 Pod 模板谜酒。每個 ReplicaSet 都通過根據(jù)需要創(chuàng)建和刪除 Pod 以使得副本個數(shù)達到期望值,進而實現(xiàn)其存在價值妻枕。當(dāng) ReplicaSet 需要創(chuàng)建新 Pod 時僻族,會使用所提供的 Pod 模板。

ReplicaSet 通過 Pod 上的 metadata.ownerReferences 字段連接到附屬 Pod 屡谐,該字段給出當(dāng)前對象的屬主資源述么。ReplicaSet 所獲得的 Pod 都在其 ownerReferences 字段中包含了屬主 ReplicaSet 的標識信息。正是通過這一連接愕掏,ReplicaSet 知道它所維護的 Pod 集合的狀態(tài)度秘,并據(jù)此計劃其操作行為。

如何使用

雖然 ReplicaSet 可以獨立使用饵撑,但它主要被 Deployments 用作協(xié)調(diào) Pod 創(chuàng)建剑梳、刪除和更新的機制。當(dāng)創(chuàng)建 Deployments 時滑潘,會自動創(chuàng)建 ReplicaSet 垢乙。

創(chuàng)建一個 ReplicaSet

vim replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: nginx
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx
kubectl create -f replicaset.yaml

可以看到

replicaset.apps/frontend created

查看

kubectl get all
NAME                                    READY   STATUS        RESTARTS   AGE
pod/frontend-4t9sl                      1/1     Running       0          28s
pod/frontend-c85k7                      1/1     Running       0          28s
pod/frontend-j4vd9                      1/1     Running       0          28s

NAME                       DESIRED   CURRENT   READY   AGE
replicaset.apps/frontend   3         3         3       28s

可以看到,創(chuàng)建了一個 replicaset 和 三個 Pod 语卤。這時如果刪除一個 Pod 追逮,那么 replicaset 會維持三個 Pod 蓖租,所以會創(chuàng)建一個新的 Pod 。

Deployment

一個 Deployment 控制器為 Pods 和 ReplicaSet 提供聲明式的更新能力羊壹。

Deployment 的使用場景

  • 創(chuàng)建 Deployment 以將 ReplicaSet 上線蓖宦。ReplicaSet 在后臺創(chuàng)建 Pods 。檢查 ReplicaSet 的上線狀態(tài)油猫,查看是否成功稠茂。
  • 通過更新 Deployment 的 PodTemplateSpec ,聲明 Pod 的新狀態(tài)情妖。新的 RepicaSet 會被創(chuàng)建睬关,Deployment 以受控速率將 Pod 從舊 ReplicaSet 遷移到新 ReplicaSet 。每個新的 ReplicaSet 都會更新 Deployment 的修訂版本毡证。
  • 如果 Deployment 的當(dāng)前狀態(tài)不穩(wěn)定电爹,回滾到較早的 Deployment 版本。每次回滾都會更新 Deployment 的修訂版本料睛。
  • 擴大 Deployment 規(guī)模以承擔(dān)更多負載丐箩。
  • 暫停 Deployment 以應(yīng)用對 PodTemplateSpec 所做的多項修改,然后恢復(fù)其執(zhí)行以啟動新的上線版本恤煞。
  • 使用 Deployment 狀態(tài)來判斷上線過程是否出現(xiàn)停滯屎勘。
  • 清理不再需要的 ReplicaSet 。

創(chuàng)建 Deployment

vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
    # deployment 的名稱
  name: nginx-deployment
  labels:
    app: nginx
spec:
    # deployment 由 replicas 指定創(chuàng)建 pod 的數(shù)量
  replicas: 3
  # deployment 匹配要管理的 Pods
  selector:
    # 根據(jù)標簽匹配
    matchLabels:
      app: nginx
  # pod 模板
  template:
    metadata:
        # 標簽居扒,deployment 會根據(jù)這個標簽來匹配要管理的 pod
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

創(chuàng)建

kubectl apply -f deployment.yaml
kubectl get all

可以看到概漱,創(chuàng)建了三個 pod

NAME                                    READY   STATUS        RESTARTS   AGE
pod/nginx-deployment-66b6c48dd5-h85lf   1/1     Running       0          3m3s
pod/nginx-deployment-66b6c48dd5-rtm28   1/1     Running       0          3m3s
pod/nginx-deployment-66b6c48dd5-xxjcm   1/1     Running       0          3m3s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           3m3s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-66b6c48dd5   3         3         3       3m3s

調(diào)整 pod 的數(shù)量,只需要修改 replicas 字段的值喜喂。

有狀態(tài)的應(yīng)用 StatefulSets

StatefulSet 是用來管理有狀態(tài)應(yīng)用的工作負載 API 對象瓤摧。

StatefulSet 用來管理 Deployment 和擴展一組 Pod ,并且能為這些 Pod 提供序號和唯一性保證玉吁。和 Deployment 相同的是照弥,StatefulSet 管理了基于相同容器定義的一組 Pod。不同的是诈茧,StatefulSet 為每個 Pod 維護了一個固定的 ID 产喉。這些 Pod 是基于相同的聲明來創(chuàng)建的捂掰,但是不能相互替換敢会,無論怎么調(diào)度,每個 Pod 都有一個永久不變的 ID 这嚣。

StatefulSet 和其他控制器使用相同的工作模式鸥昏。

vim statefulset.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: datadir1
  labels:
    type: local
spec:
  storageClassName: my-storage-class
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/tmp/data1"
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: datadir2
  labels:
    type: local
spec:
  storageClassName: my-storage-class
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/tmp/data2"
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: datadir3
  labels:
    type: local
spec:
  storageClassName: my-storage-class
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/tmp/data3"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx 
  serviceName: "nginx"
  replicas: 3 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.cn-beijing.aliyuncs.com/qingfeng666/nginx:latest
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: my-storage-class
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete

創(chuàng)建

kubectl apply -f statefulset.yaml
kubectl get all

可以看到

NAME                                    READY   STATUS        RESTARTS   AGE
pod/web-0                               1/1     Running       0          2m2s
pod/web-1                               1/1     Running       0          119s
pod/web-2                               1/1     Running       0          116s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/nginx        ClusterIP   None         <none>        80/TCP    2m2s

NAME                   READY   AGE
statefulset.apps/web   3/3     2m2s

查看 pod

kubectl get pod web-0 -o widr

可以看到

NAME    READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          8m26s   10.244.1.72   node1   <none>           <none>

DaemonSet 后臺任務(wù)

DaemonSet 確保所有(或者某些)節(jié)點上運行一個 Pod 副本。當(dāng)有節(jié)點加入集群時姐帚,也會為它們新增一個 Pod 吏垮。當(dāng)有節(jié)點從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它所創(chuàng)建的所有 Pod 膳汪。

DaemonSet 的典型用法

  • 在集群的每個節(jié)點上運行 Daemon 唯蝶,比如 glusterd 或 ceph
  • 在每個節(jié)點上運行日志收集 Daemon ,比如 flunentd 或 logstash
  • 在每個節(jié)點上運行監(jiān)控 Daemon 遗嗽,比如 Prometheus Node Exporter 或 collected

編寫 DaemonSet Spec

創(chuàng)建 DaemonSet

vim daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: registry.cn-beijing.aliyuncs.com/qingfeng666/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

創(chuàng)建

kubectl apply -f daemonset.yaml

可以看到

daemonset.apps/fluentd-elasticsearch created

查看運行的 daemonset

kubectl -n kube-system get po -o wide | grep fluentd

可以看到

fluentd-elasticsearch-7b8jx      1/1     Running   0          5m32s   10.244.0.22       master   <none>           <none>
fluentd-elasticsearch-wfm9v      1/1     Running   0          5m32s   10.244.2.12       node2    <none>           <none>
fluentd-elasticsearch-x2mn9      1/1     Running   0          5m32s   10.244.1.78       node1    <none>           <none>

Daemon Pods 是如何調(diào)度的

DaemonSet 確保所有符合條件的節(jié)點都運行該 Pod 的一個副本粘我。通常,運行 Pod 的節(jié)點有 kubernetes 調(diào)度器選擇痹换。不過 DaemonSet Pods 由 DaemonSet 控制器創(chuàng)建和調(diào)度征字。這就帶來了以下問題:

  • Pod 行為的不一致性。正常 Pod 在被創(chuàng)建后等待調(diào)度時處于 Pending 狀態(tài)娇豫,DaemonSet Pod 創(chuàng)建后不會處于 pending 狀態(tài)下
  • Pod 搶占由默認調(diào)度器處理匙姜。啟用搶占后,DaemonSet 控制器將不再不考慮 Pod 優(yōu)先級和搶占的情況下制定調(diào)度決策

ScheduleDaemonSetPods 允許使用默認調(diào)度器而不是 DaemonSet 控制器來調(diào)度 DaemonSets 冯痢,方法是將 NodeAffinity 條件不是 .spec.nodeName 條件添加到 DaemonSet Pods 氮昧。默認調(diào)度器接下來將 Pod 綁定到模板主機。如果 DaemonSet Pod 的節(jié)點親和性配置已存在浦楣,則被替換郭计。DaemonSet 控制器僅在創(chuàng)建或修改 DaemonSet Pod 時執(zhí)行這些操作,并且不會更改 DaemonSet 的 .spec.template 椒振。

與 Daemon Pods 通信

與 DaemonSet 中的 Pod 通信的幾種模式

  • NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用 hostPort 昭伸,從而可以通過節(jié)點 IP 訪問到 Pod∨煊客戶端能通過某種方法獲取節(jié)點 IP 列表庐杨,并且基于此也可以獲取到響應(yīng)的端口。
  • DNS:創(chuàng)建具有相同 Pod 選擇器的無頭服務(wù)通過使用 endpoints 資源或從 DNS 中檢索到多個 A 記錄來發(fā)現(xiàn) DaemonSet夹供。
  • Service:創(chuàng)建具有相同 Pod 選擇器的服務(wù)灵份,并使用該服務(wù)隨機訪問到某個節(jié)點上的守護進程(沒有辦法訪問到特定節(jié)點)

更新 DaemonSet

如果節(jié)點的標簽被修改,DaemonSet 將立刻向新匹配上的節(jié)點添加 Pod 哮洽,同時刪除不匹配的節(jié)點上的 Pod填渠。

和 Deployments 的區(qū)別

DaemonSet 和 Deployment 非常類似,它們都能創(chuàng)建 Pod鸟辅,并且 Pod 中的進程都不希望被終止(比如 web 服務(wù)器氛什、存儲服務(wù)器)。建議為無狀態(tài)的服務(wù)使用 Deployment 匪凉,比如前段服務(wù)枪眉。對于這些服務(wù)而言,對副本的數(shù)量進行擴容再层、縮容贸铜、平滑升級堡纬,比精確控制 Pod 運行在某個主機上要重要的多。當(dāng)需要 Pod 副本總是運行在全部或特定主機上蒿秦,并需要它們先于其他 Pod 啟動時烤镐,應(yīng)該使用 DaemonSet。

Job

Job 會創(chuàng)建一個或多個 Pod 棍鳖,并確保指定數(shù)量的 Pod 成功終止职车。隨著 Pod 成功結(jié)束,Job 跟蹤記錄成功完成的 Pod 個數(shù)鹊杖。當(dāng)數(shù)量達到指定的成功個數(shù)閾值時悴灵,任務(wù)(即 Job)結(jié)束。刪除 Job 的操作會清除所創(chuàng)建的所有 Pod骂蓖。

Job 可以用來執(zhí)行一次或多次有限次數(shù)的积瞒,或者定期每天執(zhí)行的業(yè)務(wù)。

定義一個 job 登下,計算 π 到小數(shù)點后100位茫孔,并將結(jié)果打印出來

vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: registry.cn-beijing.aliyuncs.com/google_registry/perl:5.26
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(100)"]
      restartPolicy: Never
  backoffLimit: 4
kubectl apply -f job.yaml

可以看到

job.batch/pi created
kubectl get job

可以看到

NAME   COMPLETIONS   DURATION   AGE
pi     0/1           46s        46s
kubectl describe pod pi-h9ww5

可以看到

Name:         pi-h9ww5
Namespace:    default
Priority:     0
Node:         node2/192.168.190.133
Start Time:   Thu, 25 Mar 2021 15:15:26 +0800
Labels:       controller-uid=16ba5e81-8b9e-4515-904b-013535baa2a6
              job-name=pi
Annotations:  <none>
Status:       Succeeded
IP:           10.244.2.14
IPs:
  IP:           10.244.2.14
Controlled By:  Job/pi
Containers:
  pi:
    Container ID:  docker://573f0764e80f87bd457a06ff81c65d3982b6478a452d6ad3535718601bc9eb1a
    Image:         registry.cn-beijing.aliyuncs.com/google_registry/perl:5.26
    Image ID:      docker-pullable://registry.cn-beijing.aliyuncs.com/google_registry/perl@sha256:97821e418498785bb995b2c7609841ac57df0cc0156a761875db60403be0e1d8
    Port:          <none>
    Host Port:     <none>
    Command:
      perl
      -Mbignum=bpi
      -wle
      print bpi(100)
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Thu, 25 Mar 2021 15:18:38 +0800
      Finished:     Thu, 25 Mar 2021 15:18:38 +0800
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-c9dkq (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  default-token-c9dkq:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-c9dkq
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m36s  default-scheduler  Successfully assigned default/pi-h9ww5 to node2
  Normal  Pulling    3m36s  kubelet            Pulling image "registry.cn-beijing.aliyuncs.com/google_registry/perl:5.26"
  Normal  Pulled     26s    kubelet            Successfully pulled image "registry.cn-beijing.aliyuncs.com/google_registry/perl:5.26" in 3m10.737708126s
  Normal  Created    25s    kubelet            Created container pi
  Normal  Started    25s    kubelet            Started container pi

從所有 pod 里面選擇 jobname 是 pi 的 pod

pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods

可以看到

pi-h9ww5
kubectl logs pi-h9ww5

可以看到

3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市被芳,隨后出現(xiàn)的幾起案子缰贝,更是在濱河造成了極大的恐慌,老刑警劉巖畔濒,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剩晴,死亡現(xiàn)場離奇詭異,居然都是意外死亡侵状,警方通過查閱死者的電腦和手機赞弥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趣兄,“玉大人绽左,你說我怎么就攤上這事⊥叮” “怎么了拼窥?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹋凝。 經(jīng)常有香客問我鲁纠,道長,這世上最難降的妖魔是什么仙粱? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任房交,我火速辦了婚禮,結(jié)果婚禮上伐割,老公的妹妹穿的比我還像新娘候味。我一直安慰自己,他們只是感情好隔心,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布白群。 她就那樣靜靜地躺著,像睡著了一般硬霍。 火紅的嫁衣襯著肌膚如雪帜慢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天唯卖,我揣著相機與錄音粱玲,去河邊找鬼。 笑死拜轨,一個胖子當(dāng)著我的面吹牛抽减,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播橄碾,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼卵沉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了法牲?” 一聲冷哼從身側(cè)響起史汗,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拒垃,沒想到半個月后停撞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡悼瓮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年怜森,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谤牡。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡副硅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翅萤,到底是詐尸還是另有隱情恐疲,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布套么,位于F島的核電站培己,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胚泌。R本人自食惡果不足惜省咨,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玷室。 院中可真熱鬧零蓉,春花似錦笤受、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至章喉,卻和暖如春汗贫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秸脱。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工落包, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人摊唇。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓咐蝇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遏片。 傳聞我的和親對象是個殘疾皇子嘹害,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友吮便。感恩相遇笔呀!感恩不離不棄。 中午開了第一次的黨會髓需,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評論 0 11
  • 彩排完许师,天已黑
    劉凱書法閱讀 4,199評論 1 3
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒僚匆。表情可以傳達很多信息微渠。高興了當(dāng)然就笑了,難過就哭了咧擂。兩者是相互影響密不可...
    Persistenc_6aea閱讀 124,521評論 2 7