標籤:

關於GitHub遷移到K8S的最佳實踐,你最看重哪方面?

全球最大的代碼託管和編程社交網路的GitHub,近期已經在開發、SRE等團隊的配合下將服務切換到Kubernetes,因為其坐擁千萬用戶和億級代碼倉庫,這可不是一個小工程,今天數人云就跟大家分享下GitHub遷移到Kubernetes的整個過程。

在過去的一年中,GitHub逐步發展了運行Ruby On Rails應用的基礎設施,該應用負責github.com和api.github.com。目前所有的WEB和API請求都由運行在GitHub Metal Cloud上的Kubernetes容器集群中。

將關鍵應用遷移到Kubernetes是一個非常有意思的挑戰,今天就給大家分享下:

為什麼嘗試改變——釋放SRE工程師

在此之前,主要的Ruby On Rails應用(github/github)還類似於8年前:「Unicorn processes」由Ruby進程管理器調用運行在 Puppet-managed的「God」。同樣的,部署ChatOps如同第一次引入時所作:Capistrano在每個前端伺服器上建立SSH連接,然後更新代碼,重新啟動應用,當峰值請求負載超過可用的前端CPU容量時,GitHub站點的SRE會釋放額外的容量,並將其添加到活動前端伺服器池當中。

在近幾年中,雖然基本生產方法沒有太大的變化,不過GitHub本身有了很多改變如:新的功能、更大的社區、更多的員工、以及更多的需求。所以這也就產生了很多新的問題,許多團隊想將其負責的功能從某個大的應用中提取出來,形成一個可以獨立運行和部署的小型服務。伴隨著運行服務數量的增加,SRE團隊開始為數十個其他應用提供類似的配置,從而增加了在伺服器維護、配置和其他工作上花費的時間,但這些工作又和改進整個GitHub的工作流程沒有直接關聯。

新服務因為它們的複雜性和SRE團隊的時間問題,需要幾天、幾周或者幾個月的時間來進行部署,隨著時間的推移,一些問題逐漸顯現:這種方法並沒有為工程師提供他們需要的靈活性,以繼續構建世界級的服務。

工程師們需要一個自助平台,可以在上面試驗、部署和擴展新的服務,還需要同樣的平台來滿足Ruby On Rails應用的需求,這樣工程師或機器人就能以秒、天或更長的時間來分配額外的計算機資源去響應需求的變化。

為了滿足這些需求,SRE、平台和開發者體驗團隊開始了一個聯合項目:每天數十次地將github.comapi.github.com的代碼部署到Kubernetes集群。

為什麼是Kubernetes?

為了評估「平台即服務」的工具,GitHub仔細研究了Kubernetes,它是Google的一個項目,用於自動化部署、擴展和管理容器化應用的開源系統,通過以下幾點為Kubernetes特性做了評估:該項目獲得了火熱的開源社區支持,首次運行實踐(允許部署小型集群和應用在最初的幾個小時),大量關於設計的經驗。

因此迅速地擴大了實驗力度和範圍:立了一個小的項目去構建Kubernetes集群和部署工具,用來支持即將到來的Hack Week從而獲得一些實際場景中的經驗,GitHub內部對這個項目反映非常積極。

為什麼從github/github開始?

在項目最初階段,GitHub做了一個深思熟慮的決定:關鍵性工作負載的:github/github遷移,許多因素促成了這一決定,比較重要的幾點是:

  • 需要自助擴展工具來處理持續的增長
  • 希望確保開發習慣和模式適用於大型應用和較小的服務
  • 可以更好地將應用與開發、Staging、生產、Enterprise、和其他環境隔離
  • 遷移一個關鍵的、高知名度的工作負載可以激發信心,讓更多的Kubernetes在GitHub上採用。

Rapid iteration and confidence building with a review lab

作為遷移的一部分,進行了一些設計以及原型,並驗證了前端伺服器使用Kubernetes的基礎服務如:Pod、部署和服務。通過在容器中運行gitub/github現有的測試套件,可以對這種新設計進行一些驗證,但仍需觀察這個容器是如何成為更大的Kubernetes資源一部分的,很快就清楚地認識到,在驗證階段,對Kubernetes和打算運行的服務進行探索性測試環境是必備的。

與此同時,項目成員觀察到,現有的github/github抓取請求的模式已經開始顯示出增長十分困難的跡象,部署速度和工程師的數量成正比,使用幾個額外的部署環境作為驗證拉取請求到github/github的部分過程也是如此,在工作高峰時,功能齊全的部署環境數量往往是固定的,這就降低了部署拉取請求的過程,工程師門經常要求在「Branch Lab」中測試更多的子系統,同時允許多名工程師同時進行部署,但每個工程師只能啟動一個「Unicorn Process」,所以只在測試API和UI變更時有用,因為這些需求重疊很多,所以可以將這些項目結合起來,並開始在github/github上開發一個新的基於Kubernet/github的部署環境,被稱之為:Review Lab。

  • 在構建Review Lab的過程中,還發布了幾個子項目:
  • 在AWS VPC上運行的Kubernetes集群管理使用了Terraform & Kops
  • 一組Bash集成測試使用短暫的Kubernetes集群,後來在項目開始時大量使用,增強對Kuberbetes的信心。
  • 一個github Dockerfile/github
  • 對內部CI平台的增強,用來支持構建和將容器發布到容器註冊中心
  • YAML表示50+Kubernetes資源,簽入github/github
  • 對內部部署應用的增強,支持將Kubernetes的資源從一個存儲庫部署到Kubernetes的命名空間,以及從內部存儲庫中創建Kubernetes
  • 該服務結合了Haproxy和Consul-Template,將Unicorn Pods路由到現有的服務,發布服務信息。
  • 一種讀取Kubernetes事件的服務,並將異常事件發送給內部服務跟蹤系統
  • 一種名為kube-me且與Rpc兼容的服務,通過聊天向用戶公開一組有限的kubectl命令。
  • 最終的結果是一個基於聊天的界面,用於為任何拉取請求創建GitHub的獨立部署,一旦請求通過了所有需要的CI任務,用戶即可部署他們的請求:

如同之前的「Branch Lab」一樣,實驗室在最後一次部署後就被清理掉,由於每個實驗室都是在其Kubernetes名稱空間中創建的,清理工作就像刪除名稱空間一樣簡單,部署系統會在需要時自動執行。

Review Lab是一個成功的項目積累了許多經驗和成果,在為工程師提供這種環境之前,還為Kubernetes集群設計提供了必要的驗證基礎和原型環境,以及Kubernetes資源的設計和配置,這些資源現在用以描述github/github的工作負載,在發布後,它幫助工程師建立了信心,GitHub非常滿意這個環境賦予工程師實驗和通過自助的方式去解決問題。

Metal Cloud上的Kubernetes

  • 隨著Review Lab的發布後,注意力就轉移到了github.com上,為了滿足關鍵服務的性能的可靠性需求(依賴於低延遲訪問其他數據服務),需要構建Kubernetes的基礎設施,去支持在物理數據中心和POP中運行的雲計算,同樣,有12個子項目:
  • 關於容器網路,因為一個及時且詳盡的帖子,GitHub選擇了Calico,其提供了需要在IPIP模式下快速發送一個集群的功能,與此同時也提供了可以在以後的網路基礎設施中進行探索的靈活性。
  • 通過十幾次閱讀Kelesyhightower寫的《Kubernetes the hard way 》,GitHub將一些手動操作的伺服器組裝到了一個臨時的Kubernetes集群中,此集群通過了相關測試。
  • 還構建了一些小工具,為每個集群生成所需的CA和配置,格式可以由Puppet和Secret Systems 使用。
  • 對兩個實例配置進行了處理:Kubernetes節點和Kubernetes Apiservers,這種方式允許用戶提供已經配置的集群名稱,以便在規定的時間內引入。
  • 構建了一個小型的Go服務,用於消耗容器日誌,將Key/Value格式的元數據附加到每一行,並將它們發送到主機的本地Syslog端點。
  • 加強內部負載均衡服務,用來支持Kubernetes Node Port。

這些工作並沒有白費,都通過了內部驗收測試的集群,因此,GitHub的信心十足,同樣的一組Inputs(由Review Lab使用的Kubernetes資源),相同的數據集(網路服務Review Lab連接到VPN上),同樣的工具都會產生類似的結果,不到一周,雖然大部分的時間都花費在了內部通信和排序上,但對遷移產生了非常重大的影響:可以將整個工作負載從運行在AWS上的Kubernetes集群遷移到一個運行在GitHub數據中的集群。

Raising the confidence bar

Kubernetes集群在Github Metal Cloud上的成功和可複製性,所以是時候對「Unicorn」進行部署來替代當前前端伺服器池了,在GitHub,工程師及其團隊通過創建一個Flipper特性去驗證新功能是很常見的做法,若可行即選擇它,然後加強部署系統再去部署一套新的Kubernetes資源,github-produciton名稱空間和現有的生產伺服器,提高GLB支持員工請求路由到不同的後端:基於Flipper-infuenced的cookie,允許員工在任務控制欄的一個按鈕上選擇實驗Kubernetes後端。

來自內部用戶的負載可以幫助發現問題、修復BUG,並開始適應Kubernetes的生產,在此期間,通過模擬未來想要執行的應用、編寫運行手冊和執行Failure Tests來增強信心,還將少量的生產流量路由到這個集群,去確認對於負載下性能和可靠性的設定,從每秒100個請求開始,然後擴展到github.comapi.github.com請求的10%,在幾個模擬試驗中曾短暫地停止用來重新評估完全遷移的風險。

Cluster Groups

因為一些Failure Tests導致了意料之外的結果,特別是模擬單個Apiserver節點故障的測試破壞了集群,這種方式對運行工作負載的可用性造成了負面影響,根據調查顯示,這些測試沒有取得決定性的效果,但幫助識別出相關的破壞可能是一個相互作用的各種客戶連接到Kubernetes Apiserver(像Calico-Agent Kubelet Kube-Proxy,Kube-Controller-Manager)和內部負載均衡器的行為在一個Apiserver節點中的失敗,因為檢測到Kuberntes集群降級可能會破壞服務,所以開始關注了每個站點上運行的關鍵應用,並自動化地將請求從一個不健康的集群遷移到其他健康的集群。

類似的工作已經放在GitHub的流程圖中,支持此應用部署到多個獨立運營的網站,和其他積極的方式進行取捨。最終選定的設計是:使用部署系統支持多個「分區」增強它通過一個定製的支持提供集群乏味內配置Kubernetes資源注釋,放棄現有的聯合解決方案,允許使用業務邏輯已經出現在GitHub的部署系統。

從10%到100%

有了集群組,GitHub逐漸將前端伺服器轉換為Kubernetes節點,並增加了路由到Kubernetes的流量,與其他一些工程師團隊一起,在一個多月的時間內完成了前端的轉換,同時,在這此期間保持了預計的性能和可接受的錯誤率。

在遷移過程中,遇到了一直持續至今的問題:在高負載/或高利用率的容器中,一些Kubernetes節點會出現內核錯誤並會重啟,雖然GitHub對這種情況不是很滿意,而且進行了最高優先順序的排查,但還是很高興地看到Kubernetes能夠自動地繞過這些故障,並繼續在錯誤範圍內服務流量。

GitHub進行了一些Failure Tests,模擬了與echo c/proc/sysrq觸發相似的內核錯誤,這是一個很有用的補充。

未來

本文的靈感來自於將此應用遷移到Kubernetes的經驗,並且期待著更多的遷移,雖然在第一次遷移的範圍被有意限制在無狀態的工作負載中,但對在Kubernetes上嘗試運行有狀態的服務模式抱有很大興趣。

在項目的最後階段,GitHub還發布了一個工作流,用於將新的應用和服務部署到類似的Kubernetes集群中。工程師們幾個月以來已經在此集群中部署了數十個應用,每一個都需要SRE的配置管理和支持,有了自助式的應用供應工作流,SRE可以將更多的時間花在向工程團隊的其他成員交付基礎設施產品上去支持最佳實踐,為每個人構建更快,更有彈性的GitHub體驗。


推薦閱讀:

梁勝:Kubernetes 已成為新的基礎設施標準
Kubernetes Handbook v1.0發布附pdf下載地址- jimmysong.io
有人在嘗試使用Kubernetes嗎?
Kubernetes 為什麼這麼重要?
Kubernetes漏洞搞垮了應用程序!癱瘓 1 個小時

TAG:GitHub | Kubernetes |