試驗背景:
開始時間:2019年12月11日
結束時間:2019年12月13日
最后一次更新:2020年4月30日(問題三)
自己編寫一個后台程序,嘗試推送到Cloud Foundry上,並開放從MindSphere以外訪問的權限。
程序實現以下功能:
1、使用MindSphere提供的API獲得指定時序的Token
2、啟動定時任務,從時序數據中拉取數據,並打印在日志中。
3、提供一個REST接口,用來獲取數據。
4、程序開啟log日志,打印到Cloud Foundry的容器中。
前提條件:
1、電腦已經安裝Power Shell。
2、提前編寫好要測試的程序。
3、擁有MindSphere的Developer賬號。
操作隨記:
(一)編寫程序
程序地址:https://github.com/quchunhui/demo-macket/tree/master/mindsphere
(二)登陸Cloud Foundry
Cloud Foundry的登陸,可以參考上一篇博客。
命令:cf login -a https://api.cf.cn1.mindsphere-in.cn --sso --skip-ssl-validation
博客地址:https://www.cnblogs.com/quchunhui/p/12015167.html
(三)創建CF空間並賦予權限
1、切換到已有組織(org),相關命令如下:
切換組織:cf target -o rexelcn0
2、創建測試程序的運行空間(space),相關命令如下:
創建空間:cf create-space rexel-mf-api-test
查看所有空間:cf spaces
3、更新空間的Role(角色)及Permission(權限),相關命令如下:
查看Space中的使用者及其權限:cf space-users rexelcn0 rexel-mf-api-test
附加:
如果希望使用其他賬戶完成后續的操作,可以使用一下命令來添加權限。
為指定用戶添加SpaceManager權限:cf set-space-role chunhui.qu@rexel.com.cn rexelcn0 rexel-mf-api-test SpaceManager
為指定用戶添加SpaceDeveloper權限:cf set-space-role chunhui.qu@rexel.com.cn rexelcn0 rexel-mf-api-test SpaceDeveloper
(四)將應用程序部署到Cloud Foundry
1、在程序根目錄中創建manifest.yml文件
文件內容如下:
--- applications: - name: rexel-mindsphere-api-test instances: 1 random-route: true path: target/rexel-mindspere-api-0.0.1.jar memory: 512M
2、將程序推送到CF的空間,相關命令如下:
跳轉入Spaces:cf target -s rexel-mf-api-test
跳轉到程序根目錄:cd D:\MyWork\22_Github\rexel-cn\rexel-jarvis\rexel-mindsphere-api
程序打包:mvn package(注意,如果程序修改了,一定要重新打包,因為cf push上傳的jar包,不是源代碼,這一點非常重要。)
推送程序:cf push
列出所有應用及運行狀態:cf apps
查看應用的詳細狀態:cf app rexel-mf-api-test
【小插曲1】
執行cf push的時候報錯一個錯誤
在程序根目錄中使用mvn package重新編譯打包,然后再次執行cf push之后問題解決。
【小插曲2】
程序上傳之后,cf提示啟動失敗
按照提示的命令查看了日志。命令:cf.exe logs rexel-mindsphere-api-test --recent
可以看到提示內存不夠。
嘗試將manifest.yml中配置的內存大小調高,重新推送之后解決。修改之后的manifest.yml文件內容
--- applications: - name: rexel-mindsphere-api-test instances: 1 random-route: true path: target/rexel-mindspere-api-0.0.1.jar memory: 1G
(五)SSH進入到空間查看運行
官網操作手冊:https://developer.mindsphere.io/zh/paas/paas-cloudfoundry-ssh.html
1、檢查空間SSH是否開啟
命令:cf space-ssh-allowed rexel-mf-api-test
2、開始指定空間SSH權限:
默認是開啟的,如果沒有開啟,可以使用以下命令打開權限。
命令:cf allow-space-ssh rexel-mf-api-test
3、為應用開啟SSh權限:
命令:cf enable-ssh rexel-mindsphere-api-test
注意不要弄錯了空間名(rexel-mf-api-test)和應用名(rexel-mindsphere-api-test)
4、重新啟動應用:
命令:cf restart rexel-mindsphere-api-test
5、SSH進入應用空間:
命令:cf ssh rexel-mindsphere-api-test
6、進入日志所在路徑:
在spring程序的logback中,配置的日志路徑為:/home/vcap/logs
進入路徑:cd /home/vcap/logs/
7、查看日志是否正常:
命令:less rexel-md-test2019-12-11.log
(六)將程序注冊到MindSphere
1、使用MindSphere賬號登錄
2、選擇Developer Cockpit(開發駕駛艙)
3、選擇儀表盤選項卡。
4、單擊創建新的應用。
類型:Standard
基礎設施:MindSphere Cloud Foundry。
顯示名稱:Rexel MindSphere Api Test(字面上容易理解的就可以)
內部名稱:rexelmfapitest(這將會為成為應用URL的一部分。初始化創建后,內部名稱不能被更改!)
版本:1.0.0(MindSphere 支持 Major.Minor.Patch 方案。版本必須以 >=1 的主號碼開頭。保存之后版本不能被更改。)
應用圖標:隨便上傳一個就可以。我用了一個鋼鐵俠第一任人工智能助理Jarvis的圖片。
輸入組件名稱。 示例應用的組件名稱為hello-spring-cloud。
組件名稱
組件名稱必須與 manifest.yml 中的 Cloud Foundry 應用名稱匹配。否則,生產系統中的自動注冊將會失敗。
組件名稱:rexel-mindsphere-api-test(必須與 manifest.yml 中的 Cloud Foundry 應用名稱匹配。否則,生產系統中的自動注冊將會失敗。)
Cloud Foundry URL:rexel-mindsphere-api-test-comedic-hippopotamus-vl.apps.cn1.mindsphere-in.cn(使用 cf app {app_name} 來獲取您部署的應用的 URL。)
端點:為您的組件添加至少一個端點。使用 /** 來匹配您應用的所有路徑。
關於端點: 您可以為端點使用任意路徑。 不允許使用 /api,因為這是為從相對路徑(例如 /api/iot/v3/timeseries)調用 MindSphere api 預留的。 避免使用keywords,因為這是為 SQL 操作預留的。 您可以使用通配符。 * 匹配路徑中任何字符,** 匹配任何字符和子路徑。
點擊保存。將被重定向到應用詳細信息。 應用程序處於In-Development狀態,並且准備好注冊了。
可以看到應用創建成功。(有沒有開心的感覺?)
【小插曲】
保存失敗,因為說明中不能使用中文。
使用有道詞典,將中文翻譯成應為,重新搞一次解決。
(七)配置應用角色和范圍
參考官網資料:https://developer.mindsphere.io/zh/howto/howto-cf-running-app.html
1、切換到授權管理選項卡。
2、選擇應用。
3、創建一個應用范圍並選擇分配給哪個角色。
關於角色和范圍:https://developer.mindsphere.io/zh/concepts/concept-roles-scopes.html
這里暫時只賦予一個權限mdsp:core:iot.timUser(讀取時間序列的權限)
(八)注冊應用
1、切換到儀表盤選項卡,打開應用詳細信息,單擊注冊。
(九)分配應用角色
1、從Launchpad 中打開 Settings 應用,並切換到角色選項卡。
2、選擇一個應用角色並單擊編輯分配。
分配一個或多個用戶到應用角色。
結束編輯。登出 MindSphere 並重新登陸。
(十)授權管理
使用密鑰管理器API授權您的應用訪問其他租戶數據。該操作主要針對某個應用需要訪問其他不同租戶的數據的情形,例如,在沒有用戶交互的情況下頻繁進行數據處理時。
1、在 MindSphere Launchpad Developer/Operator Cockpit 授權管理應用憑證中,點擊對應的 APP 名稱,選擇右側簽發訪問權限
2、選擇所需權限類別,並提交
3、將顯示的對應信息保存,
注意:此信息只顯示一次
注意:此信息只顯示一次
注意:此信息只顯示一次
4、將對應信息添加至應用 Manifest .yml 文件中,並重新上傳應用
--- applications: - name: rexel-mindsphere-api-test instances: 1 random-route: true path: target/rexel-mindspere-api-0.0.1.jar memory: 1G env: HOST_ENVIRONMENT: cn1 MDSP_OS_VM_APP_NAME: rexelmfapitest MDSP_OS_VM_APP_VERSION: 1.0.0 MDSP_KEY_STORE_CLIENT_ID: <只顯示一次的客戶ID> MDSP_KEY_STORE_CLIENT_SECRET: <只顯示一次的客戶密鑰>
5、使用Postman測試是否部署成功
先使用 base 64 工具加密客戶ID與客戶秘鑰,格式為客戶ID:客戶秘鑰(半角符號)
工具地址:https://www.base64encode.org/
工具截圖:
以獲取Token為例,使用Postman測試一下:
請求類型:POST
請求地址:https://gateway.cn1.mindsphere-in.cn/api/technicaltokenmanager/v3/oauth/token
Header:
Body 選項卡設置格式為Raw ,格式為JSON,內容為:
{ "appName": "rexelmfapitest", "appVersion": "1.0.0", "hostTenant": "rexelcn0", "userTenant": "rexelcn0" }
點擊發送之后,可以看到已經可以正常獲取Token信息
(十一)從外部訪問應用程序提供的接口
與MindSphere的人員確認過了,目前暫不支持,直接從外部訪問部署到MindSphere上的應用。
有兩種方式進行應用落地:
方式一:
開發一整套的應用(包括前端和后端,比如Spring + Vue),推送到CF,並注冊到MindSphere上。
這種方式的缺點是,必須擁有MindSphere賬號的用戶才有可能訪問應用。
方式二:
在MindSphere之外,如阿里雲上面開發獨立的應用,通過MindSphere開放的API接口來獲取數據,
這種方式的缺點是,需要獨立服務器以及數據庫等配套組件支撐。好處是與MindSphere解耦。
我嘗試了第一種方式,自己寫了一個最簡單的頁面(一個按鈕,一個顯示數據的文本框),嘗試部署到MindSphere上。
(十二)部署並測試Web頁面
寫了一個最簡單的web頁面,部署的方式與Spring后台程序一樣,
唯一需要注意的是manifest.yml的內容必須多一個而配置就是:buildpack: staticfile_buildpack_offline
用來告訴CF這是一個靜態的文件。
那么,如何訪問后台應用app中的接口呢?
將靜態的頁面推送上去之后,不管三七二十一,先訪問一下后台試試(接口地址可能不對),結果從瀏覽器控制台上可以看到如下錯誤:
Refused to connect to 'http://localhost:8081/rexel/timeseries/test' because it violates the following Content Security Policy directive: "default-src 'self' static.cn1.mindsphere-in.cn". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
問了相關技術人員,建議我去看一下MindSphere->Cockpit下的content-security-policy(內容安全策略),
MindSphere默認的CSP設置如下:
default-src 'self' static.cn1.mindsphere-in.cn; style-src * 'unsafe-inline'; script-src 'self' 'unsafe-inline' static.cn1.mindsphere-in.cn; img-src * data:;
網上找了一些資料,對Content Security Policy這個詞進行了快速掃盲,試圖找到解決辦法
網友博客:
https://www.jianshu.com/p/74ea9f0860d2
MindSphere官網介紹:
https://developer.mindsphere.io/zh/concepts/concept-csp.html#_3
https://developer.mindsphere.io/zh/howto/howto-csp.html
CSP官網:
https://content-security-policy.com/
首先,嘗試了取消CSP的安全限制,將CSP的設置修改如下
default-src 'self' *; style-src * 'unsafe-inline'; script-src 'self' 'unsafe-inline' *; img-src * data:;
然后界面返回了這么一個鬼東西,已經是完全懵逼狀態,
MindSphere Gateway error: A redirect is required to get the users approval
問了一下西門子的朋友,說是每次修改DSP之后,MindSphere后台服務會重啟,需要等十幾分鍾再登陸。
吃過午飯,回來重新試了一次之后,發現成功了,簡直高興的不得了。然而
【小插曲】
發現由於html里寫的訪問地址是localhost,剛好我電腦本地的后台程序也在運行中,
所以,訪問的是我本地的程序,並不是注冊在Cloud Foundry上的程序,白他媽的高興一場,還興奮的去和老板報了喜,
怎么辦?自己挖的坑,哭着也得填完。
於是重新想西門子的售后發起求助,尋求解決辦法。
最終,經過售后一頓猛如虎的操作之后終於解決。
解決辦法:
地址1:http://localhost:8081/rexel/timeseries/test
地址2:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/rexel/timeseries/test
地址3:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/v1/rexel/timeseries/test
地址4:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
地址5:https://supplab-rexelcn0-staticweb-rexelcn0.cn1.mindsphere-in.cn-supplab.cn1.mindsphere-in.cn/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
地址6:/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
結果地址6最終生效,問題終於得以解決,吹出去的牛逼也算是能圓回來了,差點沒讓老衲圓寂在電腦前。
2020/4/22追記:
關於前端頁面訪問后端的地址,有一點需要注意:后端服務的注冊版本對接口有影響。
如下圖,我們的應用版本是純數字,系統給的接口版本號是:大寫的V1
如果應用版本不是數字,而是如v1.0.0這樣的,系統給的接口版本是:小寫的v1
(十三)注銷應用
萬事有始有終,應用可以正常使用了,現在開始嘗試將一個應用注銷。
先來回憶一下上線的步驟
1、在cf上創建org、space
2、賦予用戶在space中的權限
3、將應用push到cf並啟動
4、在ms(MindSphere的簡稱)上注冊應用
5、賦予相應的角色和范圍
所以,徹底下線應用的操作就應該和上面的相反,
不過個人認為,上面的第5步應該不需要執行,刪除了應用按理說應該可以自動取消相應的授權、角色和范圍。
所以,直接從上面的第4步開始,let's go go go......................
1、在ms上注銷應用(這里注銷的是一個以前測試的應用)
可以看到應用刪除成功了
檢查一下,是否按照我的猜想,授權、角色和范圍都已經刪除干凈。
先檢查一下授權:嗯,被刪除的“myfirstapp”已經消失了。
再來檢查一下角色和范圍:很好,這里也被刪的很干凈。
2、從cf上停止並刪除app
先檢查一下空間。命令:cf spaces
我們要刪除的應用在rexel-demo中。
進入到要刪除的空間,命令:cf space rexel-demo
查看一下在空間中運行的應用,命令:cf apps
暫停應用。命令:cf stop rexel-mindsphere-api-test
刪除應用。命令:cf delete cf stop rexel-mindsphere-api-test
重新查看是否已經刪除。命令:cf apps
最后看到空間中已經沒有任何app了,可以放心的刪除空間了。
3、刪除空間
刪除空間。命令:cf delete-space rexel-demo
查看空間,確認是否成功刪除。命令:cf spaces
(十四)Backing Services的創建及關聯
官網地址:https://developer.mindsphere.io/zh/paas/index.html
1. 查看可用的Backing services:
命令:cf marketplace
會列出service的名字,不同套餐,及說明。具體套餐請參考官網介紹。
2.創建Backing services實例
命令:cf create-service elasticsearch5 elasticsearch-xs my-elasticsearch-service
3. 檢查創建的serivce狀態
命令:cf services
剛剛創建完成的狀態:create in progress
過幾分鍾再次查看的狀態:create succeeded
4. 把App與Service進行關聯
命令:cf bind-service rexel-service my-elasticsearch-service
需要注意的是,需要等待service創建成功之后才可以進行關聯,如果service處於創建中狀態進行關聯,會提示如下錯誤:
錯誤:An operation for service instance my-elasticsearch-service is in progress.
5.重新載入或重新啟動應用
要使應用能夠訪問服務實例,請運行 cf restage
或 cf restart
來重新載入或重新啟動應用。
命令:cf restart rexel-service
6.獲取服務實例訪問憑證
將服務實例綁定到應用后,Elasticsearch 數據庫的憑證將存儲在應用的環境變量中。運行 cf env APP-NAME
顯示環境變量。
命令:cf env rexel-service
應用環境變量樣例:(用戶名,密碼,端口等敏感字段均進行了修改脫敏)
System-Provided: { "VCAP_SERVICES": { "elasticsearch5": [ { "binding_name": null, "credentials": { "host": [ "http://eld521309a.service.dc1.a9ssvc:9213" ], "hosts": [ "eld55509a-es-0.node.dc1.a9ssvc" ], "password": "a9sa1d17b178af842aa1a2349474997dd67bf438a2b", "port": 9213, "scheme": "http", "username": "a9s76348fd458842b5234cc5e3f5ce46c3582a3e7c38" }, "instance_name": "my-elasticsearch-service", "label": "elasticsearch5", "name": "my-elasticsearch-service", "plan": "elasticsearch-xs", "provider": null, "syslog_drain_url": null, "tags": [ "searchengine" ], "volume_mounts": [] } ] } } { "VCAP_APPLICATION": { "application_id": "32309d25-88fb-4b5b-b16d-c449d1d7e1b9", "application_name": "rexel-service", "application_uris": [ "rexel-service-shy-mongoose-wj.apps.cn1.mindsphere-in.cn" ], "application_version": "fffa6fd1-b50d-4d6f-8ce4-c2f155600af5", "cf_api": "https://api.cf.cn1.mindsphere-in.cn", "limits": { "disk": 512, "fds": 16384, "mem": 700 }, "name": "rexel-service", "organization_id": "d36d5255-6364-4d96-bab1-c2d5a0ca760a", "organization_name": "tenant0", "process_id": "32309d25-88fb-4b5b-b16d-c449d1d7e1b9", "process_type": "web", "space_id": "b64f9b6c-b09f-42a4-a4b7-ebcb6b4d4167", "space_name": "rexel-ids", "uris": [ "rexel-service-shy-mongoose-wj.apps.cn1.mindsphere-in.cn" ], "users": null, "version": "fffa6fd1-b50d-4d6f-8ce4-c2f155600af5" } } User-Provided: HOST_ENVIRONMENT: cn1 MDSP_KEY_STORE_CLIENT_ID: rexelcn0-rexelservice-1.0.0 MDSP_KEY_STORE_CLIENT_SECRET: xxxxxxxxxxxxx MDSP_OS_VM_APP_NAME: rexelservice MDSP_OS_VM_APP_VERSION: 1.0.0 No running env variables have been set No staging env variables have been set
7.解綁服務實例
命令:cf unbind-service rexel-service my-elasticsearch-service
8.刪除服務實例
命令:cf delete-service my-elasticsearch-service
查看一下服務實例狀態。狀態為:delete in progress
過幾分鍾,再次查看服務實例狀態。可以看到服務實例已經被刪除。
(十五)其他嘗試
這部分后面有時間會繼續補充
1、使用MindSphere的數據分析工具
2、使用MindSphere提供的后台服務(以Mongodb為例)
【總結】
1、MindSphere整個基於Cloud Foundry開展的,Cloud Foundry是業界第一個開源PaaS雲平台,
整個驗證過程一步一個坎,其根本原因是對Cloud Foundry的不熟悉,后續有時間需要多學習一下這個平台,
如果時間允許,最好自己安裝部署一遍。
2、MindSphere的小白級的資料太少,如果是一點基礎都沒有的,很難順利上手,
而且資料不是基於“用戶場景”的,像我的這種嘗試場景,需要各處去尋找資料,知識也連不起來。
對使用者來說不是很友好。
附:其他可能遇到的問題
【問題一】
錯誤日志:
You have exceeded your organization's memory limit: app requested more memory than available
問題原因:
每個org都有內存等限制,超過org的內存限制就會出現這個問題。
查看Org的內存限制
查看org詳情。命令:cf org rexelcn0
查看org的配額。命令:cf quota cf-quota-1552463110231
注意應用的內存大小不要超過這個限制就可以。
我嘗試着將org中沒有用到的空間給刪除掉,重新push了一次應用。
【問題二】
問題描述:
想ssh進入應用,查看一下運行狀態,應用是重新部署上去的,結果提示以下錯誤。
Error opening SSH connection: ssh: handshake failed: ssh: unable to authenticate, attempted methods [password none], no supported methods remain
檢查了space和app對ssh的支持狀態都沒有問題。
問題原因:
修改了app的ssh權限之后,需要重新啟動一下app,否則權限不會生效。
解決辦法:
重啟app。命令:cf restart rexel-mindsphere-api-test
ssh進入app。命令:cf ssh rexel-mindsphere-api-test
【問題三】
問題描述:
前端頁面中嵌入了地圖,結果在顯示的時候一直報錯
Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Centent Security Policy directive: 'self' 'unsafe-inline' static.cn1.mindsphere-in.cn"
解決辦法:
在應用的內容安全策略(CSP)中增加unsafe-eval。
default-src 'self' *; style-src * 'unsafe-inline'; script-src * 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:;
附:角色范圍整理
附:CF操作命令:
http://cli.cloudfoundry.org/zh-Hans/cf/
--END--
解綁服務實例¶
運行 cf unbind-service
可以解除應用與服務間的綁定關系。