2016-12-04 19 views
0

我有一個Python程序,我每2小時在Kubernetes集羣上作爲Job運行。我也有一個網絡服務器,只要用戶點擊頁面上的按鈕就可以開始工作。最多確保在Kubernetes上執行的作業的單個實例並寫入Postgresql

我需要確保在任何給定時間最多隻有一個作業實例正在羣集上運行。

鑑於我正在使用Kubernetes來運行作業並從作業內部連接到Postgresql,因此解決方案應該以某種方式利用這兩者。我雖然有點它和附帶以下思路:

  1. 查找Kubernetes的設置,將設置此限制,嘗試啓動第二個實例,然後將失敗。我無法找到這個設置。
  2. 創建共享鎖或互斥鎖。缺點是,如果工作崩潰,我可能無法在退出之前解鎖。
    1. Kubernetes運行ETCD,也許我可以使用
    2. 在PostgreSQL,創建一個「鎖定」表時,新的實例連接,它會檢查,如果它是唯一一個運行。以某種方式使用交易,以便贏得並繼續,而其他人退出。我還沒有想到這一點,但應該工作。
  3. 查詢kubernetes我在工作中使用的標籤的API,看看是否有一些實例。這可能不是原子的,所以不止一個實例可能會滑過。

鑑於我所做的平臺選擇,對於這個問題常見的解決方案是什麼?我該怎麼做,這樣我纔不會重新發明輪子並擁有可靠的東西?

回答

1

完全不同的方法是運行執行作業功能的(網絡)服務器。在高層次上,這個想法是,網絡服務器可以聯繫這個新的作業服務器來執行功能。另外,這個新的作業服務器將有一個內部cron來每2小時觸發一次相同的功能。

有可能是2種的方法來實現這一點:

  1. 你可以把jobserver代碼內部檢查機制,以確保即使2 API調用同時發生的作業服務器,只有一個執行,而其他等待。您可以使用語言平臺的鎖定功能來實現此目的,或使用消息隊列。
  2. 您可以將檢查機制置於jobserver代碼之外(在數據庫中)以確保只執行一個API調用。類似於你的建議。如果你使用postgres交易,你不必擔心你的工作會崩潰,鎖的價值仍然保持不變。

這兩種方法的優點/缺點都很簡單。我認爲1 & 2之間的主要區別在於,如果更新作業服務器代碼,那麼您可能會遇到2臺作業服務器可能同時運行的情況。這會破壞你想要的隔離屬性。因此,數據庫可能工作得更好,或者在k8s意義上更具慣用意義(所有服務器都是無狀態的,因此所有k8s好吃的東西都可以工作;將任何共享狀態放在可以處理併發的數據庫中)。

解決你的想法,這裏有我的想法:

  1. 查找K8S的設置,將限制這樣的:K8S不會使用相同的名稱開始的東西(在規範的元數據)。但其他任何事情都可以找到工作,而K8s將開始另一項工作。

  2. a)etcd3支持分佈式鎖定原語。但是,我從來沒有用過這個,我真的不知道要注意什麼。

  3. b)postgres鎖定值應該工作。即使在發生工作崩潰的情況下,您也不必擔心剩餘鎖定的價值。

  4. 查詢k8s API服務器應該是原子的東西不是一個好主意,就像你說的。我已經使用了一個對k8s事件有反應的系統(比如對象規範中的註釋更改),但是我有一些錯誤,我的'操作員'突然停止獲取k8s事件並需要重新啓動,或者如果我想要要將更新推送到事件處理服務器,則可能同時存在2個事件處理程序。

我會建議堅持你最熟悉的東西。在我的情況下,這將實施一個作業服務器,如k8s部署,作爲服務器運行並監聽事件/ API調用。

+0

謝謝,我會嘗試使用「k8s不會啓動同名的東西」的方法,或者可能是「postgres lock」。 – user7610

相關問題