特斯拉 Model 3 估 7 月投產,拚下半年如期交車

美國電動車廠特斯拉(Tesla)周三盤後公布前季財報再度由盈轉虧,不過這並不打緊,因為按照特斯拉說法,Model 3 平價電動車有望如期交車,這才是投資人所最關心的。

特斯拉獲利表現不理想,去年第四季淨損 1.21 億美元,或相當於每股 0.78 美元,若扣除一次性費用,每股虧損降低至 0.69 美元,但還是高於分析師原預估每股虧 0.53 美元。

當季營收來到 22.8 億美元,較去年同期成長88%,且優於分析師預估的 22.2 億美元。特斯拉去年 11 月 21 日已完成太陽能面板廠 SolarCity 的收購作業,SolarCity 當季貢獻營收 1.31 億美元。

特斯拉當日宣布,Model 3 預計2017年 7 月可限量投產,9 月產量可開始放大,預估 2018 年每周可產出 10,000 輛。特斯拉原預期 Model 3 可在下半年開始交車,現在兌現承諾的機率大大提高,這激勵特斯拉股價盤後大漲 2.49%、暫報 280.02 美元。

第四季 Model S、Model X 產量合計來到 24,882 輛,年增 77%;銷售量合計為 22,252 輛,成長 27%。(紐約時報)

展望 2017 年,特斯拉預期 Model S 與 Model X 交車量將介於 47,000 至 50,000 輛,換算年成長率最高為 71%。另外,特斯拉還說太陽能車頂下半年就能開始量產。

(本文內容由授權使用。圖片出處:Public Domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

北市邁向智慧城市倡3U,推U-Car電動車共享服務

臺北市政府 23 日宣布,將以「共享、綠能、E化」作為施政規劃主軸,積極導入智慧交通解決方案,近期更推出「3U」計畫,整合 YouBike、U-Motor 及 U-Car 服務,提供給民眾更便利的交通模式,減少私人運具的持有率,藉由綠能交通運具減輕城市嚴重的交通與環境污染問題,同時以此鼓勵智慧城市相關產業創新及促進智慧城市發展。

北市府資訊局及臺北智慧城市專案辦公室此次成功協助媒合威摩、裕隆、蓋亞、和運與電馳等業者,共同推動 3U 計劃,並於今日邀請基隆市、桃園市及新竹市等首長代表共同參與北基桃竹四城市的3U智慧綠能交通生活圈,會中展示 3U 運具,希望結合地方政府及民間業者的力量,打造 3U 首都生活圈。

臺北市副市長林欽榮表示,北市府正努力打造 3U 首都生活圈,目前已有YouBike公共自行車、民間業者營運之 U-Motor 電動機車共享,未來將陸續於北市公有停車場及公共住宅建置充電柱供民眾使用,並鼓勵業者投入資源、提供 U-Car 電動車共享服務,會後並與現場貴賓及業者親身體驗 WeMo。中央已延長電動車免收貨物稅至 2021 年,鼓勵民眾使用電動車輛,北市亦將響應此政策,未來臺北市電動車登記數量達 1,000 輛前,停放至公有停車位充電將僅收取停車費用,市府補助電費以鼓勵市民使用電動車。

此外,北市府指出,目前已建置 300 處公共自行車租賃站,提供 9,838 輛 YouBike 供市民使用,預計 106 年底能完成 400 站建置,提供 13,000 輛公共自行車,讓市民能更方便地使用 YouBike。威摩科技在 2016 年 10 月成功推出 WeMo Scooter 電動機車共享服務,北市希望仿此模式提供場域,鼓勵民間業者推出電動車共享服務。而考量民眾交通需求,未來也將與基隆市、桃園市及新竹市等鄰近城市研議,共同打造電動車友善環境並拓展 3U 首都生活圈,朝共享、綠能、e 化的智慧城市邁進。

(本文內容由授權使用。圖片出處:Pixabay CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

FC EXPO 2017:氫燃料技術更成熟,日本力推奧運「氫應用」

FC EXPO 2017 除了展出最受關注的燃料電池乘用車輛外,根據EnergyTrend的觀察,展會的焦點也擺脫過去對於白金衝擊成本的迷思,現場除了有普遍大眾所關注的燃料電池車輛外,更深入到其他的關鍵部件,包括高壓氫氣瓶,質量輕且壽命更高的金屬電池堆等,可以預期燃料電池對於普及化又更邁進一步。

2017年FC EXPO在歷經許多車廠過去兩年間,擘畫出未來對於燃料電池車輛(Fuel Cell Vehicle /FCEV)的願景,吸引更多參觀者的目光,再加上中國對於燃料電池車輛的發展將大力補貼,讓參觀者呈現出超越以往的盛況,除了歐美的國家外,也吸引許多來自中國的參觀者。根據EnergyTrend在現場的了解,日系車廠的發展重心在本次展覽中可看出顯著差異性。

對於豐田來說,為了配合2020東京奧運的活動,2017年已開始進行兩輛燃料電池巴士的示範運行,預計在2018年開始正式銷售,並且在2020年達到一百輛的銷售目標。本田則是將重心放在清能家庭的應用示範,搭配自行開發的SHS(Smart Hydrogen Station)訂製型產氫系統,可將再生能源透過SHS轉換成輕氣,供給FCEV使用,家庭所需電力可再透過FCEV產生電力供給家庭使用;日產則提出e-Bio Fuel cell概念,使用乙醇水(45% Ethanol)做為車輛燃料,搭配上自行開發的固態氧化燃料電池(Solid Oxide Fuel Cell/SOFC)燃料電池系統,可免除高壓加氫站所產生的安全問題,更可與生質能做結合。

圖一  豐田與本田FCEV空間配置比較

根據EnergyTrend在現場的分析,對於兩家日系FCEV的觀察,比較豐田所發表的Mirai,以及本田所發表的Clarity兩輛乘用車,雖然在車輛動力與續航力都相當的情況下,仍可從空間配置看出差異點(圖一)。以電池堆的配置來看,豐田將燃料電池堆放置在底盤下方,鋰電池則在後座高壓氣瓶的上方,兩顆氣瓶的空間站比刻意平均化,讓行李廂空間保有傳統車輛的大容量表現;本田則是將電池堆置於引擎室,大氣瓶的體積刻意增大,除了車輛重量配置的考量外,車室空間也顯得更加寬敞。

圖二:GPTFC及其合作夥伴

關於中國方面,隨著中國政府對於燃料電池補貼目錄即將出臺,吸引更多中國廠商投入該行業發展,也因此中國在FC EXPO 2017也增加更多的參展攤位,江蘇氫電新能源/GPTFC除了展出自行開發的金屬電堆外(圖二),透過光陽機電的系統集成以及自行開發的測試設備,再加上江蘇氫聯合的充電站基礎建設,以及使用高安全性的液態儲氫的氫陽能源,成為一個從電池堆到周邊充電的完整燃料電池產業鏈。

圖三 江蘇冰城

江蘇冰城展出了自行開發的金屬電池堆(圖三),輕量化的金屬電池特性可搭在於無人機使用,使用其開發的1kW氣冷式金屬電池堆搭配上三公斤重的氣瓶,可讓無人飛機運行2~4小時的長效續航力;現場也展示了50W的輕巧型電池堆,可提供攜帶型裝置所需的長效電力,應用於戶外監控或者備用電源使用。

圖四 北京科泰克

北京科泰克/CTC展出了中國專屬的高壓氣瓶,可供應乘用車與公交車使用,都是採用三型高壓瓶,內層為鋁合金材質,外層搭配上多層的碳纖維纏繞,最外層再加上玻璃纖維,以保護外力對於碳纖維產生的結構安全影響,目前已可滿足35MPA以及70 MPA 兩種國際規格,考量車輛體積的應用靈活度,35MPA目前以公交車為主流,70MPA 則為乘用車應用。

(觀察與分析報導:EnergyTrend研究經理 呂理舜)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Tesla於台灣發表休旅款 Model X,車門採鷹翼設計

特斯拉繼 1 月時在台舉行首批 Model S 交車典禮,今天在合作商 BellaVita 場地舉行休旅車款式 Model X 在台發表大會。Model X 定價新台幣4,043,000 元,最多可乘載7 人。

Model X 依據電池容量和性能分為 4 個版本,共有 75D、90D、100D、P100D,各配備75、90、100 kWh 電池,其中 P100D 的加速性能最好,從靜止到百公里只要花3.1 秒。而在內裝上面,分為三種乘載版本:5 人座、6 人座、7 人座。

▲ 特斯拉Model X 的不同版本和座位內裝。

 

至於電動車最重要的智慧成分,除了駕駛座前的面版顯示時速、油耗等訊息,車前有3 個鏡頭,車後也有 1 個鏡頭,並且能與 Autopilot 自動輔助駕駛配合,增加更多攝影鏡頭輔助駕駛抵達目的地。

▲Model X 的車門採鷹翼門設計,車門兩側只要留下1 英尺(約30 公分)寬的空間,就能順利進入車子。

 

特斯拉的休旅車適應全球各地的狀況,像是在香港和台灣地狹人稠,Model X 採上掀式的車門設計鷹翼門,是兩段式的車門設計,先往上升,再向外展開,不用怕停車空間狹小。Model X 電動車省掉內燃機,讓房車設計上給予乘坐者更多空間,像是要上車不必彎下腰才能上車,車體高度相當高,直接可以站立走進去。

 

▲ 特斯拉全球副總裁、亞太區總裁任宇翔示範直接走進Model X 車裡。

 

特斯拉除了 Model S、Model X 等車款在台陸續運購或交車之外,充電服務網也陸續在全台各地設點。這次 Model X 發表大會選在 BellaVita,BellaVita 的停車場也有提供特斯拉車子所需要的充電站,讓來BellaVita 逛街的人要離開時,車子已經充電完了,能順利開回家。

▲Model X 內裝,可看到駕駛座的儀表板。

 

保養方面,特斯拉建議每年或是里程累積達 20,000 公里時進行年度保養,另外在訂購特斯拉車時可選擇預付3 年或4 年期的「保養計畫」。特斯拉在台北跟台中有授權的鈑噴中心,未來也會陸續認證合作商提供維修服務。原先做為保養服務據點的內湖園區,特斯拉全球副總裁、亞太區總裁任宇翔透露特斯拉在台總部也將進駐內湖。

▲5 人座的Model X。

 

另外定價較低,號稱是百萬平價車款的 Model 3 也可以在官網預購。

(合作媒體:。圖片出處:科技新報)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

從疫情中的體溫測量到分塊思想的運用

Once upon a time,COVID-19席捲全球,Chinese Government要求學校複課時必須測量學生體溫
YC中學有幾萬名同學,要找到發燒的同學進行隔離 如果要讓一位老師完成所有測溫任務,那這將是一個大工程,效率會很低(左圖)
所以將學校所有同學分成班級進行,然後匯總,效率會更高(右圖)

剛剛中我們說的:

將學校所有同學分成班級進行,然後匯總

這就是一種分塊
那問題來了,什麼是分塊呢?
其實通過剛剛的情景,你已經領悟到了分塊的本質:

將一個整體劃分為若干個小塊,進行處理

算法中,與之對應的就是:

整體 小塊
學校 班級
數組 若干元素

那麼,分塊到底是怎麼一種思想呢?
整塊維護,殘塊查找

還是以測量體溫舉例:

現在YC中學要查找體溫在36℃~37.5℃區間內的同學
怎麼做呢?
不可能又去挨個同學去統計、去數吧
那就做一張大表吧,在之前測溫的時候就把34 ~ 35℃、35 ~36℃、36 ~ 37℃、37 ~ 38℃、38 ~ 39℃……的同學分別列出來,數量分別加出來
然後36 ~ 37℃可以就直接在表裡查出人數
那37 ~ 37.5℃怎麼辦呢?
表內並沒有37 ~ 37.5℃的這樣0.5大小的區間啊
那就在37 ~ 38℃這個區間去找唄
方法可以直接暴力遍歷,也可以二分查找等等

剛剛解決的問題就是一個典型的分塊
像34 ~ 35℃、35 ~36℃、36 ~ 37℃、37 ~ 38℃、38 ~ 39℃這種列在表上給出的就是整塊
37 ~ 37.5℃這種表上沒有,包含在一個其他整塊中的但又不足一個整塊的就叫做殘塊

不難發現,其實分塊這個思想是一種暴力,一種優化的暴力,但往往也很有效
Such as 線段樹過於臃腫,代碼冗長,大材小用;而直接暴力就會TLE,不能滿足數據大小
這就很適合分塊了
那麼我們具體怎麼做呢?

我們先要求得應該分為多少個區塊嘛,然後求得每個區塊應該包含多少個元素
然後在輸入時分塊
要使情況最優,那麼區塊既不能太少也不能太多
太少,整塊的數量會太少,花費大量的時間處理殘塊
太多,區塊的長度會太短,失去整體處理區塊的意義
所以,我們取塊數為根號n
而開平方開不盡的n,我們通常在最後接一個不足整塊元素的假整塊(可以看做整塊)
這樣在最壞情況下
我們要處理接近根號n整塊,還要對長度為 2倍根號n 的殘塊最後單獨處理

	cin>>n;
	blo=sqrt(n);//sqrt()開平方函數
	for(int i=1;i<=n;i++){
		cin>>a[i];//儲存元素a[i]
		pos[i]=(i-1)/blo+1;//pos[i]為記錄元素a[i]屬於第幾個整塊
		m[pos[i]]=max(a[i],m[pos[i]]);//尋找第pos[i]個整塊的最大值存入m[pos[i]]
	}

我們先統計左右殘塊,然後再統計整塊

	cin>>q;
	int l,r;
	while(q--){
		cin>>l>>r;
		l++;
		r++;
		int ans=0;
		for(int i=l;i<=min(r, pos[l]*blo);i++){//統計左殘缺塊 
			ans=max(ans,a[i]);
		} 
		if(pos[l]!=pos[r]){//存在右殘缺塊 
			for(int i=(pos[r]-1)*blo+1;i<=r;i++){//統計右殘缺塊 
				ans=max(ans,a[i]);
			}
		} 
		for( int i=pos[l]+1;i<=pos[r]-1;i++){//統計中間整塊 
			ans=max(ans,m[i]);
		}	
		cout<<ans<<endl;
	}

分塊入門之求最大值

先看一個例題

分塊入門之求最大值
Input
第一行給出一個数字N,接下來N+1行,每行給出一個数字Ai,(1<=i<=N<=1E5)
接來給出一個数字Q(Q<=7000),代表有Q個詢問
每組詢問格式為a,b即詢問從輸入的第a個數到第b個數,其中的最大值是多少
Output
如題所述
Sample Input
10 0 1 2 3 2 3 4 3 2 1 0 5 0 10 2 4 3 7 7 9 8 8
Sample Output
4 3 4 3 2

模板題,然後剛剛已經講過了這個代碼
唯一的坑就在於接下來N+1行都是数字Ai
也就是有n+1数字Ai
也就是n需要n++

#include <bits/stdc++.h>
using namespace std;
int n;
int a[101000];
int q;
int blo;
int pos[101000];
int m[101000];
//blo為區間大小,pos[i]表示a[i]元素位於第pos[i]塊,m[i]表示區塊最大值
int main(){
	cin>>n;
	n++;
	blo=sqrt(n);
	for(int i=1;i<=n;i++){
		cin>>a[i];
		pos[i]=(i-1)/blo+1;
		m[pos[i]]=max(a[i],m[pos[i]]);
	}
	cin>>q;
	int l,r;
	while(q--){
		cin>>l>>r;
		l++;
		r++;
		int ans=0;
		for(int i=l;i<=min(r, pos[l]*blo);i++){//統計左殘缺塊 
			ans=max(ans,a[i]);
		} 
		if(pos[l]!=pos[r]){//存在右殘缺塊 
			for(int i=(pos[r]-1)*blo+1;i<=r;i++){//統計右殘缺塊 
				ans=max(ans,a[i]);
			}
		} 
		for( int i=pos[l]+1;i<=pos[r]-1;i++){//統計中間整塊 
			ans=max(ans,m[i]);
		}	
		cout<<ans<<endl;
	}
	return 0;
}

教主的魔法

[Noip模擬題]教主的魔法
Description
教主最近學會了一種神奇的魔法,能夠使人長高
於是他準備演示給XMYZ信息組每個英雄看
於是N個英雄們又一次聚集在了一起
這次他們排成了一列,被編號為1、2、……、N
每個人的身高一開始都是不超過1000的正整數
教主的魔法每次可以把閉區間[L, R](1≤L≤R≤N)內的英雄的身高全部加上一個整數W
(雖然L=R時並不符合區間的書寫規範,但我們可以認為是單獨增加第L(R)個英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪
於是他們有時候會問WD閉區間 [L,R] 內有多少英雄身高大於等於C
以驗證教主的魔法是否真的有效
WD巨懶,於是他 把這個回答的任務交給了你
Input
第1行為兩個整數N、Q。Q為問題數與教主的施法數總和
第2行有N個正整數,第i個數代表第i個英雄的身高
第3到第Q+2行每行有一個操作:
(1)若第一個字母為”M”,則緊接着有三個数字L、R、W
表示對閉區間 [L, R]內所有英雄的身高加上W
(2)若第一個字母為”A”,則緊接着有三個数字L、R、C
詢問閉區間 [L, R] 內有多少英雄的身高大於等於C
N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000
Output
對每個”A”詢問輸出一行,僅含一個整數,表示閉區間 [L, R] 內身高大於等於C的英雄數。Sample Input
5 3 1 2 3 4 5 A 1 5 4 M 3 5 1 A 1 5 4
Sample Output
2 3
【輸入輸出樣例說明】
原先5個英雄身高為1、2、3、4、5,此時[1, 5]間有2個英雄的身高大於等於4
教主施法后變為1、2、4、5、6,此時[1, 5]間有3個英雄的身高大於等於4

很多元素,進行增加、查找最大值操作

多了一個修改操作,不是很難
同理像查找這樣整塊維護,殘塊增加
我們就再增加一個數組,統一記錄每個整塊變化量是多少
記錄每個整塊的變化量,然後最後找最值的時候,單個整塊的最值加上或者減去變化量比較就可以了
殘塊的單個元素直接加上或者減去變化量,找最值

void update(int x,int y,int v){
    if(pos[x]==pos[y]){
        for(int i=x;i<=y;i++)a[i]=a[i]+v;
    }
    else{
        for(int i=x;i<=pos[x]*block;i++)a[i]=a[i]+v;
        for(int i=(pos[y]-1)*block+1;i<=y;i++)a[i]=a[i]+v;
    }
    reset(pos[x]);reset(pos[y]);
    for(int i=pos[x]+1;i<pos[y];i++)
       add[i]+=v;
}

#include<bits/stdc++.h>
using namespace std;
int n;
int q,m,block;
int a[1010000],b[1010000],pos[1010000],add[1010000];
void reset(int x){
    int l=(x-1)*block+1,r=min(x*block,n);
    for(int i=l;i<=r;i++)
        b[i]=a[i];
    sort(b+l,b+r+1);
}
int find(int x,int v){
    int l=(x-1)*block+1,r=min(x*block,n);
    int last=r;
    while(l<=r){
        int mid=(l+r)>>1;
        if(b[mid]<v)l=mid+1;
        else r=mid-1;
    }
    return last-l+1;
}
void update(int x,int y,int v){
    if(pos[x]==pos[y]){
        for(int i=x;i<=y;i++)a[i]=a[i]+v;
    }
    else{
        for(int i=x;i<=pos[x]*block;i++)a[i]=a[i]+v;
        for(int i=(pos[y]-1)*block+1;i<=y;i++)a[i]=a[i]+v;
    }
    reset(pos[x]);reset(pos[y]);
    for(int i=pos[x]+1;i<pos[y];i++)
       add[i]+=v;
}
int query(int x,int y,int v){
    int sum=0;
    if(pos[x]==pos[y]){
        for(int i=x;i<=y;i++)if(a[i]+add[pos[i]]>=v)sum++;
    }
    else {
        for(int i=x;i<=pos[x]*block;i++)
            if(a[i]+add[pos[i]]>=v)sum++;
        for(int i=(pos[y]-1)*block+1;i<=y;i++)
            if(a[i]+add[pos[i]]>=v)sum++;
    }
    for(int i=pos[x]+1;i<pos[y];i++)
        sum+=find(i,v-add[i]);
    return sum;
}
int main(){
    cin>>n>>q;
    block=int(sqrt(n));
    for(int i=1;i<=n;i++){
        cin>>a[i];
        pos[i]=(i-1)/block+1;
        b[i]=a[i];
    }
    if(n%block)m=n/block+1;
    else m=n/block;
    for(int i=1;i<=m;i++)reset(i);
    for(int i=1;i<=q;i++){
        char ch[5];int x,y,v;
        cin>>ch>>x>>y>>v;
        if(ch[0]=='M'){
        	update(x,y,v);
		}else{
			cout<<query(x,y,v)<<endl;
		}
    }
    return 0;
}

END

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

C/S C# WPF銳浪報表教程

前言:銳浪報表是一種中國式報表的報表開發工具。博主使用銳浪報表有一段時間了,積累了一些經驗希望能幫助你快速掌握並使用

第一章:集成項目

首先我們先去銳浪報表官網下載並安裝銳浪報表。

創建WPF應用程序。(C/S端使用銳浪報表基本都一樣

 添加銳浪報表的引用,在資源管理器目錄中找到引用並右鍵,點擊添加引用。

 在引用管理器左側目錄中展開COM並找到Grid++Report Engine 6 Type Library,勾選上點擊確定。(這裡有四個銳浪報表的引用,不要加錯了)

 在資源管理器中展開引用找到gregn6Lib

 右鍵gregn6Lib點擊屬性,將獨立設置為True,將嵌入式互操作類型設置為True

在資源管理器中右鍵WPFPrintReportRL項目——添加——新建文件夾,命名為report

 集成銳浪報表的WPF項目環境基本配置差不多了,下面我們打開安裝完畢銳浪報表的編輯器

 在上方導航目錄中找到插入——報表頭,就會生成這個UI編輯面板

如果我們需要打印一些參數,則在左上方的目錄中找到參數集合——新增——參數

 將這個參數命名,我使用的是Name,這個參數的命名就是後面程序需要在在報表中傳遞的參數

 在上方導航欄中找到插入——綜合文本框,將鼠標在UI編輯面板左鍵點擊一下生成綜合文本框,然後我們雙擊綜合文本框編輯內容。

點擊插入域引用類型選擇為參數參數選擇為剛才命名為Name的參數,點擊確定

 做完以上操作后的UI編輯面板,隨後我們另存到使用VS創建的WPFPrintReportRL項目下的report目錄中

切回VS,在資源管理器中上方找到並點擊显示所有文件,然後資源管理起中report文件夾下會显示出你剛保存的報表文件右鍵——包括在項目中

 對報表文件右鍵——屬性,將複製到輸出目錄更改為:如果較新則複製

主窗體的後台代碼,已經加入註釋,各位慢慢品味。

            GridppReport gr = new GridppReport();//報表對象
            //建議不要在報表中存儲連接字符串字符串
            //如果不設置ConnectionString或QuerySQL屬性,則會使用報表內的連接字符串和SQL語句
            gr.ConnectionString = "";//連接字符串
            gr.QuerySQL = "";//SQL語句
            gr.LoadFromFile("report\\案例報表.grf");//本地報表路徑
            gr.ParameterByName("Name").AsString = "古河渚";//主報表傳參
            gr.Print(false);//不預覽打印

接下來我們在資源管理器中右鍵WPFPrintReportRL項目——屬性——生成,將目標平台更改為x86

 隨後我們運行項目,報表如期而至打印了出來。(這裏博主使用的是虛擬打印機,點我下載,將打印機設置里默認打印機設置為 pdfFactory Pro

銳浪報表安裝后目錄中已提供案例與文檔,博主Demo項目已上傳交流群,點擊最上方標題即可交流群學習。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

docker鏡像瘦身思路

docker鏡像瘦身思路

一、簡介

      docker鏡像太大,帶來了以下幾個問題:

  • 存儲開銷

      這塊影響其實不算很大,因為對服務器磁盤來說,15GB的存儲空間並不算大,除非用戶服務器的磁盤空間很緊張

  • 部署時間

      這塊影響真的很大,交付件zip包太大,導致用戶部署該產品時,花費的時間變長,客戶現場中反饋部署時間超過1.5小時,這嚴重影響用戶的體驗,降低滿意度

  • 性能不穩定

      如果客戶的服務器規格不夠(特別是磁盤讀寫性能不夠),會增大部署失敗的概率。

二、瘦身思路

       以下思路是我在該任務中嘗試使用用於鏡像瘦身的方法,均可以不同程度的降低DOcker鏡像的尺寸。

  • 清理Docker鏡像中的無用安裝包

      在Dockerfile構建Docker鏡像過程中,有可能引入臨時文件,比如:安裝包i、文件壓縮包。這些臨時文件忘記清理,導致佔據了一定的尺寸,有必要對其進行清理。

        如下Dockerfile:   

FROM xxxx/xxxx-jdk:1.0.0RUN apt-get update && apt-get install -y git maven 
mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip  

Dockerfile裏面經常安裝很多工具,安裝完后,需要及時刪除安裝包緩存

(alpine) apk del openssh vim:刪除包及其依賴包

(Ubuntu) Apt-get clean:刪除所有已下載的包文件

(centos) Yum clean all: yum 會把下載的軟件包和header存儲在cache中,而不自動刪除。如果覺得佔用磁盤空間,可以使用yum clean指令進行清除,更精確 的用法是yum clean headers清除header,yum clean packages清除下載的rpm包,yum clean all一全部清除

      上面的dockerfile中在安裝工具后應該執行下: && apt-get clean && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y git maven 
    mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip && apt-get clean && rm -rf /var/lib/apt/lists/*

 

   實例:

      

FROM centos:7
RUN yum update -y RUN yum install -y wget unzip socat java-1.8.0-openjdk-headless
# Set permissions
RUN yum clean all
EXPOSE 8486

 

   修改:將黃色標示的部分改寫成如下,大小從691Mb下降到583Mb

RUN yum update -y  && yum install -y wget unzip socat java-1.8.0-openjdk-headless && yum clean all
  • 避免不必要的工具安裝

     有的Dockerfile中安裝了很多工具,這個工具的加在一起尺寸比較大,這塊需要挨個排查:客戶環境下,需不需要安裝該工具?很多工具其實是面向開發使用的,而用戶根本不會使用,那麼就沒有必要在客戶環境上使用安裝這麼工具的鏡像,應該仔細排除工具的必要性,會給鏡像瘦身帶來比較大的收益。比如, dockerfile中安裝了JDK。 這個有些情況下,完全沒必要,實際上可能jre就能搞定。

     總之,能不安裝,就不安裝;能少安裝,就少安裝;能用輕量級的工具,盡量用輕量級的工具!!!

  • 多階段構建

      Docker多階段構建是17.05以後引入的新特性,旨在解決編譯、構建複雜和鏡像大小的問題。對於多階段構建,可以在Dockerfile中使用多個FROM語句。每個FROM指令可以使用不同的基礎,並且每個指令都開始一個新的構建。您可以選擇性地將工件從一個階段複製到另一個階段,從而在最終image中只留下您想要的內容。

      如下圖所示為多階段構建的使用示例:

把多個Dockerfile合併在一塊,每個Dockerfile單獨作為一個“階段”,“階段”之間可以互相聯繫,讓后一個階段構建可以使用前一個階段構建的產物,形成一條構建階段的chain,最終結果僅產生一個image,避免產生冗餘的多個臨時images或臨時容器對象。

       1)多階段構建使用之前

      針對多階段構建的特點,分析我們產品裏面的dockerfile,如下面所示,該操作的目的是將tar包拷貝值容器內的路徑下,並解壓、執行後續操作。然而COPY層具有一定的大小,只起到臨時層的作用。(特別是這個tar包足足幾百MB!)。

 

FROM xxxx:${project.version}COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
RUN mkdir /opt/opendaylight \
      && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight \&& rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz \ 
      && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current && mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
EXPOSE 8181   

     2)  使用多階段構建

       使用多階段構建,修改后的dockerfile如下圖所示,修改實現將第一階段拷貝並解壓好的文件複製過來即可,少了拷貝tar包的環節,這樣使得最終形成的鏡像中鏡像層數得到有效的降低,也一定程度上降低了鏡像尺寸。

FROM xxxx:${project.version} as baseFirst
COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
RUN mkdir /opt/opendaylight \
      && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight \&& rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz \ 
      && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current 

FROM xxxxxe:${project.version} as baseSecondRUN mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
COPY --from=baseFirst /opt/opendaylight/current  /opt/opendaylight/current
RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
EXPOSE 8181
  • Copy和賦權同時執行
FROM ubuntu:16.04
# Copy APIKeys
COPY ./messageservice/ /tmp/zookeeper/gerrit  ------A 
EXPOSE 2181 2888 3888
B------> RUN useradd $ZK_USER && [ `id -u $ZK_USER` -eq 1000 ] && [ `id -g $ZK_USER` -eq 1000 ] && chown -R $ZK_USER:$ZK_USER /opt/$ZK_DIST/ /opt/zookeeper/ /var/lib/ /var/log/ /tmp/zookeeper/    
USER $ZK_USER

      問題排查如下:A處copy的文件700MB太大,很多文件沒用到

                               B處給/tmp/zookeeper添加屬組和屬主,該層也很大

       修改:使用 COPY –chown=1000:1000   ./messageservice/ /tmp/zookeeper/gerrit, 鏡像大小從1.4GB 下降到700Mb

  • 鏡像層的復用

      這一塊修改得當的話,得到的收益是最大的!!!最大的!!!最大的!!!

      我們知道docker鏡像具有層級結構,如果很多鏡像具有相同的層,則這些相同的層就能得到復用(把多個鏡像生成一個tar),docker不會保存兩份相同放入層文件,通過提高層得復用能顯著降低整體的鏡像尺寸。比如常見方法有:替換統一的基礎鏡像、創建出統一的基礎鏡像、調整層的順序等等。這裏東西沒有整理,就不上圖了,可以自行腦補,查閱資料即可

我這邊經過這一步調整后,zip產品包從11.45GB下降到6.96GB

 

最終zip包從15GB下降到7GB

    

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

【SEED Labs】DNS Rebinding Attack Lab

Lab Overview

實驗環境下載:https://seedsecuritylabs.org/Labs_16.04/Networking/DNS_Rebinding/

在這個實驗中模擬的物聯網設備是一個恆溫器,用於控制室內溫度。要成功設置溫度,客戶端需要能夠與物聯網服務器交互。由於物聯網設備在防火牆後面,外部機器不能與物聯網設備交互,因此不能控制恆溫器。為了擊敗防火牆保護,攻擊代碼必須首先進入內部網絡。這並不難,當來自內部網絡的用戶訪問攻擊者的網站時,攻擊者的代碼(JavaScript代碼)實際上是從用戶的瀏覽器中運行的,因此在受保護的內部網絡中運行。然而,由於瀏覽器實現的沙箱保護,攻擊者的代碼仍然不能與物聯網設備交互,即使它現在在內部網絡中。

這個實驗的目標是使用DNS重綁定攻擊來繞過沙箱保護,這樣攻擊者的javascript代碼就可以成功地從設備獲得必要的信息,並使用這些信息來獲得溫度測量的一個非常高的值。

本實驗涵蓋以下主題:

• DNS server setup

• DNS rebinding attack

• Attacks on IoT devices

• Same Origin Policy

我們的攻擊目標是防火牆後面的一個物聯網設備。我們不能從外部直接訪問這個物聯網設備。我們的目標是讓內部用戶運行我們的JavaScript代碼,這樣我們就可以使用DNS重新綁定攻擊與物聯網設備交互。

許多物聯網設備都有一個簡單的內置web服務器,因此用戶可以通過web api與這些設備交互。通常,這些物聯網設備由防火牆保護,它們不能從外部直接訪問。由於這種類型的保護,許多物聯網設備沒有實現強大的身份驗證機制。如果攻擊者能夠找到與它們交互的方法,就很容易危及其安全性。

我們使用一個簡單的webserver來模擬這種易受攻擊的物聯網設備,該服務器提供兩個api:密碼和溫度。物聯網設備可以設置室溫。為此,我們需要向服務器的溫度API發送一個HTTP請求;請求應該包括兩部分數據:目標溫度值和密碼。密碼是定期更改的秘密,但可以使用密碼API獲取。因此,要成功設置溫度,用戶首先需要獲得密碼,然後將密碼附加到溫度API中。密碼不是用於身份驗證的;它用於抵抗跨站請求偽造(CSRF)攻擊。沒有這種保護,一個簡單的CSRF攻擊就足夠了;沒有必要使用更複雜的DNS重新綁定攻擊。為了簡單起見,我們硬編碼了密碼;在實際系統中,密碼將定期重新生成。

LabEnvironment

在這個實驗室中,我們將使用三台機器,分別稱為用戶VM、本地DNS服務器和攻擊者VM。為了簡單起見,我們使用VirtualBox中的NAT網絡適配器將這些虛擬機放在同一個網絡上。在現實世界中,它們不在同一個網絡上。我們還假設運行在用戶VM上的設備在防火牆後面,因此攻擊者VM不能直接訪問物聯網設備。這個實驗室的設置相當複雜,因為我們需要配置三個VM並在它們上運行多個服務器,包括一個IoT web服務器(在用戶VM上)、一個web服務器和一個DNS服務器(在攻擊者VM上)以及一個DNS服務器(在本地DNS服務器上)

LabTasks

Task1: Configure the User VM 

Step1. 減少Firefox的DNS緩存時間。為了減少DNS服務器的負載並加快響應時間,Firefox瀏覽器緩存DNS結果。默認情況下,緩存的過期時間為60秒。這意味着我們的DNS重新綁定攻擊需要等待至少60秒。為了讓我們的實驗更輕鬆,我們把時間減少到10秒或更少。在URL字段中輸入about:config。單擊警告頁面后,我們將看到首選項名稱及其值的列表。搜索dnsCache,找到以下條目並將其值更改為10:

更改后,應該退出Firefox瀏覽器,並重新啟動;否則,更改將不會生效。

Step 2. 改變/etc/hosts.我們需要將以下條目添加到/etc/hosts文件中。我們將使用www.seedIoT32.com作為物聯網web服務器的名稱。此服務器可以運行在不同的VM上,但為了簡單起見,我們在用戶VM上運行物聯網服務器(其IP地址為192.168.43.175):

 Step3.  Local DNS Server 。我們需要配置用戶VM以使用特定的本地DNS服務器。這是通過將本地DNS服務器設置為解析器配置文件(/etc/resolv.conf)中的第一個名稱服務器條目來實現的。一個挑戰是所提供的VM使用動態主機配置協議(DHCP)來獲取網絡配置參數,如IP地址、本地DNS服務器等。DHCP客戶機將用DHCP服務器提供的信息覆蓋/etc/resolv.conf文件。

要將信息導入/etc/resolv.conf而不用擔心DHCP,一種方法是將以下條目添加到/etc/resolvconf/resolv.conf.d/head文件(192.168.43.78為本地DNS服務器的IP地址):

 頭文件的內容將預先寫入動態生成的解析器配置文件。通常,這隻是一個註釋行(/etc/resolv.conf中的註釋來自這個頭文件)。在進行更改之後,我們需要運行以下命令使更改生效:

Step 4. Testing 。配置用戶VM之後,使用dig命令從您選擇的主機名獲取IP地址。從這個響應中,請提供證據證明這個響應確實來自你們的服務器。如果找不到證據,說明配置不成功。

 Task2: Start the IoT server on the User VM 

在此任務中,我們將在用戶VM上啟動物聯網服務器。通過web服務器,用戶可以與物聯網設備通信。

Step 1. 安裝 Flask. 我們使用Flask web框架來開發物聯網服務器     sudo pip3 install Flask==1.1.1

 Step 2. Start the IoT server. 物聯網服務器代碼包含在user_vm.zip,可以從實驗室的網站上下載。解壓縮文件后,進入user_vmf文件夾,通過運行準備好的腳本start IoT .sh或直接運行“flask run”啟動物聯網服務器。需要注意的是,我們使用端口8080作為物聯網服務器(該端口號在實驗室設置中是硬編碼的;將其更改為不同的数字將破壞實驗室設置)。

 Step 3. Testing the IoT server 。要測試物聯網服務器,請將瀏覽器指向用戶VM上的以下URL。如果一切都設置正確,我們應該能夠看到一個恆溫器。我們也可以通過拖動滑動條來改變溫度設置。

 Task3: Start the attack web server on the Attacker VM 

在本實驗室中,只能從防火牆后訪問物聯網設備,即,僅來自實驗設置中的用戶VM。將惡意代碼發送到用戶虛擬機上的一種典型方式是讓用戶訪問我們的網站,這樣放置在web頁面上的JavaScript代碼就可以進入用戶虛擬機上。在這個任務中,我們將啟動一個web服務器來託管這些web頁面。

Step 1. 安裝 Flask。 我們的惡意web服務器也是基於Flask web框架開發的。

Step 2. Start the attacker’s web server 。攻擊者的服務器代碼包含在attacker_vm.zip,可以從實驗室的網站上下載。解壓縮文件后,進入attacker_vm文件夾,通過運行準備好的腳本start_webserver.sh或直接運行“flask run”來啟動web服務器。

 Step3. Testing the Attacker’s web server. 

Task4: Configure the DNS server on the Attacker VM 

攻擊者VM也充當了attacker32.com域名的命名服務器。BIND9服務器已經在攻擊者VM上運行,我們需要為它準備一個區域文件。一個示例區域文件包含在attackr_vm文件夾中。我們應該相應地更改區域文件,並將其複製到/etc/bind文件夾中。

將以下區域條目添加到/etc/bind/name .因此上面的區域文件將由BIND9服務器使用。

 如果一切都設置正確,我們可以嘗試以下dig命令,看看我們得到的響應是否與我們放在區域文件中的響應相同

Task5: Configure the Local DNS Server

在本地DNSserver上,我們設置attacker32.com域的轉發記錄,因此每當本地 DNS 服務器收到此域內主機的 DNS 查詢時,它只需將 DNS 查詢發送到指定轉發記錄的 IPaddress,而不是前往 root server 和the .com server,以找出attacker32.com域的名稱服務器的位置。

要將此類記錄添加到本地 DNS 服務器,我們需要將以下行添加到 /etc/bind/named.conf

 

 

 

在用戶機上測試,dig成功:

Task6. Understanding the Same-Origin Policy Protection

同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能。瀏覽器的同源策略,限制了來自不同源的“document”或腳本,對當前“document”讀取或設置某些屬性。影響“源”的因素有:host(域名或IP地址,如果是IP地址則看做是一個根域名)、子域名、端口、協議。在瀏覽器中,<script>、<img>、<iframe>、<link>等標籤都可以跨域加載資源,而不受同源策略的限制,但是瀏覽器限制了JavaScript的權限,使其不能讀、寫返回的內容。

attacker_vm的change界面

單擊click之後,user_vm的溫度並不會改變

 user_vm的change界面

單擊click之後,user_vm的溫度變為99℃

Task7. Defeat the Same-Origin Policy Protection 

擊敗同源的主要想法保護來自這樣一個事實:策略執行基於主機名,而不是IP地址,所以只要我們使用www.attacker32.com的URL,我們遵守SOP的政策,但這並不意味着我們是限制與www.attacker32.com web服務器進行通信。

在用戶的瀏覽器向www.attacker32.com發送請求之前,它首先需要知道www.attacker32.com的IP地址。一個DNS請求將從用戶的機器發出。如果IP地址沒有緩存在本地DNS服務器上,一個DNS請求最終會被發送到attacker32.com的nameserver,它運行在攻擊者的VM上。因此,攻擊者可以決定在響應中放入什麼。

Step 1: Modify the JavaScript code. 在攻擊者虛擬機中,在www.attacker32.com:8080/change中運行的JavaScript代碼存儲在以下文件中:attacker_vm/rebind_malware/templates/js/change.js。由於該頁面來自www.attacker32.com服務器,根據同源策略,只能與同一服務器交互。因此,我們需要將代碼的第一行從http://www.seediot32.com:8080更改為以下內容:

 Step2: Conduct the DNS rebinding 。我們的JavaScript代碼發送請求到www.attacker32.com,請求將返回到攻擊者VM。這不是我們想要的,我們希望將請求發送到iot服務器。這可以通過DNS重新綁定技術實現。我們首先映射 www. attacker32.com 為攻擊者VM的IP地址,這樣用戶可以從http: //www.attacker32.com/change獲得實際頁面。在我們點擊網頁上的按鈕之前,我們重新映射www.attacker32.com主機名到iot服務器的IP地址,按鈕觸發的請求將到達iot服務器。這正是我們想要的。

修改好相應文件進行刷新:

同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源。所以xyz.com下的js腳本採用ajax讀取abc.com裏面的文件數據是會被拒絕的。同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。不受同源策略限制的1. 頁面中的鏈接,重定向以及表單提交是不會受到同源策略限制的。2. 跨域資源的引入是可以的。但是js不能讀寫加載的內容。如嵌入到頁面中的<script src=”…”></script>,<img>,<link>,<iframe>等

Task8. Launch the Attack 

使用用戶機訪問下列url:

 

 

每當10秒倒計時為0,溫度將會被設定為88度:

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

Asp.Net Core入門之靜態文件

靜態文件(css,js,html等類型文件)通常位於 web根目錄下,而ASP.Net Core框架默認內容根目錄下的wwwroot文件夾為web根目錄。這裏簡單解釋下內容根目錄:實際就是指包含可執行程序exe,程序集dll,配置文件json,xml等的文件目錄.

1.訪問web根目錄靜態文件

正常情況下,靜態文件是無法直接訪問的,需要我們添加如下靜態文件的中間件,這是框架內置自帶的。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseStaticFiles(); 
}

然後我們就可通過web根目錄的相關路徑訪問靜態文件。例如,Web 應用程序項目模板包含 wwwroot 文件夾中的多個文件夾 :

  • wwwroot
    • css
    • images
    • js

然後就可以通過如下格式的URL:https://localhost:5001/images/123.jpg 來訪問靜態文件。

2.訪問web根目錄之外的靜態文件

有些時候,可能有些靜態文件我們並不是放在web根目錄下面的。例如如下一個目錄層次結構,其中要提供的靜態文件位於 Web 根目錄之外:

  • wwwroot
    • css
    • images
    • js
  • Content
    • images
      • img.jpg

如果通過URL:https://localhost:5001/Content/images/img.jpg是無法訪問的,這個時候我們就需要額外的指定靜態文件路徑:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
           //wwroot目錄下靜態文件
 app.UseStaticFiles(); //wwwroot之外的靜態文件 app.UseStaticFiles(new StaticFileOptions { //指定實際物理路徑 FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"Content/images")), //設置URL請求的文件路徑 RequestPath = new Microsoft.AspNetCore.Http.PathString("/MyStaticFiles") }); }

然後就可以通過如下格式的URL:https://localhost:5001/MyStaticFiles/img.jpg 來訪問靜態文件。

3.提供默認文件

UseDefaultFiles中間件用於啟用默認文件的功能,例如我們打開一個網站只輸入網站地址,就會自動跳出網站首頁。這裏的網站首頁實際就相當於一個默認文件。

ASP.Net Core為我們簡化了默認文件的搜索功能,我們只需要添加中間件即可。

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

要提供默認文件,必須在 UseStaticFiles 前調用 UseDefaultFiles。 UseDefaultFiles 實際上用於重寫 URL,不提供文件。 通過 UseStaticFiles 啟用靜態文件中間件來提供文件。

 UseDefaultFiles 默認支持以下幾種類型文件:

  • default.htm
  • default.html
  • index.htm
  • index.html

當然,框架也支持自定義默認文件,感興趣的同學可以研究一下。

例如如下一個目錄層次結構:

  • wwwroot
    • Index.html
    • css
    • images
    • js
  • 通過URL:https://localhost:5001/訪問時,會自動跳轉到並打開Index.html頁面

4.啟用目錄瀏覽功能

出於安全考慮,目錄瀏覽默認處於禁用狀態,需通過添加UseDirectoryBrowser中間件的方式開啟。

public void Configure(IApplicationBuilder app)
{
    //默認文件
 app.UseDefaultFiles(); //靜態文件  app.UseStaticFiles(); //目錄瀏覽  app.UseDirectoryBrowser(); }

另外,需要註冊目錄瀏覽的服務

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

例如如下一個目錄層次結構:

   wwwroot

  • 123.jpg
  • 234.jpg

通過URL:https://localhost:5001/訪問時,由於wwwroot根目錄下不存在默認文件,所以會打開文件目錄。

 

 5.UseFileServer

UseFileServer 結合了 UseStaticFilesUseDefaultFiles 和 UseDirectoryBrowser(可選)的功能。

例如以下目錄層次結構:

  • wwwroot
    • 123.jpg
    • 234.jpg
  • Content
    • images
      • 234.jpg

以下代碼啟用靜態文件、默認文件和及 MyStaticFiles 的目錄瀏覽:

public void Configure(IApplicationBuilder app)
{
//靜態文件 app.UseStaticFiles(); app.UseFileServer(new FileServerOptions { FileProvider = new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), "Content")), RequestPath = "/MyStaticFiles",
//啟用目錄 EnableDirectoryBrowsing = true }); }

EnableDirectoryBrowsing 屬性值為 true 時必須註冊服務 AddDirectoryBrowser

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

 

通過URL:https://localhost:5001/MyStaticFiles/訪問時,由於目錄下不存在默認文件,所以會打開文件目錄。

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

004.OpenShift命令及故障排查

一 CLI訪問OpenShift資源

1.1 資源操作


OCP將OpenShift集群中的為由主節點管理的對象統稱為資源,如:node、service、pod、project、deployment、user。

即使針對的是不同的資源,OpenShift命令行工具也提供了一種統一的、一致的方法來更新、修改、刪除和查詢這些資源。

oc命令行工具提供了在軟件開發項目的整個交付生命周期中修改和管理資源的常見操作。

1.2 安裝oc工具


在OpenShift安裝過程中,oc命令行工具安裝在所有master和node節點上,還可以在不屬於OpenShift集群的機器。

安裝后,可以使用用戶名和密碼對任何主節點通過身份驗證后執行相關命令。

根據使用的平台,安裝oc命令行工具有以下幾種方式:

yum安裝:在RHEL平台上,可通過以下命令安裝oc客戶端命令。

[user@host ~]$ sudo yum install atomic-openshift-clients

其它 Linux 發行版本和操作系統,需在擁有 OpenShift 訂閱后,在 Red Hat Customer Portal 中下載。

提示:oc安裝完成后自動補全需要退出一次才可生效,或者source /etc/bash_completion.d/oc。

1.3 oc主要查詢命令


[student@workstation ~]$ oc –help #显示幫助信息

[student@workstation ~]$ oc login -u developer -p redhat https://master.lab.example.com #登錄到OpenShift集群

提示:從client成功通過身份驗證之後,OpenShift將授權令牌保存在用戶的主文件夾中。此令牌用於後續請求,從而無需重新輸入憑據或完整的主URL。

  1 [root@master ~]# oc whoami
  2 system:admin					#master的root用戶為集群的最高權限的用戶
  3 [student@workstation ~]$ oc whoami		        #查看當前用戶
  4 developer
  5 [student@workstation ~]$ oc new-project working	#創建project
  6 [student@workstation ~]$ oc status		        #查看項目狀態
  7 In project working on server https://master.lab.example.com:443
  8 You have no services, deployment configs, or build configs.
  9 Run 'oc new-app' to create an application.
 10 [student@workstation ~]$ oc delete project working	#刪除project
 11 [student@workstation ~]$ oc logout		        #退出該集群。
 12 [student@workstation ~]$ oc get pods		#查看pod
 13 NAME                      READY     STATUS    RESTARTS   AGE
 14 hello-openshift-1-6ls8z   1/1       Running   0          4h
 15 [student@workstation ~]$ oc get all		        #查看所有主要組件信息
 16 [student@workstation ~]$ oc get pods -w		#-w表示以監視模式運行


1.4 oc 其他命令


oc describe:如果oc get提供的摘要不夠,可以使用oc describe命令檢索關於資源的更詳細信息。

[student@workstation ~]$ oc describe pod hello-openshift-1-6ls8z

oc export:使用oc export命令導出資源的定義。典型的用例包括創建備份,或者用於修改定義。默認情況下,export命令以YAML格式輸出對象表示,但是可以通過提供-o選項來更改。

oc create:使用oc create命令從資源定義創建資源。通常,這與用於編輯定義的oc export命令相匹配。

oc delete RESOURCE_TYPE name:使用oc delete命令從OpenShift集群中刪除資源。

注意:部分資源直接刪除後會重新創建,如基於rc的pod,需要對OpenShift體系資源展示形式有一個基本的了解。

oc exec:使用oc exec命令在容器中執行命令,可以使用此命令作為腳本的一部分運行交互式和非交互式批處理命令。

oc rsh POD:oc rsh pod命令打開到容器的遠程shell會話,要遠程登錄到容器shell並執行命令,請運行以下命令。

[student@workstation ~]$ oc rsh <pod>

注意:oc rsh需要pod中存在相應的shell,如bash。

二 OpenShift資源類型

2.1 常見資源


OpenShift容器平台中的應用程序由不同類型的資源組成,主要常見的類型有:

  • Container:如何在可移植Linux環境中運行一個或多個進程的定義。容器從一個映像啟動,並且通常與同一機器上的其他容器隔離。
  • Image:一個分層的Linux文件系統,包含應用程序代碼、依賴關係和函數庫等。image由一個名稱標識,該名稱可以是當前集群的本地名稱,也可以指向遠程Docker倉庫。
  • Pod:部署在節點上並共享唯一IP地址和卷(持久存儲)的一個或多個容器,Pods還為每個容器定義安全性和運行時策略。
  • Label:標籤是鍵值對,可以分配給系統中的任何資源進行分組和選擇。通常資源使用標籤來標識其他資源集。
  • Volume:默認情況下容器不是持久性的,即容器的內容在重新啟動時被清除。volume是掛載在pod及其容器上的文件系統,它們可能由許多本地或網絡的存儲提供。最簡單的卷類型是EmptyDir,它是一台機器上的臨時目錄。
  • Node:node是集群中用來運行容器的節點,node通常由管理員管理,而不是由最終用戶管理。
  • Service:service是表示一組pod的邏輯名稱,service被分配一個IP地址和一個DNS名稱,可以通過端口或route向集群外部公開。名為SERVICE_HOST的環境變量會自動注入到其他pod中。
  • Route:route是一個DNS條目,創建它是為了指向一個service,以便可以從集群外部訪問它。可以配置一個或多個路由器來處理這些route,通常通過HAProxy負載均衡器。
  • Replication Controller:Replication Controller基於匹配一組label的Templates維護特定數量的pod。如果刪除了pod,控制器將創建該pod的新副本。Replication Controller最常用來表示基於image的應用程序部分的單個部署。
  • Deployment Configuration:deployment configuration定義pod的模板,並在屬性更改時管理部署新映像或配置更改。單個deployment configuration通常類似於單個微服務。deployment configuration可以支持許多不同的部署模式,包括完全重啟、可定製的滾動更新以及生命周期前後的順序。每個deployment都表示為一個replication controller。
  • Build Configuration:build configuration包含如何將源代碼和基本image構建為新image的描述。Build可以是基於源代碼的,可以為常見語言(如Java、PHP、Ruby或Python)或基於docker的(從Dockerfile創建構建)使用構建器映像。每個build configuration都有webhook,可以通過對其基本映像的更改自動觸發。
  • Build:構建從源代碼、其他圖像、Dockerfiles或二進制輸入創建新image。Build在容器中運行,具有與普通pod相同的限制。Build通常會導致將image推入Docker倉庫中,但也可以選擇運行post-build測試而不push到image倉庫。
  • Image Streams and Image Stream Tags:IS使用標記名稱對相關is進行分組。它類似於源代碼倉庫中的分支。每個is可以有一個或多個標記(默認標記稱為“latest”),這些標記可能指向外部Docker倉庫、同一is中的其他標記,或者被控製為直接指向已知image。此外,可以通過集成的Docker倉庫直接將image push到docker倉庫。
  • Secret:secret資源可以保存文本或二進制secrets,以便注入至pod。默認情況下,在/var/run/secrets/kubernetes.io/serviceaccount上,每個容器都有一個secret,其中包含訪問API有限特權的令牌。可以創建新的secret並將它們掛載到自己的pod中,也可以引用構建中的secret(用於連接遠程服務器),或者使用它們將遠程image導入到is中。
  • Project:所有上述資源(node除外)都存在於項目中。項目具有成員列表及其role(如view、edit或admin),以及運行的pod上的一組安全控制,並限制項目可以使用多少資源,資源名稱在項目中是惟一的。


使用oc types命令快速查看可用的概念和類型。

2.2 創建應用


簡單的應用程序、複雜的多層應用程序和微服務應用程序都可以使用資源定義文件來描述。

這個文件包含許多pod定義、連接這些pod的服務定義、用於水平伸縮應用程序pod的rc或dc、用於持久存儲應用程序數據的持久卷,以及OpenShift可以管理的任何其他需要的內容。

oc new-app命令可以使用-o json或-o yaml選項分別創建以json或yaml格式的定義文件的資源。可以使用oc create -f <filename>命令調用定義文件,並將其用於創建應用程序,或者與其他資源定義文件合併以創建複合應用程序。

oc new-app命令可以以許多不同的方式創建在OpenShift上運行的pod應用程序。它可以使用source-to-image (S2I)流程從現有docker映像、Dockerfiles或原始源代碼創建pod。

運行oc new-app -h命令,了解在OpenShift上創建新應用程序的所有不同選項。最常見的選項如下:

運行以下命令創建應用程序。OpenShift根據Docker配置文件的ADD_REGISTRY選項定義的倉庫 pull image。

$ oc new-app mysql MYSQL_USER=user MYSQL_PASSWORD=pass MYSQL_DATABASE=testdb -l

db=mysql

根據私有倉庫中的image創建應用程序。

$ oc new-app –docker-image=myregistry.com/mycompany/myapp –name=myapp

根據存儲在Git庫中的源代碼創建應用程序。

$ oc new-app https://github.com/openshift/ruby-hello-world –name=ruby-hello

創建基於存儲在Git庫中的源代碼並引用IS的應用程序。

$ oc new-app https://mygitrepo/php-hello -i php:7.0 –name=php-hello

從Docker配置文件的ADD_REGISTRY指令定義的可用倉庫之一創建一個基於mysql映像的應用程序。l db=mysql選項定義了一個值為mysql的db標籤。

$ oc new-app mysql MYSQL_USER=user \

MYSQL_PASSWORD=pass \

MYSQL_DATABASE=testdb \

-l db=mysql

下圖显示了oc new-app命令在參數為容器image時創建的Kubernetes和OpenShift資源。該命令創建dc、is和svc,可以通過端口或route從外部訪問。



提示:通過使用帶有源代碼的oc new-app,將創建一個build configuration,而bc又從源代碼創建一個新的應用程序。但是,如果命令中沒有使用源代碼,則不會創建gc。該命令始終為應用程序創建dc和svc。

三 oc使用練習

3.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

3.2 本練習準備


[student@workstation ~]$ lab manage-oc setup

3.3 驗證OpenShift

  1 [student@workstation ~]$ oc login -u admin -p redhat https://master.lab.example.com
  2 [student@workstation ~]$ oc project default
  3 Already on project "default" on server "https://master.lab.example.com:443".
  4 [student@workstation ~]$ oc project default
  5 Already on project "default" on server "https://master.lab.example.com:443".
  6 [student@workstation ~]$ oc get nodes
  7 NAME                     STATUS    ROLES     AGE       VERSION
  8 master.lab.example.com   Ready     master    23h       v1.9.1+a0ce1bc657
  9 node1.lab.example.com    Ready     compute   23h       v1.9.1+a0ce1bc657
 10 node2.lab.example.com    Ready     compute   23h       v1.9.1+a0ce1bc657
 11 [student@workstation ~]$ oc describe node master.lab.example.com		#查看master節點詳情
 12 [student@workstation ~]$ oc describe node node1.lab.example.com
 13 [student@workstation ~]$ oc describe node node2.lab.example.com
 14 [student@workstation ~]$ oc get pods -o wide
 15 NAME                       READY     STATUS    RESTARTS   AGE       IP              NODE
 16 docker-registry-1-8v7sh    1/1       Running   4          23h       10.129.0.30     node2.lab.example.com
 17 docker-registry-1-rrmhm    1/1       Running   2          23h       10.128.0.12     node1.lab.example.com
 18 registry-console-1-xzxxp   1/1       Running   4          23h       10.129.0.31     node2.lab.example.com
 19 router-1-fwttd             1/1       Running   4          23h       172.25.250.12   node2.lab.example.com
 20 router-1-xdw84             1/1       Running   2          23h       172.25.250.11   node1.lab.example.com
 21 [student@workstation ~]$ oc  describe pod docker-registry-1-8v7sh		#查看pod詳情


3.4 pod操作


[student@workstation ~]$ oc exec docker-registry-1-8v7sh hostname #執行pod中命令

docker-registry-1-8v7sh

[student@workstation ~]$ oc exec router-1-fwttd ls /

[student@workstation ~]$ oc exec docker-registry-1-8v7sh cat /etc/resolv.conf

提示:只要pod中存在的命令,都可以通過oc exec直接執行。

[student@workstation ~]$ oc rsh docker-registry-1-8v7sh #進入pod的shell

sh-4.2$ ls /

3.5 oc其他操作


[student@workstation ~]$ oc status -v #現實詳細的狀態



[student@workstation ~]$ oc get events #查看集群生命周期事件

[student@workstation ~]$ oc get all #獲取所有資源信息

3.6 導出資源


[student@workstation ~]$ oc export pod docker-registry-1-8v7sh

提示:oc export命令通常用於導出現有資源,並將它們轉換為配置文件(YAML或JSON),以便備份或在集群的其他地方重新創建資源。

[student@workstation ~]$ oc export svc,dc docker-registry –as-template=docker-registry

#通過將–as-template選項傳遞給oc export命令,將多個資源作為OpenShift模板同時導出。

[student@workstation ~]$ oc export svc,dc docker-registry > docker-registry.yaml #也可以使用重定嚮導出

[student@workstation ~]$ oc export –help #查看幫助

四 oc常見故障排除

4.1 常見環境信息


使用RPM安裝的OCP,那麼master和node的ocp相關服務將作為Red Hat Enterprise Linux服務運行。從master和node使用標準的sosreport實用程序,收集關於環境的信息,以及docker和openshift相關的信息。

[root@master ~]# sosreport -k docker.all=on -k docker.logs=on

sosreport命令創建一個包含所有相關信息的壓縮歸檔文件,並將其保存在/var/tmp目錄中。

另一個有用的診斷工具是oc adm diagnostics命令,能夠在OpenShift集群上運行多個診斷檢查,包括network、日誌、內部倉庫、master節點和node節點的服務檢查等等。oc adm diagnostics –help命令,獲取幫助。

4.2 常見診斷命令


oc客戶端命令是用來檢測和排除OpenShift集群中的問題的主要工具。它有許多選項,能夠檢測、診斷和修復由集群管理的主機和節點、服務和資源的問題。若已授權所需的權限,可以直接編輯集群中大多數託管資源的配置。

  • oc get events


事件允許OpenShift記錄集群中生命周期事件的信息,以統一的方式查看關於OpenShift組件的信息。oc get events命令提供OpenShift namespace的事件信息,可實現以下事件的捕獲:

    • Pod創建和刪除
    • pod調度的節點
    • master和node節點的狀態


事件通常用於故障排除,從而獲得關於集群中的故障和問題的高級信息,然後使用日誌文件和其他oc子命令進一步定位。

示例:使用以下命令獲得特定項目中的事件列表。

[student@workstation ~]$ oc get events -n <project>

也可以通過Web控制台進行事件的查看events。

  • oc log


oc logs命令查看build、deployment或pod的日誌輸出,。

示例1:使用oc命令查看pod的日誌。

[student@workstation ~]$ oc logs pod

示例2:使用oc命令查看build的日誌。

[student@workstation ~]$ oc logs bc/build-name

使用oc logs命令和-f選項實時跟蹤日誌輸出。例如,這對於連續監視build的進度和檢查錯誤非常有用。

也可以通過Web控制台進行事件的查看log。

  • oc rsync


oc rsync命令將內容複製到正在運行的pod中的目錄或從目錄複製內容。如果一個pod有多個容器,可以使用-c選項指定容器ID。否則,它默認為pod中的第一個容器。通常用於從容器傳輸日誌文件和配置文件。

示例1:將pod目錄中的內容複製到本地目錄。

[student@workstation ~]$ oc rsync <pod>:<pod_dir> <local_dir> -c <container>

示例2:將內容從本地目錄複製到pod的目錄中。

[student@workstation ~]$ oc rsync <local_dir> <pod>:<pod_dir> -c <container>

  • oc port-forward


使用oc port-forward命令將一個或多個本地端口轉發到pod。這允許在本地監聽特定或隨機端口,並將數據轉發到pod中的特定端口。

示例1:本地監聽3306並轉發到pod的3306.

[student@workstation ~]$ oc port-forward <pod> 3306:3306

五 TS常見故障

5.1 資源限制和配額問題


對於設置了資源限制和配額的項目,不適當的資源配置將導致部署失敗。使用oc get events和oc describe命令來排查失敗的原因。

例如試圖創建超過項目中pod數量配額限制的pod數量,那麼在運行oc get events命令時會提示:

Warning FailedCreate {hello-1-deploy} Error creating: pods “hello-1” is forbidden:

exceeded quota: project-quota, requested: cpu=250m, used: cpu=750m, limited: cpu=900m

5.2 S2I build失敗


使用oc logs命令查看S2I構建失敗。例如,要查看名為hello的構建配置的日誌:

[student@workstation ~]$ oc logs bc/hello

例如可以通過在build configuration策略中指定BUILD_LOGLEVEL環境變量來調整build日誌的詳細程度。

  1 {
  2 "sourceStrategy": {
  3 ...
  4 "env": [
  5 {
  6 "name": "BUILD_LOGLEVEL",
  7 "value": "5"
  8 }
  9 ]
 10 }
 11 }


5.3 ErrImagePull和imgpullback錯誤


通常是由不正確的deployment configuration造成、部署期間引用的錯誤或缺少image或Docker配置不當造成。

使用oc get events和oc describe命令排查,通過使用oc edit dc/<deploymentconfig>編輯deployment configuration來修復錯誤。

5.4 docker配置異常


master和node上不正確的docker配置可能會在部署期間導致許多錯誤。

通常檢查ADD_REGISTRY、INSECURE_REGISTRY和BLOCK_REGISTRY設置。使用systemctl status, oc logs, oc get events和oc describe命令對問題進行排查。

可以通添加/etc/sysconfig/docker配置文件中的–log-level參數來更改docker服務日誌級別。

示例:將日誌級別設置為debug。

OPTIONS=’–insecure-registry=172.30.0.0/16 –selinux-enabled –log-level=debug’

5.5 master和node節點失敗


運行systemctl status命令,對atomicopenshift-master、atom-openshift-node、etcd和docker服務中的問題進行排查。使用journalctl -u <unit-name>命令查看與前面列出的服務相關的系統日誌。

可以通過在各自的配置文件中編輯–loglevel變量,然後重新啟動關聯的服務,來增加來自atom-openshift-node、atomicopenshift-master-controllers和atom-openshift-master-api服務的詳細日誌記錄。

示例:設置OpenShift主控制器log level為debug級別,修改/etc/sysconfig/atomic-openshift-master-controllers文件。

OPTIONS=–loglevel=4 –listen=https://0.0.0.0:8444

延伸:

Red Hat OpenShift容器平台有五個級別的日誌詳細程度,無論日誌配置如何,日誌中都會出現帶有致命、錯誤、警告和某些信息嚴重程度的消息。

  • 0:只有錯誤和警告
  • 2:正常信息(默認)
  • 4:debug級信息
  • 6:api級debug信息(請求/響應)
  • 8:帶有完整請求體的API debug信息

5.6 調度pod失敗


OpenShift master調度pod在node上運行,通常由於node本身沒有處於就緒狀態,也由於資源限制和配額,pod無法運行。

使用oc get nodes命令驗證節點的狀態。在調度失敗期間,pod將處於掛起狀態,可以使用oc get pods -o wide命令進行檢查,該命令還显示了計劃在哪個節點上運行pod。使用oc get events和oc describe pod命令檢查調度失敗的詳細信息。

示例1:如下所示pod調度失敗,原因是CPU不足。

{default-scheduler } Warning FailedScheduling pod (FIXEDhello-phb4j) failed to

fit in any node

fit failure on node (hello-wx0s): Insufficient cpu

fit failure on node (hello-tgfm): Insufficient cpu

fit failure on node (hello-qwds): Insufficient cpu

示例2:如下所示pod調度失敗,原因是節點沒有處於就緒狀態,可通過oc describe排查。

{default-scheduler } Warning FailedScheduling pod (hello-phb4j): no nodes

available to schedule pods

六 常見問題排查

6.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

6.2 本練習準備


[student@workstation ~]$ lab common-troubleshoot setup

6.3 創建應用


[student@workstation ~]$ oc new-project common-troubleshoot

[student@workstation ~]$ oc new-app –name=hello -i php:5.4 \ #從源代碼創建應用

> http://services.lab.example.com/php-helloworld


6.4 查看詳情


[student@workstation ~]$ oc describe is php -n openshift





結論:由上可知,倉庫中不存在所需鏡像。

6.5 修正錯誤


[student@workstation ~]$ oc new-app –name=hello -i php:7.0 http://services.lab.example.com/php-helloworld

[student@workstation ~]$ oc get pod -o wide #再次查看發現一隻出於pending

NAME READY STATUS RESTARTS AGE IP NODE

hello-1-build 0/1 Pending 0 40s <none> <none>

6.6 查看詳情

  1 [student@workstation ~]$ oc log hello-1-build		#查看log
  2 W0720 20:22:16.455008   18942 cmd.go:358] log is DEPRECATED and will be removed in a future version. Use logs instead.
  3 [student@workstation ~]$ oc get events			#查看事件
  4 LAST SEEN   FIRST SEEN   COUNT     NAME                             KIND      SUBOBJECT   TYPE      REASON             SOURCE              MESSAGE
  5 56s         4m           15        hello-1-build.15b31cbd8da8ff1e   Pod                   Warning   FailedScheduling   default-scheduler   0/3 nodes are available: 1 MatchNodeSelector, 2 NodeNotReady.
  6 [student@workstation ~]$ oc describe pod hello-1-build	#查看詳情
  7 ……
  8 Warning  FailedScheduling  31s (x22 over 5m)  default-scheduler  0/3 nodes are available: 1 MatchNodeSelector, 2 NodeNotReady.
  9 結論:由上可知,沒有node可供調度此pod。
 10 [root@master ~]# oc get nodes				#在master節點進一步排查node情況
 11 NAME                     STATUS     ROLES     AGE       VERSION
 12 master.lab.example.com   Ready      master    1d        v1.9.1+a0ce1bc657
 13 node1.lab.example.com    NotReady   compute   1d        v1.9.1+a0ce1bc657
 14 node2.lab.example.com    NotReady   compute   1d        v1.9.1+a0ce1bc657
 15 結論:由上可知,node狀態異常,都未出於ready狀態。


6.7 檢查服務


[root@node1 ~]# systemctl status atomic-openshift-node.service

[root@node2 ~]# systemctl status atomic-openshift-node.service

[root@node1 ~]# systemctl status docker

[root@node2 ~]# systemctl status docker




結論:由上可知,node節點的docker異常。

6.8 啟動服務


[root@node1 ~]# systemctl start docker

[root@node2 ~]# systemctl start docker

6.9 確認驗證


[root@master ~]# oc get nodes #再次查看node狀態

NAME STATUS ROLES AGE VERSION

master.lab.example.com Ready master 1d v1.9.1+a0ce1bc657

node1.lab.example.com Ready compute 1d v1.9.1+a0ce1bc657

node2.lab.example.com Ready compute 1d v1.9.1+a0ce1bc657

[student@workstation ~]$ oc get pods #確認pod是否正常調度至node

NAME READY STATUS RESTARTS AGE

hello-1-build 1/1 Running 0 22m

[student@workstation ~]$ oc describe is #查看is詳情




結論:由上可知,IS也將image推送至內部倉庫。

七 oc命令綜合實驗

7.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

7.2 本練習準備


[student@workstation ~]$ lab execute-review setup

7.3 git項目至本地


[student@workstation ~]$ cd /home/student/DO280/labs/execute-review/

[student@workstation execute-review]$ git clone http://services.lab.example.com/node-hello

7.4 docker構建image


[student@workstation execute-review]$ cd node-hello/

[student@workstation node-hello]$ docker build -t node-hello:latest .

[student@workstation node-hello]$ docker images #查看image

REPOSITORY TAG IMAGE ID CREATED SIZE

node-hello latest ff48daa00d8e 12 seconds ago 495 MB

registry.lab.example.com/rhscl/nodejs-6-rhel7 latest fba56b5381b7 22 months ago 489 MB

7.5 修改docker tag


[student@workstation node-hello]$ docker tag ff48daa00d8e \

> registry.lab.example.com/node-hello:latest

[student@workstation node-hello]$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

node-hello latest ff48daa00d8e About a minute ago 495 MB

registry.lab.example.com/node-hello latest ff48daa00d8e About a minute ago 495 MB

registry.lab.example.com/rhscl/nodejs-6-rhel7 latest fba56b5381b7 22 months ago 489 MB

7.6 push image

[student@workstation node-hello]$ docker push registry.lab.example.com/node-hello:latest

7.7 創建project


[student@workstation ~]$ oc login -u developer -p redhat \

> https://master.lab.example.com

[student@workstation ~]$ oc projects

[student@workstation ~]$ oc project execute-review

[student@workstation ~]$ oc new-app registry.lab.example.com/node-hello –name hello

[student@workstation ~]$ oc get all #查看全部資源


7.8 排查ImagePullBackOff


[student@workstation ~]$ oc logs hello-1-2jkkj #查看日誌

Error from server (BadRequest): container “hello” in pod “hello-1-2jkkj” is waiting to start: trying and failing to pull image

[student@workstation ~]$ oc describe pod hello-1-2jkkj #查看詳情

[student@workstation ~]$ oc get events –sort-by=’.metadata.creationTimestamp’ #查看事件

結論:由上可知,為image pull失敗。

7.9 手動pull鏡像


[student@workstation ~]$ oc get pod -o wide

NAME READY STATUS RESTARTS AGE IP NODE

hello-1-2jkkj 0/1 ImagePullBackOff 0 8m 10.128.0.45 node1.lab.example.com

hello-1-deploy 1/1 Running 0 8m 10.129.0.72 node2.lab.example.com

[root@node1 ~]# docker pull registry.lab.example.com/node-hello #手動拉去也失敗

Using default tag: latest

Trying to pull repository registry.lab.example.com/node-hello …

All endpoints blocked.

結論:由上可知,所有endpoint都被阻塞了。這種類型的錯誤通常發生在OpenShift中,原因是不正確的部署配置或無效docker配置。

7.10 修正docker配置


[root@node1 ~]# vi /etc/sysconfig/docker

將BLOCK_REGISTRY=’–block-registry registry.access.redhat.com –block-registry docker.io –block-registry registry.

lab.example.com’

修改為

BLOCK_REGISTRY=’–block-registry registry.access.redhat.com –block-registry docker.io’

[root@node1 ~]# systemctl restart docker

提示:node2也需要如上操作。

7.11 更新pod


[student@workstation ~]$ oc rollout latest hello

[student@workstation ~]$ oc get pods #確認

NAME READY STATUS RESTARTS AGE

hello-1-deploy 0/1 Error 0 22m

hello-2-75x9t 1/1 Running 0 47s

7.12 確認驗證


[student@workstation ~]$ oc logs hello-2-75x9t #查看log

nodejs server running on http://0.0.0.0:3000

7.13 暴露服務


[student@workstation ~]$ oc expose svc hello –hostname=hello.apps.lab.example.com

route “hello” exposed

7.14 測試服務


[student@workstation ~]$ curl http://hello.apps.lab.example.com

Hi! I am running on host -> hello-2-75x9t

[student@workstation ~]$ lab execute-review grade #腳本驗證試驗

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化