整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          前端網頁加載渲染鏈路優化

          面性能和用戶體驗的各個指標怎么來優化呢?open signal官方提供了2018年2月份統計的全世界4G網絡覆蓋率和通信速率的統計分布圖如下,在目前移動互聯網的浪潮下,我們要利用好用戶終端設備的每個字節的流量。

          當然頁面性能和體驗優化并不是一蹴而就的,需要不斷的研究、跟蹤,發現問題,解決問題。但是我們可以在一開始編寫業務代碼的時候就做的更好,做到極致。所以,關于優化實戰我們主要分為兩部分:加載渲染鏈路優化 和 編程代碼優化。

          加載渲染鏈路優化

          從訪問url到頁面呈現,整個鏈路可以做優化的思路。

          幸運的是,W3C推薦的Navigation Timing標準中所定義的核心的頁面性能數據,它包含了從上個頁面銷毀到跳轉到當前頁面加載完成每個階段所消耗的時間。在canIuse上查到的兼容性也很好:

          利用這個接口可以很方便的幫助我們排查鏈路問題。在Navigation Timing標準中介紹到這個API主要包含兩個接口:PerformanceTiming和PerformanceNavigation,這兩個接口由瀏覽器進行實現和維護,當瀏覽器創建頁面的時候就會把接口定義的相關數據掛載到window.performance.timing和window.performance.navigation這兩個屬性上。我們可以打開一個網頁看一下:

          我們把這兩個圖對比一下,就可以很容易的排查出頁面的加載鏈路問題。

          靜態資源鏈路

          打開頁面的第一步是請求頁面的html,這里面涉及TTFB這個綜合指標。同時如果有必要我們也可以統計DNS時間和TCP時間。

          DNS時間:主要是根據請求域名查詢到對應主機IP的時間。這個和DNS服務器有關系,也可能和本地緩存有關,如果這個很慢,可以找服務商排查下問題。

          TCP時間:tcp是承接http協議的下層協議。主要是路由到主機ip,并建立tcp鏈接的時間。這個時間反應了服務器到用戶客戶端之間鏈路是否通暢,網絡是否通暢。

          請求完HTML之后,就開始解析html代碼,按照從上至下、自然順序解析,解析內聯CSS代碼或者加載外鏈CSS腳本,解析內聯Javascript腳本,或者加載外鏈Javascript腳本。由于瀏覽器是單線程的,這些CSS和Javascript腳本很可能就會造成頁面卡頓。參考 瀏覽器線程理解與microtask與macrotask。

          加載

          CDN是內容分發網絡,主要用于緩存靜態資源。CDN服務商一般會在全國各地部署服務,而且帶寬很大,這樣訪問CDN的資源時就可以有較短的路由路徑,而且帶寬也比較大,訪問比較快。

          1. 建議最好把html, CSS、JS、font、img這些資源放在CDN上,沒有CDN也可以放在OSS存儲服務上,總之比自己的服務器硬盤快多了,至少服務商會在不同區域做分布式部署
          2. 如果沒有錢買CDN服務,那么就盡可能少的加載外聯CSS和JS代碼,注意html頭部可以增加dns-prefetch,減少DNS解析時間
          3. 不是在首屏展示的資源,不要立即加載,可以在頁面onload之后加載,或者首屏渲染完成再加載
          4. 壓縮CSS、JS、font、img,盡量減少體積,服務端開啟gzip
          5. 考慮資源combo請求,減少http請求量,瀏覽器一般都有并發限制, 比如chrome一次6個并發http請求,不同瀏覽器內核可能不一樣。
          6. <script>加載腳本會阻塞瀏覽器主線程,考慮異步化,參考 script標簽的defer與async
          7. 利用好緩存,利用好http響應頭緩存字段,開啟靜態資源緩存,減少資源下載,建議開啟service worker緩存,這個是作為APP Cache的替代方案,參考MDN;
          8. 對于單純的獲取數據做展示,盡量采用JSONP請求數據,而不是AJAX,提升數據請求性能。參考jsonp而不是AJAX?
          9. 開啟HTTP/2 ,HTTP2支持鏈接復用,可以很高效下載多個小文件。HTTP/2 的目的是通過支持完整的請求與響應復用來減少延遲,通過有效壓縮 HTTP 標頭字段將協議開銷降至最低,同時增加對請求優先級和服務器推送的支持。

          解析渲染

          加載完JS和CSS之后,瀏覽器開始解析執行。Chrome的渲染流程是這樣的:(可以參考 高性能CSS動畫)

          為了讓瀏覽器更快的解析渲染,我們需要考慮這幾點:

          1. CSS嵌套層級不要太深,不超過3級,避免在最內層使用通配選擇器。參考關于 CSS 選擇器性能
          2. JS腳本不要太復雜,考慮輕量化架構,降低JS復雜性,減少解析時間,盡量不要引用復雜的第三方腳本。
          3. 按需加載模塊,按需打包,首頁僅僅加載和執行和首屏相關的腳本。其他腳本延遲加載執行。
          4. 考慮依賴的第三方模塊是不是必須,需不需要精簡。
          5. 打包優化,code split 和 tree shaken。常用webpack和rollup的優化。
          6. 用戶交互相關事件綁定(比如頁面scroll,用戶左右滑動等),添加參數{passive:true},減少瀏覽器事件等待。因為這些事件屬于可阻止事件,瀏覽器不知道用戶會不會阻止,所以需要等待js執行,然后再做響應。添加passive參數,就告訴瀏覽器不用等待了。
          7. IOS8以后的ios支持wkwebview,但是很多app之前用的還是uiwebview,建議轉換成wkwebview,獲得性能的提升(UIwebview在執行JS時會阻塞UI渲染進程,WKwebview不會)。

          介紹一下code split的方案: react-loadable

          // 未處理
          import OtherComponent from './OtherComponent';
          const MyComponent = () => (
           <OtherComponent/>
          );
          // 使用react-loadable按需加載
          import Loadable from 'react-loadable';
          const LoadableOtherComponent = Loadable({
           loader: () => import('./OtherComponent'),
           loading: () => <div>Loading...</div>,
          });
          const MyComponent = () => (
           <LoadableOtherComponent/>
          );
          

          這個也可以在打包工具統一配置,不用每個模塊都自己寫。

          只有瀏覽器盡快渲染出來,用戶才能盡快的可以交互。

          數據埋點

          上面我們梳理了加載到解析渲染過程應該做的事情,那么如果你這些都做好了,發現網頁表現依然不盡人意,那么你就要考慮做一下數據埋點。其實數據埋點在企業項目中也是必不可少的,和性能體驗優化構成閉環。通過數據來發現頁面性能和體驗的問題,更有針對的進行解決。

          事實上數據埋點分為三類:

          1. 業務埋點,統計諸如pv、uv、點擊率、流失率、轉化率等
          2. 大數據埋點,統計與用戶行為相關信息,比如那個用戶點擊了那個商品,上報用戶id和商品id,方便后臺分析用戶和商品的關系,可以用做大數據分析,推薦算法來為用戶推薦商品。

          工程埋點,統計工程上的數據信息,比如頁面秒開率,dns時間等,也就是我們上節課總結的性能和體驗數據指標。

          資源緩存

          這一節我們單獨介紹緩存,是的,利用好緩存可以解決很多問題,包括頁面加載和渲染的問題都能得到很好的優化。

          常見的h5緩存方案有很多種,

          通常,與頁面加載性能相關的,有下面幾種緩存,

          (1)MemoryCache

          MemoryCache,資源存放在內存中,一般資源響應回來就會放進去,頁面關閉就會釋放。內存存取性能可達磁盤緩存性能的100倍,但這還不是MemoryCache的最大優勢,MemoryCache最大的優勢是離排版渲染引擎非常近,可以直接被讀取,甚至無需經過線程轉換。在真實的頁面訪問過程中,獲取資源的時間,磁盤IO僅僅是其中的一部分,更多的時間往往消耗在各種線程拋轉。

          (2)ClientCache

          ClientCache,客戶端緩存,比如,手淘里的ZCache(離線壓縮包緩存),本質上屬于磁盤緩存。這類Cache的優點是能以相對可控的方式讓資源提前緩存在磁盤,但它也有一系列的成本。比如,它需要一套服務器與客戶端協同的下發更新邏輯,服務器端需要管理下發,客戶端需要提前解壓縮。我們可能覺得提前解壓并不是什么弱點,但如果有一千個離線包,這個問題就比較嚴重了,如果不提前解壓,就無法保證首次訪問性能,如果提前解壓會讓IO非常繁忙,可能會造成客戶端打開時嚴重卡頓。

          (3)HttpCache

          HttpCache,是歷史比較悠久的緩存,它利用標準的 Cache-Control 與服務器端進行協商,根據標準的規則去緩存或更新資源。它應用非常廣泛,是非常有效果的一種磁盤緩存。它的缺點是完全由瀏覽器按標準規則控制,其它端的控制力度非常弱。比如,某些被HttpCache緩存的靜態資源出問題了,通常只能是改頁面,不再使用出問題的資源,而無法主動清除出問題的資源。參考http請求緩存頭,HTTP協商緩存VS強緩存原理

          (4)NetCache

          網絡相關的Cache,一般是指DNS解析結果的緩存,或預連接的緩存。DNS預解析和預連接是非常重要的,創建一個Https連接的成本非常大,通常需要600ms以上,也就是說,頁面如果有關鍵資源需要全新建連接,秒開基本是不可能了。

          (5)CDN

          CDN一般是通過負載均衡設備根據用戶IP地址,以及用戶請求的URL,選擇一臺離用戶比較近,緩存了用戶所需的資源,有較好的服務能力的服務器,讓用戶從該服務器去請求內容。它能讓各個用戶的緩存共享,縮短用戶獲取資源的路徑,來提升整體的性能。

          當然,還有其它非常多類型的Cache,比如,

          JS相關,V8 Bytecode Cache,字節碼緩存,能極大的減少JS解析耗時,甚至可以提升3-6倍的性能。參考:前端優化系列 – JS解析性能分析

          渲染相關,圖片解碼數據緩存,是一塊非常大的內存緩存,約100M,能保證頁面滾動過程可以實時獲取到圖片解碼數據,讓滾動非常流暢。

          頁面相關,頁面緩存,Safari的PageCache,Firefox的Back-Forward Cache,UC瀏覽器的WebViewCache,都是一樣性質的緩存,將整個執行過的頁面保存在內存。標準的頁面緩存,進入的條件非常苛刻,大部分情況都無法進入,而且在前進后退的場景才允許使用。

          緩存優化實例

          前面介紹了很多理論層面的內容,我們接下來介紹一些實踐優化案例。

          (1)預置資源進MemoryCache

          在頁面的onPageFinished的回調里面去檢查是否有資源可以預置,如果有,就通過相關接口把資源設置進內核的MemoryCache。我們并不知道用戶即將會訪問什么頁面,如果把大量的資源都預置進內存,而用戶卻沒有使用,那就會造成浪費。另外,資源在內核內存,僅僅是加快了資源的加載速度,頁面的首屏包含非常多非常復雜的流程,某個流程的加速并不一定能帶來整體性能的提升,比如,非關鍵的JS放在內存,可能就會先于一些關鍵JS被提前執行,反而讓首屏更慢。所以,選擇放那些資源進內存也是非常有講究的,能預置的資源一般是 非常關鍵的更新頻率較低的少量公共基礎資源。

          對于一般公司來說,沒有能力自己定制webview渲染的內核,可以看下系統默認webview內核有沒有這樣的接口來實現操作MemoryCache預置數據的能力。

          (2)預加載資源進HttpCache

          預置資源進內存,對加載性能的提升是最明顯的,但成本也是最大的,會占用用戶手機寶貴的內存資源。另外一種預置資源的思路是,提前通過內核去預加載一些資源,資源加載回來之后就直接保存在標準的HttpCache。資源在HttpCache和在客戶端緩存(比如,手淘ZCache)的性能差別不大。但如果資源不能放進ZCache,通過這種方式提前放到HttpCache,也是一種優化思路。

          (3)使用WebViewCache極速切換頁面

          H5頁面的加載流程是非常重的一套流程,即使同一個頁面多次重復訪問,也需要走比較完整的流程,耗時極長,這與用戶的期望是不符的,通常用戶期望訪問過的頁面就能快速展現出來。在一些特定的場景,H5也是可以做到極速展現的,比如,前進后退。其它的場景,比如頁內幾個TAB切換,是否也可以用上這類緩存呢?也是可以的。原理上也是比較簡單的,在頁面首次訪問時,會將排版渲染好的頁面放進WebViewCache里,WebViewCache是存儲完整頁面的一塊內存。

          用戶再次訪問該頁面時,會將WebViewCache內存中的完整頁面讀取出來,直接繪制展現,而無需再進行加載解析排版渲染等流程,從而達到極速打開的效果。

          除了內核提供WebViewCache基礎技術之外,前端也需要與內核進行一定的交互,比如,通過JSAPI查詢當前頁面是否在WebViewCache,如果在則返回它在WebViewCache列表的位置,然后前端就可以使用JSAPI去跳轉到相應位置的頁面,內核就把頁面從內存讀取和展現出來。使用此類技術,頁面一般能在500ms左右完全展現出來,具有非常好的用戶體驗。

          當然這個也是需要瀏覽器內核提供這種能力,如果公司有自己的內核開發團隊,可以做到定制。

          (4)前端使用LocalStorage緩存HTML文檔

          當前前端渲染非常流行,頁面大部分的邏輯都會由前端JS去執行,JS執行完才會生成完整的HTML文檔,而JS執行的成本是非常大的,JS執行時間可能占據首屏時間的50%,有些甚至能達到80%。那么,我們有沒有可能將JS執行生成的完整HTML文檔緩存起來呢,下次訪問時直接使用已緩存的頁面,而無需重復執行JS?這也是可以的原理上也不復雜,首次訪問頁面時,JS執行完之后會生成完整的HTML文檔,我們將HTML文檔緩存到LocalStorage里面。

          在后續的訪問中,我們優先從LocalStorage里面讀取HTML文檔,解析排版渲染頁面,而無需JS執行去生成頁面,讓頁面展現速度得到極大的提升。

          這種方案的關鍵在于前端能夠實現一套DOM-Diff更新的機制,在從LocalStorage讀取HTML頁面的同時,前端還會發起請求去更新HTML文檔,在新的HTML文檔回來之后,會和舊的文檔進行Diff,針對Diff來進行局部更新,這樣能保證頁面得到及時的更新。

          (5) service worker

          參考使用 Service Workers提升體驗,這里附帶介紹下這個方案,目前service worker 只有在android的webview中可用,ios還不支持。我們通過先注冊一個serviceworker服務,指定哪些資源和數據需要存儲,然后下次請求頁面會自動激活這個service worker,頁面請求時會先從service worker中返回緩存的數據。當然service worker中需要自己處理版本和維護數據更新。

          、介紹

          在docker中可以將容器中的目錄掛載出來,在k8s中pod可以部署在不同節點,假如該節點的機器宕機了,k8s可能就會將此Pod轉移到其他機器,就不是原先的機器了。k8s有自己的一套掛載方案,如下圖所示,

          原理為將所有節點的掛載的目錄統一抽象管理為叫做 存儲層的概念,使用技術如NFS網絡文件系統,在每一個節點都會有如50G的存儲空間,該空間之間的數據是同步的,這樣就解決了某一節點宕機了,Pod轉移到其他節點了依然可以獲取到掛載的目錄。



          1、搭建NFS網絡文件系統



          • 所有機器安裝 yum install -y nfs-utils
          • nfs主節點,這里我們對應k8s的主節點(我配置兩個主節點,選擇了其中一個) 創建同步文件的目錄 mkdir -p /nfs/k8s/data,設置暴露目錄echo "/nfs/k8s/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
          • nfs主節點啟動RPC遠程綁定現在啟動并且開機也要啟動 systemctl enable rpcbind --now
          • nfs主節點啟動nfs 服務端,并且開啟自動啟動 systemctl enable nfs-server --now
          • nfs主節點使配置生效 exportfs -r, 輸出目錄查看 exportfs



          • 其他節點可檢查哪些目錄可以同步,執行命令 showmount -e 192.168.134.110,注意IP換成自己的



          • 其他節點也創建同步的目錄,目錄名隨意,我定義成一樣的 mkdir -p /nfs/k8s/data
          • 將主節點和其他節點關聯起來 ,在其他節點執行 mount -t nfs 192.168.134.110:/nfs/k8s/data /nfs/k8s/data
          • 測試,可以在任意一個節點添加修改文件,去其他檢查是否同步修改了

          2、原生方式創建Deployment并應用目錄掛載到nfs

          如下使用yaml的方式將鏡像nginx中的目錄/usr/share/nginx/html掛載到了nfs服務端的/nfs/data/nginx-pv目錄,只要在掛載目錄/nfs/data/nginx-pv里加文件,也會同步到了pod里/usr/share/nginx/html

          kubectl apply -f nfs-demo.yaml

          apiVersion: apps/v1
          kind: Deployment
          metadata:
            labels:
              app: nginx-pv-demo
            name: nginx-pv-demo
          spec:
            replicas: 2
            selector:
              matchLabels:
                app: nginx-pv-demo
            template:
              metadata:
                labels:
                  app: nginx-pv-demo
              spec:
                containers:
                - image: nginx
                  name: nginx
                  volumeMounts:
                  - name: html
                    mountPath: /usr/share/nginx/html
                volumes:
                  - name: html
                    nfs:
                      server: 192.168.134.110
                      path: /nfs/data/nginx-pv

          注意掛載的目錄一定要先創建好否則查詢當前應用時出現如下一直在創建中



          進入這個pod詳細信息,可以看到報錯的詳細問題 kubectl describe pod nginx-pv-demo-dc6884649-4phvz



          這種方式缺點:1、需要提前創建好掛載的機器目錄;2、當Pod刪除,機器掛載的目錄不會同時刪除;3、無法指定目錄的存儲大小

          3、使用靜態PV/PVC持久卷方式

          PV持久卷,可以指定大小,當PVC刪除,并釋放對應的PV



          PV:持久卷(Persistent Volume),將應用需要持久化的數據保存到指定位置

          PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷規格

          2、存儲掛載PV/PVC實戰

          1、在nfs目錄中創建PV的靜態目錄

          #nfs主節點
          mkdir -p /nfs/k8s/pv/data/01
          mkdir -p /nfs/k8s/pv/data/02
          mkdir -p /nfs/k8s/pv/data/03

          2、創建靜態PV持久卷

          執行命令 kubectl apply -f pvdemo.yaml

          以下可以寫在一個文件中 ,用---分割,會自動識別成三個文件,server為主節點的IP地址。storageClassName表示一個標志,在后面創建PVC時需要用到。

          apiVersion: v1
          kind: PersistentVolume
          metadata:
            name: pv01-10m
          spec:
            capacity:
              storage: 10M
            accessModes:
              - ReadWriteMany
            storageClassName: nfs
            nfs:
              path: /nfs/k8s/pv/data/01
              server: 192.168.134.110
          ---
          apiVersion: v1
          kind: PersistentVolume
          metadata:
            name: pv02-1gi
          spec:
            capacity:
              storage: 1Gi
            accessModes:
              - ReadWriteMany
            storageClassName: nfs
            nfs:
              path: /nfs/k8s/pv/data/02
              server: 192.168.134.110
          ---
          apiVersion: v1
          kind: PersistentVolume
          metadata:
            name: pv03-3gi
          spec:
            capacity:
              storage: 3Gi
            accessModes:
              - ReadWriteMany
            storageClassName: nfs
            nfs:
              path: /nfs/k8s/pv/data/03
              server: 192.168.134.110

          3、查詢PV持久卷


          簡寫


          4、創建PVC

          pvc.yaml如下:storageClassName: nfs 對應創建的PV

          kind: PersistentVolumeClaim
          apiVersion: v1
          metadata:
            name: nginx-pvc
          spec:
            accessModes:
              - ReadWriteMany
            resources:
              requests:
                storage: 200Mi
            storageClassName: nfs

          因為申請的storage: 200Mi 指定了大小,所以被分配了擁有1G容量的PV



          5、刪除PVC

          對應的PV也會被釋放Released



          6、查詢PVC



          7、創建Deployment應用同時掛載PVC

          執行 kubectl apply -f pvcdemo.yaml

          將創建好的PVC nginx-pvc掛載到當前創建的應用中。

          apiVersion: apps/v1
          kind: Deployment
          metadata:
            labels:
              app: nginx-deploy-pvc
            name: nginx-deploy-pvc
          spec:
            replicas: 2
            selector:
              matchLabels:
                app: nginx-deploy-pvc
            template:
              metadata:
                labels:
                  app: nginx-deploy-pvc
              spec:
                containers:
                - image: nginx
                  name: nginx
                  volumeMounts:
                  - name: html
                    mountPath: /usr/share/nginx/html
                volumes:
                  - name: html
                    persistentVolumeClaim:
                      claimName: nginx-pvc

          8、測試

          修改掛載的目錄,即可查看文件有沒有同步。

          告:

          HostPath 卷存在許多安全風險,最佳做法是盡可能避免使用 HostPath。 當必須使用 HostPath 卷時,它的范圍應僅限于所需的文件或目錄,并以只讀方式掛載。

          如果通過 AdmissionPolicy 限制 HostPath 對特定目錄的訪問,則必須要求 volumeMounts 使用 readOnly 掛載以使策略生效。

          hostPath 卷能將主機節點文件系統上的文件或目錄掛載到你的 Pod 中。 雖然這不是大多數 Pod 需要的,但是它為一些應用程序提供了強大的逃生艙。

          例如,hostPath 的一些用法有:

          • 運行一個需要訪問 Docker 內部機制的容器;可使用 hostPath 掛載 /var/lib/docker 路徑。
          • 在容器中運行 cAdvisor 時,以 hostPath 方式掛載 /sys
          • 允許 Pod 指定給定的 hostPath 在運行 Pod 之前是否應該存在,是否應該創建以及應該以什么方式存在。

          除了必需的 path 屬性之外,你可以選擇性地為 hostPath 卷指定 type。hostPath卷類型支持的type值如下:

          取值

          行為


          空字符串(默認),用于向后兼容,意味著在安裝hostPath卷之前不會執行任何檢查

          DirectoryOrCreate

          如果在給定路徑上什么都不存在,那么將根據需要創建空目錄,權限設置為 0755,具有與 kubelet 相同的組和屬主信息。

          Directory

          在給定路徑上必須存在的目錄。

          FileOrCreate

          如果在給定路徑上什么都不存在,那么將在那里根據需要創建空文件,權限設置為 0644,具有與 kubelet 相同的組和所有權。

          File

          在給定路徑上必須存在的文件。

          Socket

          在給定路徑上必須存在的 UNIX 套接字。

          CharDevice

          在給定路徑上必須存在的字符設備。

          BlockDevice

          在給定路徑上必須存在的塊設備。

          當使用這種類型的卷時要小心,因為:

          • HostPath 卷可能會暴露特權系統憑據(例如 Kubelet)或特權 API(例如容器運行時套接字),可用于容器逃逸或攻擊集群的其他部分。
          • 具有相同配置(例如基于同一 PodTemplate 創建)的多個 Pod 會由于節點上文件的不同而在不同節點上有不同的行為。
          • 下層主機上創建的文件或目錄只能由 root 用戶寫入。 你需要在特權容器中以 root 身份運行進程,或者修改主機上的文件權限以便容?能夠寫入 hostPath 卷。

          hostPath卷類型測試

          測試選擇在第二個節點服務器上使用hostPath,將Pod調度限制在該節點,如果不加以限制,Pod可能會被調度到其他節點服務器上,Pod無法啟動。

          // hostPath 類型卷配置文件
          [root@c7-1 hostpath-manual-storageclass]# cat pv-volume-hostpath.yaml 
          apiVersion: v1
          kind: PersistentVolume
          metadata:
            name: pv-hostpath10g
            labels:
              type: local
          spec:
            storageClassName: manual
            capacity:
              storage: 10Gi
            accessModes:
              - ReadWriteOnce
            hostPath:
              path: "/mnt/data"
          // pvc 申領配置文件
          [root@c7-1 hostpath-manual-storageclass]# cat pvc-hostpath-manual.yaml 
          apiVersion: v1
          kind: PersistentVolumeClaim
          metadata:
            name: pvc-hostpath10g
          spec:
            storageClassName: manual
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 10Gi
          // Pod 配置文件,引用hostPath類型的卷
          [root@c7-1 hostpath-manual-storageclass]# cat pod-hostpath.yaml 
          apiVersion: v1
          kind: Pod
          metadata:
            name: pod-pv-hostpath
          spec:
            nodeName: c7-2.runoqd.com		// 指定該Pod被調度到的節點
            volumes:
              - name: pv-storage10g
                persistentVolumeClaim:
                  claimName: pvc-hostpath10g
            containers:
              - name: pod-pv-hostpath
                image: nginx
                ports:
                  - containerPort: 80
                    name: "http-server"
                volumeMounts:
                  - mountPath: "/usr/share/nginx/html"
                    name: pv-storage10g

          創建相關資源并驗證


          主站蜘蛛池模板: 亚洲一区精品伊人久久伊人| 综合久久久久久中文字幕亚洲国产国产综合一区首| 国产精品免费视频一区| 免费无码毛片一区二区APP| 国模吧一区二区三区| 亚洲av鲁丝一区二区三区| 91久久精品国产免费一区| 99精品国产一区二区三区2021 | 97久久精品无码一区二区天美| 国产在线观看精品一区二区三区91| 国产伦精品一区二区三区不卡| 日韩一区二区免费视频| 精品一区二区三区四区电影| 中文字幕日韩一区| 国产激情з∠视频一区二区| 亚洲AV无码一区二三区| 韩国美女vip福利一区| 无码人妻一区二区三区免费看| 国精产品一区一区三区| 熟女性饥渴一区二区三区| 一区二区三区91| 亚洲AV永久无码精品一区二区国产| 无码中文人妻在线一区二区三区| 久久精品亚洲一区二区三区浴池| 日本精品一区二区三区在线观看| 国产AV国片精品一区二区| 国语对白一区二区三区| 色综合视频一区中文字幕| 成人区人妻精品一区二区三区| 国产精品一区二区四区| 国产成人久久一区二区三区| 日本精品一区二区三区在线视频 | 久久久久人妻精品一区蜜桃| 丰满人妻一区二区三区视频53| 久久精品国产一区二区三区| 国产一区三区二区中文在线| 激情内射日本一区二区三区| 亚洲电影一区二区| 精品一区二区三区免费观看| 久热国产精品视频一区二区三区 | 亚洲AV无码一区二区三区人|