Skip to content

Kubernetes 拡張メカニズムクイズ

関連ドキュメント: Kubernetes 拡張メカニズム

選択式問題

1. CRD (Custom Resource Definition) の主な目的は何ですか?

  • A) 既存の Kubernetes リソースを変更すること
  • B) custom resource type で Kubernetes API を拡張すること
  • C) pod networking を設定すること
  • D) storage volume をプロビジョニングすること
回答を表示

回答: B) custom resource type で Kubernetes API を拡張すること

解説: CRD を使用すると、native Kubernetes resource のように動作する custom resource type を定義して、Kubernetes API を拡張できます。

2. custom controller の reconciliation loop が実行する主なタスクは何ですか?

  • A) リソースを即座に削除すること
  • B) current state と desired state の差分を調整すること
  • C) API server に新しい API を登録すること
  • D) network policy を適用すること
回答を表示

回答: B) current state と desired state の差分を調整すること

解説: custom controller の reconciliation loop は、リソースの current state を監視し、desired state (spec) と比較して、差分がある場合に desired state を実現するためのアクションを実行します。

3. Operator pattern の中核コンポーネントは何ですか?

  • A) Deployment と Service
  • B) CRD と Custom Controller
  • C) ConfigMap と Secret
  • D) Ingress と NetworkPolicy
回答を表示

回答: B) CRD と Custom Controller

解説: Operator pattern は、CRD を使用してアプリケーション設定を定義し、custom controller を使用してデプロイ、アップグレード、復旧などの運用知識を自動化します。

4. MutatingAdmissionWebhook の主な用途は何ですか?

  • A) API request を拒否すること
  • B) API request を変更すること
  • C) API response をログに記録すること
  • D) API version をアップグレードすること
回答を表示

回答: B) API request を変更すること

解説: MutatingAdmissionWebhook は、API request が永続化される前にそれらを変更できます。一般的な用途には、sidecar container injection、default の設定などがあります。

5. scheduler framework における Filter plugin の役割は何ですか?

  • A) node に score を割り当てること
  • B) pod を実行できない node を除外すること
  • C) pod を node に bind すること
  • D) node resource を reserve すること
回答を表示

回答: B) pod を実行できない node を除外すること

解説: Filter plugin は、pod の要件を満たさない node をフィルタリングし、候補から除外します。

6. Aggregated API Server と CRD の違いは何ですか?

  • A) 違いはなく、同じものです
  • B) Aggregated API はより多くの制御を提供しますが、別個の server を実行する必要があります
  • C) CRD は Aggregated API より多くの機能を提供します
  • D) Aggregated API は非推奨です
回答を表示

回答: B) Aggregated API はより多くの制御を提供しますが、別個の server を実行する必要があります

解説: Aggregated API Server は、API の動作、custom storage backend、高度な機能を完全に制御できますが、別個の API server をデプロイして維持する必要があります。CRD はよりシンプルですが、制限があります。

7. Kubernetes における Finalizer の目的は何ですか?

  • A) リソース削除を高速化すること
  • B) cleanup が完了するまでリソース削除を防ぐこと
  • C) 失敗した pod を自動的に再起動すること
  • D) リソース作成を検証すること
回答を表示

回答: B) cleanup が完了するまでリソース削除を防ぐこと

解説: Finalizer は、controller が必要な cleanup operation(外部リソースの削除など)を実行して finalizer を削除するまで、リソース削除をブロックします。

8. pod が node に bind された後に実行される scheduler extension point はどれですか?

  • A) PreFilter
  • B) PostBind
  • C) Reserve
  • D) Score
回答を表示

回答: B) PostBind

解説: PostBind plugin は、pod が node に正常に bind された後に呼び出されます。これらは情報提供用で、cleanup や通知に使用されます。

9. Istio で admission webhook を介して sidecar を injection するために使用される annotation は何ですか?

  • A) istio.io/inject
  • B) sidecar.istio.io/inject
  • C) istio-injection
  • D) auto-inject.istio.io
回答を表示

回答: B) sidecar.istio.io/inject

解説:sidecar.istio.io/inject annotation は、Istio の mutating webhook が Envoy sidecar を pod に注入するかどうかを制御します。Namespace レベルの制御では istio-injection label を使用します。

10. scheduler framework における Score plugin の目的は何ですか?

  • A) 不適切な node をフィルタリングすること
  • B) node をランク付けして最適なものを選択すること
  • C) pod を選択された node に bind すること
  • D) pod specification を検証すること
回答を表示

回答: B) node をランク付けして最適なものを選択すること

解説: Score plugin は、フィルタリングを通過した node に score を割り当てます。scheduler は、すべての Score plugin からの合計 score が最も高い node を選択します。

短答問題

1. CRD の schema validation にはどの標準が使用されますか?

回答を表示

回答: OpenAPI v3 Schema (openAPIV3Schema)

解説: CRD は spec.versions[].schema.openAPIV3Schema の OpenAPI v3 schema を使用して、custom resource の構造と validation rule を定義します。

2. Kubernetes controller における Owner Reference の役割は何ですか?

回答を表示

回答: リソース間の ownership relationship を定義し、garbage collection と event propagation を管理すること

解説: Owner Reference は親子関係を定義し、Kubernetes garbage collection によって親が削除されたときに子を自動的に削除します。

3. ValidatingAdmissionPolicy と ValidatingAdmissionWebhook の違いは何ですか?

回答を表示

回答: ValidatingAdmissionPolicy は CEL expression を使用して in-process で実行される一方、ValidatingAdmissionWebhook は external HTTP endpoint を呼び出します。

解説: ValidatingAdmissionPolicy(1.26 で導入)は、より優れたパフォーマンスを提供し、external webhook infrastructure を必要としませんが、webhook より柔軟性は低くなります。

4. controller-runtime library とは何で、なぜ一般的に使用されますか?

回答を表示

回答: controller-runtime は、client caching、leader election、reconciliation loop management など、Kubernetes controller を構築するための共通パターンを提供する library です。

解説: Kubebuilder project の一部である controller-runtime は、boilerplate code と best practice を抽象化し、信頼性の高い operator をより簡単に構築できるようにします。

5. CRD における conversion webhook の目的は何ですか?

回答を表示

回答: Conversion webhook は、同じ CRD の異なる API version 間でリソースを変換します。

解説: CRD に複数の version(例: v1alpha1、v1beta1、v1)がある場合、conversion webhook は version 間の変換を処理し、API evolution をサポートします。

ハンズオン問題

1. 次の要件を満たす CRD を作成してください:

  • Name: WebApp
  • Group: apps.example.com
  • Fields: replicas (integer, minimum 1), image (string, required)
回答を表示
yaml
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.creationTimestamp

2. "production" namespace 内のすべての Deployment を検証する ValidatingAdmissionWebhook configuration を作成してください。

回答を表示
yaml
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: 10

解説:

  • namespaceSelector は webhook を environment: production label を持つ namespace に制限します
  • failurePolicy: Fail は webhook が利用できない場合に request を拒否します
  • sideEffects: None は webhook に副作用がないことを示します

3. custom controller の簡単な reconciliation loop pseudocode を作成してください。

回答を表示
go
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
}

重要ポイント:

  • resource not found を常に処理する(削除済みの場合があります)
  • 外部リソースの cleanup には finalizer を使用する
  • garbage collection のために owner reference を設定する
  • status subresource を個別に更新する
  • 定期的なチェックのために requeue interval を考慮する

高度な問題

1. 複雑な分散システム向けの Kubernetes Operator を設計してください。

回答を表示

CRD 設計:

yaml
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.readyReplicas

Controller の中核ロジック:

  • phase-based state management(Creating、Running、Upgrading、Failed)
  • 自動障害復旧(Primary が失敗した場合の Failover)
  • rolling upgrade strategy(replica を先にアップグレードし、その後 primary をアップグレード)
  • backup management(scheduled backup のための CronJob)

Architecture:

PostgresCluster CR
       |
       v
   Controller
       |
       +---> StatefulSet (PostgreSQL pods)
       +---> Service (Primary endpoint)
       +---> Service (Replica endpoint)
       +---> Secret (Credentials)
       +---> ConfigMap (PostgreSQL config)
       +---> CronJob (Backups)
       +---> PodDisruptionBudget

2. scheduler framework を使用して custom scheduler を実装する方法を説明してください。

回答を表示

Scheduler Plugin Implementation:

go
// 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:

yaml
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: NodeResourcesBalancedAllocation

Extension Points Summary:

Extension PointPurposeRuns When
PreFilterPod-level checksBefore filtering
FilterNode eliminationFor each node
PostFilterHandle unschedulableWhen no node fits
PreScorePrepare for scoringBefore scoring
ScoreNode rankingFor filtered nodes
NormalizeScoreScore normalizationAfter all scores
ReserveResource reservationAfter node selection
PermitFinal approvalBefore binding
PreBindPre-binding actionsBefore API binding
BindActual bindingAPI server update
PostBindPost-binding cleanupAfter binding