扩展 Kubernetes 测验
本测验用于测试你对 Kubernetes 扩展机制的概念性和实践性知识。它涵盖 Custom Resource Definitions (CRD)、custom controllers、API 扩展、webhooks 以及 operator pattern 等主题。
选择题
- 在 Kubernetes 中定义 custom resources 最常见的方式是什么?
- A) 使用 ConfigMap 定义资源 schema
- B) 创建 CustomResourceDefinition (CRD)
- C) 直接修改 API server 代码
- D) 使用 Aggregation Layer
显示答案
答案:B) 创建 CustomResourceDefinition (CRD)
解释: 在 Kubernetes 中定义 custom resources 最常见的方式是创建 CustomResourceDefinition (CRD)。CRD 是一种机制,允许你通过定义新的资源类型来扩展 Kubernetes API。
使用 CRDs 可带来以下好处:
- 可以在不修改现有 Kubernetes API server 的情况下添加新的资源类型。
- 可以使用
kubectl等标准 Kubernetes 工具管理 custom resources。 - 可以利用资源验证、版本管理和 status subresources 等功能。
CRD 示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct其他选项的问题:
- ConfigMaps 用于存储配置数据,不适合用于 API 扩展。
- 直接修改 API server 代码很复杂、难以维护,并且可能在升级期间导致问题。
- Aggregation Layer 是定义 custom resources 的另一种方式,但它比 CRDs 更复杂,因为它需要实现单独的 API server。
- Kubernetes Operator 的主要目的是什么?
- A) 优化 cluster nodes 的资源使用
- B) 将复杂应用程序的运维知识编码到自动化软件中
- C) 提高 Kubernetes API server 性能
- D) 扩展 cluster networking 功能
显示答案
答案:B) 将复杂应用程序的运维知识编码到自动化软件中
解释: Kubernetes Operator 的主要目的是将复杂应用程序的运维知识编码到自动化软件中。operator pattern 是人类操作员管理复杂应用程序方式的软件实现。
operators 的关键特征:
- 将 custom resources 与 custom controllers 结合起来,实现特定于应用程序的逻辑。
- 自动化应用程序部署、升级、备份、恢复和扩缩容等运维任务。
- 持续监控应用程序状态,并调整到期望状态。
- 将领域知识编码化,以支持复杂应用程序的声明式管理。
operators 的常见使用场景:
- 数据库的自动化管理(例如 PostgreSQL、MySQL、MongoDB)
- 消息系统的部署和配置(例如 Kafka、RabbitMQ)
- 监控系统的设置和维护(例如 Prometheus)
- service meshes 的管理(例如 Istio)
Operator 示例 - Prometheus Operator:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: prometheus
spec:
serviceAccountName: prometheus
replicas: 2
version: v2.35.0
serviceMonitorSelector:
matchLabels:
team: frontend
resources:
requests:
memory: 400Mi通过这个简单的声明式配置,Prometheus Operator 会自动处理以下复杂任务:
- 部署 Prometheus servers
- 创建和管理配置文件
- 自动发现 service monitoring targets
- 高可用设置
- 存储管理
- 升级协调
其他选项不是 operators 的主要目的:
- 资源使用优化是 HPA (Horizontal Pod Autoscaler)、VPA (Vertical Pod Autoscaler) 等的职责。
- 提高 API server 性能不是 operators 的主要目的。
- 扩展 networking 功能是 CNI plugins 或 service meshes 的职责。
- Kubernetes 中 Admission Webhooks 的主要功能是什么?
- A) 处理 API server 的身份认证
- B) 拦截资源创建或修改请求,以验证或修改它们
- C) 监控 cluster events 并发送告警
- D) 提供用于与外部系统集成的 APIs
显示答案
答案:B) 拦截资源创建或修改请求,以验证或修改它们
解释: Kubernetes 中 Admission Webhooks 的主要功能是拦截资源创建或修改请求,以验证或修改它们。Admission webhooks 提供一种机制,可在 Kubernetes API server 将请求存储到持久化存储(etcd)之前拦截请求。
两种 admission webhooks:
Validating Webhook:
- 验证资源创建、更新和删除请求。
- 可以允许或拒绝请求,但不能修改请求。
- 用于策略强制、安全检查、配置验证等。
Mutating Webhook:
- 可以验证和修改资源创建与更新请求。
- 用于设置默认值、注入 sidecar containers、添加 labels 等。
- 在 validating webhooks 之前运行。
Admission webhook 配置示例:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-policy-validator
webhooks:
- name: pod-policy.example.com
clientConfig:
service:
namespace: webhook-namespace
name: webhook-service
path: "/validate-pods"
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
scope: "Namespaced"
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
timeoutSeconds: 5admission webhooks 的常见使用场景:
- 强制执行安全策略(例如禁止 privileged containers)
- 强制设置 resource requests 和 limits
- 自动注入 sidecar containers(例如 Istio)
- 自动添加 labels 和 annotations
- 限制 image registries
- 应用基于 namespace 的策略
其他选项的问题:
- 处理 API server 的身份认证是 Authentication Plugins 的职责。
- 监控 cluster events 并发送告警是 event listeners 或监控工具的职责。
- 提供用于与外部系统集成的 APIs 是 API 扩展的一般目的,但不是 admission webhooks 的主要功能。
- Kubernetes API server 中 Aggregation Layer 的主要目的是什么?
- A) 优化 API server 性能
- B) 将多个 API servers 合并为单个 API server
- C) 将 custom API servers 集成到 main API server 中以扩展 API
- D) 在 cluster 内提供 service discovery
显示答案
答案:C) 将 custom API servers 集成到 main API server 中以扩展 API
解释: Kubernetes API server 中 Aggregation Layer 的主要目的是将 custom API servers 集成到 main API server 中以扩展 API。这提供了另一种扩展 Kubernetes API 的方式,虽然更复杂,但比 CRDs 提供更强大的功能。
Aggregation Layer 的关键特征:
- 将 custom API servers 集成到 Kubernetes API server 的 URL 空间中。
- Custom API servers 可以拥有自己的存储、业务逻辑、API 版本等。
- Main API server 将请求代理到适当的 custom API server。
- 身份认证和授权由 main API server 处理。
使用 Aggregation Layer 的场景:
- 需要复杂验证逻辑时
- 需要自定义存储后端时
- 需要与现有 APIs 不同的行为时
- 需要资源转换或特殊状态计算时
APIService 资源示例:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1alpha1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1alpha1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100此配置会将针对 metrics.k8s.io/v1alpha1 API group 的请求路由到 kube-system namespace 中的 metrics-server service。
使用 Aggregation Layer 的真实示例:
- metrics-server:提供 node 和 pod resource usage metrics
- service-catalog:与外部 service brokers 集成
- custom-metrics-apiserver:为 HPA 提供 custom metrics
其他选项的问题:
- Aggregation Layer 不是用于优化 API server 性能的。
- 将多个 API servers 合并为一个并不是准确描述。Aggregation Layer 将多个 API servers 集成到单个 URL 空间中,但这些 servers 是分别运行的。
- Aggregation Layer 不提供 service discovery。那是 Kubernetes Services 的职责。
- Kubernetes 中 Custom Controller 的主要角色是什么?
- A) 监控 cluster nodes 的资源使用
- B) 观察 custom resources 的状态并协调到期望状态
- C) 处理 API server 请求的身份认证和授权
- D) 管理 cluster networking
显示答案
答案:B) 观察 custom resources 的状态并协调到期望状态
解释: Kubernetes 中 Custom Controller 的主要角色是观察 custom resources 的状态并协调到期望状态。Controllers 实现“reconciliation loop”,这是 Kubernetes 中的核心运维模式,用于持续将系统的实际状态调整到期望状态。
custom controllers 的关键特征:
- Watch 特定资源类型(通常是通过 CRDs 定义的 custom resources)。
- 对资源变更事件作出响应并执行业务逻辑。
- 执行任务,将资源的实际状态调整为期望状态。
- 更新资源的 status 字段以反映当前状态。
custom controllers 的常见组件:
- Informer: Watch Kubernetes API server 并接收资源变更事件。
- Work Queue: 存储和管理待处理事件。
- Reconciler: 比较资源的期望状态和实际状态,并执行必要任务。
- Client: 与 Kubernetes API 交互以创建、更新和删除资源。
Custom controller 示例 - 简单 reconcile 函数:
func (c *Controller) reconcile(key string) error {
// Split key into namespace and name
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
return err
}
// Get custom resource
instance, err := c.customResourceLister.CustomResources(namespace).Get(name)
if errors.IsNotFound(err) {
// Resource deleted - perform cleanup
return nil
}
if err != nil {
return err
}
// Check resource state and perform necessary tasks
// e.g., create sub-resources, integrate with external systems, update status, etc.
// Update status
instanceCopy := instance.DeepCopy()
instanceCopy.Status.Phase = "Reconciled"
_, err = c.customResourceClient.CustomResources(namespace).UpdateStatus(instanceCopy)
return err
}custom controllers 的常见使用场景:
- 自动化复杂应用程序的部署和管理
- 与外部系统集成(例如 cloud resource provisioning)
- 自动化备份和恢复流程
- 实现高级部署策略(例如 canary deployments、blue-green deployments)
其他选项的问题:
- 监控 cluster nodes 的资源使用是 metrics-server 或 Prometheus 等监控工具的职责。
- 处理 API server 请求的身份认证和授权是 authentication 和 authorization plugins 的职责。
- 管理 cluster networking 是 CNI plugins 或 network controllers 的职责。
- 在 Kubernetes 中,CRDs (CustomResourceDefinitions) 使用什么格式来定义验证 schemas?
- A) JSON Schema
- B) XML Schema
- C) OpenAPI v3 Schema
- D) GraphQL Schema
显示答案
答案:C) OpenAPI v3 Schema
解释: 在 Kubernetes 中,用于定义 CRDs (CustomResourceDefinitions) 验证 schemas 的格式是 OpenAPI v3 Schema。此 schema 定义 custom resources 的结构和字段类型,并由 API server 用于验证资源创建和更新请求。
CRD 验证 schema 示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required: ["spec"]
properties:
spec:
type: object
required: ["cronSpec", "image"]
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct在此示例中,openAPIV3Schema 字段定义以下验证规则:
spec字段是必需的。- 在
spec中,cronSpec和image字段是必需的。 cronSpec是字符串,并且必须遵循 cron 表达式模式。image是字符串。replicas是整数,并且必须在 1 到 10 之间。
OpenAPI v3 Schema 提供多种验证功能:
- 指定必需字段
- 数据类型验证(string、number、boolean、object、array 等)
- 字符串模式验证(正则表达式)
- 数值范围验证(minimum、maximum)
- 数组长度验证
- Enum 值验证
- 嵌套 object 结构定义
其他选项的问题:
- JSON Schema 是 OpenAPI 的基础,但 Kubernetes 明确使用 OpenAPI v3 Schema。
- XML Schema 不用于 Kubernetes API。
- GraphQL Schema 用于 GraphQL APIs,但不用于 Kubernetes API。
- 在 Kubernetes 中为 custom resources 启用 status subresource 的主要好处是什么?
- A) 更快的资源创建
- B) 分离 spec 和 status 更新,并进行 RBAC 控制
- C) 自动备份和恢复功能
- D) 简化资源版本管理
显示答案
答案:B) 分离 spec 和 status 更新,并进行 RBAC 控制
解释: 在 Kubernetes 中为 custom resources 启用 status subresource 的主要好处是分离 spec 和 status 更新,并能够通过 RBAC (Role-Based Access Control) 控制访问。
启用 status subresource 的好处:
关注点分离:
spec字段定义用户指定的期望状态。status字段报告 controllers 观察到的实际状态。- 这种分离明确了用户和 controllers 的职责。
RBAC 控制:
- 可以只向 controllers 授予 status 更新权限,同时给普通用户只读权限。
- 这可以防止未经授权修改 status 信息。
冲突预防:
- 即使用户更新
spec的同时 controller 更新status,也不会发生冲突。 - 这是因为这两个字段通过单独的 API 请求更新。
- 即使用户更新
Scale Subresource 支持:
- 启用 status subresource 也允许启用 scale subresource。
- 这使得可以使用 HPA (Horizontal Pod Autoscaler) 等标准 Kubernetes 扩缩容工具。
在 CRD 中启用 status subresource 的示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
subresources:
status: {} # Enable status subresource
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
# Spec field definitions...
status:
type: object
properties:
# Status field definitions...
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTabcontroller 更新 status 的示例:
// Update status only
statusUpdate := &v1alpha1.MyResource{}
statusUpdate.Name = instance.Name
statusUpdate.Namespace = instance.Namespace
statusUpdate.Status.Phase = "Running"
statusUpdate.Status.Message = "Resource is running"
_, err = c.clientset.MyGroup().MyResources(namespace).UpdateStatus(statusUpdate)其他选项的问题:
- status subresource 不会提高资源创建速度。
- 它不提供自动备份和恢复功能。
- 资源版本管理通过 CRD 的
versions字段处理,并不直接与 status subresource 相关。
- Kubernetes 中 Webhook Conversion 的主要目的是什么?
- A) 将 API 请求路由到外部 services
- B) 处理 custom resources 不同版本之间的转换
- C) 将身份认证 tokens 转换为不同格式
- D) 将日志数据转换为结构化格式
显示答案
答案:B) 处理 custom resources 不同版本之间的转换
解释: Kubernetes 中 Webhook Conversion 的主要目的是处理 custom resources 不同版本之间的转换。此功能支持 CRDs 的多个版本,并支持版本之间的平滑迁移。
webhook conversion 的关键特征:
多版本支持:
- CRDs 可以同时支持多个 API 版本(例如 v1alpha1、v1beta1、v1)。
- 每个版本可以有不同的 schemas 和字段。
自动转换:
- API server 会自动处理客户端请求版本与存储版本之间的转换。
- conversion webhook 在此过程中提供自定义转换逻辑。
存储版本独立性:
- 即使存储版本发生变化,使用旧版本的 clients 也可以继续工作。
- webhook 负责处理旧版本与新版本之间的双向转换。
CRD 中 conversion webhook 配置示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
# v1 schema definition...
- name: v1beta1
served: true
storage: false
schema:
openAPIV3Schema:
# v1beta1 schema definition...
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: webhook-system
name: crd-conversion-webhook
path: /convert
caBundle: <base64-encoded-ca-cert>
conversionReviewVersions: ["v1", "v1beta1"]
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTabconversion webhook server 实现示例:
func (s *WebhookServer) ServeConvert(w http.ResponseWriter, r *http.Request) {
var body []byte
if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil {
body = data
}
}
// Decode ConversionReview request
convertReview := v1.ConversionReview{}
if err := json.Unmarshal(body, &convertReview); err != nil {
// Error handling
return
}
// Perform conversion logic
if convertReview.Request.DesiredAPIVersion == "stable.example.com/v1" {
// v1beta1 -> v1 conversion
for i, obj := range convertReview.Request.Objects {
v1beta1Obj := &v1beta1.CronTab{}
if err := json.Unmarshal(obj.Raw, v1beta1Obj); err != nil {
// Error handling
return
}
// Conversion logic
v1Obj := &v1.CronTab{
Spec: v1.CronTabSpec{
CronSpec: v1beta1Obj.Spec.Cron, // Field name change
Image: v1beta1Obj.Spec.Image,
Replicas: v1beta1Obj.Spec.Replicas,
},
}
// Encode converted object
raw, err := json.Marshal(v1Obj)
if err != nil {
// Error handling
return
}
convertReview.Response.ConvertedObjects = append(
convertReview.Response.ConvertedObjects,
runtime.RawExtension{Raw: raw},
)
}
} else {
// v1 -> v1beta1 conversion
// Similar logic...
}
// Set response
convertReview.Response.UID = convertReview.Request.UID
convertReview.Response.Result.Status = "Success"
// Send response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(convertReview)
}其他选项的问题:
- 将 API 请求路由到外部 services 是 API aggregation 的职责。
- 转换身份认证 tokens 是 authentication plugins 的职责。
- 转换日志数据是 logging systems 的职责。
- 以下哪一项不是帮助开发 Kubernetes operators 的框架?
- A) Operator Framework
- B) Kubebuilder
- C) Metacontroller
- D) Kubespray
显示答案
答案:D) Kubespray
解释: Kubespray 不是帮助开发 Kubernetes operators 的框架。Kubespray 是一个使用 Ansible playbooks 部署和管理 Kubernetes clusters 的工具。它专注于 cluster 安装和配置,与 operator 开发无关。
实际用于 Kubernetes operator 开发的框架包括:
Operator Framework:
- Red Hat 开发的 operator 开发工具包
- 关键组件:
- Operator SDK:Operator 脚手架和开发工具
- Operator Lifecycle Manager (OLM):Operator 安装和升级管理
- Operator Metering:Operator 使用情况报告
- 支持 Go、Ansible 和基于 Helm 的 operator 开发
Kubebuilder:
- Kubernetes SIG (Special Interest Group) 开发的框架
- 用于以 Go 开发 controllers 的 SDK
- 提供代码生成、CRD 管理和测试工具
- 基于 controller-runtime 库
Metacontroller:
- 轻量级、基于 webhook 的 operator 框架
- 可以使用多种语言实现 controller 逻辑
- 声明式 controller 定义
- 适合快速开发简单 controllers
各框架的功能比较:
| 框架 | 主要语言 | 复杂度 | 功能 |
|---|---|---|---|
| Operator Framework | Go、Ansible、Helm | 中高 | 综合工具包,多种开发选项 |
| Kubebuilder | Go | 中 | 标准化模式,代码生成工具 |
| Metacontroller | 语言无关 | 低 | 基于 Webhook,简单实现 |
Operator 开发示例(使用 Kubebuilder):
# Initialize project
kubebuilder init --domain example.com --repo github.com/example/my-operator
# Create API
kubebuilder create api --group apps --version v1alpha1 --kind MyApp
# Implement controller (edit controller.go file)
# Create CRD and deploy controller
make install
make deploy其他选项说明:
- Operator Framework 是 Red Hat 的综合 operator 开发工具包。
- Kubebuilder 是 Kubernetes SIG 开发的基于 Go 的 controller 开发框架。
- Metacontroller 是轻量级、基于 webhook 的 operator 框架。
- Kubernetes 中 Custom Resource Definitions (CRD) 与 Aggregated APIs 的主要区别是什么?
- A) CRDs 不支持版本管理,但 Aggregated APIs 支持
- B) CRDs 不支持验证 schemas,但 Aggregated APIs 支持
- C) CRDs 实现简单但灵活性有限,而 Aggregated APIs 实现复杂但提供更多灵活性
- D) CRDs 只支持 cluster-scoped resources,而 Aggregated APIs 只支持 namespace-scoped resources
显示答案
答案:C) CRDs 实现简单但灵活性有限,而 Aggregated APIs 实现复杂但提供更多灵活性
解释: Kubernetes 中 Custom Resource Definitions (CRD) 与 Aggregated APIs 的主要区别在于实现复杂度和灵活性之间的权衡。CRDs 实现简单但灵活性有限,而 Aggregated APIs 实现复杂但提供更多灵活性。
CRDs (CustomResourceDefinitions) 的特征:
- 实现简单:可以通过单个 YAML 文件定义新的 API 资源。
- 使用现有 API server:无需实现单独的 API server。
- 灵活性有限:
- 存储限制为 etcd。
- 继承默认 API server 的行为。
- 难以实现复杂验证或转换逻辑。
- 通过 webhooks 扩展:某些功能可以通过 validating webhooks、conversion webhooks 等扩展。
Aggregated APIs 的特征:
- 实现复杂:必须开发并部署单独的 API server。
- 高灵活性:
- 可以使用自定义存储后端
- 可以实现复杂业务逻辑
- 可以实现自定义身份认证和授权逻辑
- 可以实现特殊状态计算和转换逻辑
- 完整 API server 功能:可以利用标准 Kubernetes API server 的所有功能。
选择标准:
| 标准 | 选择 CRD | 选择 Aggregated API |
|---|---|---|
| 实现复杂度 | 低 - 简单 YAML 定义 | 高 - 需要开发单独的 API server |
| 开发时间 | 短 - 可以在几分钟内实现 | 长 - 需要完整的 API server 开发 |
| 维护 | 容易 - 由现有 API server 管理 | 困难 - 需要维护单独服务 |
| 存储选项 | 仅 etcd | 可使用自定义存储后端 |
| 业务逻辑 | 有限 - 通过 controllers 实现 | 灵活 - 可直接在 API server 中实现 |
| 性能 | 通常良好 | 可自定义优化 |
| 使用场景 | 简单 CRUD 操作、标准模式 | 复杂 API 行为、特殊验证/转换 |
示例场景:
适合 CRDs 的场景:
- 简单应用程序配置管理
- 基本 CRUD 操作是主要需求
- 快速原型设计和开发
适合 Aggregated APIs 的场景:
- 与外部数据库集成
- 复杂数据转换和验证
- 需要特殊身份认证机制
- 高性能或特殊用途 APIs
其他选项的问题:
- CRDs 支持版本管理(A 不正确)。
- CRDs 通过 OpenAPI v3 Schema 支持验证 schemas(B 不正确)。
- CRDs 和 Aggregated APIs 都支持 cluster-scoped 和 namespace-scoped resources(D 不正确)。
简答题
- 说明如何使用 CustomResourceDefinition (CRD) 定义 custom resources,以及如何为这些资源设置验证规则。
显示答案
答案:
如何定义 CustomResourceDefinition (CRD):
CRD 是一种扩展 Kubernetes API 以定义新资源类型的机制。当你创建 CRD 时,会创建一个新的 RESTful API endpoint,并且可以使用 kubectl 等标准工具管理该资源。
1. 基本 CRD 结构:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: <plural>.<group> # e.g., crontabs.stable.example.com
spec:
group: <api-group> # e.g., stable.example.com
names:
kind: <kind-name> # e.g., CronTab
plural: <plural-name> # e.g., crontabs
singular: <singular-name> # e.g., crontab
shortNames: # optional
- <short-name> # e.g., ct
scope: Namespaced # or Cluster
versions:
- name: <version> # e.g., v1
served: true # whether to serve via API server
storage: true # whether this is the storage version
schema:
openAPIV3Schema:
# schema definition2. 设置验证规则:
CRDs 的验证规则通过 openAPIV3Schema 字段设置。此 schema 遵循 OpenAPI v3 格式,并定义资源的结构和字段类型。
基本验证规则示例:
schema:
openAPIV3Schema:
type: object
required: ["spec"]
properties:
spec:
type: object
required: ["cronSpec", "image"]
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
default: 13. 高级验证功能:
OpenAPI v3 Schema 提供多种验证功能:
必需字段:将字段名添加到
required数组yamlrequired: ["fieldName1", "fieldName2"]数据类型:使用
type字段指定数据类型yamltype: string | number | integer | boolean | array | object字符串约束:验证字符串长度和模式
yamlminLength: 3 maxLength: 64 pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'数值约束:验证数值范围
yamlminimum: 0 maximum: 100 multipleOf: 5数组约束:验证数组长度和元素
yamlminItems: 1 maxItems: 10 uniqueItems: true items: type: stringEnum 值:指定允许的值列表
yamlenum: ["value1", "value2", "value3"]默认值:为字段指定默认值
yamldefault: "default-value"Additional properties:控制是否允许额外属性
yamladditionalProperties: false
4. 完整 CRD 示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required: ["spec"]
properties:
spec:
type: object
required: ["cronSpec", "image"]
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
default: 1
status:
type: object
properties:
active:
type: boolean
lastScheduleTime:
type: string
format: date-time
subresources:
status: {} # Enable status subresource
additionalPrinterColumns:
- name: Schedule
type: string
description: The cron schedule
jsonPath: .spec.cronSpec
- name: Image
type: string
description: The image to use
jsonPath: .spec.image
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct5. 应用和使用 CRD:
# Apply CRD
kubectl apply -f crontab-crd.yaml
# Create custom resource
cat <<EOF | kubectl apply -f -
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
name: my-crontab
spec:
cronSpec: "* * * * */5"
image: my-cron-image
replicas: 3
EOF
# View custom resources
kubectl get crontabs
kubectl get ct # Using short name6. 测试验证规则:
使用无效值创建资源会导致验证错误:
cat <<EOF | kubectl apply -f -
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
name: invalid-crontab
spec:
cronSpec: "invalid-cron-spec" # Pattern mismatch
image: my-cron-image
replicas: 20 # Exceeds maximum
EOF此命令将返回类似以下的错误:
Error from server (Invalid): error when creating "STDIN": admission webhook "validate-crontab.example.com" denied the request:
- spec.cronSpec: Invalid value: "invalid-cron-spec": does not match pattern '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
- spec.replicas: Invalid value: 20: must be less than or equal to 107. 最佳实践:
- 清晰且详细的 schema 定义
- 明确指定必需字段
- 提供适当的默认值
- 限制字符串模式和数值范围
- 启用 status subresource
- 配置 additional printer columns
- 建立版本管理策略
- 说明 Kubernetes Operator Pattern 的核心概念以及实现 operators 的常见方法。
显示答案
答案:
Kubernetes Operator Pattern 的核心概念:
operator pattern 是一种 Kubernetes 扩展机制,它将特定于应用程序的运维知识编码到软件中,以自动管理复杂应用程序。此模式模仿人类操作员管理复杂系统的方式。
1. 核心概念:
- 声明式管理:用户声明期望状态,operator 将当前状态调整为期望状态。
- 编码领域知识:将特定应用程序的运维知识和最佳实践编码化。
- Reconciliation Loop:持续观察实际状态并调整到期望状态。
- Custom Resources:用于存储特定于应用程序的配置和状态。
- Controllers:Watch custom resources 的变更并执行必要任务。
2. Operators 的常见功能:
- 安装和升级:部署应用程序组件并升级版本
- 自动恢复:检测故障并执行恢复任务
- 备份和还原:自动化数据备份和还原流程
- 扩缩容:根据 workload 需求自动扩展和收缩
- 配置管理:处理特定于应用程序的配置变更
- 运维自动化:自动化日常运维任务(例如数据库压缩、索引重建)
实现 Operators 的方法:
1. 使用 Operator SDK:
Operator SDK 是 Red Hat Operator Framework 的一部分,是简化 operator 开发的工具。
# Install Operator SDK
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.25.0/operator-sdk_linux_amd64
chmod +x operator-sdk_linux_amd64
sudo mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk
# Create Go-based operator project
operator-sdk init --domain example.com --repo github.com/example/my-operator
# Create API
operator-sdk create api --group apps --version v1alpha1 --kind MyApp --resource --controller
# Create CRD
make manifests
# Build and deploy operator
make docker-build docker-push
make deploy2. 使用 Kubebuilder:
Kubebuilder 是 Kubernetes SIG 开发的框架,提供 controller 开发工具。
# Install Kubebuilder
curl -L https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH) | tar -xz -C /tmp/
sudo mv /tmp/kubebuilder_*/bin/kubebuilder /usr/local/bin/
# Initialize project
kubebuilder init --domain example.com --repo github.com/example/my-operator
# Create API
kubebuilder create api --group apps --version v1alpha1 --kind MyApp
# Create CRD and deploy controller
make install
make deploy3. Controller 实现:
operator 的核心是 reconciliation 函数。此函数观察 custom resources 的当前状态并执行必要任务。
// Reconcile function example
func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := r.Log.WithValues("myapp", req.NamespacedName)
// Get custom resource
var myApp appsv1alpha1.MyApp
if err := r.Get(ctx, req.NamespacedName, &myApp); err != nil {
if errors.IsNotFound(err) {
// Resource deleted - perform cleanup
return ctrl.Result{}, nil
}
// Error occurred
return ctrl.Result{}, err
}
// 1. Check if required resources exist
deployment := &appsv1.Deployment{}
err := r.Get(ctx, types.NamespacedName{Name: myApp.Name, Namespace: myApp.Namespace}, deployment)
if errors.IsNotFound(err) {
// Create deployment if it doesn't exist
deployment = r.deploymentForMyApp(&myApp)
log.Info("Creating a new Deployment", "Deployment.Namespace", deployment.Namespace, "Deployment.Name", deployment.Name)
if err := r.Create(ctx, deployment); err != nil {
log.Error(err, "Failed to create new Deployment")
return ctrl.Result{}, err
}
// Deployment creation successful
return ctrl.Result{Requeue: true}, nil
} else if err != nil {
log.Error(err, "Failed to get Deployment")
return ctrl.Result{}, err
}
// 2. Check if deployment is in desired state
size := myApp.Spec.Size
if *deployment.Spec.Replicas != size {
deployment.Spec.Replicas = &size
if err := r.Update(ctx, deployment); err != nil {
log.Error(err, "Failed to update Deployment")
return ctrl.Result{}, err
}
// Deployment update successful
return ctrl.Result{Requeue: true}, nil
}
// 3. Update status
if myApp.Status.AvailableReplicas != deployment.Status.AvailableReplicas {
myApp.Status.AvailableReplicas = deployment.Status.AvailableReplicas
if err := r.Status().Update(ctx, &myApp); err != nil {
log.Error(err, "Failed to update MyApp status")
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}
// Deployment creation function
func (r *MyAppReconciler) deploymentForMyApp(m *appsv1alpha1.MyApp) *appsv1.Deployment {
ls := labelsForMyApp(m.Name)
replicas := m.Spec.Size
dep := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: m.Name,
Namespace: m.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: ls,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: ls,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Image: m.Spec.Image,
Name: "myapp",
Ports: []corev1.ContainerPort{{
ContainerPort: 8080,
Name: "http",
}},
}},
},
},
},
}
// Set owner reference
ctrl.SetControllerReference(m, dep, r.Scheme)
return dep
}4. Custom Resource Definition:
定义由 operator 管理的 custom resources 的 API。
// MyApp API
type MyAppSpec struct {
// Application image
Image string `json:"image"`
// Number of replicas
Size int32 `json:"size"`
// Configuration options
Config map[string]string `json:"config,omitempty"`
}
type MyAppStatus struct {
// Number of available replicas
AvailableReplicas int32 `json:"availableReplicas"`
// Last update time
LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
// Status message
Message string `json:"message,omitempty"`
}
// MyApp resource
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Replicas",type=integer,JSONPath=`.spec.size`
// +kubebuilder:printcolumn:name="Available",type=integer,JSONPath=`.status.availableReplicas`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
type MyApp struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MyAppSpec `json:"spec,omitempty"`
Status MyAppStatus `json:"status,omitempty"`
}5. 基于 Ansible 或 Helm 的 Operators:
Operator SDK 除了 Go 之外,也支持使用 Ansible 或 Helm 开发 operators。
基于 Ansible 的 operator:
# Create Ansible-based operator
operator-sdk init --plugins=ansible --domain example.com
operator-sdk create api --group apps --version v1alpha1 --kind MyApp --generate-role
# Edit roles/myapp/tasks/main.yml基于 Helm 的 operator:
# Create Helm-based operator
operator-sdk init --plugins=helm --domain example.com --helm-chart=<chart-name>6. 部署和测试 Operators:
# Deploy operator
make deploy
# Create custom resource
kubectl apply -f config/samples/
# Check operator logs
kubectl logs -f deployment/my-operator-controller-manager -n my-operator-system
# Check resource status
kubectl get myapps
kubectl describe myapp my-app7. Operator 成熟度级别:
operator 成熟度模型定义 operators 的能力级别:
- Basic Install:应用程序安装和配置
- Seamless Upgrades:版本之间的自动升级
- Full Lifecycle:备份、还原、故障恢复等
- Deep Insights:自动扩缩容、调优等
- Auto Pilot:基于监控的自动优化
8. 最佳实践:
- 增量实现功能(从简单功能开始)
- 彻底的错误处理和日志记录
- 确保幂等性(相同输入得到相同结果)
- 设置 owner references(资源层次结构和垃圾回收)
- 通过 status updates 报告进度
- 编写 unit tests 和 integration tests
- 清晰的文档
- 说明 Kubernetes 中 Admission Webhooks 的类型以及各自的使用场景。
显示答案
答案:
Kubernetes Admission Webhooks 的类型和使用场景:
Admission webhooks 是一种机制,可以在 Kubernetes API server 将请求存储到持久化存储(etcd)之前拦截并修改或验证请求。Admission webhooks 大体分为两类:Mutating webhooks 和 Validating webhooks。
1. Mutating Webhook:
Mutating webhooks 可以修改进入 API server 的请求对象。这些 webhooks 在 validating webhooks 之前运行。
关键特征:
- 可以修改请求对象
- 多个 mutating webhooks 以链式方式运行
- 每个 webhook 接收前一个 webhook 修改后的对象
配置示例:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: sidecar-injector.example.com
clientConfig:
service:
namespace: webhook-system
name: sidecar-injector
path: "/inject"
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
scope: "Namespaced"
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
timeoutSeconds: 5常见使用场景:
Sidecar Container 注入:
- 在 Istio 和 Linkerd 等 service meshes 中自动注入 proxy sidecar
- 添加 logging 和 monitoring sidecars
- 示例:Istio 的 sidecar injector 会在 pods 创建时自动添加 Envoy proxy containers
设置默认值:
- 自动设置 resource requests 和 limits
- 应用 security context 默认值
- 自动添加 labels 和 annotations
- 示例:为所有 pods 设置默认 CPU 和 memory requests
应用 Image Policies:
- 修改 image registry URLs
- 将 image tags 转换为 digests
- 示例:将
nginx:latest改为internal-registry.example.com/nginx:v1.19.0
Volume 修改:
- 添加默认 volume mounts
- 自动挂载 ConfigMap 或 Secret
- 示例:为所有 pods 自动挂载 service account token volume
应用 Network Policies:
- 添加默认 network settings
- 修改 DNS 配置
- 示例:对特定 namespace 中的所有 pods 应用特定 DNS 设置
2. Validating Webhook:
Validating webhooks 可以验证进入 API server 的请求并允许或拒绝它们。这些 webhooks 在 mutating webhooks 之后运行。
关键特征:
- 不能修改请求对象
- 只能允许或拒绝请求
- 多个 validating webhooks 并行运行
- 所有 webhooks 都必须允许请求,请求才会被处理
配置示例:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-policy-validator
webhooks:
- name: pod-policy.example.com
clientConfig:
service:
namespace: webhook-system
name: pod-policy-validator
path: "/validate"
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
scope: "Namespaced"
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
timeoutSeconds: 5常见使用场景:
强制执行安全策略:
- 禁止 privileged containers
- 禁止 root user 执行
- 限制 host network/PID/IPC 使用
- 示例:拒绝以 privileged mode 运行的 pods
验证资源约束:
- 强制要求 resource requests 和 limits
- 应用 resource caps
- 强制执行 QoS classes
- 示例:拒绝没有 memory limits 的 pods
验证 Image Policies:
- 仅允许 approved registries
- 禁止使用 latest tag
- 验证 vulnerability scan 结果
- 示例:只允许来自 official registries 的 images
验证 Labels 和 Annotations:
- 检查 required labels
- 验证 label formats
- 示例:要求所有 pods 必须包含
app和environmentlabels
基于 Namespace 的策略:
- 每个 namespace 的 resource limits
- 每个 namespace 的 feature restrictions
- 示例:在 production namespaces 中应用更严格的策略
3. Webhook 实现方法:
Admission webhooks 实现为提供 HTTPS endpoints 的 services。这些 services 接收 AdmissionReview 请求,处理它们,并返回 AdmissionResponse。
基本 Webhook Server 实现示例 (Go):
package main
import (
"encoding/json"
"io/ioutil"
"net/http"
admissionv1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)
var (
runtimeScheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(runtimeScheme)
deserializer = codecs.UniversalDeserializer()
)
// Mutating webhook handler
func mutateHandler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
// Decode AdmissionReview request
admissionReview := admissionv1.AdmissionReview{}
if _, _, err := deserializer.Decode(body, nil, &admissionReview); err != nil {
http.Error(w, "Failed to decode request", http.StatusBadRequest)
return
}
// Decode pod object
pod := corev1.Pod{}
if err := json.Unmarshal(admissionReview.Request.Object.Raw, &pod); err != nil {
http.Error(w, "Failed to decode pod", http.StatusBadRequest)
return
}
// Create patch (add sidecar container)
patch := []map[string]interface{}{
{
"op": "add",
"path": "/spec/containers/-",
"value": map[string]interface{}{
"name": "sidecar",
"image": "sidecar-image:latest",
"resources": map[string]interface{}{
"limits": map[string]interface{}{
"cpu": "100m",
"memory": "100Mi",
},
"requests": map[string]interface{}{
"cpu": "50m",
"memory": "50Mi",
},
},
},
},
}
// Convert patch to JSON
patchBytes, err := json.Marshal(patch)
if err != nil {
http.Error(w, "Failed to marshal patch", http.StatusInternalServerError)
return
}
// Create response
admissionResponse := admissionv1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
Patch: patchBytes,
PatchType: func() *admissionv1.PatchType {
pt := admissionv1.PatchTypeJSONPatch
return &pt
}(),
}
// Send response
admissionReview.Response = &admissionResponse
resp, err := json.Marshal(admissionReview)
if err != nil {
http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(resp)
}
// Validating webhook handler
func validateHandler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
// Decode AdmissionReview request
admissionReview := admissionv1.AdmissionReview{}
if _, _, err := deserializer.Decode(body, nil, &admissionReview); err != nil {
http.Error(w, "Failed to decode request", http.StatusBadRequest)
return
}
// Decode pod object
pod := corev1.Pod{}
if err := json.Unmarshal(admissionReview.Request.Object.Raw, &pod); err != nil {
http.Error(w, "Failed to decode pod", http.StatusBadRequest)
return
}
// Validation logic
allowed := true
var message string
// Check for privileged containers
for _, container := range pod.Spec.Containers {
if container.SecurityContext != nil && container.SecurityContext.Privileged != nil && *container.SecurityContext.Privileged {
allowed = false
message = "Privileged containers are not allowed"
break
}
}
// Create response
admissionResponse := admissionv1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: allowed,
}
if !allowed {
admissionResponse.Result = &metav1.Status{
Message: message,
Status: "Failure",
Reason: metav1.StatusReasonForbidden,
Code: 403,
}
}
// Send response
admissionReview.Response = &admissionResponse
resp, err := json.Marshal(admissionReview)
if err != nil {
http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(resp)
}
func main() {
http.HandleFunc("/mutate", mutateHandler)
http.HandleFunc("/validate", validateHandler)
fmt.Println("Starting webhook server on :8443")
http.ListenAndServeTLS(":8443", "tls.crt", "tls.key", nil)
}4. Webhook 部署和配置:
Webhook servers 通常部署在 Kubernetes cluster 内,并且需要 service 和 TLS certificates。
# Webhook server deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-server
namespace: webhook-system
spec:
replicas: 1
selector:
matchLabels:
app: webhook-server
template:
metadata:
labels:
app: webhook-server
spec:
containers:
- name: server
image: webhook-server:latest
ports:
- containerPort: 8443
volumeMounts:
- name: tls
mountPath: "/etc/webhook/certs"
readOnly: true
volumes:
- name: tls
secret:
secretName: webhook-server-tls
---
# Webhook server service
apiVersion: v1
kind: Service
metadata:
name: webhook-server
namespace: webhook-system
spec:
selector:
app: webhook-server
ports:
- port: 443
targetPort: 84435. 最佳实践:
- 性能优化:Webhooks 位于 API server 请求路径中,因此必须快速响应。
- 错误处理:考虑 webhook server 失败时的行为,并适当设置
failurePolicy。 - 范围限制:仅将 webhooks 应用于必要的资源和操作。
- 测试:在各种场景中彻底测试 webhook 行为。
- 监控:监控 webhook server 性能和错误。
- 版本管理:支持多个 AdmissionReview 版本,为 API 版本变化做准备。
实践题
- 编写一个满足以下要求的 CustomResourceDefinition (CRD):
- API Group: webapp.example.com
- Version: v1
- Kind: WebApp
- Scope: Namespaced
- Required fields: spec.image, spec.replicas
- Validation rules: replicas must be an integer between 1 and 10
- Enable status subresource
显示答案
答案:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: webapps.webapp.example.com
spec:
group: webapp.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required: ["spec"]
properties:
spec:
type: object
required: ["image", "replicas"]
properties:
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
port:
type: integer
default: 80
env:
type: array
items:
type: object
required: ["name"]
properties:
name:
type: string
value:
type: string
status:
type: object
properties:
availableReplicas:
type: integer
phase:
type: string
subresources:
status: {}
additionalPrinterColumns:
- name: Replicas
type: integer
jsonPath: .spec.replicas
- name: Image
type: string
jsonPath: .spec.image
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: webapps
singular: webapp
kind: WebApp
shortNames:
- wa此 CRD 具有以下特征:
基本信息:
- API Group:
webapp.example.com - Version:
v1 - Kind:
WebApp - Scope:
Namespaced
- API Group:
Schema 验证:
spec字段是必需的。spec.image和spec.replicas是必需字段。spec.replicas必须是 1 到 10 之间的整数。spec.port是可选字段,默认值为 80。spec.env是可选字段,定义环境变量数组。
Status Subresource:
- 启用
statussubresource,以便 controllers 可以更新 status。 - 定义了
status.availableReplicas和status.phase字段。
- 启用
Additional Printer Columns:
- 运行
kubectl get webapps时,会显示 Replicas、Image 和 Age 列。
- 运行
名称配置:
- Plural:
webapps - Singular:
webapp - Kind:
WebApp - Short name:
wa
- Plural:
可以使用此 CRD 创建如下 custom resources:
apiVersion: webapp.example.com/v1
kind: WebApp
metadata:
name: my-webapp
namespace: default
spec:
image: nginx:1.19
replicas: 3
port: 8080
env:
- name: ENV_VAR1
value: "value1"
- name: ENV_VAR2
value: "value2"Controllers 可以 watch 此资源并更新 status:
status:
availableReplicas: 3
phase: Running- 编写一个满足以下要求的 Mutating Admission Webhook 配置:
- Add sidecar container to all pod creation requests
- Apply only to a specific namespace (monitoring)
- Webhook service: webhook-service.webhook-system.svc
- Path: /mutate
显示答案
答案:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: sidecar-injector.example.com
clientConfig:
service:
namespace: webhook-system
name: webhook-service
path: "/mutate"
caBundle: ${CA_BUNDLE} # Replace with base64-encoded CA certificate in actual environment
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
scope: "Namespaced"
namespaceSelector:
matchLabels:
monitoring-injection: enabled
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
timeoutSeconds: 5
failurePolicy: Fail
---
# Add label to namespace
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
labels:
monitoring-injection: enabled此配置具有以下特征:
Webhook 配置:
- Name:
sidecar-injector - Webhook service:
webhook-service.webhook-system.svc - Path:
/mutate
- Name:
范围:
- API Group:
""(core API group) - API Version:
v1 - Operation:
CREATE(仅在 pod 创建时应用) - Resource:
pods - Scope:
Namespaced
- API Group:
Namespace Selector:
- 仅应用于带有
monitoring-injection: enabledlabel 的 namespaces - 将此 label 添加到
monitoringnamespace
- 仅应用于带有
其他设置:
admissionReviewVersions:支持的 AdmissionReview API 版本sideEffects:webhook 无副作用timeoutSeconds:webhook 响应等待时间failurePolicy:webhook 失败时拒绝请求
webhook server 应实现如下逻辑:
func mutateHandler(w http.ResponseWriter, r *http.Request) {
// Decode request
body, _ := ioutil.ReadAll(r.Body)
admissionReview := admissionv1.AdmissionReview{}
deserializer.Decode(body, nil, &admissionReview)
// Decode pod object
pod := corev1.Pod{}
json.Unmarshal(admissionReview.Request.Object.Raw, &pod)
// Define sidecar container
sidecarContainer := corev1.Container{
Name: "monitoring-sidecar",
Image: "monitoring-agent:latest",
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("100m"),
corev1.ResourceMemory: resource.MustParse("100Mi"),
},
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("50m"),
corev1.ResourceMemory: resource.MustParse("50Mi"),
},
},
VolumeMounts: []corev1.VolumeMount{
{
Name: "shared-data",
MountPath: "/var/monitoring",
},
},
}
// Create patch
patch := []map[string]interface{}{
{
"op": "add",
"path": "/spec/containers/-",
"value": sidecarContainer,
},
{
"op": "add",
"path": "/spec/volumes/-",
"value": map[string]interface{}{
"name": "shared-data",
"emptyDir": map[string]interface{}{},
},
},
}
// Convert patch to JSON
patchBytes, _ := json.Marshal(patch)
// Create response
admissionResponse := admissionv1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
Patch: patchBytes,
PatchType: func() *admissionv1.PatchType {
pt := admissionv1.PatchTypeJSONPatch
return &pt
}(),
}
// Send response
admissionReview.Response = &admissionResponse
resp, _ := json.Marshal(admissionReview)
w.Header().Set("Content-Type", "application/json")
w.Write(resp)
}此 webhook 会自动向在 monitoring namespace 中创建的所有 pods 添加一个 monitoring sidecar container。该 sidecar container 使用 monitoring agent image,并挂载共享 volume 以与 main container 共享数据。