kubernetes extension point


以下大部分來自於k8s document, 筆者只是總結歸納, 解釋不足的地方請參閱相關文檔

Intention

Non-sustainable way to customize Kubernetes

  • Fork & Sending PRs to upstream
  • without extensibility...
  • 增加k8s維護團隊負擔
  • 可能脫離k8s規范

Extension Patterns

extension pattern
webhook 通過http post一個請求,然后通過遠程的server來決策, plugin是通過調用一個二進制可執行程序來決策, controller是實現資源自動化的一種方式,通過聲明式的資源定義,定義一個資源的期望狀態,然后controller不斷獲取實際狀態進行狀態轉換到達期望狀態,所以他會不斷地讀取api-server的信息, 系統中內置的kube-controller-manager就包含許多這樣的controller。

Extension Points

extension point

kubectl plugin

可以實現kubectl自定義的命令 ,在k8s v1.10為alpha version
Plugin loader會在 Search order 中依次查找以下plugin.yaml及其對應的binary, plugin.yaml 對自定義命令進行聲明,binary實現具體的程序邏輯。

API Access Extensions

Webhook Token Authentication

讓外部的webhook server來決策是否允許該請求通過認證。
--authentication-token-webhook-config-file flag指定配置文件, 配置文件的格式如kubeconfig形式

# clusters refers to the remote service.
clusters:
  - name: name-of-remote-authn-service
    cluster:
      certificate-authority: /path/to/ca.pem         # CA for verifying the remote service.
      server: https://authn.example.com/authenticate # URL of remote service to query. Must use 'https'.

# users refers to the API server's webhook configuration.
users:
  - name: name-of-api-server
    user:
      client-certificate: /path/to/cert.pem # cert for the webhook plugin to use
      client-key: /path/to/key.pem          # key matching the cert

# kubeconfig files require a context. Provide one for the API server.
current-context: webhook
contexts:
- context:
    cluster: name-of-remote-authn-service
    user: name-of-api-sever
  name: webhook

當api-server收到上述請求之后會POST一個 authentication.k8s.io/v1beta1 TokenReview對象給webhook, 服務器會返回對應的狀態和用戶信息,形如:

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    "token": "(BEARERTOKEN)"
  }
}
{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      "username": "janedoe@example.com",
      "uid": "42",
      "groups": [
        "developers",
        "qa"
      ],
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    }
  }
}

Authenticating Proxy

通過添加一個api-server信任的proxy, 在proxy 這一層進行用戶身份認證,通過后proxy 會將用戶信息傳遞給api-server

Authorization Webhook

用戶授權的webhook, 工作原理與上述Authentication webhook 大致相同

Admission control

admissoin controller 是編譯在api-server中的一系列binary, 通過在api-server的flag中指定執行哪些controller進行插件式的使用,實現資源、權限等的檢查和修改。例如resourceQuta, limitRanger, 官方提供的controller必須提前編譯進api-server, reload必須重啟服務,基於上述不足,k8s提供了不同的擴展方式。

Dynamic Admission Controller

用戶提供一個webhook來進行自定義(beta in 1.9), webhook分為MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。 MutatingAdmissionWebhook執行修改操作,為用戶未設置的資源字段提供默認值等, ValidatingAdmissionWebhook 執行一些檢查操作,可以拒絕用戶的請求來增加額外的准入策略,例如可以控制所有的容器鏡像都是來自一個特定的registry, 拒絕來自其他鏡像倉庫的pod部署 。
使用的時候通過一個config file (--admission-control-config-file)來配置webhook server的地址:

apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
  name: <name of this configuration object>
webhooks:
- name: <webhook name, e.g., pod-policy.example.io>
  rules:
  - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE
    resources:
    - pods
  clientConfig:
    service:
      namespace: <namespace of the front-end service>
      name: <name of the front-end service>
    caBundle: <pem encoded ca cert that signs the server cert used by the webhook>

但是會有一些側面效應,比如改了用戶的配置會讓用戶感到莫名其妙,可能破壞一些自動化contoller的執行邏輯,在將來的版本中會對可更改的字段進行限制。
ref: github example-webhook-admission-controller

PodPreset

可以在pod創建的時候注入一些信息, 例如一些volume mounts, secrets, environment variables 甚至是一個sidecar, podPreset通過匹配lable來判斷是否對該pod注入,如果注入失敗並不會影響原來pod的正常運行。流程:

  • Retrieve all PodPresets available for use.
  • Check if the label selectors of any PodPreset matches the labels on the pod being created.
  • Attempt to merge the various resources defined by the PodPreset into the Pod being created.
  • On error, throw an event documenting the merge error on the pod, and create the pod without any injected resources from the PodPreset.
  • Annotate the resulting modified Pod spec to indicate that it has been modified by a PodPreset. The annotation is of the form podpreset.admission.kubernetes.io/podpreset- : " ".

如果想要顯式拒絕這種注入, 可以定義一個annotataion: podpreset.admission.kubernetes.io/exclude: "true".
下面是podPreset的定義:


apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-database
spec:
  selector:
    matchLabels:
      role: frontend
  env:
    - name: DB_PORT
      value: "6379"
  volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir: {}

Initializers

initializers比上述兩者功能都強大,可以對某種類型的資源進行更改, 通過配置InitializerConfiguration 來決定一種資源類型應該被什么initializers處理, 配置文件如下:

apiVersion: admissionregistration.k8s.io/v1alpha1
kind: InitializerConfiguration
metadata:
  name: example-config
initializers:
  # the name needs to be fully qualified, i.e., containing at least two "."
  - name: podimage.example.com
    rules:
      # apiGroups, apiVersion, resources all support wildcard "*".
      # "*" cannot be mixed with non-wildcard.
      - apiGroups:
          - ""
        apiVersions:
          - v1
        resources:
          - pods

一個資源類型可以有多個initializers串行初始化,每種initilizers需要實現對應的controller, controller執行更改或驗證操作,然后從metadata.initalizers.pending list中移除該initializers, 當所有的initializer都被移除之后pod才能被調度到node之上,如果initializers未執行完,則默認無法看到該資源對象。
反過來說,如果一個initialier controller 下線后,該資源類型都無法創建成功。
ref:

ImagePolicyWebhook

通過一個webhook 來判斷是否允許拉取指定的鏡像

User-Defined Types

在k8s中每一種資源都由group, version, kind三要素來唯一標識, 對於自定義的資源也需要定義這三要素,k8s提供了兩種自定義資源的方式,CRD與API Aggregation, CRD是通過K8S CustomResourceDefinition類型將聲明的類型添加到k8s中, API Aggregation則提供了一個可以注冊自己編寫的api-server的方式,讓自定義的api-server來提供自定義類型。資源定義只是一種靜態的方式,資源的行為的自動化才能為資源提供生命力,而controller就是來實現資源的自動化的方式。

Custom Resource Definitions (CRD)

  • Do not require programming
  • Easy to deploy: kubectl create -f crd.yaml
  • No new point-of-failure

舉個栗子: etcd operator, 定義好一個etcd資源后,一鍵部署,告別復雜配置, controller會將所有的配置負責
官方提供的sample controller 是一個從編寫crd到controller很好的例子, 整個流程需要注意的幾點:

  • CustomResourceDefinition yaml 編寫yaml配置文件
  • code-gen 使用code generator生成自定義資源的client-go sdk, 來實現controller
  • informer 監聽api-server資源變化的事件,在相應事件發生的時候進行webhook回調
  • controller 添加自動化的程序邏輯
  • interagation with others: events, Garbage conllector(ownerReferences) 配置event事件,GC等
  • resource management, requests and limit, 像cpu和memory一樣可以指定request, 和limit進行資源管理
    整個controller的事件循環如下
    controller
    CoreOS團隊開源了一個快速提供controller的工具,可以快速開發出一個controller,值得參考一下
    ref: some awesome operators

API Aggregation

  • Require coding, built atop k8s.io/apiserver library
  • Highly customizable, like adding a new verb, create/delete hooks
  • Typed fields, validation, defaults
  • Multi-versioning, supporting old clients
  • Generated OpenAPI schema
  • Supports protobuf
  • Supports strategic merge patch

主要有以下三個作用

  1. Provide an API for registering API servers.
  2. Summarize discovery information from all the servers.
  3. Proxy client requests to individual servers.

注冊一個apiserver的大致流程

  1. setup extension apiserver
    • run as a Deployment
    • register with the core apiserver using an apiregistration.k8s.io/v1beta1/APIService
  2. setup etcd storage for the extension apiserver
    • run as StatefulSet or etcd operator
  3. setup the extension controller-manager
    • run as a Deployment (maybe the same Pod as the extension apiserver)
    • configure to talk to the core apiserver (extension APIs are used through core

使用起來較為復雜,官方倉庫中的 apiserver library 提供了一些基礎模塊以及一些api interface, kubernetes-incubator/apiserver-builder 則提供了一個framwork, 可以在其上快速構建一個自己的api-server。
ref: sample api-server

kubernetes-incubator api aggregation

  • service catalog (提供了Open service broker API, 可以將外部的服務暴露出來, 使用起來如同pv&pvc)
  • metrics-server (官方提供的輕量級的heapster實現,收集node和pod的信息 )

此處整理一下github中關於apiserver的幾個項目

  • kubernetes/apiserver library為其他api server提供了基礎模塊,其中kubernetes, Aggregator, service catalog都是使用該庫來實現的
  • kubernetes/kube-aggregator 是為api server提供聚合功能的組件,可以自定義api server注冊到aggerator中
  • kubernetes/sample-apiserver是演示apisever library的官方demo
  • kubernetes/apiextensions-apiserver 是CRD的實現,This API server provides the implementation for CustomResourceDefinitions which is included as delegate server inside of kube-apiserver.
  • kubernetes-incubator/service catalog 是具體使用aggregator機制的一種第三方的api server
  • kubernetes-incubator/Apiserver-builder 提供了一個framwork,The Apiserver-builder is a complete framework for generating the apiserver, client libraries, and the installation program.

還有關於metric的幾個項目

  • kubernetes/metrics Kubernetes metrics API type definitions and clients. 定義了規范, 數據類型, 被heapster, metric server所實現
  • kub ernetes-incubator/custom-metrics-apiserver 實現自定義Metric的框架,可以更方便的實現metric規范
  • kubernetes-incubator/metrics-server 從1.8開始資源使用的Metric數據可以直接從metricAPI獲得,通過kubectl top就可以看到,之前需要部署一個Heapster才可以, 通過metric-server來服務,通過shell腳本安裝的話會自動安裝該aggregrator,可以用來Horizontal Pod Autoscaler , schedualer 調度,是一個輕量級的內存服務器, 可以代替heapster
  • Prometheus Adapter. 非官方項目,但是用的比較多,也是一個自定義Metic實現,同上述metrics-server功能類似,但是可以將prometheus中監控數據暴露給集群使用, 可以使用這些監控數據實現自定義方式的擴縮容和調度。整個自動擴縮容架構如下所示 : k8s-hpa

CRD summary

其實CRD, APIServer 本身就是兩種類型,分別位於group下: apiextensions.k8s.io/v1beta1 apiregistration.k8s.io/v1,只是這另種resource比較特殊,可以定義其他resource, 與其說是將擴展,不如說是使用了這兩種resource,不過重難點在於controller的實現 。

scheduler

kubernetes scheduler component, 首先是predicates 過濾掉不符合的node, 然后priority來選擇合適的node
自定義的三種方式:

  1. 其實是通過kube-scheduler的--policy-config-file flag來配置, 參見這里
  2. 直接配置一個新的scheduler,與kube-scheuler並排執行, 通過pod啟動時的spec.schedulerName來選擇scheduler。參見這里
  3. schduler extender, 在kube-schduler調用結果之后調用附加的webhook,使用方式就是在上面kube-scheduler的--policy-config-file flag的配置文件中增加一個extender字段來配置extender。參見這里

Infrastructure Extensions

基礎設施層的擴展大多數都已經稱為規范,由於涉及較多,此處不做討論


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM