Add comment

master
dongming 2 years ago
parent 03d20a809e
commit 0d77e58a2b

@ -1,17 +1,26 @@
# 构建 operator 的镜像
# Build the manager binary
###################### build 阶段 ###########################
# 获取编译需要的环境,并且将这个阶段(镜像)命名为 builder
FROM golang:1.19 as builder
# 参数定义,用户选择性的设置这些参数 TARGETOS="linux" TARGETARCH="amd64|arm64" docker build
ARG TARGETOS
ARG TARGETARCH
# 指定工作目录,后续的命令都是在这个目录下进行
WORKDIR /workspace
# Copy the Go Modules manifests
# 拷贝 go 依赖相关的文件
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
# 下载依赖
RUN go mod download
# Copy the go source
# 拷贝 operator 相关的文件及文件夹
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
@ -21,13 +30,20 @@ COPY controllers/ controllers/
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
# 开始执行构建,这里会产出我们需要的可执行的二进制文件
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager main.go
######################### 创建运行镜像阶段 ################################
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
# 定义运行镜像的来源
FROM gcr.io/distroless/static:nonroot
# 指定工作目录,后续的执行都在此目录下
WORKDIR /
COPY --from=builder /workspace/manager .
# 从 builder 阶段(镜像)中拷贝之前生成的可执行二进制文件
COPY --from=builder /workspace/manager
# 设置运行的账户
USER 65532:65532
# 设置入口文件。如果镜像的时候,我们没有指定运行命令,将会自动运行此命令。
ENTRYPOINT ["/manager"]

@ -1,6 +1,9 @@
# Image URL to use all building/pushing image targets
# 镜像的环境变量如果不设置将使用controller:latest作文镜像名称。
# 这个环境变量将会被使用在 构建镜像、推送镜像、部署operator的时候来使用
IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.25.0

@ -1,16 +1,16 @@
domain: mashibing.com
domain: mashibing.com # 初始化的时候 --domain 的参数
layout:
- go.kubebuilder.io/v3
projectName: demo
repo: mashibing.com/demo/app
- go.kubebuilder.io/v3 # 插件名称,决定了生成文件的内容
projectName: demo # 项目名称,默认值是项目所在文件夹的名称
repo: mashibing.com/demo/app # 项目的 git repo 地址
resources:
- api:
crdVersion: v1
namespaced: true
controller: true
domain: mashibing.com
group: demo
kind: App
path: mashibing.com/demo/app/api/v1
version: v1
version: "3"
crdVersion: v1 # 版本,创建 api 的时候 --version 的参数
namespaced: true # 默认行为,指定这个资源是 namespace
controller: true # 创建 api 的时候,是否生成 controller
domain: mashibing.com # 和 第一层级中的 domain 相同
group: demo # 创建 api 时 --group 的参数。在 operator 中group 的名称为 <group>.<domain> 也就是说这里的group名字为 demo.mashibing.com
kind: App # 创建 api 时 --kind 的参数
path: mashibing.com/demo/app/api/v1 # api 的 pkg 路径
version: v1 # api 的版本
version: "3" # kubebuilder 生成的项目的版本

@ -41,17 +41,19 @@ type AppStatus struct {
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// 定义我们CRD的对象
// App is the Schema for the apps API
type App struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
metav1.TypeMeta `json:",inline"` // 元信息
metav1.ObjectMeta `json:"metadata,omitempty"` // 元信息
Spec AppSpec `json:"spec,omitempty"`
Status AppStatus `json:"status,omitempty"`
Spec AppSpec `json:"spec,omitempty"` // crd 的核心内容crd 的描述定义
Status AppStatus `json:"status,omitempty"` // crd 现阶段状态的的内容
}
//+kubebuilder:object:root=true
// 定义我们CRD的列表
// AppList contains a list of App
type AppList struct {
metav1.TypeMeta `json:",inline"`

@ -25,12 +25,15 @@ import (
)
var (
// 创建GV
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "demo.mashibing.com", Version: "v1"}
//用GV开创建 Builder
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// 用Builder 创建Scheme对象的方法
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

@ -0,0 +1,50 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.2
creationTimestamp: null
name: apps.demo.mashibing.com
spec:
group: demo.mashibing.com
names:
kind: App
listKind: AppList
plural: apps
singular: app
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: 定义我们CRD的对象 App is the Schema for the apps API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AppSpec defines the desired state of App
properties:
foo:
description: Foo is an example field of App. Edit app_types.go to
remove/update
type: string
type: object
status:
description: AppStatus defines the observed state of App
type: object
type: object
served: true
storage: true
subresources:
status: {}

@ -0,0 +1,33 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
- demo.mashibing.com
resources:
- apps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- demo.mashibing.com
resources:
- apps/finalizers
verbs:
- update
- apiGroups:
- demo.mashibing.com
resources:
- apps/status
verbs:
- get
- patch
- update

@ -27,6 +27,7 @@ import (
demov1 "mashibing.com/demo/app/api/v1"
)
// 是提供调和函数(把现阶段的状态,和我们定义的状态进行统一。趋近的调和函数),对象中的数据,可以是在上层统一管理
// AppReconciler reconciles a App object
type AppReconciler struct {
client.Client
@ -37,6 +38,7 @@ type AppReconciler struct {
//+kubebuilder:rbac:groups=demo.mashibing.com,resources=apps/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=demo.mashibing.com,resources=apps/finalizers,verbs=update
// 我们核心功能函数要去定义operator的行为
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
@ -50,10 +52,12 @@ func (r *AppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
_ = log.FromContext(ctx)
// TODO(user): your logic here
// 实现你的业务逻辑
return ctrl.Result{}, nil
}
// 将 controller 注册到 manager 中
// SetupWithManager sets up the controller with the Manager.
func (r *AppReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).

@ -37,18 +37,22 @@ import (
)
var (
// 一个对象用来管理gvk和gostructcrd映射以及一些互相转换的方法。
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
func init() {
// k8s 内置的 GVK 和 gostruct 的映射也就是这个scheme需要的方法和映射注入到scheme变量中
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
// 本 operator 中的 GVK 和 gostruct 的映射也就是这个scheme需要的方法和映射注入到scheme变量中
utilruntime.Must(demov1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}
func main() {
// 处理命令行参数
var metricsAddr string
var enableLeaderElection bool
var probeAddr string
@ -63,10 +67,13 @@ func main() {
opts.BindFlags(flag.CommandLine)
flag.Parse()
// 处理日志的参数
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
// 完成处理命令
// 创建 manager
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Scheme: scheme, // 前面创建的 gvk 和 gostruct 映射的对象
MetricsBindAddress: metricsAddr,
Port: 9443,
HealthProbeBindAddress: probeAddr,
@ -89,6 +96,7 @@ func main() {
os.Exit(1)
}
// 注册我们的 controller
if err = (&controllers.AppReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
@ -98,6 +106,7 @@ func main() {
}
//+kubebuilder:scaffold:builder
// 添加探活的path
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
os.Exit(1)
@ -107,6 +116,7 @@ func main() {
os.Exit(1)
}
// 启动程序
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")

Loading…
Cancel
Save