1. updater整體邏輯
updater整體邏輯是比較簡單的琐簇。
(1)定義了一個NewUpdater的對象
(2)然后每隔1分鐘,執(zhí)行NewUpdater.RunOnce
1.1 updater參數(shù)
updater輪轉周期碉怔,默認是1分鐘
updaterInterval = flag.Duration("updater-interval", 1*time.Minute, `How often updater should run`)
rs最小可用的副本數(shù)酌儒。比如默認是2表示弯予,如果一個rs當前只有2個副本可用肛跌,本輪是不會驅逐的,保障rs服務的可用性
minReplicas = flag.Int("min-replicas", 2, `Minimum number of replicas to perform update`)
pod每輪的驅逐比例
evictionToleranceFraction = flag.Float64("eviction-tolerance", 0.5,`Fraction of replica count that can be evicted for update, if more than one pod can be evicted.`)
驅逐限速郑临,這里用了令牌桶算法栖博,就個就是令牌桶的QPS。如果是0或者-1表示不限速厢洞,默認是不限速
evictionRateLimit = flag.Float64("eviction-rate-limit", -1,`Number of pods that can be evicted per seconds. A rate limit set to 0 or -1 will disable the rate limiter.`)
令牌桶的burst大小
evictionRateBurst = flag.Int("eviction-rate-burst", 1, `Burst of pods that can be evicted.`)
暴露Prometheus metrics指標的地址
address = flag.String("address", ":8943", "The address to expose Prometheus metrics.")
是否檢驗AdmissionControllerStatus仇让。如果開啟的話,updater必須等
useAdmissionControllerStatus = flag.Bool("use-admission-controller-status", true,
"If true, updater will only evict pods when admission controller status is valid.")
vpa作用的命名空間躺翻,默認是所有命名空間
namespace = os.Getenv("NAMESPACE")
vpaObjectNamespace = flag.String("vpa-object-namespace", apiv1.NamespaceAll, "Namespace to search for VPA objects. Empty means all namespaces will be used.")
)
1.2 NewUpdater結構體對象
// NewUpdater creates Updater with given configuration
func NewUpdater(
cgClient dynamic.Interface, // 為了操作cgroups資源丧叽,增加的dynamic客戶端
cgGvr schema.GroupVersionResource, // cgroups的 gvr
kubeClient kube_client.Interface,
vpaClient *vpa_clientset.Clientset,
minReplicasForEvicition int,
evictionRateLimit float64,
evictionRateBurst int,
evictionToleranceFraction float64,
useAdmissionControllerStatus bool,
statusNamespace string,
recommendationProcessor vpa_api_util.RecommendationProcessor, // 處理推薦資源相關的process,在vertical-pod-autoscaler/pkg/utils/vpa/capping.go
evictionAdmission priority.PodEvictionAdmission, // 默認為空
selectorFetcher target.VpaTargetSelectorFetcher, // selector相關
priorityProcessor priority.PriorityProcessor, // 驅逐優(yōu)先級處理公你。會更加資源diff進行過濾
namespace string,
) (Updater, error) {
evictionRateLimiter := getRateLimiter(evictionRateLimit, evictionRateBurst)
factory, err := eviction.NewPodsEvictionRestrictionFactory(kubeClient, minReplicasForEvicition, evictionToleranceFraction)
if err != nil {
return nil, fmt.Errorf("Failed to create eviction restriction factory: %v", err)
}
return &updater{
cgClient: cgClient,
cgGvr: cgGvr,
vpaLister: vpa_api_util.NewVpasLister(vpaClient, make(chan struct{}), namespace),
podLister: newPodLister(kubeClient, namespace),
eventRecorder: newEventRecorder(kubeClient),
evictionFactory: factory,
recommendationProcessor: recommendationProcessor,
evictionRateLimiter: evictionRateLimiter,
evictionAdmission: evictionAdmission,
priorityProcessor: priorityProcessor,
selectorFetcher: selectorFetcher,
useAdmissionControllerStatus: useAdmissionControllerStatus,
statusValidator: status.NewValidator(
kubeClient,
status.AdmissionControllerStatusName,
statusNamespace,
),
}, nil
}
1.3 updater流程
每隔1分鐘進行以下的運行邏輯:
-
獲取所有的vpa, 并進行遍歷踊淳,對于每個vpa而言,執(zhí)行以下步驟
1.1 如果vpa.model != auto 或者vpa.model != recreate, 直接跳過這個vpa
1.2 根據(jù)vpa對應的selector, 獲取所有的pods陕靠,假設為 allPods
1.3 從allPods中過濾deletionTimestamp != nil 的pods, 假設為 activesPods
1.4 從activesPods中過濾可以進行驅逐的pod, 假設為canEvictedPods. 判斷邏輯如下:
-
updater啟動時有兩個參數(shù):defaultUpdateThreshold = 0.10迂尝。podLifetimeUpdateThreshold = time.Hour * 12
含義為:
如果一個pod從開始運行到當前時間,沒有超過12小時(podLifetimeUpdateThreshold)剪芥,不能進行驅逐
如果一個pod從資源改變在 0.1范圍內(nèi)垄开,不應該驅逐。這個0.1是 cpu + memory的和税肪。
結合OOM事件溉躲,判斷pod是否應該Evict,這個目前待確定細節(jié)
-
經(jīng)過第一步益兄,得到一個map, key=vap, value= canEvictedPods (這是一個列表锻梳,表示需要驅逐的pod)
-
遍歷上訴map, 針對某個vpa進行以下邏輯判斷。
updater啟動時還有兩個參數(shù)净捅,控制沒輪驅逐時pod的數(shù)量
- evictionTolerance 表示當前沒輪驅逐的比例,默認0.5疑枯。 假設當前vpa對應的canEvictedPods有10個pod, 那么當前只會驅逐5個。
- min-replica 表示rs最少可用的pod數(shù)量蛔六。例如一個rs 當前只有2個pod running, 就是前面滿足了驅逐條件神汹,到這里也不會驅逐庆捺。
熱升級調整的邏輯:
(1)修改 podLifetimeUpdateThreshold = 30s
(2)跳過canEvictedPods邏輯
2. updater驅逐邏輯如下:
每隔1分鐘進行以下的運行邏輯:
-
獲取所有的vpa, 并進行遍歷,對于每個vpa而言屁魏,執(zhí)行以下步驟
1.1 如果vpa.model != auto 或者vpa.model != recreate, 直接跳過這個vpa
1.2 根據(jù)vpa對應的selector, 獲取所有的pods滔以,假設為 allPods
1.3 從allPods中過濾deletionTimestamp != nil 的pods, 假設為 activesPods
1.4 從activesPods中過濾可以進行驅逐的pod, 假設為canEvictedPods. 判斷邏輯如下:
-
updater啟動時有兩個參數(shù):defaultUpdateThreshold = 0.10。podLifetimeUpdateThreshold = time.Hour * 12
含義為:
如果一個pod從開始運行到當前時間氓拼,沒有超過12小時(podLifetimeUpdateThreshold)你画,不能進行驅逐
如果一個pod從資源改變在 0.1范圍內(nèi),不應該驅逐桃漾。這個0.1是 cpu + memory的和坏匪。
結合OOM事件,判斷pod是否應該Evict撬统,這個目前待確定細節(jié)
-
經(jīng)過第一步适滓,得到一個map, key=vap, value= canEvictedPods (這是一個列表,表示需要驅逐的pod)
-
遍歷上訴map, 針對某個vpa進行以下邏輯判斷恋追。
updater啟動時還有兩個參數(shù)凭迹,控制沒輪驅逐時pod的數(shù)量
- evictionTolerance 表示當前沒輪驅逐的比例,默認0.5。 假設當前vpa對應的canEvictedPods有10個pod, 那么當前只會驅逐5個苦囱。
- min-replica 表示rs最少可用的pod數(shù)量嗅绸。例如一個rs 當前只有2個pod running, 就是前面滿足了驅逐條件,到這里也不會驅逐撕彤。
2.1 總結
感覺驅逐邏輯遷移到cgroupManager可以如下:
(1)繼承上訴的步驟1鱼鸠,步驟2,因為是熱升級羹铅,所以不用關注步驟三(考慮min-replica )
(2)OOM事件會影響pod驅逐蚀狰,但是是熱升級的情況下感覺可以忽略
3.vpa的修改pod資源的邏輯
vap修改的都是pod的request值,但是limit值會按照比例進行擴縮
Deploy yaml中沒有指定limit职员,vpa也不會修改limit
vpa不會修改pod的QOS類型
舉例說明會更清楚一點:
場景1 deploy yaml中設置了requet, limit
假設deploy yaml中定義的資源為:(這里limit:request=2:1)
resources:
limits:
cpu: 2
memory: 2Gi
requests:
cpu: 1
memory: 1Gi
而vpa推薦值為:cpu=25m mem=262144k造锅。那么這個pod實際運行時的request如下:
resources:
limits: //limit會改變,會維持limit:request=2:1的關系
cpu: 50m
memory: 500Mi
requests: // request采用的是vpa的值
cpu: 25m
memory: 262144k
場景2 pod yaml只中設置了requet沒有設置limit
假設pod yaml中定義的資源為:(這里沒有l(wèi)imit)
resources:
requests:
cpu: 1
memory: 1Gi
而vpa推薦值為:cpu=25m mem=262144k。那么這個pod實際運行時的request如下:
resources:
requests: // request采用的是vpa的值廉邑。也不會有l(wèi)imit
cpu: 25m
memory: 262144k
場景3 pod yaml沒有設置resources
假設pod yaml中定義沒有定義資源:(besteffort)
而vpa推薦值為:cpu=25m mem=262144k。那么這個pod實際運行時的request如下:
resources:
requests: // request采用的是vpa的值倒谷。也不會有l(wèi)imit
cpu: 25m
memory: 262144k