本文均爲我的工做中的一些理解,可能存在紕漏、疏忽、認知錯誤的地方,敬請諒解,歡迎評論區討論。java
通常來講,若是說要作容器化,那就是兩個方向,docker swarm或者k8s,前者複雜度低一些,易於從docker-compose轉換。後者功能完善,可是學習和維護難度很高。nginx
我的認爲,若是計劃作容器化,目前幾乎沒有什麼理由去選擇swarm了。除了ConfigMap、Secret,或者Ingress,k8s好用的功能還有很多,swarm幾乎沒有什麼優點。
不過若是是計劃將零散的docker-compose部署的服務快速聚合起來,統一管理,那swarm 仍是能夠一用的。
可是我這裏爲何要單獨把 容器化 和 k8s 分開說呢?由於目前所在的公司,採起的策略就是隻作「容器化」:
將服務環境,代碼,配置文件等全部依賴項打包爲基礎容器和Dockerfile,使用docker-compose的方式控制。除此以外,其他全部因素不變。
從服務部署的角度來講,服務確實被打包了,若是須要擴容/遷移,docker容器天然是比直接在宿主機上部署方便了許多。可是停留在這個階段,我以爲不合理。git
簡單來講,咱們目前的「容器化」是這麼作:docker
dockerfile
+docker-compose.yaml
咱們也確實有了一些收益:
一、每當服務器擴容時,無需在服務器上配置服務環境,只需安裝docker+部署服務,若是後續服務器轉作他用,也不用擔憂是否會有影響。
二、服務一致性獲得保證,同樣的代碼能夠獲得同樣的結果,宿主機很難影響到容器,幾乎不會出現同一個版本代碼在不一樣服務器上表現不一致的狀況。
可是運行一段時間後,我以爲這樣作的收益並無很高:
一、沒有辦法縱觀全局,觀測全部服務,每一個服務的運行狀態仍是須要登陸對應的服務器才能看到。這樣和不作容器化沒有什麼區別。
二、nginx配置並不能與容器聯動,一旦容器須要更換服務器仍是須要手動更新(靜態維護,compose寫死docker內網IP)
三、雖然配置了服務日誌收集,可是一旦服務部署的服務器有變更,仍是須要人工修改日誌收集的agent。後端
正如這一段的標題,爲何不繼續向前走?作的更多?你上swarm/k8s不就能在master上管理整個集羣了嗎?
是的,不管是swarm仍是k8s,都是能夠選擇的,可是因爲現實的種種緣由,目前只能停留在這一步。服務器
把代碼和環境打包在一塊兒只是容器化的第一步,還須要繼續往前走,才能解決殘留問題。靜態維護容器,其實有點把容器當虛擬機的意味,只不過每一個虛擬機裏只有一個服務。理想狀況下,容器變更致使的路由問題和服務間互相發現/訪問都應該是自動的,而非靜態。
不管是直接使用docker,仍是用docker swarm仍是有不少問題須要人爲去解決。而k8s都有方案。
基於我對於k8s淺顯的理解,我以爲,推動容器化,應該有如下幾個問題要關注和解決:
一、配置和日誌:
配置:能夠直接用ConfigMap+Secret解決。
日誌:Sidecar模式比較不錯,直接在Pod內啓動一個agent負責這個Pod內的全部文件日誌收集。Pod之間不共享。
日誌服務端也有幾個可選項,通常用ES,若是日誌量很小也能夠用loki(日誌正文無索引,可是更輕便)。運維
雖然經過stdout/stderr收集日誌也能夠,可是這樣沒有Sidecar方式靈活。並且日誌能夠經過文件名進行更多區分。通常仍是會選擇Sidecar方式收集日誌。
這兩個問題解決了,容器就已經能夠基礎的運行:ide
二、請求路由和服務發現/服務間的互相請求:
除了上述這個點,還有一些點須要去討論:容器在調度過程當中會發生變更,被殺死或者重啓的。gitlab
Ingress我以爲能夠算是k8s的入口網關了,一個Ingress資源須要一個實際的Ingress Controller才能實現。通常來講,用Ingress-nginx就能夠。
其次,Service能夠將服務抽象,對外提供一個穩定的虛擬endpoint,能夠用於鏈接,對內能夠按照label轉發請求到Pod上。
這樣訪問Service就能夠將請求發送到對應的Pod,而不須要直接訪問Pod。學習
關於服務發現和服務間的請求,coreDNS徹底能夠解決。每一個Service建立後,都會在DNS內留下記錄,其餘服務能夠直接使用DNS訪問
通常來講,域名全程爲:<service-name>.<namespace>.svc.cluster.local
,後面的能夠省略,指定<service-name>.<namespace>
就能夠確切訪問到服務了,經過這樣簡單的方式進行服務發現,那麼服務間的互相訪問也天然沒有太大問題。
這兩個問題解決以後,請求能夠順利從外部路由到目標容器,榮期間也能夠順利互相發現/互相訪問。
那麼若是要跨越這一步,實現完整的容器化,距離還有多遠?還須要解決什麼問題?
雖然沒法實際去操做,去將當前的項目改形成k8s,可是這並不妨礙思考一下,「如今距離徹底k8s化有多遠,還須要解決那些問題。」
先從單個容器來講:
代碼配置方面,是在阿里雲ACM上,代碼直接拉取的。改成ConfigMap應該沒有太大問題。
日誌收集方面,目前是使用的promtail作爲agent,將日誌發送到loki。改成Pod內增長一個promtail容器也應該沒有太大問題
promtail的配置能夠存在ConfigMap上,不一樣的服務按照命名區分就能夠了。
還有一個要注意的點,就是docker必定要配置容器日誌大小限制,以避免docker日誌打滿。
因爲日誌會先寫服務容器內,再被promtail容器讀,不須要保留太多,通常也不須要直接登陸容器看文件日誌。
服務路由和服務發現方面:
從nginx靜態路由改成Ingress-nginx因該也不會有太大困難,把如今的nginx配置導入,後端轉發到Service就能夠了。
目前服務發現很簡單粗暴,直接訪問其餘內網域名(每一個服務配置了一個內網域名),從nginx繞一圈。這個改動並不大,只不過從內網域名改爲Service域名就能夠了。
部署發佈方面:
目前使用jenkins+gitlab 來實現代碼發佈,測試和預發佈環境都是分支觸發,對應分支有代碼提交就會觸發部署。(特殊分支只能merge,不容許直接提交)
這部分應該不須要太大改動,只是實際的部署執行步驟須要改一下。
服務監控打點方面:
目前對於服務本身的監控沒有太大需求,如今服務自身沒有任何打點。
若是要用的化,仍是promtheus比較合適,官方對於java、go都有客戶端。自定義打metric難度不大。
目前來講,我以爲這些問題若是都能實際解決,應該就能比較好的完成遷移。固然實際過程當中必然也會遇到不少問題,不過見招拆招嘛,有問題解決問題就能夠了。
在結論部分,我以爲要先強調的一點是:不一樣人看待問題的角度不一樣,不能說誰對誰錯。
從運維的角度來講,上k8s很好,部署新服務很簡單,服務器擴容/縮容也方便了許多,再也不強依賴宿主機等等。
可是從全局管理的角度來講,可能會有不少考慮:
一、如今的痛點是否能夠接受,有不必立刻上k8s,上了以後會不會有什麼問題。
二、研發都須要對k8s有必定理解,每一個研發都須要再學習。不然在開發/調試/查問題上有影響。
三、相比於nginx靜態配置+靜態服務來講,k8s動態的地方多了不少,依賴也多了不少。維護整個系統須要關注更多的內容(好比etcd)一旦出現問題須要更多的知識才能調查清楚。
簡而言之,引入k8s,對於運維角度來講,無疑是大好事,各方面都更好。可是,不管是引入k8s仍是引入其餘新的技術,都須要綜合權衡,才能讓服務愈來愈好。