25000 linuxddos去後門優化版叢集_Ambari 支援多叢集管理
注意:本文使用的版本是 Ambari 2.7.4
/ 場景 /
在使用Ambari的時候,它本身預設是隻能管理一個叢集的。這在實際使用的時候,會比較不方便,尤其是如果用來管理ElasticSearch,Redis一類的叢集時,因為叢集數量多,就更加捉襟見肘了。
而如果想要管理多個叢集,要麼就付費使用Clouder Manager企業版,這個是支援多叢集管理的;或者就一個叢集對應一個Ambari,分別訪問;另外就只能自己進行二次開發了,其實Ambari本身是可以通過Rest API建立多個叢集的,只是在Ambari-Web專案中,只能看到一個。
/ 程式碼分析 /
前面也說了,實際Ambari是支援多叢集管理的,只是ambari-web專案只能看到一個。而ambari-web專案就是用ember.js寫的前端專案,實際都是使用Rest API呼叫ambari-server的。
因為我不是很會前端程式碼,而且也沒有使用過ember框架,所以看在分析程式碼時,還是比較費勁,讓我們一起來進行分析吧。
首先,我們可以在app/app.js檔案中,找到一個clusterName的屬性定義,然後全域性搜尋這個屬性,尋找看哪個地方進行了賦值。
一個一個排除中......
最後,我們可以看到在這個檔案中app/controllers/global/cluster_controller.js,有這樣的程式碼:
/** * load cluster name */ loadClusterName: function (reload, deferred) { var dfd = deferred || $.Deferred(); if (App.get('clusterName') && !reload) { App.set('clusterName', this.get('clusterName')); this.set('isClusterNameLoaded', true); dfd.resolve(); } else { App.ajax.send({ name: 'cluster.load_cluster_name', sender: this, data: { reloadPopupText: Em.I18n.t('app.reloadPopup.noClusterName.text'), errorLogMessage: 'failed on loading cluster name', callback: this.loadClusterName, args: [reload, dfd], shouldUseDefaultHandler: true }, success: 'reloadSuccessCallback', error: 'reloadErrorCallback', callback: function () { if (!App.get('currentStackVersion')) { App.set('currentStackVersion', App.defaultStackVersion); } } }).then( function () { dfd.resolve(); }, null ); } return dfd.promise(); },
可以看到,這個就是用來載入叢集名稱的,然後可以看到回撥方法為:
reloadSuccessCallback: function (data) { this._super(); if (data.items && data.items.length > 0) { App.setProperties({ clusterId: data.items[0].Clusters.cluster_id, clusterName: data.items[0].Clusters.cluster_name, currentStackVersion: data.items[0].Clusters.version, isKerberosEnabled: data.items[0].Clusters.security_type === 'KERBEROS' }); this.set('isClusterNameLoaded', true); } },
哈哈~~,請允許我嘚瑟一下,這部分程式碼相當的一目瞭然:如果叢集的數量大於0時,只取第一個叢集,並設定給App。
貌似找到了關鍵程式碼,那就得先驗證是否可行了。
/ 驗證 /
因為是純前端框架,我們修改這部分程式碼時,可以不用進行打包,直接修改服務端的檔案即可。
在服務端,編輯/usr/lib/ambari-server/web/javascript/app.js這個檔案,找到前面所說的程式碼,並做修改:
reloadSuccessCallback: function (data) { this._super(); if (data.items && data.items.length > 0) { App.setProperties({ clusterId: data.items[1].Clusters.cluster_id, clusterName: data.items[1].Clusters.cluster_name, currentStackVersion: data.items[1].Clusters.version, isKerberosEnabled: data.items[1].Clusters.security_type === 'KERBEROS' }); this.set('isClusterNameLoaded', true); } },
注意:在進行這個修改之前,需要通過Rest Api再建立一個叢集,保證當前Ambari中,有兩個叢集存在,否則會報錯的。
這裡可以看到,我把叢集的獲取下標改為了1,因為當前Ambari擁有兩個叢集,所以這個就會是取第二個叢集,而不是預設的第一個。
儲存檔案,直接重新整理Ambari的管理頁面。
搞定!可以看到,叢集變為了第二個,證明這個方法是可行的。當然,我們不可能每次切換叢集時,都去手動修改下標吧。讓我們再來優化一下。Comn On~
/ 優化 /
這裡的優化思路就是把叢集名字加到頁面的Url中去,比如:?cluster=cluster1,因為頁面是純前端專案,所有請求都是通過非同步載入的,沒有改變本身頁面的url,所以這個方法也是可行的。
還是修改上面的檔案:/usr/lib/ambari-server/web/javascript/app.js,上程式碼:
reloadSuccessCallback: function (data) { this._super(); if (data.items && data.items.length > 0) { var cluster = window.location.search.match(/cluster=([^&]+)/); if (cluster && cluster.length > 1) { cluster = cluster[1]; } console.log("cluster: ",cluster) let clusterInfo = data.items[0]; for(let i in data.items){ if(data.items[i].Clusters.cluster_name === cluster){ clusterInfo = data.items[i] break; } } App.setProperties({ clusterId: clusterInfo.Clusters.cluster_id, clusterName: clusterInfo.Clusters.cluster_name, currentStackVersion: clusterInfo.Clusters.version, isKerberosEnabled: clusterInfo.Clusters.security_type === 'KERBEROS' }); this.set('isClusterNameLoaded', true); } },
不怎麼會寫前端,就將就著看吧,基本功能還是實現了。
儲存,現在我們訪問ambari頁面時,就可以加叢集的引數了。
分別訪問http://localhost:8001/?cluster=cluster1 和http://localhost:8001/?cluster=cluster2,就可以看到兩個不同的叢集啦。
到這裡,基本的多叢集方案就可用了。但有人就要問了,每次我都要手動輸入,而且也看不到當前擁有的叢集列表,咋辦?
那我們再來優化一下:
/ 再優化 /
我們通過http://localhost:8001/clusters?fields=Clusters/security_type,Clusters/version,Clusters/cluster_id這個介面,可以獲取叢集列表:
{ "href" : "http://localhost:8001/api/v1/clusters?fields=Clusters/provisioning_state,Clusters/security_type,Clusters/version,Clusters/cluster_id&_=1586855363652", "items" : [ { "href" : "http://localhost:8001/api/v1/clusters/cluster", "Clusters" : { "cluster_id" : 2, "cluster_name" : "cluster", "provisioning_state" : "INSTALLED", "security_type" : "NONE", "version" : "HDP-3.0" } }, { "href" : "http://localhost:8001/api/v1/clusters/cluster2", "Clusters" : { "cluster_id" : 52, "cluster_name" : "cluster2", "provisioning_state" : "INSTALLED", "security_type" : "NONE", "version" : "HDP-3.0" } } ]}
然後用Vuejs或者其他的作為一個列表顯示,然後把連線分別指向http://localhost:8001/?cluster={clusterName},這樣就可以看到當前所有叢集,並直接進行跳轉了。
/ 總結 /
從最終效果來看,其實修改的地方本身不多,但其中的思路還是比較重要,如何分析現有系統、找到需要修改的地方,這裡其實用得最多的就是全域性搜尋了,搜尋到對應的屬性或方法,然後依次排除。
不得不說,搞定一個這樣的技巧還是非常有成就感的,不僅自身的思路得到了提升,同時也節省了很多多餘的工作。因為不這樣解決的話,就要自己去做二次開發了。
其實對於Ambari支援多叢集管理,在網上搜索到的都沒有類似的處理方式,算是有一點成就感吧。