# Kubernetes Operator开发实战
关键代码:使用kube-rs实现基础调谐循环
use kube::{Api, Client, Resource};
use kube::runtime::controller::{Controller, Action};
use std::sync::Arc;
#[derive(Clone)]
struct Context {
client: Client,
}
async fn reconcile(obj: Arc<MyCustomResource>, ctx: Context) -> Result<Action, kube::Error> {
// 调谐逻辑:检查当前状态,创建/更新/删除资源
let client = ctx.client;
let name = obj.name_any();
println!("Reconciling resource: {}", name);
// 获取期望状态
let desired = obj.spec.desired_state;
// 获取当前状态
let current = get_current_state(&client, &name).await?;
if current != desired {
// 执行调谐操作
apply_desired_state(&client, &name, &desired).await?;
println!("Applied desired state for {}", name);
}
Ok(Action::requeue(Duration::from_secs(3600)))
}
fn error_policy(obj: Arc<MyCustomResource>, error: &kube::Error, ctx: Context) -> Action {
println!("Error reconciling {}: {:?}", obj.name_any(), error);
Action::requeue(Duration::from_secs(60))
}
1.2 CRD定义与资源模型
原理说明:CustomResourceDefinition (CRD) 定义自定义资源的Schema。需要定义Spec(期望状态)、Status(实际状态)、Metadata(元数据)。使用kube-derive宏可以自动生成Kubernetes资源结构体。
关键代码:定义自定义资源结构体
use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
#[kube(
group = "example.com",
version = "v1",
kind = "MyApp",
plural = "myapps",
namespaced
)]
pub struct MyAppSpec {
pub replicas: i32,
pub image: String,
pub port: i32,
#[serde(default)]
pub env: Vec<EnvVar>,
}
#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)]
pub struct EnvVar {
pub name: String,
pub value: String,
}
#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)]
pub struct MyAppStatus {
pub available_replicas: i32,
pub phase: String,
}
1.3 资源监听与事件驱动
原理说明:Controller通过Informer机制监听资源变化。当CRD资源发生创建、更新、删除事件时,自动触发调谐。kube-rs提供了内置的watcher和reflector组件。
关键代码:配置控制器监听
use kube::runtime::controller::Controller;
use kube::runtime::watcher::Config;
#[tokio::main]
async fn main() -> Result<(), kube::Error> {
let client = Client::try_default().await?;
let context = Context { client: client.clone() };
// 创建控制器
Controller::new(
Api::<MyApp>::all(client.clone()),
Config::default()
)
.owns(
Api::<Deployment>::all(client.clone()),
Config::default()
)
.shutdown_on_signal()
.run(reconcile, error_policy, context)
.for_each(|_| futures::future::ready(()))
.await;
Ok(())
}
1.4 子资源管理
原理说明:Operator通常需要管理多个Kubernetes子资源(Deployment、Service、ConfigMap等)。通过ownerReferences建立资源归属关系,实现级联删除和状态同步。
关键代码:创建和管理子资源
async fn create_deployment(
client: &Client,
app: &MyApp,
parent: &MyApp,
) -> Result<Deployment, kube::Error> {
let deployment = Deployment {
metadata: ObjectMeta {
name: Some(app.name_any()),
owner_references: Some(vec![
OwnerReference {
api_version: MyApp::api_version(&()).to_string(),
kind: MyApp::kind(&()).to_string(),
name: parent.name_any(),
uid: parent.uid().unwrap().clone(),
controller: Some(true),
block_owner_deletion: Some(true),
}
]),
..Default::default()
},
spec: Some(DeploymentSpec {
replicas: Some(app.spec.replicas),
template: PodTemplateSpec {
spec: Some(PodSpec {
containers: vec![Container {
name: "app".to_string(),
image: Some(app.spec.image.clone()),
ports: Some(vec![ContainerPort {
container_port: app.spec.port,
..Default::default()
}]),
..Default::default()
}],
..Default::default()
}),
..Default::default()
},
..Default::default()
}),
..Default::default()
};
let api: Api<Deployment> = Api::namespaced(client.clone(), &app.namespace().unwrap());
api.create(&Default::default(), &deployment).await
}
二、实操步骤
步骤1:项目初始化
# 创建Rust项目
cargo new my-operator
cd my-operator
# 添加依赖
cargo add kube --features derive,runtime
cargo add k8s-openapi --features v1_27
cargo add tokio --features full
cargo add serde serde_json schemars futures
cargo add tracing tracing-subscriber
步骤2:定义自定义资源
创建src/crd.rs,定义MyApp CRD结构体,包含Spec和Status字段。
步骤3:实现调谐逻辑
创建src/reconciler.rs,实现reconcile函数,处理CRD资源的创建、更新、删除事件。
步骤4:配置控制器
在main.rs中初始化客户端、创建Controller实例、配置监听参数。
步骤5:部署与测试
# 构建Operator
cargo build --release
# 应用CRD定义
kubectl apply -f crd.yaml
# 部署Operator
kubectl apply -f operator-deployment.yaml
# 创建自定义资源实例
kubectl apply -f myapp-instance.yaml
步骤6:验证运行
# 查看Operator日志
kubectl logs -l app=my-operator
# 查看CRD资源状态
kubectl get myapps
kubectl describe myapp my-app-instance
三、常见问题与故障排查
3.1 CRD版本兼容问题
现象:Operator无法识别自定义资源
解决:确保CRD版本与kube-rs使用的k8s-openapi版本匹配。检查CRD定义的apiVersion和kind是否与代码一致。
3.2 调谐循环死循环
现象:Operator持续触发调谐,CPU高负载
解决:检查调谐逻辑中是否修改了触发调谐的资源。使用ownerReferences避免循环触发。在调谐函数中实现状态比较,避免无意义的更新。
3.3 权限不足
现象:Operator无法创建/更新子资源
解决:检查RBAC配置,确保ServiceAccount具有足够的权限。使用ClusterRole和ClusterRoleBinding授予跨命名空间权限。
3.4 资源泄漏
现象:删除CRD实例后,子资源未被清理
解决:正确设置ownerReferences,确保子资源通过GC自动清理。在调谐函数中实现最终的清理逻辑。
3.5 状态更新失败
现象:Status字段无法更新
解决:使用kube::runtime::reflector确保Status更新使用正确的资源版本。检查API Server的status子资源权限。
四、总结与扩展学习
核心要点
1. 控制器模式:理解调谐循环是Operator的核心,通过观察-比较-执行实现自动化
2. CRD设计:合理设计Spec和Status,遵循Kubernetes API约定
3. 资源管理:使用ownerReferences管理子资源生命周期,实现级联清理
4. 错误处理:实现健壮的错误策略,避免无限重试和资源泄漏
扩展学习方向
1. 高级模式:学习Finalizer、Admission Webhook、Operator SDK等高级特性
2. 测试框架:使用envtest和kube-rs的测试工具编写集成测试
3. 性能优化:学习缓存策略、并发控制、批量处理等性能优化技术
4. 生态系统:探索Crossplane、Kubebuilder、Operator Lifecycle Manager等工具
5. 云原生安全:学习RBAC、Pod Security Policies、OPA Gatekeeper等安全实践
推荐资源
- [kube-rs官方文档](https://kube.rs/)
- [Kubernetes Operator模式](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
- [Rust异步编程指南](https://rust-lang.github.io/async-book/)
- [云原生计算基金会CNCF](https://www.cncf.io/)