說實話,Rancher的官方文檔真的很全,圍繞着UI的方方面面都面面俱到。但看多了卻發現,不少東西都淺嘗輒止,尤爲某個東西實在不懂的時候,看文檔只能讓本身更沒頭緒。因此此文的目的是方便本身可以在須要的時候回憶出點點滴滴。html
Rancher1.6的傻瓜式操做給了我很大的幫助,也幫我贏得了大部分運維的支持,最終得以施展。但Rancher2.0不管是開發版仍是beta版,都並非那麼友好,老是莫名其妙的出現各類各樣的問題。後來由於工做的調動,沒有繼續研究新版。不過如今終於有時間了,當前最新版本2.1.4,因此此文的基礎也就是2.1.4。前端
另外,本文不會花篇幅去介紹如何安裝或者解決安裝中的問題,但涉及到的,我都會附上連接。本文主要的做用一個是備忘,還一個是手冊。若是之後回頭看這篇文章,發現忘了的看一遍就回憶起來了,照着作一遍的環境就搭好了那就完美了。node
有必要在這裏提早聲明一下先決條件(並非說實際上就是這個數據,而是個人環境是這個數據)。從Rancher1.6開始到如今的2.1.4,每個版本都用過。不一樣的版本對先決條件敏感,如1.6是敏感度最遲鈍的,只要保證OS內核3.1.10以上(含)便可。至於Docker版本,在查閱Rancher文檔的時候,不少地方明確指出最高支持版本17.02,但實際使用過程當中,只要是最新版本的均可以。如下是具體的環境說明:mysql
物理機OS:Ubuntu 18.04linux
Docker:18.09nginx
harbor:1.7.1git
Gitlab:10.4.4sql
從零開始,現有三臺物理機,兩臺服務器,一臺筆記本,服務器上只跑一個虛擬機實例,筆記本跑兩個虛擬機實例。但須要注意的是:若是須要拷貝虛擬機,必須是同物理機上的拷貝,而不能誇物理機拷貝,哪怕用了什麼ovf虛擬機格式,也都不行,由於在實際使用的時候會出現一些莫名的錯誤,也可能不出,全靠運氣。如下是主要步驟(可直接點擊穿越到教程,教程來源於網絡):docker
一、更新源(apt-get update && apt-get upgrade)數據庫
二、修改vi命令(默認vi命令不友好)
四、設置limit
五、安裝docker
六、配置加速器(加速器可用daoclould也可用阿里的,這裏貼出的是daoclould的)
七、設置機器域名host指向(若是是直接使用IP訪問的話,跳過這個)
8.一、安裝rancher
sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher
8.二、安裝harbor
九、登陸Rancher建立集羣導入機器
十、全部機器harbor登陸受權(若是不須要本身手動pull私服上的鏡像,此步跳過)
額外須要注意的是:
一、最新版本的docker默認採用https方式拉取鏡像(確切的說是自1.3.2版本開始),若是使用http,那就須要在機器上添加過濾,詳情點擊。
二、自受權的https證書,須要在機器上信任,信任方式點此。
三、Rancher內部是k8s,k8s集羣中,不會讀取宿主機的證書。故在宿主機配置了證書信任,不會滲透到k8s集羣。也就是說在宿主機信任證書,對於k8s來講,沒有任何影響。這個產生一個很大問題,就是在Rancher裏配置了鏡像庫後,Rancher沒法登錄到鏡像庫,緣由就是CA證書不被信任。這直接致使私有鏡像私服被廢了,除非公司花錢買證書,或者使用如阿里雲鏡像私服這樣第三方服務。阿里雲地址點此。
這一部分是說明1.6和2.0兩部分,Rancher的概念,目的是着重理解Rancher。
前段時間看了本書叫《碼農翻身:用故事給技術加點料》,這個思路很清奇,久久不能忘。遂本章也用說故事的方式來闡明概念。
小明的志向是當一個農場主。雖然他歷來沒幹過,可是他如今準備幹了。
因而他買了一塊地,首先他用柵欄圍了起來,防止牛羊越獄,同時也防止可惡的豺狼豹子偷獵牛羊。而後小明對圈內的地進行的劃分,A區域B區域……,這樣能夠方便管理。每一個區域他又建了不少棚舍,不過棚舍之間是互通的,這樣牛羊就不會寂寞,能夠串串門。
萬事俱備只差牛羊,小明考慮直接去牛羊中心,路途遙遠,倒不如去最近的代理商,代理商就像超市,把牛羊從廠家運送過來,這樣省時又省力。爲了保險起見,小明只買了幾百只牛羊,而後趕到本身規劃好的農場。
其實小明的工做很簡單,定時檢查一下牛羊的狀態,是否是餓了渴了或者生病了又或者死亡了,不過若是牛羊死亡了,小明就必須再買一頭回來。有時候小明還會給牛羊作個造型美化一下,小明說這叫升級,固然若是美化失敗了,小明還會恢復原樣,小明又叫這個回滾。
小明很滿意本身的農場,但以爲一我的有點無聊,因而他又創建了一個站臺,站在站臺上能夠看到某個區域的每一個棚舍,就像動物園同樣。而後開放給你們,不只能賺點外快,還不會以爲無聊。
今後,小明過上了幸福的農場主生活,實現了人生理想。
故事到此結束,如今解釋一下文中的概念:
一、小明:rancher的master節點
二、柵欄:rancher集羣
三、區域:集羣
四、棚舍:項目
五、牛羊:容器
六、牛羊中心:docker hub鏡像中心
七、代理商:國內鏡像如阿里雲
八、升級:鏡像升級
九、回滾:鏡像回滾
十、站臺:負載均衡(HA)
十一、小明的工做:cattle編排引擎
小明的幸福沒過多久,就出現問題了。第一,小明天天不只要進行繁瑣的工做,還要接待到訪的遊客,忙得團團轉。第2、牧場過小了,訪客太多了,每次都有人抱怨等待的時間過久了。小明痛定思痛決定要改善這兩個問題,好在經營了一段時間,手裏攢了很多積蓄。
首先,他擴大了牧場,區域劃分保持不變,之前一個大棚舍,如今建好幾個大棚舍,但棚舍裏作好規劃,不一樣棚舍養不一樣的牛羊,同時棚舍之間是獨立的,防止牛羊亂竄,但同樣的同一個棚舍仍是不由止的。另外,大棚舍裏的小棚舍,也得改造,每次遊客來都反應髒亂差。因此,給每一頭牛羊創建單獨的房間,再裝飾的很是精美,除此以外,每一個房間還會配備專人管理,最後起個洋氣的名字,叫pod。
而後,僱傭一大批的人,把小明之前的工做都細化分工下去,好比待在pod裏,負責牛羊的管理,好比升級和回滾。而後每一個大棚舍自治,牛羊的採購、參觀等等獨立化,這樣管理起來更方便,同時若是一個大棚捨出現問題,也不會影響到別的大棚舍。
接着站臺也要優化一下,之前是固定的幾個站臺,你們都按序排隊。如今不用那麼麻煩了,由於大棚舍自治了,每一個大棚舍單獨售票,因此只須要安排幾個迎賓,遊客來了,問一下去哪一個大棚舍,而後直接帶過去就好了,大大減小了訪客的等待時間。
最後,因爲規模相比以前不可同日而語,各個流程小明沒法手動管理,因而小明又規劃了一個叫流程的東西,想要幹什麼東西話,只須要按照流程走就對了。
至此,全部問題都解決了,而且小明也解放了,天天只須要巡視工做就成了,小日子過得不要不要得。
故事到此結束,如今解釋一下文中的概念:
一、小明:rancher的master節點
二、柵欄:rancher集羣
三、區域:集羣
四、大棚舍:命名空間
五、小棚舍:項目
六、pod:pod,k8s對容器的包裝,負責容器的生命週期
七、牛羊中心:docker hub鏡像中心
八、代理商:國內鏡像如阿里雲
九、升級:鏡像升級
十、回滾:鏡像回滾
十一、站臺:負載均衡(nginx),之前會在固定的IP上,如今只要在集羣的任何一臺機器上便可,由於會有專門的「迎賓」處理
十二、爲小明工做的人:k8s編排引擎
1三、流程:流水線(CI/CD)
有一個以JAVA編寫的微服務,如今要部署上線。
首先,環境分爲本地環境(dev)、測試環境(test)、預發佈環境(uat)、線上環境(live)。
而後,根據業務劃分命名空間,好比後臺統一爲service,手機客戶端統一爲app
而後,根據業務劃分項目,如用戶管理的後臺服務項目,則命名爲user-manager
而後,根據代碼項目劃分服務,好比認證服務是user-auth,登陸是user-login
而後,根據實際代碼,配置負責均衡暴露服務,爲外界提供接口
同時,配備日誌採集,能夠統一查看各個項目的日誌
簡單說下原理,Rancher按如下步驟運行:
一、Rancher啓動一個jenkins鏡像,此鏡像能夠經過配置一個負載均衡來暴露出去訪問後臺界面,用戶名是admin,密碼是容器裏的環境變量ADMIN_PASSWORD,默認是cgfh9ljx7dtx7s2vmqf7r9xcf6zj45s5lxcwg95zmtqz9n58mg84pc,若是啓動流水線報錯,登陸jenkins,進去系統設置->全局安全設置,找到「防止跨站點請求僞造」,肯定勾選,而後點擊保存(若是已勾選,那麼勾選掉,保存,再編輯,勾選,保存),再從新啓動流水線便可。
二、將流水線任務生成groovy腳本,而後在jenkins上建立任務並執行。
三、流水線的每個階段對應一個鏡像,Rancher會啓動對應的容器,執行流水線配置的流程。
一個典型的jenkins流水線腳本,相似以下:
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils def label = "buildpod.${env.JOB_NAME}.${env.BUILD_NUMBER}".replace('-', '_').replace('/', '_') podTemplate(label: label, namespace: 'p-8j2pf-pipeline', instanceCap: 1, serviceAccount: 'jenkins',volumes: [emptyDirVolume(mountPath: '/var/lib/docker', memory: false), secretVolume(mountPath: '/etc/docker/certs.d/docker-registry.p-8j2pf-pipeline', secretName: 'registry-crt')], containers: [ containerTemplate(name: 'step-0-0', image: 'rancher/pipeline-tools:v0.1.0', ttyEnabled: true, command: 'cat' , envVars: [ envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'), ]),containerTemplate(name: 'step-1-0', image: 'maven:3.6.0-jdk-8-alpine', ttyEnabled: true, command: 'cat' , envVars: [ envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'),envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'), ]),containerTemplate(name: 'step-2-0', image: 'rancher/jenkins-plugins-docker:17.12', ttyEnabled: true, command: 'cat' , privileged: true, envVars: [ envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'PLUGIN_DOCKERFILE', value: './Dockerfile'),envVar(key: 'PLUGIN_CONTEXT', value: '.'),envVar(key: 'DOCKER_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'PLUGIN_REPO', value: '127.0.0.1:34350/scc/hyperloop/baseapi'),envVar(key: 'PLUGIN_TAG', value: 'dev'),secretEnvVar(key: 'DOCKER_USERNAME', secretName: 'p-8j2pf-12700134350', secretKey: 'username'),secretEnvVar(key: 'DOCKER_PASSWORD', secretName: 'p-8j2pf-12700134350', secretKey: 'password'), ]), containerTemplate(name: 'jnlp', image: 'rancher/jenkins-jnlp-slave:3.10-1-alpine', envVars: [ envVar(key: 'JENKINS_URL', value: 'http://jenkins:8080')], args: '${computer.jnlpmac} ${computer.name}', ttyEnabled: false)], yaml: """ apiVersion: v1 kind: Pod metadata: labels: app: jenkins execution: p-dd58c-27 spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - jenkins topologyKey: kubernetes.io/hostname """ ) { node(label) { timestamps { timeout(60) { stage('Clone'){ parallel 'step-0-0': { stage('step-0-0'){ container(name: 'step-0-0') { checkout([$class: 'GitSCM', branches: [[name: 'local/temp']], userRemoteConfigs: [[url: 'http://git.lumiai.top/york/hyperloop-baseapi.git', refspec: '+refs/heads/master:refs/remotes/local/temp', credentialsId: 'p-dd58c-27']]]) } } } } stage('打包'){ parallel 'step-1-0': { stage('step-1-0'){ container(name: 'step-1-0') { sh ''' echo "haha">baseapi.jar ''' } } } } stage('發佈'){ parallel 'step-2-0': { stage('step-2-0'){ container(name: 'step-2-0') { sh '''/usr/local/bin/dockerd-entrypoint.sh /bin/drone-docker''' } } } } } } } }
好了,說完原理,下面實操。
進入到Rancher管理平臺,依次進入dev(集羣)->service(命名空間),而後點擊流水線。
源碼管理使用本地Gitlab,代碼語言是Java,使用maven構建,提供REST風格的API接口。
目前Rancher只支持接入單個代碼庫,不支持多代碼庫同時接入。打開Gitlab,點擊我的設置->應用,而後配置應用信息,拿到應用ID和應用密鑰,最後回到Rancher輸入gitlab地址、應用ID和應用密鑰便可接入。
啓用任意代碼項目後,流水線首頁就會出現對應的數據,點擊編輯。
編輯頁面,可操做的東西很少,但很簡明易懂。
第一步克隆代碼,這一步是默認的也是必須和沒法編輯的。
點擊添加階段,輸入階段名,如「打包」,點擊完成
點擊添加步驟,步驟類型分三類,一類是運行腳本,一類是構建併發布鏡像,最後一類是部署YAML,每個階段能夠添加不少步驟。這裏點擊運行腳本,而後在下面鏡像那裏輸入maven:3.6.0-jdk-8-alpine,輸入完成後會出現提示框maven:3.6.0-jdk-8-alpine (Custom),鼠標點擊便可,最後在腳本那裏輸入mvn clean package。
打包完成後,再建立一個階段,叫「鏡像發佈」,再點擊添加步驟。
步驟類型是「構建併發布鏡像」,下面Dockerfile路徑指的是代碼中基於項目根路徑的Dockerfile路徑,鏡像名稱注意不用寫鏡像私服地址,但要帶有倉庫中對應項目名,好比harbor中我有一個項目叫shy,那麼這裏應該輸入shy/xxx:[xxx],再勾選下面的「推送鏡像到遠端鏡像倉庫」,選擇對應的鏡像庫便可。
特別須要注意的是,這一步會啓動一個叫rancher/jenkins-plugins-docker:17.12的鏡像,這個鏡像會使用默認的https推送鏡像,若是使用了Harbor,可是自簽證書,那麼這一步永遠過不去,必須是合法的CA證書。或者使用阿里雲的鏡像私服,那個CA證書確定得合法的。
鏡像發佈後,在建立一個階段,叫「上線部署」,再點擊添加步驟。
步驟類型是「部署YAML」,下面YAML路徑一樣指的是代碼中基於項目根路徑的YAML路徑。而後點擊添加, 在流水線配置的右下角有個「顯示高級選項」,打開他,配置觸發規則。也可不配置,每次手動執行。
最後點擊完成,即建立完一個完整的流水線。
一個服務不可能只有1個實例,多實例就致使日誌的排查比較困難,由於不知道訪問落到了哪一個實例上,因此一個集中式的日誌中心是頗有必要的。rancher針對每個命名空間都提供了一個專門的日誌採集接口,只須要配置日誌輸出便可。
打開全部的應用商店,搜索efk,而後點擊安裝。
接着,命名空間視圖下,點擊資源->日誌,選擇Elasticsearch,輸入剛剛建立的es的地址,肯定索引前綴,保存便可。指的注意的是,這裏的日誌粒度仍是有點粗的,只到項目這一層級,實際使用的時候,能夠多建項目,每一個項目一類服務的方式,規避粒度粗的問題。
1.x的Rancher,事先是不知道實際的IP地址的,每次都是先配置負載均衡,拿到IP再配置DNS解析。
2.x的Rancher,不用事先知道具體的IP了,訪問集羣內的任何一臺機器便可,而且不再用擔憂80端口不夠用的狀況。但因爲這個版本放棄了HA,採用的nginx,而且不支持自定義配置,致使目前只支持L7層的負載均衡。
Rancher的擴容很是容易,按照第三章的前7條執行,而後將此時的鏡像打包成系統鏡像,之後直接拿這個鏡像安裝系統。安裝完成後,直接在Rancher界面上添加主機,便可實現擴容,另外2.x的版本新主機的管理不須要手動進行,k8s會主動進行管理。
這裏說的咱們線上集羣的狀況,並進行了必定得推測。另外,docker最佳搭檔就是全部無狀態的服務,Rancher同理也最適合無狀態的服務,對於有狀態的,如mysql,最好不要丟到rancher或者說docker上運行,不穩定是其次,數據丟失可怕了。
物理機很重要,他是載體,決定了容器的狀況。
CPU:最低單U8核,越多越好,看具體狀況。
內存:32G是最低了,再少跑不了多少容器,咱們是64G。
硬盤:機械盤RAID5跑不了(這玩意讀取性能不高爲啥用他?由於生產中硬盤壞了很常見啊,呵呵),固然最好的仍是固態,但那玩意成本過高。
網卡:千兆的應該是標配了吧
1.x受限於cattle的編排能力,節點數最好保持在20臺左右,容器總量500如下,多了cattle就處理不過來了。
2.x對節點數量沒限制,可是節點的類型須要注意下:
worker:是工做節點,不限數量,咱們是除rancher自己外,其它都是worker
control:集羣控制節點,負責每一個pod的控制,咱們是設置了總機器數量的數量
etcd:k-v存儲,數量必須是奇數,咱們是設置了總機器數量的1/3
也就是說每3臺機器,有一臺的類型是worker和control以及etcd,其它兩臺是worker和control。
Rancher:主節點必須是高可用的,咱們是3個主節點,使用mysql存儲數據,中間用mycat代理。
Mysql:跑在物理機上,1主2從。
雖然Rancher是一個密閉的集羣,但宿主機被黑,跑在這上面的容器也會遭殃。但若是物理機若是開啓了防火牆,卻又會致使一些莫名的錯誤,這時該怎麼辦呢?
若是有本身的機房和機器,解決方案是:
一、關閉全部主機的防火牆,同時斷開一切與外網的鏈接,至關於一個密閉的局域網
二、將F5架設在局域網的前端,外網能夠訪問F5,內網也能夠訪問F5,但外網訪問不了內網。而後再將F5打形成一個堡壘機,最後全部請求經過F5轉發的對應的服務上。
若是是雲服務器,購買機器,不買外網IP,經過雲提供商的負載均衡訪問所購買的機器,這種和上面是如出一轍的。
最後說下登陸認證,企業通常使用ldap,或者直接數據庫密碼存儲。但推薦ldap,企業裏是很是方便的。