大數據組件包括Hadoop(HDFS、YARN)、Hbase、Spark等等。優劣勢是什麼?生產環境下會存在哪些問題或隱患?什麼類型的場景適合使用這種方式?什麼類型的公司適合使用這種架構?


Kubernetes Docker 你會遇到什麼問題

netkiller:Kubernetes Docker 你會遇到什麼問題?

zhuanlan.zhihu.com圖標

在項目中實施容器技術,你可以遇到下列問題

鏡像遇到的問題

目前docker 鏡像,沒有統一標準,體現在一下幾個方面。

使用OS發行版不統一

在使用過程中會遇到過各種本班的 OS。包括 alpine, debian, ubuntu, centos, oraclelinux, redhat 等等……

經過裁剪的 OS 面目全非,不完整

即使是鏡像採用 CentOS 母版,很多鏡像製作者會給操作系統減肥。經過優化後,已經不是官方版本,在使用過程中你會遇到各種麻煩。例如調試的時候需要 curl,wget,telnet,nslookup 等工具在鏡像中沒有。甚至 ps, top, free, find, netstat, ifconfig 命令都沒有。

很多容器都不帶 iptables 所以,即使帶有iptables 在容器中修改規則也很麻煩。

安裝位置不統一

傳統OS 以 CentOS為例,有嚴格的安裝規範,例如:

通常安裝位置是:

/etc/example 配置文件

/bin/sbin 二進位文件

/var/lib/example 數據文件

/var/log/example 日誌文件

/var/run/example PID 文件

/etc/sysconfig/example 啟動參數文件

/etc/system.d/example 啟動腳本

或者被安裝在:

/usr/local/etc 配置文件

/usr/local/bin 可執行文件

/usr/local/share 文檔

最後一種是獨立安裝在:

/usr/local/example 下

容器鏡像那可是五花八門,沒有統一標準,如果不看 Dockerfile 根本不知道作者將文件安裝到了哪裡。

常常存儲目錄被放置在根目錄。例如 /data

Linux 系統也存在BUG

在我的20年執業生涯中是遇到過 Linux 系統有BUG的,還向 Redhat 提交過 BUG。如果你採用的鏡像有BUG,你想過怎麼去debug 嗎?

容器遇到的問題

程序啟動的區別

在Linux是一般是採用守護進程方式啟動。啟動後進入後台,啟動採用 systemd 。

容器中啟動通常是直接運行,這樣的運行方式,相當於你在linux的Shell 終端直接運行一樣,是在前台運行,隨時 CTRL + C 或者關閉終端窗口,程序就會退出。容器採用這種方式啟動,就是為了讓 docker 管理容器,docker 能夠感知到容器的當前狀態,如果程序退出,docker 將會重新啟動這個容器。

守護進程方式需要記錄 pid 即父進程ID,用於後面管理該進程,例如可以實現 HUP 信號處理。也就是 reload 操作,不用退出當前程序實現配置文件刷新。處理 HUP 信號,無需關閉 Socker 埠,也不會關閉線程或進程,用戶體驗更好。

容器是直接運行(前台運行),所以沒有 PID 也不能實現 reload 操作。 配置文件更新需要重新啟動容器,容器啟動瞬間TCP Socker 埠關閉,此時用戶會 timeout。甚至該服務可能會引起集群系統的雪崩效應。

很多鏡像製作者更趨向使用環境變數傳遞啟動參數。

當然你也可以在容器中使用 systemd ,這樣做容器不能直接感知到容器的運行狀態,systemctl stop example 後,容器仍然正常。需要做存活和健康檢查。通過健康狀態判斷容器的工作情況。如果處於非健康狀態,將該節點從負載均衡節點池中將它踢出去。

Linux 啟動一個應用遠遠比docker 啟動一個容器速度要快。因為物理機或者虛擬機的Linux操作系統已經啟動,虛擬機也分配了資源,運行可執行文件基本上是瞬間啟動。而 docker 啟動容器,要分配資源(分配內存和CPU資源,新建文件系統),相當於創建一個虛擬機的過程,最後載入約200MB左右的鏡像,並將鏡像運行起來,所以啟動所需時間較長,有時不可控,尤其是Java應用更為突出。

存儲面臨的問題

傳統 Linux 直接操作本地硬碟,IO性能最大化。

私有雲還好辦公有雲處處受限。

自建的 Docker 或 Kubrnetes 可以使用宿主主機資源,公有雲只能使用網路文件系統和分散式系統。

這也是我的架構中 KVM,Docker,Kubernetes,物理機混合使用的原因,根據業務場景的需要來選擇哪種方案。

物理機上部署 docker 可以分配宿主主機的所有資源,適合做有狀態的服務的存儲持久化的需求。

私有雲 Kubernetes 適合做 CPU密集型運算服務,雖然通過local 卷和 hostPath 可以綁定,但是管理起來不如 Docker 更方便。

NFS 基本是做實驗用的,不能用在生產環境。我20年的職業生涯遇到過很多奇葩,例如 NFS 卡頓,NFS 用一段時間後訪問不了,或者可以訪問,文件內容是舊的等等。

無論是NFS是更先進的分散式文件系統,如果不是 10G乙太網,基本都不能用在生產環境。10年前我用4電口1G網卡做埠聚合勉強可以用於生產環境,不過10年前的互聯網生態跟當今不同,那時還是以圖文為主,確切的說是文字為主,配圖還很少。

所以涉及到存儲使用分散式文件系統的前提是必須是 10G以上乙太網或者8G以上的FC 存儲。這樣才不會有IO瓶頸。任何分散式文件系統都不可能比本地文件系統穩定,除了速度還有延遲等等。

10GB 電口,光口乙太網已經出來十幾年了,相對比較便宜,可以使用 4光口 10G網卡,然後做埠聚合,變成 40G 網口。

現在 40G光口交換機都在10-20萬之間。一個40G的交換口可以分出四個10GB口。

如果使用40GB以上的乙太網,那麼總成本可能會超過物理機+虛擬機的解決方案。

內部域名DNS

由於在集群環境中容器名稱是隨機,IP地址是不固定的,甚至埠也是動態的。為了定位到容器的節點,通常集群中帶有DNS功能,為每個節點分配一個域名,在其他容器中使用域名即可訪問到需要的容器。

看似沒有問題,我的職業生涯中就遇到過DNS的問題,bind,dnsmseq 我都用過,都出現過事故。解析卡頓,ping www.domain.com 後遲遲解析不出IP。最長一次用了幾分鐘才解析到IP地址。

所以後面就非常謹慎,配置文件中我們仍然使用域名,因為修改配置文件可能需要 reload 應用,或者重新部署等等。域名寫入配置,方便IP地址變更。例如 db.host=db.netkiller.cn 同時我們會在 /etc/hosts 中增加 xxx.xxx.xxx.xxx db.netkiller.cn 。這樣主要使用 /etc/hosts 做解析,一旦漏掉 /etc/hosts 配置 DNS 還能工作。

故障分析,DNS 使用 UDP 協議 53 埠,UDP 在網路中傳輸不會返回狀態,有無數種可能導致 DNS 解析失敗。例如內部的交換機繁忙,背板帶寬不夠(用戶存儲轉發數據包,你可以理解就是交換機的內存),路由的問題等等……

容器與網路

相比傳統網路,容器中的網路環境是十分複雜的。傳統網路中一個數據包僅僅經過路由器,交換機,達到伺服器,最多在服務前在增加一些防火牆,負載均衡等設備。

容器網路部分實現方式SDN(軟體定義網路)相比物理機(路由器、交換機、無服務)實現相對複雜。容器裡面使用了IP轉發,埠轉發,軟路由,lvs,7層負載均衡等等技術…… 調試起來非常複雜。docker 的 iptables 規則很頭痛。

例如一個TCP/IP 請求,需要經過多層虛擬網路設備(docker0,bridge0,tun0……)層層轉發,再經過4層和7層的各種應用拆包,封包,最終到達容器內部。

有興趣你可以測試一下對比硬體設備,容器的網路延遲和吞吐量。

容器的管理

傳統服務可以通過鍵盤和顯示器本地管理,OpenSSH 遠程管理,通過配置還能使用串口。

容器的管理讓你抓狂 docker exec 和 kubectl exec 進入後與傳統Linux差異非常大,這是鏡像製作者造成了。

有些鏡像沒有初始化 shell 只有一個 $ 符號

沒有彩色顯示

可能不支持 UTF-8,中文亂碼

可能不是標準 ANSI/XTerm 終端

鍵盤定義五花八門,可能不是美式104鍵盤

國家和時區並不是東八區,上海

HOME 目錄也是不是 /root

想查看埠情況,發現 netstat 和 ss 命令沒有。

想查看IP地址,發現 ifconfig, ip 命令沒有。

想測試IP地址是否暢通,發現 ping, traceroute 沒有。

想測試URL,發現 curl , wget 沒有。

有些鏡像 dnf,yum,apk,apt 可以使用,有些鏡像把包管理也給閹割了,你想安裝上述工具都安裝不了。

卧槽!!! 一萬匹草泥馬

然後就自己用 Dockerfile 編譯,整出200MB的鏡像,卧槽這麼大。

容器與安全

很多容器的鏡像中是不包含 iptables 的,所以無法做顆粒度很細的容器內部網路安全設置。即使你製作的鏡像帶有iptables ,多數容器的側咯,IP地址和埠是隨機變化的。

綁定IP地址又帶了容器的複雜性。

一旦攻入一個容器,進入容器後,容器與容器間基本是暢通無阻。

在容器中藏一個後門比物理機更容易,如上文所說很多容器中沒有調試相關命令,限制了你排查後門的難度。所以Dockerfile 製作鏡像,最好使用官方鏡像衍生出你的鏡像。

容器與監控

談到監控,跳不開 prometheus(普羅米修斯),它並不能覆蓋到所有監控。

我曾經寫過一篇文章《監控的藝術》網上可以搜到。

容器與CI/CD

在DevOps場景中,使用 docker 或 kubernetes 做 CI/CD 是很扯淡的。

當 git 產生提交後,gitlab/jenkins 啟動容器,下載代碼,編譯,打包,測試,產生構建物,編譯 Dockerfile ,上傳 docker 鏡像到 registry,最後部署到容器執行。

卧槽!!!速度能急死你。

於是乎,我們做了 Cache。 不用每次都 pull 鏡像,緩存 Maven 的 .m2 庫,不再清理代碼(mvn clean)提速不少,測試環境湊合用吧。 注意不mvn clean 有時會編譯出錯

至於生產環境,我就不說了,有多少人真用CD部署生產環境。

人員的問題

現實中真正精通容器應用的人很少,容器實在太複雜。Google 將 Kubernetes 設計成大而全系統,想用 Kubernetes 解決所有問題。它涵蓋了幾大塊。

操作系統,虛擬化,軟體定義網路,存儲,容器管理,用戶體系,許可權體系……

我們的大學教育是本科教育專科化,本科教育本應該重視通識教育,我們的教育卻按照專科標準教育。本科是面向學術的起點,專科是面向工作,解決實際問題。

你問一個中國大學生他會什麼,他會說:我會Java,我會Linux……

反應到工作上,就是程序猿不懂運維知識,運維攻城獅不會寫程序。員工更趨向深耕一個領域,很類似現在的醫生教育和醫院體系,專科化,割裂化,導致很多跨科的疾病難以診斷。

於是我提出了「多維度架構」。

最後總結

使用物理機,虛擬機,學習成本,試錯成本,部署成本遠遠低於容器技術。

Google 官方也曾經說過,未來 kubernetes 重點可能會轉向虛擬機。

我個人認為容器更適合CPU密集型的業務。

我的架構中 KVM,Docker,Kubernetes,物理機混合使用,根據業務場景的需要來選擇最佳方案。

前期製作符合你需求的鏡像,可能需要花費很長時間。

netkiller:Kubernetes(minikube) 私有 registry 使用詳解?

zhuanlan.zhihu.com圖標netkiller:Kubernetes Registry?

zhuanlan.zhihu.com圖標

分享一下大豬廠基於 Kubernetes 和 Docker 構建構建猛獁大數據平台機器學習模塊(內部代號Dolphin )的一些思考。

Dolphin 基礎設施中包括了 GPU 和 CPU 的混合計算服務節點,通過 Docker 對多種機器學習框架、用戶開發環境進行實例化和運行,通過 Kubernetes 提供計算集群的部署、維護、 擴展機制等功能,計算框架主要是 Tensorflow。

Why Tensorflow on Kubernetes?

如果讓數據科學家直接使用 Tensorflow,他們會遇到例如租戶隔離、資源隔離、網路隔離、難以指定 GPU 進行任務調度等等一系列軟體工程問題。

  1. 資源隔離:Tensorflow 資源無法隔離
    ,Kubernetes 提供租戶隔離,容器資源隔離和網路隔離等多種機制
  2. GPU 調度:Tensorflow 缺乏 GPU 資源的調度
    ,Kubernetes 1.4 開始支持 GPU 調度
  3. 進程管理:Tensorflow 存在進程遺留問題、無法區分正常完成還是故障退出
    ,Kubernetes 提供容器生命周期管理,進程和容器共生死
  4. 伺服器定位
    :Kubernetes 提供 DNS 伺服器提供伺服器位置,省去了 Tensorflow 的計算集群的服務節點 IP 地址配置
  5. 監控:Tensorflow 不方便日誌查看
    ,Kubernetes 提供了較為完善的 Monitoring 和 Logging 功能
  6. 存儲:Tensorflow 存在訓練數據和模型存儲問題
    ,Kubernetes 支持對接 Cephfs,GlusterFS 等 Read 性能更好的分散式存儲系統
  7. 多框架支持
    :通過定製化開發 Kubernetes 的 Custom Resource 和 Operator 介面支持 MXNet 等其他機器學習框架

當然,基於當時兩個項目在任務管理方面的實際進展,團隊也做了相應的優化:

  • 開發了基於隊列的任務調度系統,解決了 Kubernetes 沒有隊列服務的問題
  • 開發了計算節點的 GPU 監控服務,解決了 Kubernetes 目前無法監控 GPU 的資源使用情況的問題
  • 開發了 Kubernetes 中訓練服務的參數服務的生命周期管理模塊,解決了 Tensorflow 的參數服務在訓練完畢無法自我關閉的問題

最後,Dolphin 可以根據數據科學家選用的不同的機器學習演算法框架,通過 Kubernetes 編排出相應的機器學習計算集群。

如下圖所示,通過 Dolphin 調度起來的 Tensorflow 計算集群,創建出 Parameter Server 和 Work 的 POD 以及 SVC,通過 HDFS Mount 模塊將用戶數據空間映射到 Docker Container 中,執行用戶的演算法腳本進行模型訓練和服務發布。

by 劉勛,網易大數據團隊攻城獅


這個問題我們團隊是做過一些相關實踐的,當初希望使用K8s治理和編排Docker容器,然後實現spark等大數據組件的一個容器化管理。先說下產生這個想法的背景和遇到的坑:

1,背景:多版本計算資源,再明確一點來說就是,我們存在著一個場景,很多用戶有自己的spark任務,但是他們的spark的版本都不同,但是想在我們的集群上跑。

2,解決方案1:客戶自己去改代碼,支持我們的版本(不現實,他們才懶得改);解決方案2:利用yarn的支持,安裝幾個版本的spark依賴,此方案可行,但是你會發現一個問題,基本上只能兼容spark1和spark2兩個大版本,小版本不行;解決方案3:容器化spark計算節點,然後封裝各個版本的spark鏡像。

3,最後我們選了方案3,其實也是想試試這種方案是否可行,然後遇到了一些坑,也和你的提問有關係。

第一個坑,存儲資源不要用容器化去封裝,hdfs的DataNode節點要是容器化了,你會發現非常難處理,綁定本底卷?不行,萬一一台機器上的DataNode掛了在另一個機器上重啟了,如何繼續保持對應關係,而且資源不好隔離,監控上每個進程看到的存儲基本都是物理機真實存儲大小,導致了資源統計翻倍。

第二個坑,我們當時使用的是Rancher可視化k8s的編排工作,但是默認情況下,所有容器間的數據傳輸是加密的,導致了計算速度減慢了75%,後來發現了這個原因進行了無加密傳輸。

第三個坑,社區版的spark鏡像bug很多,現在可能好很多了,計算節點之間要維護狀態,當容器毀掉了一個,重新初始化的時候如何能夠正常工作,其實需要考慮很多細節。

說了這麼多來回答你的問題

優勢:靈活,兼容多版本,計算資源可以隨時銷毀和建立,而且有個可視化的工具,看起來更直觀

劣勢:大數據和容器在一起真的會打架,容器對大數據不友好,慢又不穩定。所說的不穩定基本都是一些鏡像上的bug和考慮不全面的地方。

隱患:當你有緊急任務的時候,萬一報錯了,不知道錯誤原因,可能是鏡像本身的問題,那麼修復起來很難。

適合場景:偏研究的環境,存儲類的資源全部物理機實體化,上層只封裝計算資源,基本上我覺得線上的環境最好不要用這種方式,一些線下計算的場景可以使用。


以往跑在 Kubernetes 上的大多數都是一些在線服務類型的應用,很容易發現,對於在線服務,很多是有流量的峰谷的,白天請求多,晚上請求少,應用如果是在物理機或者虛擬機,怎麼把空閑的 CPU/Memory/Network 利用起來呢?挺難搞的反正,一般應用或者一些 crontab 任務跑不滿 cpu,而且由於資源隔離的問題,誰敢在一個重要的在線服務的機器上亂搞事情呢,把機器搞掛了,你也得掛了。

Kubernetes 上就簡單多了,在離線混合部署,共用一套集群,Spark on Kubernetes 就是把原來 on Yarn 的那一套 Cluster Manager 換掉,Spark 2.3 開始已經官方開始搞了,更不說現在一堆的大數據相關的 Operator 了,敢搞的 xxx on Kubernetes 基本問題不大的。在某些方面,優勢還是很明顯的,以前運維搞一套環境,這個庫不合適那個庫不兼容,虛擬機下搞得頭都大,現在打一個鏡像就 ojbk 想要什麼依賴什麼庫自己搞就得了,省了很多跟運維打交道的時間,這不就非常大的優勢嗎。還沒想到有什麼劣勢,可能學習成本是一個,至少你得看一眼 Docker。


(`?ω?′)

運行在docker里worker環境統一 少很多傻逼問題

我們有hive語句utc timestamp不同機器出來時間不一致的問題 剛好八個小時

細想肯定是裝機時有些機器設locale有些機器改了時間 吃到屎 沒法查 那麼多機器怎麼查

還有op下環境沒下光導致集群任務分到這台機器就花式失敗

docker內一把梭就沒有這些問題 要死都是一起死的

不過hadoop fs本身是個有狀態的東西 還有一些支持的問題就不說了


k8s目前有兩個難解決的點:

1.有狀態服務不好做 (能做,但在國內落地的少)2.docker對性能或多或少有些損耗

hdfs、hbase這種存儲系統,甚至消息隊列kafka,都是有狀態的。決定了他們上k8s很難。

hbase、kafka甚至mysql此類系統,又常用於生產系統,對SLA,latency要求越快越好,因此直接用物理機符合讓業務更快這個終極目標。

如果在「對SLA」要求不高的場景,把hbase、kafka、mysql上k8s也未嘗不可。國內也有些公司這麼做了。

另外計算類框架,基本都是無狀態居多。spark/flink目前都出了run on k8s的版本。

就說這麼多把。


性能會有一定的影響,但是打通了開發,測試和運維的壁壘,極大的提升了工作效率。

典型的DevOps思想到實踐的落地。

降低了低端運維的人數,提高了高端運維的人數,運維人員定位問題,又多了一層。


有哪些公司開始用了?感覺用了性能,運維都是問題


說個讓人討厭的答案,黑貓白貓,能抓住老鼠的就是好貓。其實這些大數據組件,可以用於數據處理和應用,也可以用戶純粹的後端應用場景,我自薦自己的專欄,讓數據能賺錢,從頭開始講數據和技術是怎麼產生價值的。

對於如何評價讓大數據組件運行在Kubernetes、Docker,其實就是自行車騎得熟練了,發現不扶車把騎車會更輕鬆一點,比彎著腰強。


推薦閱讀:
相关文章