kubernetes-helm詳細(xì)介紹及使用

致讀者

完整入門示例請參考:Helm完整入門實(shí)戰(zhàn)

Helm

本指南介紹了使用 Helm 來管理 Kubernetes 集群上的軟件包的基礎(chǔ)知識。在這之前,假定您已經(jīng) 安裝了 Helm 客戶端馏慨。

如果您僅對運(yùn)行一些快速命令感興趣仆救,則不妨從 快速入門指南開始。本章包含了 Helm 命令的詳細(xì)說明,并解釋如何使用 Helm。

三大概念

Chart 代表著 Helm 包。它包含在 Kubernetes 集群內(nèi)部運(yùn)行應(yīng)用程序号杠,工具或服務(wù)所需的所有資源定義。你可以把它看作是 Homebrew formula丰歌,Apt dpkg姨蟋,或 Yum RPM 在Kubernetes 中的等價(jià)物。

Repository(倉庫) 是用來存放和共享 charts 的地方立帖。它就像 Perl 的 CPAN 檔案庫網(wǎng)絡(luò) 或是 Fedora 的 軟件包倉庫眼溶,只不過它是供 Kubernetes 包所使用的。

Release 是運(yùn)行在 Kubernetes 集群中的 chart 的實(shí)例晓勇。一個(gè) chart 通程梅桑可以在同一個(gè)集群中安裝多次灌旧。每一次安裝都會創(chuàng)建一個(gè)新的 release。以 MySQL chart為例绰筛,如果你想在你的集群中運(yùn)行兩個(gè)數(shù)據(jù)庫枢泰,你可以安裝該chart兩次。每一個(gè)數(shù)據(jù)庫都會擁有它自己的 releaserelease name铝噩。

在了解了上述這些概念以后衡蚂,我們就可以這樣來解釋 Helm:

Helm 安裝 charts 到 Kubernetes 集群中,每次安裝都會創(chuàng)建一個(gè)新的 release骏庸。你可以在 Helm 的 chart repositories 中尋找新的 chart毛甲。

'helm search':查找 Charts

Helm 自帶一個(gè)強(qiáng)大的搜索命令,可以用來從兩種來源中進(jìn)行搜索:

  • helm search hubArtifact Hub 中查找并列出 helm charts具被。 Artifact Hub中存放了大量不同的倉庫丽啡。
  • helm search repo 從你添加(使用 helm repo add)到本地 helm 客戶端中的倉庫中進(jìn)行查找。該命令基于本地?cái)?shù)據(jù)進(jìn)行搜索硬猫,無需連接互聯(lián)網(wǎng)。

你可以通過運(yùn)行 helm search hub 命令找到公開可用的charts:

$ helm search hub wordpress
URL                                                 CHART VERSION APP VERSION DESCRIPTION
https://hub.helm.sh/charts/bitnami/wordpress        7.6.7         5.2.4       Web publishing platform for building blogs and ...
https://hub.helm.sh/charts/presslabs/wordpress-...  v0.6.3        v0.6.3      Presslabs WordPress Operator Helm Chart
https://hub.helm.sh/charts/presslabs/wordpress-...  v0.7.1        v0.7.1      A Helm chart for deploying a WordPress site on ...

上述命令從 Artifact Hub 中搜索所有的 wordpress charts改执。

如果不進(jìn)行過濾啸蜜,helm search hub 命令會展示所有可用的 charts。

使用 helm search repo 命令辈挂,你可以從你所添加的倉庫中查找chart的名字衬横。

$ helm repo add brigade https://brigadecore.github.io/charts
"brigade" has been added to your repositories
$ helm search repo brigade
NAME                          CHART VERSION APP VERSION DESCRIPTION
brigade/brigade               1.3.2         v1.2.1      Brigade provides event-driven scripting of Kube...
brigade/brigade-github-app    0.4.1         v0.2.1      The Brigade GitHub App, an advanced gateway for...
brigade/brigade-github-oauth  0.2.0         v0.20.0     The legacy OAuth GitHub Gateway for Brigade
brigade/brigade-k8s-gateway   0.1.0                     A Helm chart for Kubernetes
brigade/brigade-project       1.0.0         v1.0.0      Create a Brigade project
brigade/kashti                0.4.0         v0.4.0      A Helm chart for Kubernetes

Helm 搜索使用模糊字符串匹配算法,所以你可以只輸入名字的一部分:

$ helm search repo kash
NAME            CHART VERSION APP VERSION DESCRIPTION
brigade/kashti  0.4.0         v0.4.0      A Helm chart for Kubernetes

搜索是用來發(fā)現(xiàn)可用包的一個(gè)好辦法终蒂。一旦你找到你想安裝的 helm 包蜂林,你便可以通過使用 helm install 命令來安裝它。

'helm install':安裝一個(gè) helm 包

使用 helm install 命令來安裝一個(gè)新的 helm 包拇泣。最簡單的使用方法只需要傳入兩個(gè)參數(shù):你命名的release名字和你想安裝的chart的名稱噪叙。

$ helm install happy-panda bitnami/wordpress
NAME: happy-panda
LAST DEPLOYED: Tue Jan 26 10:27:17 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
** Please be patient while the chart is being deployed **

Your WordPress site can be accessed through the following DNS name from within your cluster:

    happy-panda-wordpress.default.svc.cluster.local (port 80)

To access your WordPress site from outside the cluster follow the steps below:

1\. Get the WordPress URL by running these commands:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w happy-panda-wordpress'

   export SERVICE_IP=$(kubectl get svc --namespace default happy-panda-wordpress --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
   echo "WordPress URL: http://$SERVICE_IP/"
   echo "WordPress Admin URL: http://$SERVICE_IP/admin"

2\. Open a browser and access WordPress using the obtained URL.

3\. Login with the following credentials below to see your blog:

  echo Username: user
  echo Password: $(kubectl get secret --namespace default happy-panda-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

Now the wordpress chart is installed. Note that installing a chart creates a new release object. The release above is named happy-panda. (If you want Helm to generate a name for you, leave off the release name and use --generate-name.)

在安裝過程中,helm 客戶端會打印一些有用的信息霉翔,其中包括:哪些資源已經(jīng)被創(chuàng)建睁蕾,release當(dāng)前的狀態(tài),以及你是否還需要執(zhí)行額外的配置步驟债朵。

Helm 客戶端不會等到所有資源都運(yùn)行才退出子眶。許多 charts 需要大小超過 600M 的 Docker 鏡像,可能需要很長時(shí)間才能安裝到群集中序芦。

你可以使用 helm status 來追蹤 release 的狀態(tài)臭杰,或是重新讀取配置信息:

$ helm status happy-panda
NAME: happy-panda
LAST DEPLOYED: Tue Jan 26 10:27:17 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
** Please be patient while the chart is being deployed **

Your WordPress site can be accessed through the following DNS name from within your cluster:

    happy-panda-wordpress.default.svc.cluster.local (port 80)

To access your WordPress site from outside the cluster follow the steps below:

1\. Get the WordPress URL by running these commands:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w happy-panda-wordpress'

   export SERVICE_IP=$(kubectl get svc --namespace default happy-panda-wordpress --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
   echo "WordPress URL: http://$SERVICE_IP/"
   echo "WordPress Admin URL: http://$SERVICE_IP/admin"

2\. Open a browser and access WordPress using the obtained URL.

3\. Login with the following credentials below to see your blog:

  echo Username: user
  echo Password: $(kubectl get secret --namespace default happy-panda-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

上述信息展示了 release 的當(dāng)前狀態(tài)。

安裝前自定義 chart

上述安裝方式只會使用 chart 的默認(rèn)配置選項(xiàng)谚中。很多時(shí)候渴杆,我們需要自定義 chart 來指定我們想要的配置寥枝。

使用 helm show values 可以查看 chart 中的可配置選項(xiàng):

$ helm show values bitnami/wordpress
## Global Docker image parameters
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
## Current available global Docker image parameters: imageRegistry and imagePullSecrets
##
# global:
#   imageRegistry: myRegistryName
#   imagePullSecrets:
#     - myRegistryKeySecretName
#   storageClass: myStorageClass

## Bitnami WordPress image version
## ref: https://hub.docker.com/r/bitnami/wordpress/tags/
##
image:
  registry: docker.io
  repository: bitnami/wordpress
  tag: 5.6.0-debian-10-r35
  [..]

然后,你可以使用 YAML 格式的文件覆蓋上述任意配置項(xiàng)将塑,并在安裝過程中使用該文件脉顿。

$ echo '{mariadb.auth.database: user0db, mariadb.auth.username: user0}' > values.yaml
$ helm install -f values.yaml bitnami/wordpress --generate-name

上述命令將為 MariaDB 創(chuàng)建一個(gè)名稱為 user0 的默認(rèn)用戶点寥,并且授予該用戶訪問新建的 user0db 數(shù)據(jù)庫的權(quán)限艾疟。chart 中的其他默認(rèn)配置保持不變。

安裝過程中有兩種方式傳遞配置數(shù)據(jù):

  • --values (或 -f):使用 YAML 文件覆蓋配置敢辩”卫常可以指定多次,優(yōu)先使用最右邊的文件戚长。
  • --set:通過命令行的方式對指定項(xiàng)進(jìn)行覆蓋盗冷。

如果同時(shí)使用兩種方式,則 --set 中的值會被合并到 --values 中同廉,但是 --set 中的值優(yōu)先級更高仪糖。在--set 中覆蓋的內(nèi)容會被被保存在 ConfigMap 中∑刃ぃ可以通過 helm get values <release-name> 來查看指定 release 中 --set 設(shè)置的值锅劝。也可以通過運(yùn)行 helm upgrade 并指定 --reset-values 字段來清除 --set 中設(shè)置的值。

--set 的格式和限制

--set 選項(xiàng)使用0或多個(gè) name/value 對蟆湖。最簡單的用法類似于:--set name=value故爵,等價(jià)于如下 YAML 格式:

name: value

多個(gè)值使用逗號分割,因此 --set a=b,c=d 的 YAML 表示是:

a: b
c: d

支持更復(fù)雜的表達(dá)式隅津。例如诬垂,--set outer.inner=value 被轉(zhuǎn)換成了:

outer:
  inner: value

列表使用花括號({})來表示。例如伦仍,--set name={a, b, c} 被轉(zhuǎn)換成了:

name:
  - a
  - b
  - c

從 2.5.0 版本開始结窘,可以使用數(shù)組下標(biāo)的語法來訪問列表中的元素。例如 --set servers[0].port=80 就變成了:

servers:
  - port: 80

多個(gè)值也可以通過這種方式來設(shè)置呢铆。--set servers[0].port=80,servers[0].host=example 變成了:

servers:
  - port: 80
    host: example

如果需要在 --set 中使用特殊字符晦鞋,你可以使用反斜線來進(jìn)行轉(zhuǎn)義;--set name=value1\,value2 就變成了:

name: "value1,value2"

類似的棺克,你也可以轉(zhuǎn)義點(diǎn)序列(英文句號)悠垛。這可能會在 chart 使用 toYaml 函數(shù)來解析 annotations,labels娜谊,和 node selectors 時(shí)派上用場确买。--set nodeSelector."kubernetes\.io/role"=master 語法就變成了:

nodeSelector:
  kubernetes.io/role: master

深層嵌套的數(shù)據(jù)結(jié)構(gòu)可能會很難用 --set 表達(dá)。我們希望 Chart 的設(shè)計(jì)者們在設(shè)計(jì) values.yaml 文件的格式時(shí)纱皆,考慮到 --set 的使用湾趾。(更多內(nèi)容請查看 Values 文件

更多安裝方法

helm install 命令可以從多個(gè)來源進(jìn)行安裝:

  • chart 的倉庫(如上所述)
  • 本地 chart 壓縮包(helm install foo foo-0.1.1.tgz
  • 解壓后的 chart 目錄(helm install foo path/to/foo
  • 完整的 URL(helm install foo https://example.com/charts/foo-1.2.3.tgz

'helm upgrade' 和 'helm rollback':升級 release 和失敗時(shí)恢復(fù)

當(dāng)你想升級到 chart 的新版本芭商,或是修改 release 的配置,你可以使用 helm upgrade 命令搀缠。

一次升級操作會使用已有的 release 并根據(jù)你提供的信息對其進(jìn)行升級铛楣。由于 Kubernetes 的 chart 可能會很大而且很復(fù)雜,Helm 會嘗試執(zhí)行最小侵入式升級艺普。即它只會更新自上次發(fā)布以來發(fā)生了更改的內(nèi)容簸州。

$ helm upgrade -f panda.yaml happy-panda bitnami/wordpress

在上面的例子中,happy-panda 這個(gè) release 使用相同的 chart 進(jìn)行升級歧譬,但是使用了一個(gè)新的 YAML 文件:

mariadb.auth.username: user1

我們可以使用 helm get values 命令來看看配置值是否真的生效了:

$ helm get values happy-panda
mariadb:
  auth:
    username: user1

helm get 是一個(gè)查看集群中 release 的有用工具岸浑。正如我們上面所看到的,panda.yaml 中的新值已經(jīng)被部署到集群中了瑰步。

現(xiàn)在矢洲,假如在一次發(fā)布過程中,發(fā)生了不符合預(yù)期的事情缩焦,也很容易通過 helm rollback [RELEASE] [REVISION] 命令回滾到之前的發(fā)布版本读虏。

$ helm rollback happy-panda 1

上面這條命令將我們的 happy-panda 回滾到了它最初的版本。release 版本其實(shí)是一個(gè)增量修訂(revision)袁滥。 每當(dāng)發(fā)生了一次安裝掘譬、升級或回滾操作,revision 的值就會加1呻拌。第一次 revision 的值永遠(yuǎn)是1。我們可以使用 helm history [RELEASE] 命令來查看一個(gè)特定 release 的修訂版本號睦焕。

安裝藐握、升級、回滾時(shí)的有用選項(xiàng)

你還可以指定一些其他有用的選項(xiàng)來自定義 Helm 在安裝垃喊、升級猾普、回滾期間的行為。請注意這并不是 cli 參數(shù)的完整列表本谜。 要查看所有參數(shù)的說明初家,請執(zhí)行 helm <command> --help 命令。

  • --timeout:一個(gè) Go duration 類型的值乌助, 用來表示等待 Kubernetes 命令完成的超時(shí)時(shí)間溜在,默認(rèn)值為 5m0s
  • --wait:表示必須要等到所有的 Pods 都處于 ready 狀態(tài)他托,PVC 都被綁定掖肋,Deployments 都至少擁有最小 ready 狀態(tài) Pods 個(gè)數(shù)(Desired減去 maxUnavailable),并且 Services 都具有 IP 地址(如果是LoadBalancer赏参, 則為 Ingress)志笼,才會標(biāo)記該 release 為成功沿盅。最長等待時(shí)間由 --timeout 值指定。如果達(dá)到超時(shí)時(shí)間纫溃,release 將被標(biāo)記為 FAILED腰涧。注意:當(dāng) Deployment 的 replicas 被設(shè)置為1,但其滾動升級策略中的 maxUnavailable 沒有被設(shè)置為0時(shí)紊浩,--wait 將返回就緒窖铡,因?yàn)橐呀?jīng)滿足了最小 ready Pod 數(shù)。
  • --no-hooks:不運(yùn)行當(dāng)前命令的鉤子郎楼。
  • --recreate-pods(僅適用于 upgraderollback):這個(gè)參數(shù)會導(dǎo)致重建所有的 Pod(deployment中的Pod 除外)万伤。(在 Helm 3 中已被廢棄)

'helm uninstall':卸載 release

使用 helm uninstall 命令從集群中卸載一個(gè) release:

$ helm uninstall happy-panda

該命令將從集群中移除指定 release。你可以通過 helm list 命令看到當(dāng)前部署的所有 release:

$ helm list
NAME            VERSION UPDATED                         STATUS          CHART
inky-cat        1       Wed Sep 28 12:59:46 2016        DEPLOYED        alpine-0.1.0

從上面的輸出中呜袁,我們可以看到敌买,happy-panda 這個(gè) release 已經(jīng)被卸載。

在上一個(gè) Helm 版本中阶界,當(dāng)一個(gè) release 被刪除虹钮,會保留一條刪除記錄。而在 Helm 3 中膘融,刪除也會移除 release 的記錄芙粱。 如果你想保留刪除記錄,使用 helm uninstall --keep-history氧映。使用 helm list --uninstalled 只會展示使用了 --keep-history 刪除的 release春畔。

helm list --all 會展示 Helm 保留的所有 release 記錄,包括失敗或刪除的條目(指定了 --keep-history):

$  helm list --all
NAME            VERSION UPDATED                         STATUS          CHART
happy-panda     2       Wed Sep 28 12:47:54 2016        UNINSTALLED     wordpress-10.4.5.6.0
inky-cat        1       Wed Sep 28 12:59:46 2016        DEPLOYED        alpine-0.1.0
kindred-angelf  2       Tue Sep 27 16:16:10 2016        UNINSTALLED     alpine-0.1.0

注意岛都,因?yàn)楝F(xiàn)在默認(rèn)會刪除 release律姨,所以你不再能夠回滾一個(gè)已經(jīng)被卸載的資源了。

'helm repo':使用倉庫

Helm 3 不再附帶一個(gè)默認(rèn)的 chart 倉庫臼疫。helm repo 提供了一組命令用于添加择份、列出和移除倉庫。

使用 helm repo list 來查看配置的倉庫:

$ helm repo list
NAME            URL
stable          https://charts.helm.sh/stable
mumoshu         https://mumoshu.github.io/charts

使用 helm repo add 來添加新的倉庫:

$ helm repo add dev https://example.com/dev-charts

因?yàn)?chart 倉庫經(jīng)常在變化烫堤,在任何時(shí)候你都可以通過執(zhí)行 helm repo update 命令來確保你的 Helm 客戶端是最新的荣赶。

使用 helm repo remove 命令來移除倉庫。

創(chuàng)建你自己的 charts

chart 開發(fā)指南 介紹了如何開發(fā)你自己的chart鸽斟。 但是你也可以通過使用 helm create 命令來快速開始:

$ helm create deis-workflow
Creating deis-workflow

現(xiàn)在拔创,./deis-workflow 目錄下已經(jīng)有一個(gè) chart 了。你可以編輯它并創(chuàng)建你自己的模版富蓄。

在編輯 chart 時(shí)伏蚊,可以通過 helm lint 驗(yàn)證格式是否正確。

當(dāng)準(zhǔn)備將 chart 打包分發(fā)時(shí)格粪,你可以運(yùn)行 helm package 命令:

$ helm package deis-workflow
deis-workflow-0.1.0.tgz

然后這個(gè) chart 就可以很輕松的通過 helm install 命令安裝:

$ helm install deis-workflow ./deis-workflow-0.1.0.tgz
...

打包好的 chart 可以上傳到 chart 倉庫中躏吊。查看 Helm chart 倉庫獲取更多信息氛改。

總結(jié)

這一章介紹了 helm 客戶端的基本使用方式,包括搜索比伏,安裝胜卤,升級,和卸載赁项。也涵蓋了一些有用的工具類命令葛躏,如helm statushelm get悠菜,和 helm repo舰攒。

有關(guān)這些命令的更多信息,請查看 Helm 的內(nèi)置幫助命令:helm help悔醋。

在下一章中摩窃,我們來看一下如何開發(fā) charts。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芬骄,一起剝皮案震驚了整個(gè)濱河市猾愿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌账阻,老刑警劉巖蒂秘,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淘太,居然都是意外死亡姻僧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門蒲牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來段化,“玉大人,你說我怎么就攤上這事造成。” “怎么了雄嚣?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵晒屎,是天一觀的道長。 經(jīng)常有香客問我缓升,道長鼓鲁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任港谊,我火速辦了婚禮骇吭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘歧寺。我一直安慰自己燥狰,他們只是感情好棘脐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著龙致,像睡著了一般蛀缝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上目代,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天屈梁,我揣著相機(jī)與錄音,去河邊找鬼榛了。 笑死在讶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的霜大。 我是一名探鬼主播构哺,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼僧诚!你這毒婦竟也來了遮婶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤湖笨,失蹤者是張志新(化名)和其女友劉穎旗扑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慈省,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡臀防,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了边败。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袱衷。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖笑窜,靈堂內(nèi)的尸體忽然破棺而出致燥,到底是詐尸還是另有隱情,我是刑警寧澤排截,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布嫌蚤,位于F島的核電站,受9級特大地震影響断傲,放射性物質(zhì)發(fā)生泄漏脱吱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一认罩、第九天 我趴在偏房一處隱蔽的房頂上張望箱蝠。 院中可真熱鬧,春花似錦、人聲如沸宦搬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽床三。三九已至一罩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撇簿,已是汗流浹背聂渊。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留四瘫,地道東北人汉嗽。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像找蜜,于是被迫代替她去往敵國和親饼暑。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

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