Skip to content

从零开始:开发此项目需要的知识体系

text
# 相关代码:
- cmd/main.go              # 综合运用所有技术
- cel/evaluate.go          # 接口实现、CEL 评估
- api/v1alpha1/            # CRD 类型定义
- Dockerfile               # 容器化

本文档从零基础出发,系统性地介绍开发 Pod Running Control 项目所需的全部知识。

知识全景图


第一层:计算机基础

1.1 操作系统概念

为什么需要? 项目中涉及进程、信号处理、文件描述符等概念。

go
// cmd/main.go:32-33 - 信号处理
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)

需要掌握的概念:

概念在项目中的应用
进程init-container 是一个独立进程,os.Exit(0) 终止进程
信号SIGINT (Ctrl+C)、SIGTERM (kill) 用于优雅退出
退出码os.Exit(0) 表示成功,非零表示失败

学习资源:

  • 《Operating Systems: Three Easy Pieces》(免费在线)
  • Linux man pages: man 7 signal

1.2 网络基础

为什么需要? Kubernetes 通过 HTTP REST API 通信。

需要掌握的概念:

概念说明
HTTP 协议GET/POST/PUT/DELETE 方法
REST API资源的增删改查接口
WebSocketWatch 机制的底层实现(长连接)
TLS/HTTPS安全通信

1.3 Linux 命令行

为什么需要? 开发、调试、部署都在命令行进行。

必须掌握:

bash
# 文件操作
ls, cd, cat, grep, find

# 进程管理
ps, kill, top

# 网络调试
curl, netstat, ss

# 容器相关
docker, kubectl

第二层:Go 语言

2.1 基础语法

为什么选 Go? Kubernetes 生态标准语言,编译快、并发强、部署简单。

必须掌握的语法:

go
// 1. 变量声明
var name string = "value"
name := "value"  // 简短声明

// 2. 结构体 - 项目中的核心数据结构
type runningGate struct {
    gvr       schema.GroupVersionResource
    namespace string
    name      string
}

// 3. 函数
func Evaluate(ctx context.Context, object runtime.Object) (Result, error) {
    // 多返回值是 Go 的特色
    return result, nil
}

// 4. 错误处理 - Go 没有异常,使用返回值
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
    os.Exit(1)
}

// 5. defer - 延迟执行,常用于资源清理
defer file.Close()

2.2 接口与类型系统

为什么重要? 项目中大量使用接口实现多态。

go
// cel/condition.go - 实现 K8s 定义的接口
type ValidationCondition struct {
    Expression string
}

// 实现 cel.ExpressionAccessor 接口
var _ cel.ExpressionAccessor = &ValidationCondition{}

func (v *ValidationCondition) GetExpression() string {
    return v.Expression
}

func (v *ValidationCondition) ReturnTypes() []*celgo.Type {
    return []*celgo.Type{celgo.BoolType}
}

Go 接口的核心概念:

  • 隐式实现:只要实现了接口的所有方法,就自动满足接口
  • 空接口 interface{}/any:可以存储任意类型
go
// cel/evaluate.go:24 - any 是 interface{} 的别名
type evaluationActivation struct{ object, params any }

2.3 并发模型

为什么重要? Informer 在后台 goroutine 中运行。

go
// cmd/main.go:114-118 - goroutine 和 channel
stopCh := make(chan struct{})  // 无缓冲 channel
go func() {                     // 启动新 goroutine
    <-signalCh                  // 阻塞等待信号
    close(stopCh)               // 关闭 channel 通知停止
}()

informer.Run(stopCh)  // 主 goroutine 阻塞在这里

核心概念:

概念说明
goroutine轻量级线程,go func() 启动
channelgoroutine 间通信的管道
select多路复用,同时等待多个 channel
sync 包Mutex、WaitGroup 等同步原语

2.4 包管理

Go Modules 是现代 Go 的依赖管理方式。

bash
# go.mod 定义模块和依赖
module github.com/Iceber/pod-running-control

go 1.25.0

require (
    github.com/google/cel-go v0.26.0
    k8s.io/client-go v0.35.0
    # ...
)

常用命令:

bash
go mod init <module-name>  # 初始化模块
go mod tidy                # 整理依赖
go mod vendor              # 将依赖复制到 vendor/
go build ./...             # 编译
go test ./...              # 测试

第三层:容器技术

3.1 Docker 基础

为什么需要? 项目最终打包为容器镜像运行。

核心概念:

概念说明
镜像 (Image)只读模板,包含运行环境和代码
容器 (Container)镜像的运行实例
Dockerfile构建镜像的指令文件
Registry镜像仓库,如 Docker Hub、GHCR

3.2 Dockerfile 解析

dockerfile
# Dockerfile - 多阶段构建

# 阶段1: 编译环境
ARG BUILDER_IMAGE=golang:1.25
ARG BASE_IMAGE=gcr.io/distroless/static:nonroot

FROM --platform=$BUILDPLATFORM ${BUILDER_IMAGE} AS builder
WORKDIR /src
COPY . .
ARG TARGETARCH
RUN GOARCH=${TARGETARCH} go build -o running-control ./cmd

# 阶段2: 运行环境
FROM ${BASE_IMAGE}
WORKDIR /
COPY --from=builder /src/running-control /running-control
ENTRYPOINT ["/running-control"]

关键点:

  • 多阶段构建:编译环境和运行环境分离,最终镜像很小
  • distroless:Google 的极简镜像,只有运行时,无 shell
  • 多平台构建--platform 支持 amd64/arm64

第四层:Kubernetes 基础

4.1 架构概览

核心组件:

组件职责
API Server所有操作的入口,REST API
etcd存储集群状态
kubelet节点代理,管理 Pod 生命周期
Scheduler决定 Pod 运行在哪个节点

4.2 核心资源概念

Pod 是 K8s 最小调度单位:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: default           # 命名空间隔离
  labels:                      # 标签,用于选择
    app: test
  annotations:                 # 注解,存储元数据
    pod-running-control.io/break: 'true'
spec:
  initContainers:              # init-container 先于业务容器运行
  - name: running-control
    image: ghcr.io/iceber/pod-running-control:latest
  containers:                  # 业务容器
  - name: nginx
    image: nginx:1.14.2

4.3 init-container 机制

这是项目的核心利用点!

init-container 特性:

  1. 顺序执行:多个 init-container 按定义顺序执行
  2. 阻塞等待:前一个完成后才启动下一个
  3. 完成即销毁:退出码为 0 表示完成
  4. 失败重试:退出码非 0 会重启

4.4 API 资源模型 (GVR)

为什么重要? 项目通过 GVR 动态指定监控的资源类型。

go
// cmd/main.go:63-68
gvr := schema.GroupVersionResource{
    Group:    "pod-running-control.io",  // API 组
    Version:  "v1alpha1",                 // 版本
    Resource: "podrunninggates",          // 资源(复数)
}

GVR 示例:

资源GroupVersionResource
Pod"" (core)v1pods
Deploymentappsv1deployments
ConfigMap"" (core)v1configmaps
自定义 CRDpod-running-control.iov1alpha1podrunninggates

4.5 RBAC 权限

为什么需要? init-container 需要权限访问 API Server。

yaml
# examples/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-running-control
rules:
  - apiGroups: ['']           # core API 组
    resources: ['pods']       # 资源类型
    verbs: ["watch", "list"]  # 允许的操作

RBAC 四要素:

  1. Subject:谁(ServiceAccount、User、Group)
  2. Role:定义权限(rules)
  3. RoleBinding:将 Subject 绑定到 Role
  4. Namespace:作用范围

第五层:Kubernetes 开发

5.1 client-go 库

这是 K8s 官方的 Go 客户端库。

go
// cmd/main.go:79-86 - 创建客户端
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
    os.Exit(1)
}
client, err := dynamic.NewForConfig(config)

客户端类型:

类型说明项目使用
Typed Client强类型,如 clientset.CoreV1().Pods()-
Dynamic Client通用,可操作任意资源✅ 用于支持任意 GVR
REST Client底层 HTTP 客户端-

5.2 Informer 机制(核心!)

为什么重要? 这是项目监听资源变化的核心机制。

Informer 工作原理:

  1. List:启动时获取全量数据
  2. Watch:长连接监听增量变化
  3. 本地缓存:减少 API Server 压力
  4. 事件分发:触发注册的回调函数
go
// cmd/main.go:88-112 - Informer 创建和使用
informer := dynamicinformer.NewFilteredDynamicInformer(
    client,
    gate.gvr,
    gate.namespace,
    0,    // resyncPeriod: 重新同步间隔,0 表示不定期重同步
    nil,  // indexers
    func(opts *metav1.ListOptions) {
        opts.FieldSelector = "metadata.name=" + gate.name  // 过滤
    },
).Informer()

// 注册事件处理器
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
    AddFunc:    func(obj interface{}) { /* 资源创建 */ },
    UpdateFunc: func(old, new interface{}) { /* 资源更新 */ },
    DeleteFunc: func(obj interface{}) { /* 资源删除 */ },
})

informer.Run(stopCh)  // 启动,阻塞直到 stopCh 关闭

5.3 CRD 开发

为什么需要? 项目提供了 CRD 模式作为备选方案。

go
// api/v1alpha1/podrunninggate_types.go
// +kubebuilder:object:root=true  ← kubebuilder marker

type PodRunningGate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitzero"`
    Spec PodRunningGateSpec `json:"spec"`
}

type PodRunningGateSpec struct {
    Gates []string `json:"gates,omitempty"`
}

CRD 开发流程:

  1. 定义 Go 类型(带 marker 注释)
  2. 运行 controller-gen 生成代码
  3. 生成 CRD YAML
  4. kubectl apply 注册到集群

第六层:CEL 表达式

6.1 什么是 CEL?

Common Expression Language - Google 开发的表达式语言,K8s 1.25+ 原生支持。

特点:

  • 类型安全
  • 非图灵完备(无循环,保证终止)
  • 性能可预测(有运行时成本限制)

6.2 基础语法

cel
// 变量访问
object.metadata.name

// 存在性检查
has(object.metadata.annotations)

// in 操作符
'key' in object.metadata.annotations

// 逻辑运算
!has(x) || x == 'value'

// 集合操作
size(object.spec.gates) == 0

// 字符串操作
object.metadata.name.startsWith('test-')

6.3 在项目中的应用

go
// cmd/main.go:71-77 - CEL 编译
compositionEnvTemplate, _ := plugincel.NewCompositionEnv(
    plugincel.VariablesTypeName,
    environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()),
)
compiler := plugincel.NewCompiler(compositionEnvTemplate.EnvSet)
condition := compiler.CompileCELExpression(
    &cel.ValidationCondition{Expression: expression},
    optionalVars,
    environment.StoredExpressions,
)
go
// cel/evaluate.go - CEL 评估
func (a *evaluationActivation) ResolveName(name string) (interface{}, bool) {
    switch name {
    case cel.ObjectVarName:  // "object" 变量
        return a.object, true
    default:
        return nil, false
    }
}

// 执行评估
evalResult, evalDetails, err := compilationResult.Program.ContextEval(ctx, a)

CEL 评估流程:


学习路线建议

时间线(假设每天 2-3 小时)

阶段内容时间
1Go 语言基础2-3 周
2Docker 基础1 周
3Kubernetes 概念2 周
4client-go + Informer2 周
5CRD 开发1 周
6CEL 表达式3-5 天
总计约 2-3 个月

推荐学习资源

Go 语言:

Kubernetes:

client-go:

CEL:


动手练习

练习 1:Go 基础

go
// 实现一个简单的信号处理程序
package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    ch := make(chan os.Signal, 1)
    signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
    fmt.Println("等待信号...")
    sig := <-ch
    fmt.Printf("收到信号: %v\n", sig)
}

练习 2:Informer 入门

go
// 监听 Pod 变化
package main

import (
    "k8s.io/client-go/informers"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/cache"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    config, _ := clientcmd.BuildConfigFromFlags("", "~/.kube/config")
    clientset, _ := kubernetes.NewForConfig(config)

    factory := informers.NewSharedInformerFactory(clientset, 0)
    podInformer := factory.Core().V1().Pods().Informer()

    podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
        AddFunc: func(obj interface{}) {
            // 处理 Pod 创建事件
        },
    })

    stopCh := make(chan struct{})
    factory.Start(stopCh)
    <-stopCh
}

练习 3:CEL 表达式

bash
# 在 K8s 集群中测试 CEL
kubectl get pod test-pod -o json | \
  jq '.metadata.annotations["pod-running-control.io/break"]'

总结

开发 Pod Running Control 需要的核心技能:

最关键的理解:

  1. init-container 的阻塞特性 - 项目的核心机制
  2. Informer 的 Watch 模式 - 实时响应资源变化
  3. CEL 的评估逻辑 - 灵活表达解锁条件

掌握这些知识后,你不仅能理解这个项目,还能开发更复杂的 Kubernetes 控制器和 Operator。

基于代码自动生成的文档