Custom Scheduler クイズ (Part 2)
このクイズでは、Kubernetes で Custom Scheduler を実装し使用するための高度な理解を確認します。
クイズ問題
1. Kubernetes scheduling framework における "Bind" extension point の役割は何ですか?
A. scheduling decision を確定するために Pod を Node に bind する B. Pod と Node の間の network binding を設定する C. Pod と Service の間の binding を作成する D. Pod と volume の間の binding を設定する
回答を表示
回答: A. scheduling decision を確定するために Pod を Node に bind する
解説: Kubernetes scheduling framework における "Bind" extension point の役割は、選択された Node に Pod を bind し、scheduling decision を確定することです。binding stage は scheduling cycle の最終 stage であり、kubelet が Pod を実行できるように Pod の spec.nodeName field が設定されます。
Binding Process:
- scheduler は filtering と scoring を通じて最適な Node を選択します。
- 選択された Node に Pod を予約します (reserve)。
- binding stage で、Pod の
spec.nodeNamefield を選択された Node の名前に更新します。 - 更新された Pod 情報が API server に保存されます。
- kubelet が Pod 情報を検出し、その Node 上で Pod を実行します。
Bind Plugin Implementation Example:
// Bind plugin example
type MyBindPlugin struct {
handle framework.Handle
}
func (bp *MyBindPlugin) Name() string {
return "MyBindPlugin"
}
// Bind method implementation
func (bp *MyBindPlugin) Bind(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
// Create pod binding object
binding := &v1.Binding{
ObjectMeta: metav1.ObjectMeta{
Name: pod.Name,
Namespace: pod.Namespace,
},
Target: v1.ObjectReference{
Kind: "Node",
Name: nodeName,
APIVersion: "v1",
},
}
// Send binding request to API server
err := bp.handle.ClientSet().CoreV1().Pods(pod.Namespace).Bind(ctx, binding, metav1.CreateOptions{})
if err != nil {
return framework.NewStatus(framework.Error, err.Error())
}
return nil
}Enabling Bind Plugin in Scheduler Configuration:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
bind:
enabled:
- name: MyBindPlugin
disabled:
- name: DefaultBinder # Disable default binderChecking Binding-Related Events:
# Check pod scheduling events
kubectl get events | grep -i "Successfully assigned"Troubleshooting Binding Failures: binding stage で失敗する一般的な原因:
- API server 接続の問題
- 権限不足
- Node 名の誤り
- Race condition(別の scheduler が同じ Pod を同時に bind しようとしている)
Issues with Other Options:
- B. Pod と Node の間の network binding を設定する: Network setup は CNI plugin の役割であり、scheduler の bind stage とは関係ありません。
- C. Pod と Service の間の binding を作成する: Service と Pod の接続は label selector を通じて行われ、scheduler の bind stage とは関係ありません。
- D. Pod と volume の間の binding を設定する: Volume binding は PersistentVolumeClaim controller によって処理され、scheduler の bind stage とは別の process です。
2. 次のうち、Kubernetes の Node Affinity に関連する operator ではないものはどれですか?
A. In B. NotIn C. Exists D. Contains
回答を表示
回答: D. Contains
解説: Kubernetes の Node Affinity に関連しない operator は Contains です。Kubernetes は node affinity に対して Contains operator を提供していません。
Operators Supported in Node Affinity:
- In: Label value は指定された値のいずれかに一致する必要があります。
- NotIn: Label value は指定された値に一致してはいけません。
- Exists: 指定された label key が存在する必要があります。
- DoesNotExist: 指定された label key が存在してはいけません。
- Gt: Label value は指定された値より大きい必要があります (Greater than)。
- Lt: Label value は指定された値より小さい必要があります (Less than)。
Node Affinity Example:
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: ExistsNode Affinity Types:
- requiredDuringSchedulingIgnoredDuringExecution: Pod を Node に schedule するために満たす必要がある rule(hard requirement)。
- preferredDuringSchedulingIgnoredDuringExecution: 満たされることが望ましいが必須ではない rule(soft requirement)。
Operator Usage Examples:
In Operator:
yaml- key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2Node の
kubernetes.io/e2e-az-namelabel value はe2e-az1またはe2e-az2である必要があります。NotIn Operator:
yaml- key: kubernetes.io/e2e-az-name operator: NotIn values: - e2e-az3Node の
kubernetes.io/e2e-az-namelabel value はe2e-az3であってはいけません。Exists Operator:
yaml- key: kubernetes.io/e2e-az-name operator: Existskubernetes.io/e2e-az-namelabel は Node 上に存在する必要があります。DoesNotExist Operator:
yaml- key: emptyLabel operator: DoesNotExistemptyLabellabel は Node 上に存在してはいけません。Gt/Lt Operators:
yaml- key: node-size operator: Gt values: - "10"Node の
node-sizelabel value は 10 より大きい必要があります。
Handling Node Affinity in Custom Scheduler: Custom Scheduler を実装する際は、Pod の node affinity 要件を考慮する必要があります。
// Node affinity check example
func checkNodeAffinity(pod *v1.Pod, node *v1.Node) bool {
affinity := pod.Spec.Affinity
if affinity == nil || affinity.NodeAffinity == nil {
return true // All nodes are suitable if there's no node affinity
}
// Check required node affinity
if required := affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution; required != nil {
for _, term := range required.NodeSelectorTerms {
if matchNodeSelectorTerm(term, node) {
return true
}
}
return false // No NodeSelectorTerm matched
}
return true
}
// Check if NodeSelectorTerm matches
func matchNodeSelectorTerm(term v1.NodeSelectorTerm, node *v1.Node) bool {
// Implementation omitted
return true
}Explanation of Other Options:
- A. In: 有効な node affinity operator です。
- B. NotIn: 有効な node affinity operator です。
- C. Exists: 有効な node affinity operator です。
3. Kubernetes における Pod Topology Spread Constraints の主な目的は何ですか?
A. さまざまな Node に Pod を均等に分散する B. Pod を特定の Node にのみ配置する C. Pod を特定の zone にのみ配置する D. Pod を特定の label を持つ Node にのみ配置する
回答を表示
回答: A. さまざまな Node に Pod を均等に分散する
解説: Kubernetes における Pod Topology Spread Constraints の主な目的は、さまざまな topology domain(Node、zone、region など)に Pod を均等に分散することです。これにより、application の高可用性が向上し、resource usage が最適化され、failure tolerance が向上します。
Main Components of Pod Topology Spread Constraints:
- maxSkew: topology domain 間の Pod 数の最大差を指定します。
- topologyKey: Pod を分散する topology domain を定義する Node label key です。
- whenUnsatisfiable: constraint を満たせない場合の動作を指定します。
DoNotSchedule: constraint が満たされない場合、Pod を schedule しません。ScheduleAnyway: constraint が満たされなくても Pod を schedule します。
- labelSelector: spread calculation で考慮する既存の Pod を選択する label selector です。
Pod Topology Spread Constraints Example:
apiVersion: v1
kind: Pod
metadata:
name: web-server
labels:
app: web
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
- maxSkew: 2
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
containers:
- name: nginx
image: nginxこの例では、2 つの constraint が定義されています:
- 各 Node(
kubernetes.io/hostname)間で、app=weblabel を持つ Pod 数の差は最大 1 である必要があります。 - 各 zone(
topology.kubernetes.io/zone)間で、app=weblabel を持つ Pod 数の差は最大 2 である必要があります。
Topology Spread Calculation Method:
- 各 topology domain で label selector に一致する Pod 数を計算します。
- 最も多くの Pod を持つ domain と最も少ない Pod を持つ domain の差を計算します。
- この差が
maxSkewより大きい場合、constraint に違反しています。
Common Topology Keys:
- kubernetes.io/hostname: Node-level spread
- topology.kubernetes.io/zone: Zone-level spread
- topology.kubernetes.io/region: Region-level spread
- node.kubernetes.io/instance-type: Instance type-level spread
Use Cases:
- High availability: 複数の Node、zone、region に Pod を分散して failure tolerance を向上させる
- Resource balance: workload を cluster 全体に均等に分散する
- Cost optimization: workload を特定 type の Node に分散する
- Performance optimization: network latency を最小化するように分散する
Handling Topology Spread in Custom Scheduler: Custom Scheduler を実装する際は、Pod の topology spread constraints を考慮する必要があります。
// Topology spread constraint check example
func checkTopologySpreadConstraints(pod *v1.Pod, node *v1.Node, allPods []*v1.Pod) bool {
constraints := pod.Spec.TopologySpreadConstraints
if len(constraints) == 0 {
return true // All nodes are suitable if there are no constraints
}
for _, constraint := range constraints {
// Get topology key value
topologyValue, ok := node.Labels[constraint.TopologyKey]
if !ok {
// Skip this constraint if the node doesn't have the topology key
if constraint.WhenUnsatisfiable == v1.DoNotSchedule {
return false
}
continue
}
// Calculate the number of matching pods in the current topology domain
var matchingPods int
for _, existingPod := range allPods {
// Check if the pod matches the label selector and is in the same topology domain
if podMatchesLabelSelector(existingPod, constraint.LabelSelector) {
podNode, err := getNodeForPod(existingPod)
if err != nil {
continue
}
if podNode.Labels[constraint.TopologyKey] == topologyValue {
matchingPods++
}
}
}
// Calculate pod count in other topology domains and check skew
// (Implementation omitted)
// Check maxSkew violation
if skew > constraint.MaxSkew && constraint.WhenUnsatisfiable == v1.DoNotSchedule {
return false
}
}
return true
}Issues with Other Options:
- B. Pod を特定の Node にのみ配置する: これは nodeSelector または nodeAffinity の役割です。
- C. Pod を特定の zone にのみ配置する: これは node affinity を使って Pod を特定の zone に配置することです。topology spread constraints の主な目的は均等な分散です。
- D. Pod を特定の label を持つ Node にのみ配置する: これは nodeSelector または nodeAffinity の役割です。
A. 特定の Pod が特定の Node にのみ schedule されることを保証する B. 特定の Pod が特定の Node に schedule されるのを防ぐ C. Node が特定の Pod を拒否し、Pod がそれを許容できるようにする D. Pod 間の通信を制限する
回答を表示
回答: C. Node が特定の Pod を拒否し、Pod がそれを許容できるようにする
解説: Kubernetes における Taints and Tolerations の主な目的は、Node が特定の Pod を拒否し、Pod がそれを許容できるようにすることです。Taint は Pod が schedule されるのを防ぐために Node に適用され、toleration は特定の taint を持つ Node への scheduling を許可するために Pod に適用されます。
How Taints and Tolerations Work:
- Taints: その Node への Pod scheduling を制限するために Node に適用されます。
- Tolerations: 特定の taint を持つ Node への scheduling を許可するために Pod に適用されます。
- Effect: taint の effect は、toleration を持たない Pod に対する動作を定義します。
Taint Effect Types:
- NoSchedule: toleration を持たない Pod はその Node に schedule されません。
- PreferNoSchedule: toleration を持たない Pod はできればその Node に schedule されませんが、cluster resource が不足している場合は schedule される可能性があります。
- NoExecute: toleration を持たない Pod はその Node に schedule されず、すでに実行中の Pod は削除されます。
Taint Application Example:
# Apply taint to node
kubectl taint nodes node1 key=value:NoSchedule
# Remove taint from node
kubectl taint nodes node1 key=value:NoSchedule-Taint and Toleration Example:
# Apply taint to node
apiVersion: v1
kind: Node
metadata:
name: node1
spec:
taints:
- key: "key"
value: "value"
effect: "NoSchedule"
# Apply toleration to pod
apiVersion: v1
kind: Pod
metadata:
name: pod-with-toleration
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
containers:
- name: nginx
image: nginxToleration Operators:
- Equal: Key と value が一致する必要があります。
- Exists: Key のみ一致すればよいです(value は無視されます)。
Additional Toleration Field:
- tolerationSeconds: NoExecute effect で削除されるまで、Pod が Node 上に残ることができる時間(秒)を指定します。
tolerations:
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 300Common Use Cases:
- Dedicated nodes: 特定の workload 専用に Node を予約する
- Special hardware: GPU などの special hardware を持つ Node にのみ特定の Pod を schedule する
- Node maintenance: Node maintenance 中に新しい Pod scheduling を防ぐ
- Master node protection: control plane node に一般的な workload が schedule されるのを防ぐ
System Taints: Kubernetes は次の system taints を自動的に適用します:
- node.kubernetes.io/not-ready: Node is not ready
- node.kubernetes.io/unreachable: Node is unreachable
- node.kubernetes.io/memory-pressure: Node has memory pressure
- node.kubernetes.io/disk-pressure: Node has disk pressure
- node.kubernetes.io/pid-pressure: Node has PID pressure
- node.kubernetes.io/network-unavailable: Node's network is unavailable
- node.kubernetes.io/unschedulable: Node is marked as unschedulable
Handling Taints and Tolerations in Custom Scheduler: Custom Scheduler を実装する際は、Node taints と Pod tolerations を考慮する必要があります。
// Taint and toleration check example
func checkTaintsAndTolerations(pod *v1.Pod, node *v1.Node) bool {
// All pods can be scheduled if the node has no taints
if len(node.Spec.Taints) == 0 {
return true
}
// Check if the pod has tolerations for each taint
for _, taint := range node.Spec.Taints {
if taint.Effect == v1.TaintEffectNoSchedule || taint.Effect == v1.TaintEffectPreferNoSchedule {
// Check if the pod tolerates this taint
if !tolerationsTolerateTaint(pod.Spec.Tolerations, &taint) {
return false
}
}
}
return true
}
// Check if tolerations tolerate a taint
func tolerationsTolerateTaint(tolerations []v1.Toleration, taint *v1.Taint) bool {
for _, toleration := range tolerations {
if toleration.Key == taint.Key {
if toleration.Operator == v1.TolerationOpExists {
return true
} else if toleration.Operator == v1.TolerationOpEqual && toleration.Value == taint.Value {
return true
}
}
}
return false
}Issues with Other Options:
- A. 特定の Pod が特定の Node にのみ schedule されることを保証する: これは nodeSelector または nodeAffinity の役割です。
- B. 特定の Pod が特定の Node に schedule されるのを防ぐ: これは podAntiAffinity の役割です。
- D. Pod 間の通信を制限する: これは NetworkPolicy の役割です。
5. 次のうち、Kubernetes における Scheduler Extender の主な特性ではないものはどれですか?
A. HTTP webhook を通じて scheduler と通信する B. filtering と prioritization の機能を提供する C. scheduler codebase に直接統合されている D. 外部 process として実行される
回答を表示
回答: C. scheduler codebase に直接統合されている
解説: 「scheduler codebase に直接統合されている」は、Kubernetes における Scheduler Extender の主な特性ではありません。Scheduler extender は scheduler codebase に直接統合されておらず、HTTP webhook を通じて通信し、外部 process として実行されます。これは scheduling framework plugin との主な違いです。
Main Characteristics of Scheduler Extender:
- HTTP webhooks: scheduler は HTTP request を通じて extender と通信します。
- External process: extender は scheduler とは別の process として実行されます。
- Filtering and prioritization: extender は Node filtering と prioritization の機能を提供できます。
- Binding: extender は任意で Pod を Node に bind できます。
Scheduler Extender Configuration Example:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
extenders:
- urlPrefix: "http://extender-service:8080"
filterVerb: "filter"
prioritizeVerb: "prioritize"
weight: 5
bindVerb: "bind"
enableHTTPS: false
nodeCacheCapable: false
ignorable: true
managedResources:
- name: example.com/foo
ignoredByScheduler: trueScheduler Extender API:
Filter API: Node list を受け取り、filtered node list を返します。
POST /filterRequest body:
json{ "pod": <pod>, "nodes": <nodes>, "nodenames": <node-names> }Response body:
json{ "nodes": <filtered-nodes>, "nodenames": <filtered-node-names>, "failedNodes": <failed-nodes>, "error": <error-message> }Prioritize API: Node list を受け取り、各 Node に score を割り当てます。
POST /prioritizeRequest body:
json{ "pod": <pod>, "nodes": <nodes>, "nodenames": <node-names> }Response body:
json{ "hostPriorities": [ { "host": <node-name>, "score": <score> }, ... ], "error": <error-message> }Bind API: Pod を Node に bind します。
POST /bindRequest body:
json{ "pod": <pod>, "node": <node-name> }Response body:
json{ "error": <error-message> }
Scheduler Extender Implementation Example (Go):
package main
import (
"encoding/json"
"log"
"net/http"
v1 "k8s.io/api/core/v1"
extender "k8s.io/kube-scheduler/extender/v1"
)
// Filter handler
func filterHandler(w http.ResponseWriter, r *http.Request) {
var args extender.ExtenderArgs
var result extender.ExtenderFilterResult
// Decode request body
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Implement filtering logic
filteredNodes := make([]v1.Node, 0, len(args.Nodes.Items))
failedNodes := make(map[string]string)
for _, node := range args.Nodes.Items {
// Custom filtering logic
if customFilter(&args.Pod, &node) {
filteredNodes = append(filteredNodes, node)
} else {
failedNodes[node.Name] = "Node failed custom filter"
}
}
// Set result
result.Nodes = &v1.NodeList{Items: filteredNodes}
result.FailedNodes = failedNodes
// Send response
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// Prioritize handler
func prioritizeHandler(w http.ResponseWriter, r *http.Request) {
var args extender.ExtenderArgs
var result extender.HostPriorityList
// Decode request body
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Implement prioritization logic
result = make(extender.HostPriorityList, 0, len(args.Nodes.Items))
for _, node := range args.Nodes.Items {
// Custom score calculation
score := customScore(&args.Pod, &node)
result = append(result, extender.HostPriority{
Host: node.Name,
Score: score,
})
}
// Send response
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func main() {
http.HandleFunc("/filter", filterHandler)
http.HandleFunc("/prioritize", prioritizeHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}Scheduler Extender vs Scheduling Framework Plugin:
| Feature | Scheduler Extender | Scheduling Framework Plugin |
|---|---|---|
| Integration Method | HTTP webhook | Direct codebase integration |
| Execution Mode | External process | Inside scheduler |
| Performance | Relatively slower due to HTTP overhead | Faster due to direct integration |
| Development Language | No restriction | Go |
| Deployment | Separate service | Deployed with scheduler |
| Maintenance | Independent from scheduler | Linked to scheduler version |
Pros and Cons of Scheduler Extender: Pros:
- scheduler codebase から独立して開発できます
- さまざまな programming language で実装できます
- scheduler upgrade の影響を受けにくいです
Cons:
- HTTP communication overhead による performance degradation
- scheduling cycle の一部の stage しか拡張できません
- scheduler と extender 間で communication failure が発生する可能性があります
Explanation of Other Options:
- A. HTTP webhook を通じて scheduler と通信する: scheduler extender の有効な特性です。
- B. filtering と prioritization の機能を提供する: scheduler extender の有効な特性です。
- D. 外部 process として実行される: scheduler extender の有効な特性です。
A. Pod と Node の関係を定義する B. Pod と volume の関係を定義する C. Pod 間の関係を定義する D. Pod と Service の関係を定義する
回答を表示
回答: C. Pod 間の関係を定義する
解説: Kubernetes における Pod Affinity and Anti-Affinity の主な目的は、Pod 間の関係を定義することです。これにより、特定の Pod を他の Pod と同じ topology domain(Node、zone、region など)に配置するか(affinity)、配置しないか(anti-affinity)を制御できます。
Main Components of Pod Affinity and Anti-Affinity:
- topologyKey: Pod 間の関係を定義する topology domain を指定する Node label key です。
- labelSelector: 関係を確立する対象の Pod を選択する label selector です。
- namespaces: label selector が適用される namespace の list です。
Pod Affinity Types:
- requiredDuringSchedulingIgnoredDuringExecution: Pod を schedule するために満たす必要がある rule(hard requirement)。
- preferredDuringSchedulingIgnoredDuringExecution: 満たされることが望ましいが必須ではない rule(soft requirement)。
Pod Affinity Example:
apiVersion: v1
kind: Pod
metadata:
name: web-server
labels:
app: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: nginx
image: nginxこの例では:
- Pod Affinity: web server Pod は、
app=cachelabel を持つ Pod と同じ Node(kubernetes.io/hostname)に schedule される必要があります。 - Pod Anti-Affinity: web server Pod は、できれば
app=weblabel を持つ他の Pod とは異なる Node に schedule されるべきです。
Common Topology Keys:
- kubernetes.io/hostname: Node-level relationship
- topology.kubernetes.io/zone: Zone-level relationship
- topology.kubernetes.io/region: Region-level relationship
Use Cases:
- High availability: 同じ application の instance を異なる Node、zone、region に分散する
- Performance optimization: 相互に通信する Pod を同じ Node に配置して latency を最小化する
- Resource isolation: resource-intensive な Pod を異なる Node に分散する
- License restrictions: license restriction がある application を特定の Node に集中させる
Pod Affinity vs Node Affinity:
- Node Affinity: Pod と Node の関係を定義します。
- Pod Affinity: Pod 間の関係を定義します。
Performance Impact of Pod Affinity and Anti-Affinity: Pod affinity と anti-affinity は、すべての Node と Pod を考慮する必要があるため、計算コストが高くなる可能性があります。特に大規模 cluster では scheduling performance に影響する可能性があるため、慎重に使用する必要があります。
Handling Pod Affinity in Custom Scheduler: Custom Scheduler を実装する際は、Pod の affinity と anti-affinity 要件を考慮する必要があります。
// Pod affinity check example
func checkPodAffinity(pod *v1.Pod, node *v1.Node, allPods []*v1.Pod) bool {
affinity := pod.Spec.Affinity
if affinity == nil || affinity.PodAffinity == nil {
return true // All nodes are suitable if there's no pod affinity
}
// Check required pod affinity
for _, term := range affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
if !satisfiesPodAffinityTerm(pod, node, term, allPods) {
return false
}
}
return true
}
// Pod anti-affinity check example
func checkPodAntiAffinity(pod *v1.Pod, node *v1.Node, allPods []*v1.Pod) bool {
affinity := pod.Spec.Affinity
if affinity == nil || affinity.PodAntiAffinity == nil {
return true // All nodes are suitable if there's no pod anti-affinity
}
// Check required pod anti-affinity
for _, term := range affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
if satisfiesPodAffinityTerm(pod, node, term, allPods) {
return false
}
}
return true
}
// Check if pod affinity term is satisfied
func satisfiesPodAffinityTerm(pod *v1.Pod, node *v1.Node, term v1.PodAffinityTerm, allPods []*v1.Pod) bool {
// Implementation omitted
return true
}Issues with Other Options:
- A. Pod と Node の関係を定義する: これは nodeAffinity の役割です。
- B. Pod と volume の関係を定義する: これは volume binding と PersistentVolumeClaim の役割です。
- D. Pod と Service の関係を定義する: これは service label selector を通じて処理されます。
7. Kubernetes scheduler における "QueueSort" extension point の役割は何ですか?
A. Node を score する B. Pod が実行できない Node を除外する C. scheduling queue 内の Pod を sort する D. Pod を Node に bind する
回答を表示
回答: C. scheduling queue 内の Pod を sort する
解説: Kubernetes scheduling framework における "QueueSort" extension point の役割は、scheduling queue 内の Pod を sort することです。この extension point は、どの Pod を先に schedule するかを決定する priority を設定します。
Scheduling Queue and QueueSort: scheduler は scheduling queue 内の Pod を 1 つずつ処理します。QueueSort plugin は、この queue 内の Pod の順序を決定します。デフォルトでは、Kubernetes は PrioritySort plugin を使用して Pod priority で sort します。
QueueSort Plugin Interface:
type QueueSortPlugin interface {
Plugin
// Less determines which of two pods should be scheduled first.
// Returns true if pInfo1 should be scheduled before pInfo2.
Less(*QueuedPodInfo, *QueuedPodInfo) bool
}Default QueueSort Plugin - PrioritySort:
// PrioritySort sorts pods by pod priority.
type PrioritySort struct{}
// Name returns the plugin name.
func (pl *PrioritySort) Name() string {
return Name
}
// Less determines which of two pods should be scheduled first.
func (pl *PrioritySort) Less(pInfo1, pInfo2 *framework.QueuedPodInfo) bool {
p1 := getPodPriority(pInfo1.Pod)
p2 := getPodPriority(pInfo2.Pod)
// Higher priority pods are scheduled first.
if p1 != p2 {
return p1 > p2
}
// If priorities are equal, pods with longer wait time are scheduled first.
return pInfo1.Timestamp.Before(pInfo2.Timestamp)
}Custom QueueSort Plugin Example:
// CustomQueueSort implements custom sorting logic.
type CustomQueueSort struct{}
// Name returns the plugin name.
func (pl *CustomQueueSort) Name() string {
return "CustomQueueSort"
}
// Less determines which of two pods should be scheduled first.
func (pl *CustomQueueSort) Less(pInfo1, pInfo2 *framework.QueuedPodInfo) bool {
// Example: Prioritize pods in a specific namespace
if pInfo1.Pod.Namespace == "high-priority-namespace" && pInfo2.Pod.Namespace != "high-priority-namespace" {
return true
}
if pInfo1.Pod.Namespace != "high-priority-namespace" && pInfo2.Pod.Namespace == "high-priority-namespace" {
return false
}
// Example: Prioritize pods with a specific label
if hasLabel(pInfo1.Pod, "critical") && !hasLabel(pInfo2.Pod, "critical") {
return true
}
if !hasLabel(pInfo1.Pod, "critical") && hasLabel(pInfo2.Pod, "critical") {
return false
}
// By default, consider priority and wait time
p1 := getPodPriority(pInfo1.Pod)
p2 := getPodPriority(pInfo2.Pod)
if p1 != p2 {
return p1 > p2
}
return pInfo1.Timestamp.Before(pInfo2.Timestamp)
}
// Check if pod has a specific label
func hasLabel(pod *v1.Pod, label string) bool {
_, exists := pod.Labels[label]
return exists
}Enabling QueueSort Plugin in Scheduler Configuration:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
queueSort:
enabled:
- name: CustomQueueSort
disabled:
- name: PrioritySort # Disable default pluginCharacteristics of QueueSort Plugin:
- Single activation: 同時に有効にできる QueueSort plugin は 1 つだけです。
- Global impact: QueueSort plugin は scheduling queue 内のすべての Pod に影響します。
- Performance importance: 効率的な sorting algorithm が重要です。複雑な logic は scheduling performance に影響する可能性があります。
QueueSort Plugin Use Cases:
- Business priority: business importance に基づいて Pod を sort する
- Resource efficiency: empty space を活用するために resource request が小さい Pod を先に schedule する
- Service Level Agreements (SLA): SLA 要件に従って Pod を sort する
- Batch processing: batch job と interactive job の間の priority を調整する
Monitoring Scheduling Queue:
# Check queue information in scheduler logs
kubectl logs -n kube-system <scheduler-pod> | grep -i queue
# Check pods pending scheduling
kubectl get pods --all-namespaces -o wide | grep -i pendingIssues with Other Options:
- A. Node を score する: これは "Score" extension point の役割です。
- B. Pod が実行できない Node を除外する: これは "Filter" extension point の役割です。
- D. Pod を Node に bind する: これは "Bind" extension point の役割です。
A. より高い priority の Pod を schedule できるように、より低い priority の Pod を削除する B. より高い priority の Pod により多くの resource を割り当てる C. より高い priority の Pod をより速く実行する D. より高い priority の Pod を特定の Node にのみ配置する
回答を表示
回答: A. より高い priority の Pod を schedule できるように、より低い priority の Pod を削除する
解説: Kubernetes における Pod Priority Preemption の主な目的は、より高い priority の Pod を schedule できるように、より低い priority の Pod を削除することです。cluster resource が不足し、より高い priority の Pod を schedule できない場合、scheduler はより低い priority の Pod を preempt(削除)して空き容量を確保します。
Pod Priority and Preemption Mechanism:
- PriorityClass definition: Pod priority を定義する cluster-level resource です。
- Assign priority to pod: Pod は
spec.priorityClassNameを通じて PriorityClass を参照します。 - Scheduling order: より高い priority の Pod が scheduling queue で先に処理されます。
- Preemption process: より高い priority の Pod を schedule できない場合、scheduler はより低い priority の Pod を削除して空き容量を確保します。
PriorityClass Example:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 # Priority value (higher value means higher priority)
globalDefault: false # Whether to use this class as the default
description: "High priority pods" # Description
preemptionPolicy: PreemptLowerPriority # Preemption policy (default: PreemptLowerPriority)Applying Priority to a Pod:
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority # Reference PriorityClass name
containers:
- name: nginx
image: nginxPreemption Policies: PriorityClass には、次の値を取ることができる preemptionPolicy field があります:
- PreemptLowerPriority (default): より低い priority の Pod を preempt できます。
- Never: より低い priority の Pod を preempt しません。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-no-preemption
value: 1000000
globalDefault: false
description: "High priority pods that do not preempt other pods"
preemptionPolicy: Never # Do not preemptPreemption Process:
- scheduler がより高い priority の Pod を schedule しようとします。
- 適切な Node がない場合、scheduler は各 Node 上の preemption candidate Pod を特定します。
- preemption candidate は、より低い priority の Pod から選択されます。
- scheduler は必要な resource を解放するために最小数の Pod を preempt します。
- 選択された Pod は graceful に終了されます。
- preempt された Pod が終了すると、より高い priority の Pod が schedule されます。
Preemption Considerations:
- Graceful termination period: preempt された Pod には
terminationGracePeriodSeconds(default: 30 seconds)の graceful termination time があります。 - Pod Disruption Budget (PDB): scheduler は可能な場合、PDB に違反しないようにします。
- Node taints: preemption 後、新しい Pod が schedule されるのを防ぐために Node に taint が追加される場合があります。
- System pods: system critical Pod は通常、非常に高い priority を持ち、preempt されません。
Checking Preemption Events:
# Check preemption events
kubectl get events | grep -i preemptMonitoring Preemption-Related Metrics:
# Check preemption-related metrics in scheduler metrics
kubectl get --raw /metrics | grep scheduler_preemptionImplementing Preemption in Custom Scheduler: Custom Scheduler を実装する際は、Pod priority と preemption mechanism を考慮する必要があります。
// Preemption logic example
func preempt(pod *v1.Pod, nodes []*v1.Node) *v1.Node {
// Check pod priority
podPriority := getPodPriority(pod)
// Identify preemptable pods on each node
for _, node := range nodes {
// Get pods running on the node
nodePods := getPodsOnNode(node)
// Identify preemption candidate pods
var victims []*v1.Pod
for _, p := range nodePods {
// Select only lower priority pods
if getPodPriority(p) < podPriority {
victims = append(victims, p)
}
}
// Check if resources are sufficient after preemption
if hasEnoughResourcesAfterPreemption(node, victims, pod) {
// Execute preemption
for _, victim := range victims {
evictPod(victim)
}
return node
}
}
return nil // No suitable node found
}Pros and Cons of Preemption: Pros:
- 重要な workload の scheduling を保証します
- cluster resource を効率的に使用します
- Service Level Agreement (SLA) compliance をサポートします
Cons:
- preempt された Pod の disruption
- preemption 後の rescheduling による overhead
- 複雑な preemption decision logic
Issues with Other Options:
- B. より高い priority の Pod により多くの resource を割り当てる: Pod priority は resource allocation に直接影響しません。Resource request と limit は Pod spec で別途定義されます。
- C. より高い priority の Pod をより速く実行する: Priority は scheduling order に影響しますが、Pod の execution speed 自体は変わりません。
- D. より高い priority の Pod を特定の Node にのみ配置する: これは nodeSelector または nodeAffinity の役割であり、priority とは直接関係ありません。
9. Kubernetes scheduler における "PreFilter" extension point の役割は何ですか?
A. filtering の前に Pod と cluster state に対して preprocessing を実行する B. filtering 後に Node を score する C. Pod を Node に bind する前に verification を実行する D. scheduling queue 内の Pod を sort する
回答を表示
回答: A. filtering の前に Pod と cluster state に対して preprocessing を実行する
解説: Kubernetes scheduling framework における "PreFilter" extension point の役割は、filtering の前に Pod と cluster state に対して preprocessing を実行することです。PreFilter plugin は filtering stage で使用する data を準備し、Pod を schedule できるかを事前に check できます。
Main Functions of the PreFilter Extension Point:
- Data preparation: filtering stage で使用する data structure を初期化し準備します。
- Pre-checks: Pod を schedule できるかを事前に check します。
- State storage: scheduling cycle 中に使用する state information を保存します。
- Optimization: 不要な filtering work を防ぎ、performance を最適化します。
PreFilter Plugin Interface:
type PreFilterPlugin interface {
Plugin
// PreFilter performs preprocessing on the pod before filtering.
PreFilter(ctx context.Context, state *CycleState, pod *v1.Pod) *Status
// PreFilterExtensions returns an interface that provides additional functionality.
PreFilterExtensions() PreFilterExtensions
}
type PreFilterExtensions interface {
// AddPod updates state when a pod is added to a node.
AddPod(ctx context.Context, state *CycleState, podToAdd *v1.Pod, nodeInfo *NodeInfo) *Status
// RemovePod updates state when a pod is removed from a node.
RemovePod(ctx context.Context, state *CycleState, podToRemove *v1.Pod, nodeInfo *NodeInfo) *Status
}Default PreFilter Plugins: Kubernetes は次の default PreFilter plugin を提供しています:
- InterPodAffinity: inter-pod affinity と anti-affinity 要件を処理します。
- NodeAffinity: node affinity 要件を処理します。
- NodePorts: Pod が要求する host port を処理します。
- NodeResourcesFit: Node resource 要件を処理します。
- PodTopologySpread: Pod topology spread constraints を処理します。
- VolumeBinding: volume binding 要件を処理します。
Custom PreFilter Plugin Example:
// CustomPreFilter implements custom pre-filtering logic.
type CustomPreFilter struct {
handle framework.Handle
}
// Name returns the plugin name.
func (pl *CustomPreFilter) Name() string {
return "CustomPreFilter"
}
// PreFilter performs preprocessing on the pod before filtering.
func (pl *CustomPreFilter) PreFilter(ctx context.Context, state *framework.CycleState, pod *v1.Pod) *framework.Status {
// Example: Check if the pod is schedulable according to certain conditions
if !isPodSchedulable(pod) {
return framework.NewStatus(framework.Unschedulable, "Pod does not meet custom requirements")
}
// Example: Store data to be used in the filtering stage
data := &customPreFilterState{
// Initialize required data
}
state.Write(stateKey, data)
return nil
}
// PreFilterExtensions returns an interface that provides additional functionality.
func (pl *CustomPreFilter) PreFilterExtensions() framework.PreFilterExtensions {
return nil // Return nil if no extension functionality is needed
}
// State data structure
type customPreFilterState struct {
// Define required fields
}
// State key
var stateKey = framework.StateKey("CustomPreFilter")
// Function to check if pod is schedulable
func isPodSchedulable(pod *v1.Pod) bool {
// Implement custom logic
return true
}Enabling PreFilter Plugin in Scheduler Configuration:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
preFilter:
enabled:
- name: CustomPreFilter
disabled:
- name: NodeResourcesFit # Disable default pluginRelationship Between PreFilter and Filter:
- PreFilter: すべての Node に対する filtering を開始する前に 1 回実行されます。
- Filter: 各 Node に対して個別に実行されます。
PreFilter は Filter stage で使用する data を準備し、どの Node にも schedule できない Pod を事前に特定して、不要な filtering work を防ぎます。
PreFilter Use Cases:
- Complex constraint handling: inter-pod affinity、topology spread などの複雑な constraint を効率的に処理する
- Pre-validation: Pod を schedule できるかを事前に check し、不要な processing を防ぐ
- Data caching: filtering stage で繰り返し使用される data を事前に計算し、performance を向上させる
- State sharing: 複数の plugin 間で共有される state information を管理する
Issues with Other Options:
- B. filtering 後に Node を score する: これは "Score" extension point の役割です。
- C. Pod を Node に bind する前に verification を実行する: これは "PreBind" extension point の役割です。
- D. scheduling queue 内の Pod を sort する: これは "QueueSort" extension point の役割です。
10. Kubernetes における Node taint node.kubernetes.io/unreachable:NoExecute は何を意味しますか?
A. Node が unreachable であり、toleration を持たない Pod は削除される B. Node は unschedulable だが、既存の Pod は実行を続ける C. Node は maintenance mode であり、新しい Pod は schedule されない D. Node は resource shortage state であり、新しい Pod はできれば schedule されない
回答を表示
回答: A. Node が unreachable であり、toleration を持たない Pod は削除される
解説: Kubernetes における Node taint node.kubernetes.io/unreachable:NoExecute は、その Node が unreachable であり、この taint に対する toleration を持たない Pod が Node から削除(evict)されることを意味します。この taint は node controller によって自動的に追加され、Node の status が Ready から Unknown に変わったときに適用されます。
Node Unreachable State: Node が unreachable になる一般的な原因:
- Network connectivity の問題
- kubelet process の crash
- Node system failure
- Node power issues
Taint Components:
- Key:
node.kubernetes.io/unreachable - Value: 通常は空文字列ですが、値を持つ場合があります。
- Effect:
NoExecute- toleration を持たない Pod は Node から削除されます。
NoExecute Effect:NoExecute effect は次の動作を引き起こします:
- taint を持つ Node には新しい Pod は schedule されません。
- すでにその Node 上で実行中の Pod のうち、その taint に対する toleration を持たないものは削除されます。
System Taints: Kubernetes は Node status に基づいて次の system taints を自動的に追加します:
- node.kubernetes.io/not-ready:NoExecute: Node is not ready
- node.kubernetes.io/unreachable:NoExecute: Node is unreachable
- node.kubernetes.io/memory-pressure:NoSchedule: Node has memory pressure
- node.kubernetes.io/disk-pressure:NoSchedule: Node has disk pressure
- node.kubernetes.io/pid-pressure:NoSchedule: Node has PID pressure
- node.kubernetes.io/network-unavailable:NoSchedule: Node's network is unavailable
- node.kubernetes.io/unschedulable:NoSchedule: Node is marked as unschedulable
Default Tolerations: Kubernetes はすべての Pod に次の default toleration を自動的に追加します:
tolerations:
- key: node.kubernetes.io/not-ready
operator: Exists
effect: NoExecute
tolerationSeconds: 300
- key: node.kubernetes.io/unreachable
operator: Exists
effect: NoExecute
tolerationSeconds: 300これらの default toleration により、Node が not ready または unreachable になった場合でも、Pod は 5 分間(300 秒)その Node 上に残ることができ、一時的な network issue による不要な Pod rescheduling を防ぎます。
Custom Tolerations: critical workload では、より長い toleration time を設定できます:
apiVersion: v1
kind: Pod
metadata:
name: critical-pod
spec:
tolerations:
- key: node.kubernetes.io/unreachable
operator: Exists
effect: NoExecute
tolerationSeconds: 600 # Tolerate for 10 minutes
containers:
- name: nginx
image: nginxNode Controller Settings: node controller は、次の settings を通じて Node status change と taint application behavior を制御します:
- --node-monitor-period: Node status を check する period(default: 5 seconds)
- --node-monitor-grace-period: Node を
Unknownとして mark する前の wait time(default: 40 seconds) - --pod-eviction-timeout:
UnknownまたはNotReadyNode から Pod を削除する前の wait time(default: 5 minutes)
Checking Node Status and Taints:
# Check node status
kubectl get nodes
# Check node details
kubectl describe node <node-name>
# Check node taints
kubectl get node <node-name> -o jsonpath='{.spec.taints}'Checking Pod Tolerations:
# Check pod tolerations
kubectl get pod <pod-name> -o jsonpath='{.spec.tolerations}'Handling Taints in Custom Scheduler: Custom Scheduler を実装する際は、Node taints と Pod tolerations を考慮する必要があります。
// Taint handling example
func checkNodeUnreachableTaint(node *v1.Node) bool {
for _, taint := range node.Spec.Taints {
if taint.Key == "node.kubernetes.io/unreachable" && taint.Effect == v1.TaintEffectNoExecute {
return true // Node has unreachable taint
}
}
return false
}Issues with Other Options:
- B. Node は unschedulable だが、既存の Pod は実行を続ける: これは
NoScheduleeffect の動作です。NoExecuteeffect は toleration を持たない既存の Pod も削除します。 - C. Node は maintenance mode であり、新しい Pod は schedule されない: これは通常、
node.kubernetes.io/unschedulable:NoScheduletaint の動作です。 - D. Node は resource shortage state であり、新しい Pod はできれば schedule されない: これは
PreferNoScheduleeffect の動作であり、resource shortage は通常node.kubernetes.io/memory-pressureまたはnode.kubernetes.io/disk-pressuretaint によって示されます。