容器、容器雲與Kubernetes技術-----史上最全最易懂解釋


我們為什么使用容器?

我們為什么使用虛擬機(雲主機)? 為什么使用物理機? 這一系列的問題並沒有一個統一的標准答案。因為以上幾類技術棧都有自身最適用的場景,在最佳實踐之下,它們分別都是不可替代的。 原本沒有虛擬機,所有類型的業務應用都直接跑在物理主機上面,計算資源和存儲資源都難於增減,要么就是一直不夠用,要么就一直是把過剩的資源浪費掉,所以后來我們看到大家越來越多得使用虛擬機(或雲主機),物理機的使用場景被極大地壓縮到了像數據庫系統這樣的特殊類型應用上面。

原本也沒有容器,我們把大部分的業務應用跑在虛擬機(或雲主機)上面,把少部分特殊類型的應用仍然跑在物理主機上面。但現在所有的虛擬機技術方案,都無法回避兩個主要的問題,一個問題是虛擬化Hypervisor管理軟件本身的資源消耗與磁盤IO性能降低,另一個是虛擬機仍然還是一個獨立的操作系統,對很多類型的業務應用來說都顯得太重了,導致我們在處理虛擬機的擴縮容與配置管理工作時效率低下。所以,我們后來發現了容器的好處,所有業務應用可以直接運行在物理主機的操作系統之上,可以直接讀寫磁盤,應用之間通過計算、存儲和網絡資源的命名空間進行隔離,為每個應用形成一個邏輯上獨立的“容器操作系統”。除此之外,容器技術還有以下優點:簡化部署、多環境支持、快速啟動、服務編排、易於遷移。

容器技術的一些缺點:仍然不能做到徹底的安全隔離,技術棧復雜度飈升,尤其是在應用了容器集群技術之后。所以如果只是小規模的使用,做實驗或測試是可以的,上生產環境需要三思而后行。

 

 

器的運行原理與基本組件

Docker容器主要基於以下三個關鍵技術實現的: – Namespaces – Cgroups技術 – Image鏡像

 

 

容器引擎 容器引擎(Engine)或者容器運行時(Runtime)是容器系統的核心,也是很多人使用“容器”這個詞語的指代對象。容器引擎能夠創建和運行容器,而容器的定義一般是以文本方式保存的,比如 Dockerfile。

 

  • Docker Engine :目前最流行的容器引擎,也是業界的事實標准。

  • Rkt:CoreOS 團隊推出的容器引擎,有着更加簡單的架構,一直作為 Docker 的直接競爭對手存在,是 kubernetes 調度系統支持的容器引擎之一。

  • containerd:這個新的Daemon是對Docker內部組件的一個重構以便支持OCI規范,containerd 主要職責是鏡像管理(鏡像、元信息等)、容器執行(調用最終運行時組件執行),向上為 Docker Daemon 提供了 gRPC 接口,向下通過 containerd-shim 結合 runC,使得引擎可以獨立升級。

  • docker-shim:shim 通過調用 containerd 啟動 docker 容器,所以每啟動一個容器都會起一個新的docker-shim進程。docker-shim是通過指定的三個參數:容器id,boundle目錄和運行時(默認為runC)來調用runC的api創建一個容器。

  • runC :是 Docker 按照開放容器格式標准(OCF, Open Container Format)制定的一種具體實現,實現了容器啟停、資源隔離等功能,所以是可以不用通過 docker 引擎直接使用runC運行一個容器的。也支持通過改變參數配置,選擇使用其他的容器運行時實現。RunC可以說是各大CaaS廠商間合縱連橫、相互妥協的結果,

注:RunC在各個CaaS廠商的推動下在生產環境得到廣泛的應用。Kubernetes目前基本只支持RunC容器,對於Docker超出其容器抽象層之外的功能,一概不支持。同樣,Mesos也通過其Unified Containerizer只支持RunC容器,目前還支持Docker,但是未來的規划是只支持Unified Containerizer。CF也通過Garden只支持RunC,不支持Docker超出RunC之前的功能。

 

為什么在容器的啟動或運行過程中需要一個 docker-containerd-shim 進程呢? 其目的有如下幾點: – 它允許容器運行時(即 runC)在啟動容器之后退出,簡單說就是不必為每個容器一直運行一個容器運行時(runC) – 即使在 containerd 和 dockerd 都掛掉的情況下,容器的標准 IO 和其它的文件描述符也都是可用的 – 向 containerd 報告容器的退出狀態

rkt與containerd的區別是什么? 一個主要的不同之處是,rkt作為一個無守護進程的工具(daemonless tool),可以用來在生產環境中,集成和執行那些特別的有關鍵用途的容器。舉個例子,CoreOS Container Linux使用rkt來以一個容器鏡像的方式執行Kubernetes的agent,即kublet。更多的例子包括在Kubernetes生態環境中,使用rkt來用一種容器化的方式掛載volume。這也意味着rkt能被集成進並和Linux的init系統一起使用,因為rkt自己並不是一個init系統。kubernets支持容器進行部署,其所支持的容器不只是僅僅局限於docker,CoreOS的rkt也是容器玩家之一,雖然跟docker比起來還是明顯處於絕對下風,但有競爭總要好過沒有。

容器編排和管理系統

容器是很輕量化的技術,相對於物理機和虛機而言,這意味着在等量資源的基礎上能創建出更多的容器實例出來。一旦面對着分布在多台主機上且擁有數百套容器的大規模應用程序時,傳統的或單機的容器管理解決方案就會變得力不從心。另一方面,由於為微服務提供了越來越完善的原生支持,在一個容器集群中的容器粒度越來越小、數量越來越多。在這種情況下,容器或微服務都需要接受管理並有序接入外部環境,從而實現調度、負載均衡以及分配等任務。 簡單而高效地管理快速增漲的容器實例,自然成了一個容器編排系統的主要任務。

容器集群管理工具能在一組服務器上管理多容器組合成的應用,每個應用集群在容器編排工具看來是一個部署或管理實體,容器集群管理工具全方位為應用集群實現自動化,包括應用實例部署、應用更新、健康檢查、彈性伸縮、自動容錯等等。 容器編排和管理系統的分層結構圖

 

容器編排和管理系統界的主要選手 – Kubernetes:Google 開源的容器管理系統,起源於內部歷史悠久的 Borg 系統。因為其豐富的功能被多家公司使用,其發展路線注重規范的標准化和廠商“中立”,支持底層不同的容器運行時和引擎(比如 Rkt),逐漸解除對 Docker 的依賴。Kubernetes的核心是如何解決自動部署,擴展和管理容器化(containerized)應用程序。目前該項目在github上Star數量為43k。 – Docker Swarm: 在 Docker 1.2 版本后將 Swarm 集成在了 Docker 引擎中。用戶能夠輕松快速搭建出來 docker 容器集群,幾乎完全兼容 docker API 的特性。目前該項目在github上Star數量為5.3k。 – Mesosphere Marathon:Apache Mesos 的調度框架目標是成為數據中心的操作系統,完全接管數據中心的管理工作。Mesos理念是數據中心操作系統(DCOS),為了解決IaaS層的網絡、計算和存儲問題,所以Mesos的核心是解決物理資源層的問題。Marathon是為Mesosphere DC/OS和Apache Mesos設計的容器編排平台。目前該項目在github上Star數量為3.7k。

注:國內外有很多公司在從事基於上面三個基礎技術平台的創新創業,為企業提供增值服務,其中做得不錯的如Rancher,其產品可以同時兼容 kubernetes、mesos 和 swarm 集群系統,此外還有很多商用解決方案,如OpenShift。

中國市場的表現 在中國市場,2017 年 6 月 Kubernetes 中國社區 K8SMeetup 曾組織了國內首個針對中國容器開發者和企業用戶的調研。近 100 個受訪用戶和企業中給我們帶來了關於 Kubernetes 在中國落地狀況的一手調查資料顯示: – 在容器編排工具中,Kubernetes占據了70%市場份額,此外是Mesos約11%,Swarm不足7%; – 在中國受訪企業用戶中,Kubernetes 平台上運行的應用類型非常廣泛,幾乎包括了除hadoop大數據技術棧以外的各種類型應用; – 中國受訪企業運行 Kubernetes 的底層環境分布顯示,29%的客戶使用裸機直接運行容器集群,而在包括OpenStack、VMWare、阿里雲和騰訊雲在內的泛雲平台上運行容器集群服務的客戶占到了60%;

關於CNCF基金會

主要的容器技術廠商(包括 Docker、CoreOS、Google、Mesosphere、RedHat 等)成立了 Cloud Native Computing Foundation (CNCF) 。 CNCF對雲原生的定義是: – 雲原生技術幫助公司和機構在公有雲、私有雲和混合雲等新型動態環境中,構建和運行可彈性擴展的應用。雲原生的代表技術包括容器、服務網格、微服務、不可變基礎設施和聲明式API。 – 這些技術能夠構建容錯性好、易於管理和便於觀察的松耦合系統。結合可靠的自動化手段,雲原生技術可以使開發者輕松地對系統進行頻繁並可預測的重大變更。 – 雲原生計算基金會(CNCF)致力於培育和維護一個廠商中立的開源生態系統,來推廣雲原生技術。我們通過將最前沿的模式普惠,讓這些創新為大眾所用。

  • 雲原生以容器為核心技術,分為運行時(Runtime)和 Orchestration 兩層,Runtime 負責容器的計算、存儲、網絡;Orchestration 負責容器集群的調度、服務發現和資源管理。

注:上圖只截取了原圖的核心組件部分,完整圖表詳見https://landscape.cncf.io/images/landscape.png

Kubernetes的核心組件

Kubernetes的核心組件示意圖

 

  • etcd是Kubernetes的存儲狀態的分布式數據庫,采用raft協議作為一致性算法(raft協議原理可參見一個動畫演示http://thesecretlivesofdata.com/raft/)。

  • API Server組件主要提供認證與授權、運行一組准入控制器以及管理API版本等功能,通過REST API向外提供服務,允許各類組件創建、讀取、寫入、更新和監視資源(Pod, Deployment, Service等)。

  • Scheduler組件,根據集群資源和狀態選擇合適的節點用於創建Pod。

  • Controller Manager組件,實現ReplicaSet的行為。

  • Kubelet組件,負責監視綁定到其所在節點的一組Pod,並且能實時返回這些Pod的運行狀態。

創建Pod的整個流程時序圖

 

容器網絡

容器的大規模使用,也對網絡提供了更高的要求。網絡的不靈活也是很多企業的短板,目前也有很多公司和項目在嘗試解決這些問題,希望提出容器時代的網絡方案。 Docker采用插件化的網絡模式,默認提供bridge、host、none、overlay、macvlan和Network plugins這幾種網絡模式,運行容器時可以通過–network參數設置具體使用那一種模式。

– bridge:這是Docker默認的網絡驅動,此模式會為每一個容器分配Network Namespace和設置IP等,並將容器連接到一個虛擬網橋上。如果未指定網絡驅動,這默認使用此驅動。 – host:此網絡驅動直接使用宿主機的網絡。

– none:此驅動不構造網絡環境。采用了none 網絡驅動,那么就只能使用loopback網絡設備,容器只能使用127.0.0.1的本機網絡。

– overlay:此網絡驅動可以使多個Docker daemons連接在一起,並能夠使用swarm服務之間進行通訊。也可以使用overlay網絡進行swarm服務和容器之間、容器之間進行通訊,

– macvlan:此網絡允許為容器指定一個MAC地址,允許容器作為網絡中的物理設備,這樣Docker daemon就可以通過MAC地址進行訪問的路由。對於希望直接連接網絡網絡的遺留應用,這種網絡驅動有時可能是最好的選擇。

– Network plugins:可以安裝和使用第三方的網絡插件。可以在Docker Store或第三方供應商處獲取這些插件。

在默認情況,Docker使用bridge網絡模式。

容器網絡模型(CNM)

CNM在2015年由Docker引入,CNM有IP 地址管理(IPAM)和網絡插件功能。IPAM插件可以創建IP地址池並分配,刪除和釋放容器IP。網絡插件API用於創建/刪除網絡,並從網絡中添加/刪除容器。

容器網絡接口(CNI)

CNI誕生於2015年4月,由CoreOS公司推出,CNI是容器中的網絡系統插件,它使得類似Kubernetes之類的管理平台更容易的支持IPAM、SDN或者其它網絡方案。CNI實現的基本思想為:Contianer runtime在創建容器時,先創建好network namespace,這在實際操作過程中,首先創建出來的容器是Pause容器。之后調用CNI插件為這個netns配置網絡,最后在啟動容器內的進程。

CNI Plugin負責為容器配置網絡,包括兩個基本接口: – 配置網絡:AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error) – 清理網絡:DelNetwork(net NetworkConfig, rt RuntimeConf) error

每個CNI插件只需實現兩種基本操作:創建網絡的ADD操作,和刪除網絡的DEL操作(以及一個可選的VERSION查看版本操作)。所以CNI的實現確實非常簡單,把復雜的邏輯交給具體的Network Plugin實現。

Kubernetes CNI 插件

 

  • Flannel:CoreOS 開源的網絡方案,為 kubernetes 設計,它的功能是讓集群中的不同節點主機創建的Docker容器都具有全集群唯一的虛擬IP地址。Flannel的底層通信協議的可選余地有很多,比如UDP、VXlan、AWS VPC等等,不同協議實現下的網絡通信效率相差較多,默認為使用UDP協議,部署和管理簡單。目前為止,還不支持k8s的Network Policy。

  • Calico:一個純三層的網絡解決方案,使用 BGP 協議進行路由,可以集成到 openstack 和 docker。Calico節點組網可以直接利用數據中心的網絡結構(無論是L2或者L3),不需要額外的NAT,隧道或者Overlay Network,網絡通信性能好。Calico基於iptables還提供了豐富而靈活的網絡Policy,保證通過各個節點上的ACLs來提供Workload的多租戶隔離、安全組以及其他可達性限制等功能。如果企業生產環境可以開啟BGP協議,可以考慮calico bgp方案。不過在現實中的網絡並不總是支持BGP路由的,因此Calico也設計了一種IPIP模式,使用Overlay的方式來傳輸數據。

  • Weave Net:weaveworks 給出的網絡的方案,使用 vxlan 技術通過Overlay網絡實現的, 支持網絡的隔離和安全,安裝和使用都比較簡單。

  • Contiv: 思科開源,兼容CNI模型以及CNM模型,支持 VXLAN 和 VLAN 方案,配置較復雜。支持Tenant,支持租戶隔離,支持多種網絡模式(L2、L3、overlay、cisco sdn solution)。Contiv帶來的方便是用戶可以根據容器實例IP直接進行訪問。

  • Canal:基於 Flannel 和 Calico 提供 Kubernetes Pod 之間網絡防火牆的項目。

  • Cilium:利用 Linux 原生技術提供的網絡方案,支持 L7 和 L3、L4 層的訪問策略。

  • Romana:Panic Networks 推出的網絡開源方案,基於 L3 實現的網絡連通,因此沒有 Overlay 網絡帶來的性能損耗,但是只能通過 IP 網段規划來實現租戶划分。

從理論上說,這些CNI工具的網絡速度應該可以分為3個速度等級。 最快的是Romana、Gateway模式的Flannel、BGP模式的Calico。 次一級的是IPIP模式的Calico、Swarm的Overlay網絡、VxLan模式的Flannel、Fastpath模式的Weave。 * 最慢的是UDP模式的Flannel、Sleeve模式的Weave。

Flannel

  • UDP封包使用了Flannel自定義的一種包頭協議,數據是在Linux的用戶態進行封包和解包的,因此當數據進入主機后,需要經歷兩次內核態到用戶態的轉換。網絡通信效率低且存在不可靠的因素。

  • VxLAN封包采用的是內置在Linux內核里的標准協議,因此雖然它的封包結構比UDP模式復雜,但由於所有數據裝、解包過程均在內核中完成,實際的傳輸速度要比UDP模式快許多。Vxlan方案在做大規模應用時復雜度會提升,故障定位分析復雜。

  • Flannel的Gateway模式與Calico速度相當,甚至理論上還要快一點。Flannel的Host-Gateway模式,在這種模式下,Flannel通過在各個節點上的Agent進程,將容器網絡的路由信息刷到主機的路由表上,這樣一來所有的主機就都有整個容器網絡的路由數據了。Host-Gateway的方式沒有引入像Overlay中的額外裝包解包操作,完全是普通的網絡路由機制,它的效率與虛擬機直接的通信相差無幾。Host-Gateway的模式就只能用於二層直接可達的網絡,由於廣播風暴的問題,這種網絡通常是比較小規模的。路由網絡對現有網絡設備影響比較大,路由器的路由表有空間限制,一般是兩三萬條,而容器的大部分應用場景是運行微服務,數量集很大。

Flannel網絡通信原理示意圖

 

各CNI網絡插件的功能對比:

 

容器存儲

因為容器存活時間很短的特點,容器的狀態(存儲的數據)必須獨立於容器的生命周期,也因為此,容器的存儲變得非常重要。 – Ceph:分布式存儲系統,同時支持塊存儲、文件存儲和對象存儲,發展時間很久,穩定性也得到了驗證。之前在 OpenStack 社區被廣泛使用,目前在容器社區也是很好的選項。 – GlusterFS:RedHat 旗下的產品,部署簡單,擴展性強。 – 商業存儲:DELL EMC,NetApp等 – CSI(Container Storage Interface):定義雲應用調度平台和各種存儲服務接口的項目,核心的目標就是存儲 provider 只需要編寫一個 driver,就能集成到任何的容器平台上。 – Rook:基於 Ceph 作為后台存儲技術,深度集成到 Kubernetes 容器平台的容器項目,因為選擇了 Ceph 和 Kubernetes 這兩個都很熱門的技術,並且提供自動部署、管理、擴展、升級、遷移、災備和監控等功能

Kubernetes支持的存儲類型

  • awsElasticBlockStore

  • azureDisk

  • azureFile

  • cephfs

  • configMap

  • csi

  • downwardAPI

  • emptyDir

  • fc (fibre channel)

  • flocker

  • gcePersistentDisk

  • gitRepo (deprecated)

  • glusterfs

  • hostPath

  • iscsi

  • local

  • nfs

  • persistentVolumeClaim

  • projected

  • portworxVolume

  • quobyte

  • rbd

  • scaleIO

  • secret

  • storageos

  • vsphereVolume

Kubernetes以in-tree plugin的形式來對接不同的存儲系統,滿足用戶可以根據自己業務的需要使用這些插件給容器提供存儲服務。同時兼容用戶使用FlexVolume和CSI定制化插件。 

 

一般來說,Kubernetes中Pod通過如下三種方式來訪問存儲資源: – 直接訪問 – 靜態provision – 動態provision(使用StorageClass動態創建PV)

服務發現

容器和微服務的結合創造了另外的熱潮,也讓服務發現成功了熱門名詞。可以輕松擴展微服務的同時,也要有工具來實現服務之間相互發現的需求。 DNS 服務器監視着創建新 Service 的 Kubernetes API,從而為每一個 Service 創建一組 DNS 記錄。 如果整個集群的 DNS 一直被啟用,那么所有的 Pod應該能夠自動對 Service 進行名稱解析。在技術實現上是通過kubernetes api監視Service資源的變化,並根據Service的信息生成DNS記錄寫入到etcd中。dns為集群中的Pod提供DNS查詢服務,而DNS記錄則從etcd中讀取。 – kube-dns:kube-dns是Kubernetes中的一個內置插件,目前作為一個獨立的開源項目維護。Kubernetes DNS pod 中包括 3 個容器:kube-dns,sidecar,dnsmasq – CoreDNS:CoreDNS是一套靈活且可擴展的權威DNS服務器,作為CNCF中的托管的一個項目,自k8s 1.11 版本起被正式作為集群DNS附加選項,且在用戶使用kubeadm時默認生效。提供更好的可靠性、靈活性和安全性,可以選擇使用CoreDNS替換Kubernetes插件kube-dns。

狀態數據存儲

目前主要有三種工具,大部分的容器管理系統也都是同時可以支持這三種工具。 – etcd:CoreOS 開源的分布式 key-value 存儲,通過 HTTP/HTTPS 協議提供服務。etcd 只是一個 key-value 存儲,默認不支持服務發現,需要三方工具來集成。kubernetes 默認使用 etcd 作為存儲。 – ZooKeeper:Hadoop 的一個子項目,本來是作為 Hadoop 集群管理的數據存儲,目前也被應用到容器領域,開發語言是 Java。 – Consul:HashiCorp 開發的分布式服務發現和配置管理工具

這些工具的主要作用就是保證這個集群的動態信息能統一保存,並保證一致性,這樣每個節點和容器就能正確地獲取到集群當前的信息。

健康檢查

Kubernetes提供兩種類型的健康檢查,支持進行三種類型的探測:HTTP、Command和TCP。 – Readiness探針旨在讓Kubernetes知道您的應用何時准備好其流量服務。 Kubernetes確保Readiness探針檢測通過,然后允許服務將流量發送到Pod。 如果Readiness探針開始失敗,Kubernetes將停止向該容器發送流量,直到它通過。 – Liveness探針讓Kubernetes知道你的應用程序是活着還是死了。 如果你的應用程序還活着,那么Kubernetes就不管它了。 如果你的應用程序已經死了,Kubernetes將刪除Pod並啟動一個新的替換它。

容器監控

我們習慣於在兩個層次監控:應用以及運行它們的主機。現在由於容器處在中間層,以及 Kubernetes 本身也需要監控,因此有 4 個不同的組件需要監控並且搜集度量信息。 

1)cAdvisor + InfluxDB + Grafana:一個簡單的跨多主機的監控系統Cadvisor:將數據,寫入InfluxDBInfluxDB :時序數據庫,提供數據的存儲,存儲在指定的目錄下Grafana :提供了WEB控制台,自定義查詢指標,從InfluxDB查詢數據,並展示。 

2)Heapster + InfluxDB + Grafana:Heapster是一個收集者,將每個Node上的cAdvisor的數據進行匯總,然后導到InfluxDB,支持從Cluster、Node、Pod的各個層面提供詳細的資源使用情況。Heapster:在Kubernetes集群中獲取Metrics和事件數據,寫入InfluxDB,Heapster收集的數據比cAdvisor多,而且存儲在InfluxDB的也少。InfluxDB:時序數據庫,提供數據的存儲,存儲在指定的目錄下。Grafana:提供了WEB控制台,自定義查詢指標,從InfluxDB查詢數據,並展示。 

3)Prometheus+Grafana:Prometheus是個集DB、Graph、Statistics、Alert 於一體的監控工具。提供多維數據模型(時序列數據由metric名和一組key/value組成)和在多維度上靈活的查詢語言(PromQl),提供了很高的寫入和查詢性能。對內存占用量大,不依賴分布式存儲,單主節點工作,所以不具有高可用性,支持pull/push兩種時序數據采集方式。

考慮到Prometheus在擴展性和高可用方面的缺點,在超大規模應用時可以考察下thanos這樣的面向解決Prometheus的長時間數據存儲與服務高可用解決方案的開源項目:https://github.com/improbable-eng/thanos

容器集群的四個監控層次

 

鏡像 registry

鏡像 registry 是存儲鏡像的地方,可以方便地在團隊、公司或者世界各地分享容器鏡像,也是運行容器最基本的基礎設施。 – Docker Registry:Docker 公司提供的開源鏡像服務器,也是目前最流行的自建 registry 的方案 – Harbor:企業級的鏡像 registry,提供了權限控制和圖形界面

每種對應技術幾乎都有自己的基礎鏡像,例如: – https://hub.docker.com/_/java/ (該鏡像仍存在,但已經很長時間未更新) – https://hub.docker.com/_/python/ – https://hub.docker.com/_/nginx/ – https://hub.docker.com/_/alpine/ 一個常用的基礎鏡像Alpine Linux(體積小於5MB)

參考資料

中國開源雲聯盟容器工作組-容器技術及其應用白皮書v1.0 從風口浪尖到十字路口,寫在 Kubernetes 兩周年之際https://mp.weixin.qq.com/s/hrgXzt7YKVf6ZCFzJ-WTFA 白話Kubernetes網絡 http://dockone.io/article/2616Kubernetes 主機和容器的監控方案 http://dockone.io/article/2602CNCF 雲原生容器生態系統概要 http://dockone.io/article/3006Kubernetes 存儲系統介紹及機制實現 http://dockone.io/article/3063Kubernetes 內部組件工作原理介紹 http://dockone.io/article/5108Docker、Containerd、RunC…:你應該知道的所有 https://www.infoq.cn/article/2017%2F02%2FDocker-Containerd-RunC 從 docker 到 runC https://www.cnblogs.com/sparkdev/p/9129334.html

文章由高慶投稿,百悟科技 高級運維工程師


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM