ASP.NET Core 借助 Helm 部署應(yīng)用至K8S

前言

玩K8S也有一段時(shí)間了,借助云服務(wù)提供商的K8S控制臺(tái)扼雏,已經(jīng)可以很方便的快速部署應(yīng)用至K8S南捂。通過(guò)簡(jiǎn)單的點(diǎn)擊,可以一次性幫忙創(chuàng)建K8S 對(duì)象:Deployment缸兔、Service日裙、Ingress、ConfigMap等惰蜜。但是當(dāng)服務(wù)的規(guī)模上來(lái)后昂拂,這種方式就有點(diǎn)捉襟見(jiàn)肘。尤其是需要同時(shí)更新多個(gè)關(guān)聯(lián)服務(wù)時(shí)抛猖,就需要一個(gè)一個(gè)的去更改格侯,就有點(diǎn)不太方便。為了解決這個(gè)問(wèn)題财著,最近上手實(shí)操了一下Helm联四,發(fā)現(xiàn)生產(chǎn)力大大提升。

Helm 簡(jiǎn)介

Helm 是一個(gè)為K8S打造的包管理器撑教。通過(guò)Helm可以方便管理Kubernetes應(yīng)用程序朝墩。Helm主要有兩大核心概念:Charts、Release伟姐。

  1. Chart:用來(lái)定義收苏,安裝和升級(jí)K8S 應(yīng)用亿卤。亦可分享及版本化控制。
  2. Release:類似Image之于Container鹿霸,Release是Chart的運(yùn)行實(shí)例排吴。

目前Helm最新的版本為V3.1,較之前版本杜跷,在整體架構(gòu)上移除服務(wù)端Tiller傍念。
對(duì)于Windows系統(tǒng)而言可借助Choco快速安裝:choco install kubernetes-helm,通過(guò)執(zhí)行helm version確認(rèn)是否安裝成功葛闷。
version.BuildInfo{Version:"v3.1.0", GitCommit:"b29d20baf09943e134c2fa5e1e1cab3bf93315fa", GitTreeState:"clean", GoVersion:"go1.13.7"}

在繼續(xù)往前憋槐,請(qǐng)確保已具備基礎(chǔ)的K8S基礎(chǔ)知識(shí),并且確保本機(jī)已安裝Docker和K8S淑趾。安裝教程和K8S簡(jiǎn)單入門(mén)可參考我的這篇文章ASP.NET Core 借助 K8S 玩轉(zhuǎn)容器編排阳仔。

對(duì)于第一次接觸Helm .NETer 來(lái)說(shuō)我們可以通過(guò)VS 2019來(lái)快速體驗(yàn)一下。請(qǐng)確保已安裝Visual Studio Tools for Kubernetes扣泊。


創(chuàng)建 Chart (helm create)

打開(kāi)VS 創(chuàng)建項(xiàng)目近范,選擇Container Application for Kubernetes,創(chuàng)建一個(gè)空的ASP.NET Core Web 項(xiàng)目延蟹。


創(chuàng)建后评矩,項(xiàng)目結(jié)構(gòu)如下圖所示,與平時(shí)之間創(chuàng)建的Web項(xiàng)目而言阱飘,主要是多了一個(gè)charts目錄斥杜、Dockerfile和一個(gè)azds.yaml
項(xiàng)目結(jié)構(gòu)

除了創(chuàng)建項(xiàng)目時(shí)通過(guò)選擇Container Application for Kubernetes類型外沥匈,我們也可以通過(guò)其他方式創(chuàng)建蔗喂。我們這里手動(dòng)刪除charts目錄、Dockerfile和一個(gè)azds.yaml高帖。然后如下圖步驟即可重新生成Helm Chart缰儿。
添加 helm chart

當(dāng)然也可以通過(guò)helm create創(chuàng)建。

安裝 Chart (helm install)

在展開(kāi)之前散址,先來(lái)簡(jiǎn)要介紹Chart目錄:

k8shelmdemo/                         # Chart 目錄
├── charts                           # 這個(gè) charts 依賴的其他 charts乖阵,始終被安裝
├── Chart.yaml                       # 描述這個(gè) Chart 的相關(guān)信息、包括名字预麸、描述信息义起、版本等
├── templates                        # 模板目錄
│   ├── deployment.yaml              # deployment 控制器的 Go 模板文件
│   ├── _helpers.tpl                 # 以 _ 開(kāi)頭的文件不會(huì)部署到 k8s 上,可用于定制通用信息
│   ├── ingress.yaml                 # ingress 的模板文件
│   ├── NOTES.txt                    # Chart 幫助文本师崎,安裝后會(huì)顯示給用戶默终,例如:如何使用、列出缺省值
│   ├── service.yaml                 # service 的 Go 模板文件
│   ├── secrets.yaml                 # secrets 的 Go 模板文件
│   └── tests
│       └── test-connection.yaml
└── values.yaml                      # 模板的值文件,這些值會(huì)在安裝時(shí)應(yīng)用到 GO 模板生成部署文件

簡(jiǎn)單來(lái)說(shuō)齐蔽,Helm Chart 定義常用的K8S 對(duì)象模板两疚,通過(guò)values.yaml來(lái)填充模板。那我們就來(lái)看看填充后的輸出結(jié)果是怎樣的含滴。打開(kāi)命令提示符诱渤,進(jìn)入到Chart目錄,通過(guò)helm template --debug [release name] [chart dir]命令就可以測(cè)試Chart(亦可通過(guò)helm --dry-run --debug [release name] [chart dir]測(cè)試)谈况∩酌溃可以看到輸出了Service和Deployment。這里你可能就納悶了碑韵,不是定義了4個(gè)K8S對(duì)象模板嗎赡茸,為什么就是輸出2個(gè)yaml文件呢。這里先按住不表祝闻。

PS \K8S.Helm.Demo\charts> helm template --debug k8s-helm-demo .\k8shelmdemo\
install.go:158: [debug] Original chart version: ""
install.go:175: [debug] CHART PATH: \K8S.Helm.Demo\charts\k8shelmdemo
---
# Source: k8shelmdemo/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: k8shelmdemo
  labels:
    app: k8shelmdemo
    chart: k8shelmdemo-0.1.0
    release: k8s-helm-demo
    heritage: Helm
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: k8shelmdemo
    release: k8s-helm-demo
---
# Source: k8shelmdemo/templates/deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: k8shelmdemo
  labels:
    app: k8shelmdemo
    chart: k8shelmdemo-0.1.0
    draft: draft-app
    release: k8s-helm-demo
    heritage: Helm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8shelmdemo
      release: k8s-helm-demo
  template:
    metadata:
      labels:
        app: k8shelmdemo
        draft: draft-app
        release: k8s-helm-demo
      annotations:
        buildID: ""
    spec:
      containers:
        - name: k8shelmdemo
          image: "k8shelmdemo:stable"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          env:
          resources:
            {}

這里目前需要注意一點(diǎn)就是上面輸出的Deployment中使用的鏡像為image: "k8shelmdemo:stable"占卧。所以在安裝該Chart之前,我們需要構(gòu)造鏡像联喘。鏡像構(gòu)造很簡(jiǎn)單华蜒,在Vs中右鍵Dockerfile選擇構(gòu)建就好(請(qǐng)確保Docker已啟動(dòng))。

build docker image

觀察VS輸出窗口豁遭,會(huì)有以下輸出:

1>K8S.Helm.Demo -> D:\Programming\Coding\dotnet\K8S.Ocelot.Demo\src\K8S.Helm.Demo\bin\Debug\netcoreapp3.1\K8S.Helm.Demo.dll
1>Docker version 19.03.1, build 74b1e89
1>docker build -f "d:\programming\coding\dotnet\k8s.ocelot.demo\src\k8s.helm.demo\dockerfile" --force-rm -t k8shelmdemo  --label "com.microsoft.created-by=visual-studio" --label "com.microsoft.visual-studio.project-name=K8S.Helm.Demo" "d:\programming\coding\dotnet\k8s.ocelot.demo\src"
1>Sending build context to Docker daemon  6.192MB
1>
1>Step 1/18 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
1>Step 2/18 : WORKDIR /app
1> ---> e28362768eed
1> ---> Using cache
1> ---> 6457841dbdf1
1>Step 3/18 : EXPOSE 80
1> ---> Using cache
1> ---> bb9dc51530fe
1>Step 4/18 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
1> ---> 0a4c7c13f9d6
1>Step 5/18 : WORKDIR /src
1> ---> Using cache
1> ---> ddc36742b71c
1>Step 6/18 : COPY ["K8S.Helm.Demo/K8S.Helm.Demo.csproj", "K8S.Helm.Demo/"]
1> ---> d18831c83acd
1>Step 7/18 : RUN dotnet restore "K8S.Helm.Demo/K8S.Helm.Demo.csproj"
1> ---> Running in 64d3624eb9c0
1>  Restore completed in 7.19 sec for /src/K8S.Helm.Demo/K8S.Helm.Demo.csproj.
1>Removing intermediate container 64d3624eb9c0
1> ---> ba3624442138
1>Step 8/18 : COPY . .
1> ---> 43c4f6c4769f
1>Step 9/18 : WORKDIR "/src/K8S.Helm.Demo"
1> ---> Running in 145e155d3a5d
1>Removing intermediate container 145e155d3a5d
1>Step 10/18 : RUN dotnet build "K8S.Helm.Demo.csproj" -c Release -o /app/build
1> ---> e547e8caed4a
1> ---> Running in 146df981f291
1>Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>
1>  Restore completed in 27.08 ms for /src/K8S.Helm.Demo/K8S.Helm.Demo.csproj.
1>  K8S.Helm.Demo -> /app/build/K8S.Helm.Demo.dll
1>Build succeeded.
1>    0 Warning(s)
1>
1>Time Elapsed 00:00:02.09
1>    0 Error(s)
1>Removing intermediate container 146df981f291
1>Step 11/18 : FROM build AS publish
1> ---> 94f07ad82c1c
1> ---> 94f07ad82c1c
1>Step 12/18 : RUN dotnet publish "K8S.Helm.Demo.csproj" -c Release -o /app/publish
1> ---> Running in 60d63984fe28
1>Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
1>
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>  Restore completed in 26.94 ms for /src/K8S.Helm.Demo/K8S.Helm.Demo.csproj.
1>  K8S.Helm.Demo -> /src/K8S.Helm.Demo/bin/Release/netcoreapp3.1/K8S.Helm.Demo.dll
1>  K8S.Helm.Demo -> /app/publish/
1>Removing intermediate container 60d63984fe28
1>Step 13/18 : FROM base AS final
1> ---> 85d893dc4a81
1> ---> bb9dc51530fe
1>Step 14/18 : WORKDIR /app
1> ---> Running in 69b7fd56c371
1>Removing intermediate container 69b7fd56c371
1> ---> 219310025c54
1>Step 15/18 : COPY --from=publish /app/publish .
1>Step 16/18 : ENTRYPOINT ["dotnet", "K8S.Helm.Demo.dll"]
1> ---> 6e63a4449dbb
1> ---> Running in a43a0516c6dc
1>Removing intermediate container a43a0516c6dc
1> ---> 36f422c923fd
1>Step 17/18 : LABEL com.microsoft.created-by=visual-studio
1> ---> Running in 88d100227ee1
1>Removing intermediate container 88d100227ee1
1> ---> 4a71f8e5e761
1>Step 18/18 : LABEL com.microsoft.visual-studio.project-name=K8S.Helm.Demo
1> ---> Running in f609881010ad
1>Removing intermediate container f609881010ad
1> ---> 3301427c0fb8
1>Successfully built 3301427c0fb8
1>Successfully tagged k8shelmdemo:latest
1>SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

最終構(gòu)建的鏡像名稱為k8shelmdemo:latest叭喜。與我們上面Chart中使用的鏡像k8shelmdemo:stable不一致。如果現(xiàn)在安裝Chart蓖谢,那么應(yīng)用將無(wú)法找對(duì)應(yīng)的鏡像無(wú)法啟動(dòng)域滥。那怎么辦呢。查看deployment.yaml模板文件蜈抓,我們發(fā)現(xiàn)其鏡像引用定義為image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"。查看values.yaml發(fā)現(xiàn)如下定義:

image:
  repository: k8shelmdemo
  tag: stable
  pullPolicy: IfNotPresent

所以改法就很簡(jiǎn)單了昂儒,將values.yaml的tag更改為latest即可沟使。更改后在執(zhí)行helm template --debug [release name] [chart dir] 驗(yàn)證下。接下來(lái)通過(guò)helm install來(lái)安裝Chart渊跋。在執(zhí)行之前腊嗡,我們先通過(guò)kubectl create ns helmdemo創(chuàng)建一個(gè)獨(dú)立的命名空間以方便確認(rèn)和清理。再執(zhí)行helm install k8shelmdemo .\k8shelmdemo\ -n helmdemo 安裝(-n 指定我們剛剛創(chuàng)建的命名空間)拾酝。具體命令如下:

PS \K8S.Helm.Demo\charts> kubectl create ns helmdemo
namespace/helmdemo created
PS \K8S.Helm.Demo\charts> helm install k8shelmdemo .\k8shelmdemo\ -n helmdemo
NAME: k8shelmdemo
LAST DEPLOYED: Sun Feb 23 17:33:54 2020
NAMESPACE: helmdemo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace helmdemo -l "app=k8shelmdemo,release=k8shelmdemo" -o jsonpath="{.items[0].metadat
a.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80
PS \K8S.Helm.Demo\charts>

我們看到同時(shí)輸出了模板文件夾下的NOTES模板燕少,這時(shí)說(shuō)明helm已經(jīng)安裝了。那怎樣確保是否安裝成功了呢蒿囤。繼續(xù)執(zhí)行以下命令:

PS \K8S.Helm.Demo\charts> helm list -n helmdemo #查看指定命名空間下已安裝的chart客们,也就是運(yùn)行中的Release
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
k8shelmdemo     helmdemo        1               2020-02-23 17:33:54.2196357 +0800 CST   deployed        k8shelmdemo-0.1.0       1.0
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo # 查看指定命名空間下K8S下所有的對(duì)象
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-fcfx7   1/1     Running   0          5m8s

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/k8shelmdemo   ClusterIP   10.97.204.227   <none>        80/TCP    5m8s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           5m8s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       5m8s

至此我們可以確定Chart成功安裝。那如何訪問(wèn)剛剛部署的Web應(yīng)用呢,安裝剛剛Chart的安裝Notes底挫,通過(guò)kubectl port-forward配置端口轉(zhuǎn)發(fā)恒傻,來(lái)完成。從上面的輸出我們已經(jīng)知道對(duì)應(yīng)的Pod Name 為k8shelmdemo-689bd54677-fcfx7建邓。執(zhí)行kubectl port-forward k8shelmdemo-689bd54677-fcfx7 8090:80盈厘。

PS \K8S.Helm.Demo\charts> kubectl port-forward k8shelmdemo-689bd54677-fcfx7 8090:80 -n helmdemo
Forwarding from 127.0.0.1:8090 -> 80
Forwarding from [::1]:8090 -> 80

換一個(gè)命令行執(zhí)行curl -l http://localhost:8090 會(huì)看到輸出Hello world

更新 Chart (helm upgrade)

假設(shè)我現(xiàn)在想將輸出更新為Hello Helm官边,我們來(lái)看下怎么辦沸手。對(duì)于當(dāng)前應(yīng)用來(lái)說(shuō),更新輸出注簿,只需要更改Startup的Hello World改為Hello Helm 就好契吉,然后重新構(gòu)建鏡像。
這里思考一下滩援,因?yàn)橹匦聵?gòu)建的鏡像Tag還是k8shelmdemo:latest栅隐,所以無(wú)需對(duì)當(dāng)前Helm Chart做任何改動(dòng),所以也就無(wú)需更新玩徊。那我們?cè)撊绾胃聭?yīng)用呢租悄。如果有K8S基礎(chǔ)的同學(xué)應(yīng)該很快就能想到,直接刪除Pod即可恩袱。因?yàn)閺纳厦?code>kubectl get all -n helmdemo的輸出中泣棋,我們可以看到Chart為我們的應(yīng)用自動(dòng)創(chuàng)建了一個(gè)ReplicaSet實(shí)例,ReplicaSet主要用于確保應(yīng)用始終保持指定數(shù)量的實(shí)例運(yùn)行畔塔。所以如果刪除一個(gè)Pod潭辈,K8S會(huì)按照ReplicaSet的定義,重新啟用一個(gè)新的Pod澈吨。再重新執(zhí)行kubectl port-forward把敢,會(huì)發(fā)現(xiàn)應(yīng)用已更新。

PS: 因?yàn)楫?dāng)前demo使用的是本地鏡像谅辣,所以刪除Pod后修赞,重新運(yùn)行的pod能夠輸出更新后的結(jié)果。如果鏡像來(lái)源并非本地桑阶,那么對(duì)于同一個(gè)鏡像tag來(lái)說(shuō)柏副,就要考慮更新鏡像拉取策略。

PS \K8S.Helm.Demo\charts> kubectl delete pod/k8shelmdemo-689bd54677-fcfx7 -n helmdemo # 刪除pod
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-mrr64   1/1     Running   0          29s # 新的Pod創(chuàng)建成功

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/k8shelmdemo   ClusterIP   10.97.204.227   <none>        80/TCP    33m

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           33m

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       33m

假設(shè)現(xiàn)在需要服務(wù)部署后直接通過(guò)指定端口訪問(wèn)蚣录,無(wú)需通過(guò)kubeclt port-forward進(jìn)行端口轉(zhuǎn)發(fā)割择。那么我們就需要對(duì)Chart進(jìn)行相應(yīng)更新,將生成的Service的類型由默認(rèn)的Cluster更改為LoadBalancer模式萎河。更新values.yaml中的service節(jié)點(diǎn)如下:

service:
  type: LoadBalancer
  port: 8093

緊接著通過(guò)執(zhí)行helm upgrade [release name] [chart dir]命令更新應(yīng)用荔泳,如下蕉饼。

PS \K8S.Helm.Demo\charts> helm upgrade k8shelmdemo .\k8shelmdemo\ -n helmdemo
Release "k8shelmdemo" has been upgraded. Happy Helming!
NAME: k8shelmdemo
LAST DEPLOYED: Sun Feb 23 18:39:30 2020
NAMESPACE: helmdemo
STATUS: deployed
REVISION: 3
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w k8shelmdemo'
  export SERVICE_IP=$(kubectl get svc --namespace helmdemo k8shelmdemo -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:8093
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-pj5pd   1/1     Running   0          22m

NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/k8shelmdemo   LoadBalancer   10.97.204.227   localhost     8093:30035/TCP   65m

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           65m

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       65m
PS \K8S.Ocelot.Demo\src\K8S.Helm.Demo\charts> curl -l localhost:8093
Hello Helm!
PS \K8S.Helm.Demo\charts> helm ls -n helmdemo # 版本已更新
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
k8shelmdemo     helmdemo        2                2020-02-23 18:39:30.2059395 +0800 CST   deployed        k8shelmdemo-0.1.0       1.0

刪除 Chart (helm delete)

演示完畢澳叉,那如何刪除已發(fā)布的Release呢婴程,執(zhí)行helm delete k8shelmdemo -n helmdemo端幼。

PS \K8S.Helm.Demo\charts> helm delete k8shelmdemo -n helmdemo
release "k8shelmdemo" uninstalled
PS \K8S.Helm.Demo\charts> helm ls -n helmdemo
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
No resources found.

執(zhí)行后仗考,可以發(fā)現(xiàn)創(chuàng)建的K8S資源也已清理干凈哮幢。

最后

以上僅是對(duì) ASP.NET Core 如何使用 Helm 部署到K8S的簡(jiǎn)單介紹诸蚕,希望對(duì)入門(mén)的你有所幫助某残!對(duì)于Helm復(fù)雜的應(yīng)用鄙信,主要在于模板填充的復(fù)雜應(yīng)用译荞,大家可以結(jié)合官方Helm文檔以及eShopOnContainer中Helm示例進(jìn)行學(xué)習(xí)瓤的。

參考資料:
Get started with Visual Studio Kubernetes Tools
玩K8S不得不會(huì)的HELM

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吞歼,隨后出現(xiàn)的幾起案子圈膏,更是在濱河造成了極大的恐慌,老刑警劉巖篙骡,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稽坤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡糯俗,警方通過(guò)查閱死者的電腦和手機(jī)尿褪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)得湘,“玉大人杖玲,你說(shuō)我怎么就攤上這事√哉” “怎么了摆马?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸿吆。 經(jīng)常有香客問(wèn)我囤采,道長(zhǎng),這世上最難降的妖魔是什么惩淳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任蕉毯,我火速辦了婚禮,結(jié)果婚禮上黎泣,老公的妹妹穿的比我還像新娘。我一直安慰自己缤谎,他們只是感情好抒倚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著坷澡,像睡著了一般托呕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天项郊,我揣著相機(jī)與錄音馅扣,去河邊找鬼。 笑死着降,一個(gè)胖子當(dāng)著我的面吹牛差油,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播任洞,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蓄喇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了交掏?” 一聲冷哼從身側(cè)響起妆偏,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盅弛,沒(méi)想到半個(gè)月后钱骂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挪鹏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年见秽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狰住。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡张吉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出催植,到底是詐尸還是另有隱情肮蛹,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布创南,位于F島的核電站伦忠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏稿辙。R本人自食惡果不足惜昆码,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邻储。 院中可真熱鬧赋咽,春花似錦、人聲如沸吨娜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宦赠。三九已至陪毡,卻和暖如春米母,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毡琉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工铁瞒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桅滋。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓慧耍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親虱歪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜂绎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • 介紹 Helm 是 Deis 開(kāi)發(fā)的一個(gè)用于 Kubernetes 應(yīng)用的包管理工具,主要用來(lái)管理 Charts笋鄙。...
    小波同學(xué)閱讀 1,398評(píng)論 0 4
  • 概覽 ? Helm 簡(jiǎn)介 ? Helm 安裝使用 ? Helm 的基本使用 ? Helm 模板詳解之內(nèi)置函數(shù)與 V...
    51reboot閱讀 2,485評(píng)論 0 2
  • Helm 是 Kubernetes 的軟件包管理工具师枣。本文需要讀者對(duì) Docker、Kubernetes 等相關(guān)知...
    guoweikuang閱讀 86,580評(píng)論 3 86
  • 自從有了小喵萧落,總感覺(jué)身體被掏空践美。生活倒也沒(méi)翻天覆地,工作上的焦慮轉(zhuǎn)變成養(yǎng)育小喵的壓力找岖。時(shí)刻得記掛著它陨倡,怕他它冷...
    你是自由幸福的閱讀 153評(píng)論 0 0
  • 《2017-2018》 如果過(guò)了今天就來(lái)到2018 你有什么話要對(duì)2017表達(dá) 今年的你是否和去年一樣 坐在某個(gè)角...
    葉威閱讀 165評(píng)論 0 0