應(yīng)用編排與管理中的Job及DaemonSet怎么理解

今天就跟大家聊聊有關(guān)應(yīng)用編排與管理中的Job及DaemonSet怎么理解,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是成都創(chuàng)新互聯(lián)的服務(wù)宗旨!把網(wǎng)站當作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設(shè)中就是為了建設(shè)一個不僅審美在線,而且實用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站開發(fā)、網(wǎng)頁設(shè)計、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)推廣、探索永無止境。

一、Job

需求來源

Job 背景問題

首先我們來看一下 Job 的需求來源。我們知道 K8s 里面,最小的調(diào)度單元是 Pod,我們可以直接通過 Pod 來運行任務(wù)進程。這樣做將會產(chǎn)生以下幾種問題:

  • 我們?nèi)绾伪WC Pod 內(nèi)進程正確的結(jié)束?

  • 如何保證進程運行失敗后重試?

  • 如何管理多個任務(wù),且任務(wù)之間有依賴關(guān)系?

  • 如何并行地運行任務(wù),并管理任務(wù)的隊列大???

Job:管理任務(wù)的控制器

我們來看一下 Kubernetes 的 Job 為我們提供了什么功能:

  • 首先 kubernetes 的 Job 是一個管理任務(wù)的控制器,它可以創(chuàng)建一個或多個 Pod 來指定 Pod 的數(shù)量,并可以監(jiān)控它是否成功地運行或終止;

  • 我們可以根據(jù) Pod 的狀態(tài)來給 Job 設(shè)置重置的方式及重試的次數(shù);

  • 我們還可以根據(jù)依賴關(guān)系,保證上一個任務(wù)運行完成之后再運行下一個任務(wù);

  • 同時還可以控制任務(wù)的并行度,根據(jù)并行度來確保 Pod 運行過程中的并行次數(shù)和總體完成大小。

用例解讀

我們根據(jù)一個實例來看一下Job是如何來完成下面的應(yīng)用的。

Job 語法

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

上圖是 Job 最簡單的一個 yaml 格式,這里主要新引入了一個 kind 叫 Job,這個 Job 其實就是 job-controller 里面的一種類型。 然后 metadata 里面的 name 來指定這個 Job 的名稱,下面 spec.template 里面其實就是 pod 的 spec。

這里面的內(nèi)容都是一樣的,唯一多了兩個點:

  • 第一個是 restartPolicy,在 Job 里面我們可以設(shè)置 Never、OnFailure、Always 這三種重試策略。在希望 Job 需要重新運行的時候,我們可以用 Never;希望在失敗的時候再運行,再重試可以用 OnFailure;或者不論什么情況下都重新運行時 Alway;

  • 另外,Job 在運行的時候不可能去無限的重試,所以我們需要一個參數(shù)來控制重試的次數(shù)。這個 backoffLimit 就是來保證一個 Job 到底能重試多少次。

所以在 Job 里面,我們主要重點關(guān)注的一個是 restartPolicy 重啟策略和 backoffLimit 重試次數(shù)限制。

Job 狀態(tài)

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

Job 創(chuàng)建完成之后,我們就可以通過 kubectl get jobs 這個命令,來查看當前 job 的運行狀態(tài)。得到的值里面,基本就有 Job 的名稱、當前完成了多少個 Pod,進行多長時間。

**AGE **的含義是指這個 Pod 從當前時間算起,減去它當時創(chuàng)建的時間。這個時長主要用來告訴你 Pod 的歷史、Pod 距今創(chuàng)建了多長時間。**DURATION **主要來看我們 Job 里面的實際業(yè)務(wù)到底運行了多長時間,當我們的性能調(diào)優(yōu)的時候,這個參數(shù)會非常的有用。**COMPLETIONS **主要來看我們?nèi)蝿?wù)里面這個 Pod 一共有幾個,然后它其中完成了多少個狀態(tài),會在這個字段里面做顯示。 

查看 Pod

<br />下面我們來看一下 Pod,其實 Job 最后的執(zhí)行單元還是 Pod。我們剛才創(chuàng)建的 Job 會創(chuàng)建出來一個叫“pi”的一個 Pod,這個任務(wù)就是來計算這個圓周率,Pod 的名稱會以“${job-name}-${random-suffix}”,我們可以看一下下面 Pod 的 yaml 格式。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

它比普通的 Pod 多了一個叫 ownerReferences,這個東西來聲明此 pod 是歸哪個上一層 controller 來管理??梢钥吹竭@里的 ownerReferences 是歸 batch/v1,也就是上一個 Job 來管理的。這里就聲明了它的 controller 是誰,然后可以通過 pod 返查到它的控制器是誰,同時也能根據(jù) Job 來查一下它下屬有哪些 Pod。

并行運行 Job

我們有時候有些需求:希望 Job 運行的時候可以最大化的并行,并行出 n 個 Pod 去快速地執(zhí)行。同時,由于我們的節(jié)點數(shù)有限制,可能也不希望同時并行的 Pod 數(shù)過多,有那么一個管道的概念,我們可以希望最大的并行度是多少,Job 控制器都可以幫我們來做到。

這里主要看兩個參數(shù):一個是 completions,一個是 parallelism。

  • 首先第一個參數(shù)是用來指定本 Pod 隊列執(zhí)行次數(shù)??赡苓@個不是很好理解,其實可以把它認為是這個 Job 指定的可以運行的總次數(shù)。比如這里設(shè)置成 8,即這個任務(wù)一共會被執(zhí)行 8 次;

  • 第二個參數(shù)代表這個并行執(zhí)行的個數(shù)。所謂并行執(zhí)行的次數(shù),其實就是一個管道或者緩沖器中緩沖隊列的大小,把它設(shè)置成 2,也就是說這個 Job 一定要執(zhí)行 8 次,每次并行 2 個 Pod,這樣的話,一共會執(zhí)行 4 個批次。

查看并行 Job 運行

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

下面來看一下它的實際運行效果,上圖就是當這個 Job 整體運行完畢之后可以看到的效果,首先看到 job 的名字,然后看到它一共創(chuàng)建出來了 8 個 pod,執(zhí)行了 2 分 23 秒,這是創(chuàng)建的時間。

接著來看真正的 pods,pods 總共出來了 8 個 pod,每個 pod 的狀態(tài)都是完成的,然后來看一下它的 AGE,就是時間。從下往上看,可以看到分別有 73s、40s、110s 和 2m26s。每一組都有兩個 pod 時間是相同的,即:時間段是 40s 的時候是最后一個創(chuàng)建、 2m26s 是第一個創(chuàng)建的。也就是說,總是兩個 pod 同時創(chuàng)建出來,并行完畢、消失,然后再創(chuàng)建、再運行、再完畢。

比如說,剛剛我們其實通過第二個參數(shù)來控制了當前 Job 并行執(zhí)行的次數(shù),這里就可以了解到這個緩沖器或者說管道隊列大小的作用。

Cronjob 語法

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

下面來介紹另外一個 Job,叫做 CronJob,其實也可以叫定時運行 Job。CronJob 其實和 Job 大體是相似的,唯一的不同點就是它可以設(shè)計一個時間。比如說可以定時在幾點幾分執(zhí)行,特別適合晚上做一些清理任務(wù),還有可以幾分鐘執(zhí)行一次,幾小時執(zhí)行一次等等,這就叫定時任務(wù)。

定時任務(wù)和 Job 相比會多幾個不同的字段:

  • schedule:schedule 這個字段主要是設(shè)置時間格式,它的時間格式和 Linux 的 crontime 是一樣的,所以直接根據(jù) Linux 的 crontime 書寫格式來書寫就可以了。舉個例子: */1 指每分鐘去執(zhí)行一下 Job,這個 Job 需要做的事情就是打印出大約時間,然后打印出“Hello from the kubernetes cluster” 這一句話;

  • **startingDeadlineSeconds:**即:每次運行 Job 的時候,它最長可以等多長時間,有時這個 Job 可能運行很長時間也不會啟動。所以這時,如果超過較長時間的話,CronJob 就會停止這個 Job;

  • concurrencyPolicy:就是說是否允許并行運行。所謂的并行運行就是,比如說我每分鐘執(zhí)行一次,但是這個 Job 可能運行的時間特別長,假如兩分鐘才能運行成功,也就是第二個 Job 要到時間需要去運行的時候,上一個 Job 還沒完成。如果這個 policy 設(shè)置為 true 的話,那么不管你前面的 Job 是否運行完成,每分鐘都會去執(zhí)行;如果是 false,它就會等上一個 Job 運行完成之后才會運行下一個;

  • **JobsHistoryLimit:**這個就是每一次 CronJob 運行完之后,它都會遺留上一個 Job 的運行歷史、查看時間。當然這個額不能是無限的,所以需要設(shè)置一下歷史存留數(shù),一般可以設(shè)置默認 10 個或 100 個都可以,這主要取決于每個人集群不同,然后根據(jù)每個人的集群數(shù)來確定這個時間。

操作演示

Job 的編排文件

下面看一下具體如何使用 Job。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

Job 的創(chuàng)建及運行驗證

首先看一下 job.yaml。這是一個非常簡單的計算 pi 的一個任務(wù)。使用 kubectl creat-f job.yaml,這樣 job 就能提交成功了。來看一下 kubectl.get.jobs,可以看到這個 job 正在運行;get pods 可以看到這個 pod 應(yīng)該是運行完成了,那么接下來 logs 一下這個 job 以及 pod??梢钥吹较聢D里面打印出來了圓周率。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

并行 Job 的編排文件

下面再來看第二個例子:

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

并行 Job 的創(chuàng)建及運行驗證

這個例子就是指剛才的并行運行 Job 創(chuàng)建之后,可以看到有第二個并行的 Job。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

現(xiàn)在已經(jīng)有兩個 Pod 正在 running,可以看到它大概執(zhí)行了快到 30s。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

30s 之后它應(yīng)該會起第二個。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

第一批的 pod 已經(jīng)執(zhí)行完畢,第二批的 pod 正在 running,每批次分別是兩個Pod。也就是說后面每隔 40s 左右,就會有兩個 pod 在并行執(zhí)行,它一共會執(zhí)行 4 批,共 8 個 pod,等到所有的 pod 執(zhí)行完畢,就是剛才所說的并行執(zhí)行的緩沖隊列功能。

過一段時間再看這個 pods,可以發(fā)現(xiàn)第二批已經(jīng)執(zhí)行結(jié)束,接下來開始創(chuàng)建第三批······

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

Cronjob 的編排文件

下面來看第三個例子 —— CronJob。 CronJob 是每分鐘執(zhí)行一次,每次一個 job。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

Cronjob 的創(chuàng)建及運行驗證

如下圖 CronJob 已經(jīng)創(chuàng)建了,可以通過 get cronjob 來看到當前有一個 CronJob,這個時候再來看 jobs,由于它是每分鐘執(zhí)行一次,所以得稍微等一下。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

同時可以看到,上一個 job 還在運行,它的時間是 2m12s 左右,它的完成度是 7/8、6/8,剛剛看到 7/8 到 8/8,也就是說我們上一個任務(wù)執(zhí)行了最后一步,而且每次都是兩個兩個地去運行。每次兩個運行的 job 都會讓我們在運行一些大型工作流或者工作任務(wù)的時候感到特別的方便。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

上圖中可以看到突然出現(xiàn)了一個 job,“hello-xxxx”這個 job 就是剛才所說的 CronJob。它距離剛才 CronJob 提交已經(jīng)過去 1 分鐘了,這樣就會自動創(chuàng)建出來一個 job,如果不去干擾它的話,它以后大概每一分鐘都會創(chuàng)建出來這么一個 job,除非等我們什么時候指定它不可以再運行的時候它才會停止創(chuàng)建。

在這里 CronJob 其實主要是用來運作一些清理任務(wù)或者說執(zhí)行一些定時任務(wù)。比如說 Jenkins 構(gòu)建等方面的一些任務(wù),會特別有效。

架構(gòu)設(shè)計

Job 管理模式

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

我們來看一下 job 的架構(gòu)設(shè)計。Job Controller 其實還是主要去創(chuàng)建相對應(yīng)的 pod,然后 Job Controller 會去跟蹤 Job 的狀態(tài),及時地根據(jù)我們提交的一些配置重試或者繼續(xù)創(chuàng)建。同時我們剛剛也提到,每個 pod 會有它對應(yīng)的 label,來跟蹤它所屬的 Job Controller,并且還去配置并行的創(chuàng)建, 并行或者串行地去創(chuàng)建 pod。

Job 控制器

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

上圖是一個 Job 控制器的主要流程。所有的 job 都是一個 controller,它會 watch 這個 API Server,我們每次提交一個 Job 的 yaml 都會經(jīng)過 api-server 傳到 ETCD 里面去,然后 Job Controller 會注冊幾個 Handler,每當有添加、更新、刪除等操作的時候,它會通過一個內(nèi)存級的消息隊列,發(fā)到 controller 里面。

通過 Job Controller 檢查當前是否有運行的 pod,如果沒有的話,通過 Scale up 把這個 pod 創(chuàng)建出來;如果有的話,或者如果大于這個數(shù),對它進行 Scale down,如果這時 pod 發(fā)生了變化,需要及時 Update 它的狀態(tài)。

同時要去檢查它是否是并行的 job,或者是串行的 job,根據(jù)設(shè)置的配置并行度、串行度,及時地把 pod 的數(shù)量給創(chuàng)建出來。最后,它會把 job 的整個的狀態(tài)更新到 API Server 里面去,這樣我們就能看到呈現(xiàn)出來的最終效果了。

二、DaemonSet

需求來源

DaemonSet 背景問題

下面介紹第二個控制器:**DaemonSet。**同樣的問題:如果我們沒有 DaemonSet 會怎么樣?下面有幾個需求:

  • 首先如果希望每個節(jié)點都運行同樣一個 pod 怎么辦?

  • 如果新節(jié)點加入集群的時候,想要立刻感知到它,然后去部署一個 pod,幫助我們初始化一些東西,這個需求如何做?

  • 如果有節(jié)點退出的時候,希望對應(yīng)的 pod 會被刪除掉,應(yīng)該怎么操作?

  • 如果 pod 狀態(tài)異常的時候,我們需要及時地監(jiān)控這個節(jié)點異常,然后做一些監(jiān)控或者匯報的一些動作,那么這些東西運用什么控制器來做?

DaemonSet:守護進程控制器

DaemonSet 也是 Kubernetes 提供的一個 default controller,它實際是做一個守護進程的控制器,它能幫我們做到以下幾件事情:

  • 首先能保證集群內(nèi)的每一個節(jié)點都運行一組相同的 pod;

  • 同時還能根據(jù)節(jié)點的狀態(tài)保證新加入的節(jié)點自動創(chuàng)建對應(yīng)的 pod;

  • 在移除節(jié)點的時候,能刪除對應(yīng)的 pod;

  • 而且它會跟蹤每個 pod 的狀態(tài),當這個 pod 出現(xiàn)異常、Crash 掉了,會及時地去 recovery 這個狀態(tài)。

用例解讀

DaemonSet 語法

下面舉個例子來看一下,DaemonSet.yaml 會稍微長一些。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

首先是 kind:DaemonSet。如果之前學(xué)過 deployment,其實我們再看這個 yaml 會比較簡單。例如它會有 matchLabel,通過 matchLabel 去管理對應(yīng)所屬的 pod,這個 pod.label 也要和這個 DaemonSet.controller.label 想匹配,它才能去根據(jù) label.selector 去找到對應(yīng)的管理 Pod。下面 spec.container 里面的東西都是一致的。<br /> <br />這里用 fluentd 來做例子。DaemonSet 最常用的點在于以下幾點內(nèi)容:

  • 首先是存儲,GlusterFS 或者 Ceph 之類的東西,需要每臺節(jié)點上都運行一個類似于 Agent 的東西,DaemonSet 就能很好地滿足這個訴求;

  • 另外,對于日志收集,比如說 logstash 或者 fluentd,這些都是同樣的需求,需要每臺節(jié)點都運行一個 Agent,這樣的話,我們可以很容易搜集到它的狀態(tài),把各個節(jié)點里面的信息及時地匯報到上面;

  • 還有一個就是,需要每個節(jié)點去運行一些監(jiān)控的事情,也需要每個節(jié)點去運行同樣的事情,比如說 Promethues 這些東西,也需要 DaemonSet 的支持。

查看 DaemonSet 狀態(tài)

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

創(chuàng)建完 DaemonSet 之后,我們可以使用 kubectl get DaemonSet(DaemonSet 縮寫為 ds)。可以看到 DaemonSet 返回值和 deployment 特別像,即它當前一共有正在運行的幾個,然后我們需要幾個,READY 了幾個。當然這里面,READY 都是只有 Pod,所以它最后創(chuàng)建出來所有的都是 pod。

這里有幾個參數(shù),分別是:需要的 pod 個數(shù)、當前已經(jīng)創(chuàng)建的 pod 個數(shù)、就緒的個數(shù),以及所有可用的、通過健康檢查的 pod;還有 NODE SELECTOR,因為 NODE SELECTOR 在 DaemonSet 里面非常有用。有時候我們可能希望只有部分節(jié)點去運行這個 pod 而不是所有的節(jié)點,所以有些節(jié)點上被打了標的話,DaemonSet 就只運行在這些節(jié)點上。比如,我只希望 master 節(jié)點運行某些 pod,或者只希望 Worker 節(jié)點運行某些 pod,就可以使用這個 NODE SELECTOR。

更新 DaemonSet

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

其實 DaemonSet 和 deployment 特別像,它也有兩種更新策略:一個是 RollingUpdate,另一個是 OnDelete。

  • RollingUpdate 其實比較好理解,就是會一個一個的更新。先更新第一個 pod,然后老的 pod 被移除,通過健康檢查之后再去見第二個 pod,這樣對于業(yè)務(wù)上來說會比較平滑地升級,不會中斷;

  • OnDelete 其實也是一個很好的更新策略,就是模板更新之后,pod 不會有任何變化,需要我們手動控制。我們?nèi)h除某一個節(jié)點對應(yīng)的 pod,它就會重建,不刪除的話它就不會重建,這樣的話對于一些我們需要手動控制的特殊需求也會有特別好的作用。

操作演示

DaemonSet 的編排

下面舉一個例子。比如說我們?nèi)ジ牧诵?DaemonSet 的鏡像,然后看到了它的狀態(tài),它就會去一個一個地更新。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

上圖這個就是剛才 DaemonSet 的 yaml,會比剛才會多一些, 我們做一些資源的限制,這個都不影響。

DaemonSet 的創(chuàng)建與運行驗證

下面我們創(chuàng)建一下 DaemonSet ,然后再看一下它的狀態(tài)。下圖就是我們剛才看到的 DaemonSet 在 ready 里打出來的狀態(tài)。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

從下圖中可以看到,一共有 4 個 pod 被創(chuàng)建出來。為什么是 4 個 pod呢?因為只有 4 個節(jié)點,所以每個節(jié)點上都會運行一個對應(yīng)的 pod。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

DaemonSet 的更新

這時,我們來更新 DaemonSet, 執(zhí)行完了kubectl apply -f 后,它的 DaemonSet 就已經(jīng)更新了。接下來我們?nèi)ゲ榭?DaemonSet 的更新狀態(tài)。

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

上圖中可以看到:DaemonSet 默認這個是 RollingUpdate 的,我們看到是 0-4,現(xiàn)在是 1-4,也就是說它在更新第一個,第一個更新完成會去更新第二個,第二個更新完,就更新第三個······這個就是 RollingUpdate。RollingUpdate 可以做到全自動化的更新,不用有人值守,而是一個一個地去自動更新,更新的過程也比較平滑,這樣可以有利于我們在現(xiàn)場發(fā)布或者做一些其他操作。<br />

上圖結(jié)尾處可以看到,整個的 DaemonSet 已經(jīng) RollingUpdate 完畢。

架構(gòu)設(shè)計

DaemonSet 管理模式

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

接下來看一下 DaemonSet 架構(gòu)設(shè)計。DaemonSet 還是一個 controller,它最后真正的業(yè)務(wù)單元也是 Pod,DaemonSet 其實和 Job controller 特別相似,它也是通過 controller 去 watch API Server 的狀態(tài),然后及時地添加 pod。唯一不同的是,它會監(jiān)控節(jié)點的狀態(tài),節(jié)點新加入或者消失的時候會在節(jié)點上創(chuàng)建對應(yīng)的 pod,然后同時根據(jù)你配置的一些 affinity 或者 label 去選擇對應(yīng)的節(jié)點。

DaemonSet 控制器

應(yīng)用編排與管理中的Job及DaemonSet怎么理解

最后我們來看一下 DaemonSet 的控制器,DaemonSet 其實和 Job controller 做的差不多:兩者都需要根據(jù) watch 這個 API Server 的狀態(tài)?,F(xiàn)在 DaemonSet 和 Job controller 唯一的不同點在于,DaemonsetSet Controller需要去 watch node 的狀態(tài),但其實這個 node 的狀態(tài)還是通過 API Server 傳遞到 ETCD 上。

當有 node 狀態(tài)節(jié)點發(fā)生變化時,它會通過一個內(nèi)存消息隊列發(fā)進來,然后DaemonSet controller 會去 watch 這個狀態(tài),看一下各個節(jié)點上是都有對應(yīng)的 Pod,如果沒有的話就去創(chuàng)建。當然它會去做一個對比,如果有的話,它會比較一下版本,然后加上剛才提到的是否去做 RollingUpdate?如果沒有的話就會重新創(chuàng)建,Ondelete 刪除 pod 的時候也會去做 check 它做一遍檢查,是否去更新,或者去創(chuàng)建對應(yīng)的 pod。

當然最后的時候,如果全部更新完了之后,它會把整個 DaemonSet 的狀態(tài)去更新到 API Server 上,完成最后全部的更新。

看完上述內(nèi)容,你們對應(yīng)用編排與管理中的Job及DaemonSet怎么理解有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

名稱欄目:應(yīng)用編排與管理中的Job及DaemonSet怎么理解
標題路徑:http://bm7419.com/article36/pcghsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄商城網(wǎng)站、網(wǎng)站維護全網(wǎng)營銷推廣、標簽優(yōu)化、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)