為什么K8s在阿里能成功過?基于K8s的云原生改造實踐過程

導讀:本文描述了阿里巴巴在容器管理領域的技術演進歷程,解讀了為什么 K8s 最終能夠大獲成功的原因,以及到今年 雙11 阿里巴巴內部的 K8s 應用情況。內容著重描述了阿里巴巴基于 K8s 的云原生改造實踐過程的三大能力升級,在對應能力升級過程中沉淀的技術解決方案,以及通過這些能力升級所取得的業務價值。

從 2015 年 Google 牽頭成立 CNCF 以來,云原生技術開始進入公眾的視線并取得快速的發展,到 2018 年包括 Google、AWS、Azure、Alibaba Cloud 等大型云計算供應商都加入了 CNCF,云原生技術也從原來的應用容器化發展出包括容器、Service Mesh、微服務、不可變基礎設施、Serverless、FaaS 等眾多技術方向,CFCF 旗下也囊括了越來多的開源項目。

Kubernetes 作為 CNCF 的第一個項目從誕生之初就就令人矚目,Kubernetes 由 Google 工程師基于 Google 內部多年集群管理系統 Borg 的設計經驗,結合云計算時代的基礎設施特點重新設計而得,旨在幫助企業解決大規模 IT 基礎設施的應用容器編排難題。

Google 在 2014 年 6 月開源 Kubernetes 以后,在 Redhat、Microsoft、Alibaba 等廠商和眾多開源愛好者共同的努力下,成長為如今容器編排領域的事實標準,極大的推動了云原生領域的發展。

今天為大家分享來自阿里云的 Kubernetes 大規模實踐經驗,展現阿里云如何基于 Kubernetes 推動阿里巴巴應用運維技術棧走向云原生,如何推動 Kubernetes自身的技術進步,充分挖掘云原生時代的紅利助力阿里巴巴大幅降低 雙11 的 IT 成本。

容器在阿里巴巴的發展歷程

在 2011 年之前,阿里巴巴使用 VM 虛擬化技術將一個物理機切分為 3 個虛擬機,用于部署淘寶服務,而隨著淘寶業務的飛速發展,基于 VM 的技術方案在靈活性上跟不上業務的步伐。

因此,阿里巴巴在 2011 年就開始探索基于 Linux lxc 的容器技術,用于替代傳統基于 VM 的應用部署方案,到 2013 年,研發了基于 Linux lxc 的 T4 容器和 AI 容器編排系統。這在當時已是非常領先的技術方案,但自己研發的容器技術與基于 VM 時代的運維系統始終存在一些兼容性問題。

在 2013 年隨著 Docker 容器鏡像方案的出現,阿里巴巴技術人員立即看到了基于容器 + Docker 鏡像技術的未來,開始大力投入到這一領域的研究當中,到 2015 年 Aliswarm、Zeus、Hippo 等容器編排系統蓬勃發展,各自開疆擴土服務了阿里巴巴經濟體的一部分業務。諸多的系統在解決了業務運維成本的同時,也帶來了一定的重復建設成本,同時也導致了阿里巴巴內部的資源分布比較分散,無法統一調度多樣的業務類型發揮出不同業務錯峰使用資源的優勢。

正是在這樣的背景下,Sigma 系統應運而出并在 2017 年統一了阿里巴巴的資源池,統一調度阿里巴巴所有的核心業務,并第一次支持將在線服務與離線作業運行在同一個物理機上,大幅提高數據中心的資源利用效率并降低了阿里巴巴的 IT 成本。

隨著云原生技術的高速發展,阿里巴巴也看到了云原生技術的潛力,以及未來企業 IT 全面上云的必然趨勢,從 2018 年開始轉型到 Kubernetes 技術,通過 Kubernetes 擴展能力將Sigma 積累多年的調度能力通過 Kubernetes 的方式提供出來。

在 2019 年阿里巴巴宣布全面上云,阿里巴巴開始全面擁抱 Kubernetes,并將 Sigma 調度系統全面的遷移到基于 Kubernetes 的調度系統,該系統也正是支持了今年最大規模 雙11 電商交易系統的底層基礎設施,穩定的支持了大促前后數百次的應用變更并提供極速的應用發布與擴容體驗,為 雙11 的順暢的購物體驗立下汗馬功勞。

為什么 K8s 在阿里能成功

Kubernetes 在眾多的技術中脫穎而出,概括起來可以歸納為以下三個方面。

首先是其在誕生之初就為云時代而生,擁有超前的眼光和先進的設計理念,加之最初由天才的 Google 工程師基于其內部 Borg 多年的經驗設計而來,誕生之后就飛速發展;

后來隨著 RedHat、IBM、微軟、Vmware、阿里云等來自全球的優秀工程師大力投入,打造了繁榮的社區和生態系統,成為企業容器編排系統的首選。

阿里巴巴經濟體擁有眾多的子公司,這些子公司在加入阿里巴巴大家庭時或多或少都會有一套自有的容器編排系統,在融入阿里巴巴的基礎設施過程中,Kubernetes 是最標準也最容易被經濟體內外的客戶所接受的一個方案。

其次,Kubernetes 倡導的申明式 API 的設計理念,也貼合了阿里巴巴在應用運維領域的經驗與教訓;

傳統的運維系統通常是基于過程式的設計,而過程式的運維系統在較長的系統調用鏈路下,通常會出現因異常處理復雜而導致的系統效率低下。

在大規模應用運維系統中復雜又繁多的狀態處理也是一個大難題,基于過程式的系統設計很難確保系統的一致性,針對這些邊界異常的處理通常又導致運維系統變得非常復雜,最終為異常兜底的只能依賴運維人員的人工操作。基本上可以認為基于過程式的運維系統難以應對超大規模的應用管理,而 Kubernetes 提供的申明式 API 卻是解決應用運維狀態輪轉的一劑良藥,是提高運維技術棧整體鏈路效率的最佳實踐原則。

第三,Kubernetes 模塊化、可擴展的架構設計,滿足阿里巴巴的定制化改造以支持眾多業務運維場景的需求。

在阿里巴巴內部,即有大量的無狀態核心電商系統,也有大量的緩存、消息隊列等中間件有狀態系統,也包括大量帶有倒排索引數據的檢索系統,還有大量的 AI 計算任務,不同的應用類型對底層容器管理平臺的要求也有所不同。

因此,一個模塊化方便嵌入自定義應用管理策略、易于擴展調度模型的設計顯得至關重要,是能夠服務阿里內部眾多應用形態、提供統一容器管理基礎設施的關鍵,Kubernetes 基本上提供了這些關鍵基礎能力,雖然在實際應用過程中仍然會遇到非常多的實際問題。

阿里巴巴的 K8s 應用情況

在 2019 年 雙11,阿里巴巴內部核心業務主要運行在神龍、ECS、ECI 三種資源類型的基礎設施之上,而這些不同類型的基礎設施資源均通過 Kubernetes 統一管理,以容器的形態提供給上層應用使用,完成了核心業務的支撐。

有別于以往的 雙11,今年核心電商業務應用大規模部署在神龍裸金屬服務器上。如果有關注過阿里云技術的發展,應該不會對神龍服務器感到陌生,它是阿里云自主研發的新一代云服務器,通過“軟硬一體”的技術開創性的將云計算的虛擬化開銷分攤到低價硬件板卡上,徹底的釋放 CPU 的計算能力,第一次真正的做到了云計算虛擬化的“零”開銷。

容器也是一種輕量級的虛擬化方案,神龍+容器+Kubernetes 的結合正是云原生時代的最佳拍檔,支撐了今年最大規模的 雙11,也將是未來的主流技術形態。

阿里巴巴也在繼續使用 ECS 作為 Kubernetes 的底層資源供給,ECS 作為傳統的云計算虛擬化方式支撐了部門集團內部業務,同時結合靈活性更好的彈性容器實例 ECI 用于應對業務突發的流量峰值,為業務帶來了云計算的彈性價值,真正實現了按需申請、釋放資源的極致彈性能力,降低了業務需要提前規劃資源所帶來的成本。

這些分布在海內外的數十萬個節點的資源,被數十個 Kubernetes 集群托管,運行著阿里巴巴上萬個應用,共計超過百萬的容器,其規模之大前所未有。在今年的 雙11 中,阿里巴巴內部最大的 Kubernetes 集群規模達到萬級;當然這并不是Kubernetes 的技術極限,而是我們考慮數據中心資源效率與基礎設施容災能力之間所取的平衡,在將來如果有需要這個數字也可能變得更大。

基于 K8s 的云原生改造實踐

Kubernetes 作為云原生技術的代表,已經成為了容器編排領域的事實標準,阿里巴巴自 2017 年開始探索,到 2018 年確認技術轉型到使用 Kubernetes 來管理生產的容器。

在落地 K8s 的過程中,我們主要面臨著兩大難題:

其一,上層多樣的業務運維平臺;

為了支撐阿里巴巴內部多樣的業務形態,在內部發展出來了多個典型的業務運維平臺,每一個運維平臺的基礎設施、流程控制、應用發布策或多或少都會存在一些差別,缺少一個統一的應用運維標準。在調度與集群管理的技術演進過程中,如何牽引整個運維體系升級的同時并保持多個業務的平臺及其上業務的穩定性,這是一個巨大的工程。

其二,隨著阿里巴巴經濟體全面上云戰略的實施,整個底層基礎設施包括存儲、網絡、基礎運維軟件的技術演進也非常迅速。調度與集群管理需要在支持好基礎設施快速演進的同時,迭代自身的技術架構,并同時保證業務的穩定性。

基于 K8s 的云原生技術改造正是在這樣的背景下誕生,發展到 2019 年 Kubernetes 在內部已大規模部署,所有的核心業務也都已經運行在 K8s 集群管理中。但在這幾年的實踐過程中,有一個問題始終縈繞在工程師頭腦中,在阿里巴巴這么大體量、這么復雜的業務下,遺留了大量傳統的運維習慣以及支撐這些習慣的運維體系,在這樣的背景下落地Kubernetes (內部一個形象的比喻叫做給高速飛行的飛機更換發動機)到底是在堅持什么,哪些地方可以妥協,哪些地方必須改變?

這一章節, 將為大家分享我們這幾年對這個問題的一些思考,特別是經過了今年的 雙11 考驗后,這個問題的答案基本上得到了工程師群里的集體認可。

負責頂層設計的架構師終于可以喘一口氣:擁抱 Kubernetes 本身并不是目的,而通過擁抱 Kubernetes 撬動業務的云原生改造,通過 Kubernetes 的能力治理傳統運維體系下的沉埃頑疾,真正釋放云的彈性能力,為業務的應用交付解綁提速,才是這次技術變革的最大價值所在。

面向終態升級

在傳統的運維體系下,應用的變更都是運維通過創建操作工單發起工作流,繼而對容器平臺發起一個個的變更來完成的。比如升級一個服務器的 3000 個實例,工單會被提前計算并生成出多個批次的子任務,并逐個的調用容器平臺的接口完成變更應用的變更。

為了確保應用發布工單的順利執行,在每一個子工單內部,每一個容器的發布也是一個工作流,包括監控開關、鏡像拉取、容器啟停、服務注冊、配置推送等等,如果一切正常該流程會按預期有序的進行。

在大規模應用發布的場景中,諸如宿主機宕機、磁盤異常、IO 異常、網絡異常、內核異常等幾乎是必然存在的,如果發布流程中的某一個步驟出現了錯誤,通常情況下需要運維平臺按照一定的策略來重試,直到超過該批次的超時閾值,這將會帶來三個問題,下面逐一展開。

其一是重試帶來的效率問題;

每一個子任務的執行時間將被任務內的長尾發布所拖累,假設將 3000 個容器分為 30 批次每批 100 個(僅為示意并非最佳實踐),每一批次內出現一個容器發布異常時,該批次的發布時間將被重試拉長。

其二是失敗帶來的一致性問題;

對于發布異常的容器,在工單結束之后通常只能通過外圍鏈路巡檢的方式來治理,而事實上通常的巡檢是依賴運維人員手工操作的,帶來了極大的人工成本和不確定性。

第三是應用并發變更沖突問題。

如果在應用發布的過程中,同時提交了應用擴容的請求,由 3000 擴容到 3200 個實例,擴容的 200 個實例應該采用舊版本還是新版本,采用舊版本擴容將面臨的問題是誰最終負責這 200 個舊版本實例的升級,采用新版本擴容將面臨的是穩定性問題,如果新版本存在問題新擴容的實例將產生較大的影響。

正是因為這些復雜的問題導致多數運維系統拒絕了并發的應用變更,導致并發操作效率非常低下。

K8s 為應用管理所提供的申明式 API 的設計理念同時解決了解決了這三個問題,用戶只需要描述期望的最終狀態以及達成期望狀態的過程中需要遵守的限制條件,達成終態所需要執行的復雜操作全部交由 K8s 的來完成。

在應用發布過程中,通常情況下 K8s 通過控制并發度及最大不可用實例數來約束應用發布對服務的影響,對于發布過程中失敗的實例通過最終一致的方式在系統內部解決。正是基于這一設計,用戶發起服務變更時只是更新了應用的預期狀態,并不需要等待任何任務的結束,一并解決了應用發布效率、線上配置的一致性和并發變更沖突效率的問題。

基于面向終態的理念管理應用,我們開發 Advanced StatefulSet 的應用管理工作模型,顧名思義它基于 Kubernetes 官方的 StatefulSet 擴展而來。

在官方的工作模型中,應用通過滾動的方式完成版本升級,也就是創建新的 Pod 同時刪除舊版本的 Pod,直到整個應用切換為新的版本。

這種方式簡單直接,但存在效率的問題,比如所有應用的 Pod 需要重新的調度,這在大規模應用發布場景將給調度器帶來很大的壓力;同時,因為新版本 Pod 為全新創建,需要重新分配 IP 并掛載遠程卷,這對云計算網絡、存儲基礎設施也將是很大的挑戰;再者,因為容器是被全新調度出來的,在機器上需要重新下載新的應用鏡像,這將大幅降低應用發布的效率。

為了提高應用發布的效率和資源的確定性,開發了這一工作負載模型,它支持原地發布應用,應用發布前后應用所在的位置保持不變,同時支持了并發更新、容錯暫停等豐富的發布策略,高效的滿足了阿里巴巴內部電商應用的發布需求。因為應用發布前后位置不變,因此我們可以在灰度發布的過程中預先下載并解壓即將要發布的容器鏡像,從而大幅提高應用發布的效率。

在面向終態的應用管理中,復雜的運維過程被 K8s 內部所實現,K8s根據用戶的期望及現狀計算出需要執行的動作,并逐步的變更直到終態。面向終態帶來了卓越的運維效率提升,但同時也為系統工程架構提出了更高的要求。

我們知道在 K8s 內部是一個模塊化、分布式的系統,通往終態的運維決策分散在內部的多個模塊中,這些模塊都有可能對容器發起一些運維動作,比如控制器、運維 Operator、重調度器甚至是 kubelet。在高度自動化的系統中,一旦出現預期外的異常,其殺傷力可能會對其上運行的業務造成災難性的后果,加之 K8s 中決策分散在眾多的模塊中,所帶來的問題是系統風險的控制變得更加困難,對這個系統設計的質量有很高的要求。

為了控制整個系統的風險,如上圖所示,我們在 K8s 系統的關鍵位置對關鍵行為行為進行了埋點,針對性的制定了限流及熔斷的策略,使得整個系統即使在出現極端錯誤的場景下,也能夠最大化的保護其上運行的業務。

自愈能力升級

在阿里巴巴傳統的運維體系下,容器平臺僅生產資源,應用的啟動以及服務發現是在容器啟動后由運維平臺系統來完成的,這種分層的方法給了運維系統最大的自由度,也在容器化后促進了阿里巴巴的容器生態繁榮。

但是這種方式有一個嚴重的問題,因為容器調度平臺無法自主地去觸發容器的擴縮容,而需要和一個個運維平臺來做復雜的聯動,上層運維系統也因為需要感知到底層基礎設施的信息,從而導致進行了很多重復建設的工作。

在工程實踐上,這些復雜性使得即使經過了細心的設計與大量的投入其工作效率也不高,嚴重妨礙宿主機發生故障、重啟,容器中進程發生崩潰、卡住等異常時的自愈修復效率,同時也讓應用彈性伸縮的實現變得非常的復雜和低效。

我們解決這一問題的思路是通過 K8s 中提供了容器命令以及生命周期鉤子,將啟動應用以及檢查應用啟動狀態這一整個流程內置到 pod 中,包括與監控、VIP、服務中心、配置中心等基礎設施的交互,通過 Pod 實現容器與應用實例的生命周期統一。

容器平臺不再是僅生產資源,而是交付可以直接為業務使用的服務,從而使得可以在 K8s 系統內部完成故障自愈閉環,極大地簡化了應用故障自愈以及自動彈性擴縮容能力的建設。提高系統自愈的效率,實際上也是幫助業務獲得更好的運行時穩定性和應用運維效率。

在完成了容器與應用實例的生命周期統一之后,我們正在打造一個統一控制器編程框架:Operator Platform。

Operator Platform 由中心的控制組件與一個 sidecar 框架容器以及客戶端代碼組成,通過對通用的控制器能力的抽象,包括:事件通知、灰度管理、版本控制、緩存、命令管道等能力的封裝集成,支持多語言編寫operator,使得開發者無需要理解 K8s 的眾多的接口細節及錯誤處理,從而降低了基于 operator 的自動化運維能力的開發難度,使得越來越多的運維能力通過operator 的方式沉淀到 K8s 生態體系中來,讓更多的有狀態應用能夠自動化地部署,提高整個運維體系的運轉效率。

通過這種方式,構建了整個機器故障自愈的體系,高效的串聯起包括機器鎖定、應用驅逐、機器線下、異常修復等流程,確保了集群宿主機的在線率以及業務的可用性。未來,我們期望通過將 operator 編寫標準化的方式去推動多個運維平臺的基礎運維能力能夠被最大化的復用,減少重復建設的成本。

不可變基礎設施

第三個重要的能力升級是對不可變基礎設施的升級。

我知道 Docker 提供了一種統一的應用交付的形式,通過把應用的二進制、配置、依賴文件在構建過程中打到一個鏡像中,從而確保了應用被一次構建出來之后在多個環境中交付的確定性,避免了環境不一致帶來的諸多問題。

而 K8s 更進一步,通過將不同用途的 Docker 容器組裝在一起成為一個 pod,通常情況下在升級 pod 時需要整個的銷毀重建,從而確保應用鏡像、卷、資源規格的一致性。在落地 K8s 的過程中,堅持了不可變基礎設施的設計理念,通過 K8s pod 將原本運行在一個富容器中的應用與運維基礎組件分離到不同的容器中,并通過升級容器鏡像的方式完成應用的升級。

這里有一個概念需要澄清,并不是使用 K8s 就等于踐行了不可變基礎設施的理念,而是必須要確保應用運維通過鏡像升級而不是動態發布文件的方式完成,而事實上因為一些歷史原因,這一用法在行業中普遍存在。

當然,與 K8s 有所不同的是,我們并未強制堅持 pod 的不可變而是取了一個折中的方式,即堅持容器不可變。

原因是我們將應用容器與運維基礎設施容器分離之后,運維容器作為應用容器的 sidecar 容器,其擁有著不同的版本迭代策略。應用容器由應用運維人員負責發布,其策略因應用的不同而不同,比如電商應用使用 StatefulSet 而本地生活使用 Deployment 來管理應用,而基礎設施容器則由基礎設施運維負責,其發布策略與應用本身也存在一些差別。

為了解決這個問題,我們開發了一個叫做 SidecarSet 的基礎設施容器管理模型,它使用同一個集合統一管理多個應用的運維容器,將基礎設施的變更與應用容器的變更進行分離,從而支持基礎設施的快速演進。將基礎設施容器定義從應用 pod 中抽離出來后,應用管理員不再關心基礎容器的啟動參數,而是交由基礎設施運維人員通過配置 SidecarSet 自動為應用注入運維容器,簡化了應用運維的復雜性。

可以看到,這種關注點分離的設計,同時簡化了應用運維與基礎設施運維的負擔。

總結與展望

阿里云通過落地 K8s 推動阿里巴巴運維體系走向云原生,在應用容器發布管理效率、服務穩定性以及企業 IT 成本方面取得了很大的突破。

我們一直在思考,通過什么樣的方式能夠將阿里巴巴的應用管理經驗輸出到更多的場景,解決更多客戶面臨的應用管理難題,在企業全面云化這樣的趨勢下,如何解決企業在公有云、私有云、混合云以及多云場景的應用管理復雜性。

正是在這樣的背景下,阿里云與微軟在 2019 年 11 月聯合推出了一款用于構建和交付云原生應用的標準規范,即 Open Application Model(簡稱 OAM)。

OAM 提出了一種通用的模型,讓各平臺可以在統一的高層抽象上透出應用部署和運維能力,解決跨平臺的應用交付問題。同時,OAM 以標準化的方式溝通和連接應用開發者、運維人員、應用基礎設施,讓云原生應用交付和管理流程更加連貫、一致。

通過應用交付標準化的方法,我們期望未來在云上部署一個應用,就像手機在應用商店中安裝一個淘寶一樣便捷與高效。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374