Kubernetes Extension Mechanisms Quiz
Related Document: Kubernetes Extension Mechanisms
Multiple Choice Questions
1. What is the primary purpose of CRD (Custom Resource Definition)?
- A) To modify existing Kubernetes resources
- B) To extend the Kubernetes API with custom resource types
- C) To configure pod networking
- D) To provision storage volumes
Show Answer
Answer: B) To extend the Kubernetes API with custom resource types
Explanation: CRDs allow you to extend the Kubernetes API by defining custom resource types that behave like native Kubernetes resources.
2. What is the main task performed by a custom controller's reconciliation loop?
- A) Immediately delete resources
- B) Reconcile differences between current state and desired state
- C) Register new APIs with the API server
- D) Apply network policies
Show Answer
Answer: B) Reconcile differences between current state and desired state
Explanation: The custom controller's reconciliation loop observes the current state of resources, compares it with the desired state (spec), and takes actions to achieve the desired state when differences exist.
3. What are the core components of the Operator pattern?
- A) Deployment and Service
- B) CRD and Custom Controller
- C) ConfigMap and Secret
- D) Ingress and NetworkPolicy
Show Answer
Answer: B) CRD and Custom Controller
Explanation: The Operator pattern uses CRDs to define application configuration and custom controllers to automate operational knowledge such as deployment, upgrades, and recovery.
4. What is the primary use of MutatingAdmissionWebhook?
- A) Reject API requests
- B) Modify API requests
- C) Log API responses
- D) Upgrade API versions
Show Answer
Answer: B) Modify API requests
Explanation: MutatingAdmissionWebhook can modify API requests before they are persisted. Common uses include: sidecar container injection, setting defaults, etc.
5. What is the role of the Filter plugin in the scheduler framework?
- A) Assign scores to nodes
- B) Exclude nodes that cannot run the pod
- C) Bind the pod to a node
- D) Reserve node resources
Show Answer
Answer: B) Exclude nodes that cannot run the pod
Explanation: Filter plugins filter out nodes that don't meet the pod's requirements, excluding them from consideration.
6. What is the difference between Aggregated API Server and CRD?
- A) No difference, they are the same
- B) Aggregated API provides more control but requires running a separate server
- C) CRD provides more features than Aggregated API
- D) Aggregated API is deprecated
Show Answer
Answer: B) Aggregated API provides more control but requires running a separate server
Explanation: Aggregated API Server provides full control over API behavior, custom storage backends, and advanced features but requires deploying and maintaining a separate API server. CRDs are simpler but have limitations.
7. What is the purpose of a Finalizer in Kubernetes?
- A) To speed up resource deletion
- B) To prevent resource deletion until cleanup is complete
- C) To automatically restart failed pods
- D) To validate resource creation
Show Answer
Answer: B) To prevent resource deletion until cleanup is complete
Explanation: Finalizers block resource deletion until the controller performs necessary cleanup operations (like deleting external resources) and removes the finalizer.
8. Which scheduler extension point runs after a pod has been bound to a node?
- A) PreFilter
- B) PostBind
- C) Reserve
- D) Score
Show Answer
Answer: B) PostBind
Explanation: PostBind plugins are called after the pod has been successfully bound to a node. They are informational and used for cleanup or notifications.
9. What annotation is used to inject sidecars via admission webhook in Istio?
- A) istio.io/inject
- B) sidecar.istio.io/inject
- C) istio-injection
- D) auto-inject.istio.io
Show Answer
Answer: B) sidecar.istio.io/inject
Explanation: The sidecar.istio.io/inject annotation controls whether Istio's mutating webhook injects the Envoy sidecar into a pod. Namespace-level control uses the istio-injection label.
10. What is the purpose of the Score plugin in the scheduler framework?
- A) To filter out unsuitable nodes
- B) To rank nodes and select the best one
- C) To bind the pod to the selected node
- D) To validate pod specifications
Show Answer
Answer: B) To rank nodes and select the best one
Explanation: Score plugins assign scores to nodes that passed filtering. The scheduler selects the node with the highest combined score from all Score plugins.
Short Answer Questions
1. What standard is used for schema validation in CRDs?
Show Answer
Answer: OpenAPI v3 Schema (openAPIV3Schema)
Explanation: CRDs use OpenAPI v3 schema in spec.versions[].schema.openAPIV3Schema to define the structure and validation rules for custom resources.
2. What is the role of Owner Reference in Kubernetes controllers?
Show Answer
Answer: To define ownership relationships between resources and manage garbage collection and event propagation
Explanation: Owner Reference defines parent-child relationships and automatically deletes children when the parent is deleted through Kubernetes garbage collection.
3. What is the difference between ValidatingAdmissionPolicy and ValidatingAdmissionWebhook?
Show Answer
Answer: ValidatingAdmissionPolicy uses CEL expressions and runs in-process, while ValidatingAdmissionWebhook calls external HTTP endpoints.
Explanation: ValidatingAdmissionPolicy (introduced in 1.26) provides better performance and doesn't require external webhook infrastructure, but has less flexibility than webhooks.
4. What is the controller-runtime library and why is it commonly used?
Show Answer
Answer: controller-runtime is a library that provides common patterns for building Kubernetes controllers, including client caching, leader election, and reconciliation loop management.
Explanation: Part of the Kubebuilder project, controller-runtime abstracts away boilerplate code and best practices, making it easier to build reliable operators.
5. What is the purpose of conversion webhooks in CRDs?
Show Answer
Answer: Conversion webhooks convert resources between different API versions of the same CRD.
Explanation: When a CRD has multiple versions (e.g., v1alpha1, v1beta1, v1), conversion webhooks handle the transformation between versions to support API evolution.
Hands-on Questions
1. Write a CRD that meets the following requirements:
- Name: WebApp
- Group: apps.example.com
- Fields: replicas (integer, minimum 1), image (string, required)
Show Answer
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: webapps.apps.example.com
spec:
group: apps.example.com
names:
kind: WebApp
plural: webapps
singular: webapp
shortNames:
- wa
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required: ["image"]
properties:
replicas:
type: integer
minimum: 1
default: 1
image:
type: string
status:
type: object
properties:
availableReplicas:
type: integer
conditions:
type: array
items:
type: object
properties:
type:
type: string
status:
type: string
lastTransitionTime:
type: string
format: date-time
subresources:
status: {}
additionalPrinterColumns:
- name: Replicas
type: integer
jsonPath: .spec.replicas
- name: Available
type: integer
jsonPath: .status.availableReplicas
- name: Age
type: date
jsonPath: .metadata.creationTimestamp2. Write a ValidatingAdmissionWebhook configuration that validates all Deployments in the "production" namespace.
Show Answer
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: deployment-validator
webhooks:
- name: validate-deployment.example.com
clientConfig:
service:
name: webhook-service
namespace: webhook-system
path: /validate-deployment
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
scope: Namespaced
namespaceSelector:
matchLabels:
environment: production
failurePolicy: Fail
sideEffects: None
admissionReviewVersions: ["v1"]
timeoutSeconds: 10Explanation:
namespaceSelectorlimits the webhook to namespaces withenvironment: productionlabelfailurePolicy: Failrejects requests if the webhook is unavailablesideEffects: Noneindicates the webhook has no side effects
3. Write a simple reconciliation loop pseudocode for a custom controller.
Show Answer
func (r *WebAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
// 1. Fetch the WebApp resource
var webapp appsv1.WebApp
if err := r.Get(ctx, req.NamespacedName, &webapp); err != nil {
if errors.IsNotFound(err) {
// Resource deleted, nothing to do
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
// 2. Check if being deleted (handle finalizers)
if !webapp.DeletionTimestamp.IsZero() {
if containsFinalizer(webapp, finalizerName) {
// Perform cleanup
if err := r.cleanupExternalResources(&webapp); err != nil {
return ctrl.Result{}, err
}
// Remove finalizer
removeFinalizer(&webapp, finalizerName)
if err := r.Update(ctx, &webapp); err != nil {
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}
// 3. Add finalizer if not present
if !containsFinalizer(webapp, finalizerName) {
addFinalizer(&webapp, finalizerName)
if err := r.Update(ctx, &webapp); err != nil {
return ctrl.Result{}, err
}
}
// 4. Create or update Deployment
deployment := r.constructDeployment(&webapp)
if err := controllerutil.SetControllerReference(&webapp, deployment, r.Scheme); err != nil {
return ctrl.Result{}, err
}
if err := r.CreateOrUpdate(ctx, deployment); err != nil {
return ctrl.Result{}, err
}
// 5. Create or update Service
service := r.constructService(&webapp)
if err := controllerutil.SetControllerReference(&webapp, service, r.Scheme); err != nil {
return ctrl.Result{}, err
}
if err := r.CreateOrUpdate(ctx, service); err != nil {
return ctrl.Result{}, err
}
// 6. Update status
webapp.Status.AvailableReplicas = deployment.Status.AvailableReplicas
if err := r.Status().Update(ctx, &webapp); err != nil {
return ctrl.Result{}, err
}
// 7. Requeue after interval for periodic reconciliation
return ctrl.Result{RequeueAfter: time.Minute * 5}, nil
}Key Points:
- Always handle resource not found (may have been deleted)
- Use finalizers for cleanup of external resources
- Set owner references for garbage collection
- Update status subresource separately
- Consider requeue intervals for periodic checks
Advanced Questions
1. Design a Kubernetes Operator for a complex distributed system.
Show Answer
CRD Design:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: postgresclusters.database.example.com
spec:
group: database.example.com
names:
kind: PostgresCluster
plural: postgresclusters
shortNames:
- pg
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required: ["replicas", "version"]
properties:
replicas:
type: integer
minimum: 1
maximum: 10
version:
type: string
enum: ["14", "15", "16"]
storage:
type: object
properties:
size:
type: string
default: "10Gi"
storageClass:
type: string
backup:
type: object
properties:
enabled:
type: boolean
default: true
schedule:
type: string
default: "0 2 * * *"
retention:
type: integer
default: 7
status:
type: object
properties:
phase:
type: string
enum: ["Creating", "Running", "Upgrading", "Failed", "Deleting"]
primaryEndpoint:
type: string
replicaEndpoints:
type: array
items:
type: string
currentVersion:
type: string
conditions:
type: array
items:
type: object
properties:
type:
type: string
status:
type: string
reason:
type: string
message:
type: string
lastTransitionTime:
type: string
format: date-time
subresources:
status: {}
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.readyReplicasController Core Logic:
- Phase-based state management (Creating, Running, Upgrading, Failed)
- Automatic failure recovery (Failover when Primary fails)
- Rolling upgrade strategy (Upgrade replicas first, then primary)
- Backup management (CronJob for scheduled backups)
Architecture:
PostgresCluster CR
|
v
Controller
|
+---> StatefulSet (PostgreSQL pods)
+---> Service (Primary endpoint)
+---> Service (Replica endpoint)
+---> Secret (Credentials)
+---> ConfigMap (PostgreSQL config)
+---> CronJob (Backups)
+---> PodDisruptionBudget2. Explain how to implement a custom scheduler using the scheduler framework.
Show Answer
Scheduler Plugin Implementation:
// Plugin implementing multiple extension points
type CustomSchedulerPlugin struct {
handle framework.Handle
}
// Implement PreFilter - check pod requirements
func (p *CustomSchedulerPlugin) PreFilter(ctx context.Context, state *framework.CycleState, pod *v1.Pod) (*framework.PreFilterResult, *framework.Status) {
// Validate pod has required annotations
if _, ok := pod.Annotations["custom-scheduler/zone"]; !ok {
return nil, framework.NewStatus(framework.Unschedulable, "missing zone annotation")
}
return nil, framework.NewStatus(framework.Success, "")
}
// Implement Filter - exclude unsuitable nodes
func (p *CustomSchedulerPlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
requiredZone := pod.Annotations["custom-scheduler/zone"]
nodeZone := nodeInfo.Node().Labels["topology.kubernetes.io/zone"]
if requiredZone != nodeZone {
return framework.NewStatus(framework.Unschedulable, "zone mismatch")
}
return framework.NewStatus(framework.Success, "")
}
// Implement Score - rank suitable nodes
func (p *CustomSchedulerPlugin) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
nodeInfo, err := p.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
if err != nil {
return 0, framework.NewStatus(framework.Error, err.Error())
}
// Score based on available resources
allocatable := nodeInfo.Node().Status.Allocatable
requested := nodeInfo.Requested
cpuScore := calculateResourceScore(allocatable.Cpu(), requested.Cpu)
memScore := calculateResourceScore(allocatable.Memory(), requested.Memory)
return (cpuScore + memScore) / 2, framework.NewStatus(framework.Success, "")
}
// Register the plugin
func New(_ runtime.Object, h framework.Handle) (framework.Plugin, error) {
return &CustomSchedulerPlugin{handle: h}, nil
}Scheduler Configuration:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
preFilter:
enabled:
- name: CustomSchedulerPlugin
filter:
enabled:
- name: CustomSchedulerPlugin
score:
enabled:
- name: CustomSchedulerPlugin
disabled:
- name: NodeResourcesBalancedAllocationExtension Points Summary:
| Extension Point | Purpose | Runs When |
|---|---|---|
| PreFilter | Pod-level checks | Before filtering |
| Filter | Node elimination | For each node |
| PostFilter | Handle unschedulable | When no node fits |
| PreScore | Prepare for scoring | Before scoring |
| Score | Node ranking | For filtered nodes |
| NormalizeScore | Score normalization | After all scores |
| Reserve | Resource reservation | After node selection |
| Permit | Final approval | Before binding |
| PreBind | Pre-binding actions | Before API binding |
| Bind | Actual binding | API server update |
| PostBind | Post-binding cleanup | After binding |