当前位置: 首页 > news >正文

k8s二次开发-kubebuiler一键式生成deployment,svc,ingress

一 Kubebuilder环境搭建

注:必须在当前的K8S集群有 nginx这个ingressclass

root@k8s:~# kubectl get ingressclass
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       19h

1.1 下载kubebuilder

wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.3.0/kubebuilder_linux_amd64 -O /usr/local/sbin/kubebuilder --no-check-certificate
chmod +x /usr/local/sbin/kubebuilderkubebuilder version
Version: main.version{KubeBuilderVersion:"3.3.0", KubernetesVendor:"1.23.1", GitCommit:"47859bf2ebf96a64db69a2f7074ffdec7f15c1ec", BuildDate:"2022-01-18T17:03:29Z", GoOs:"linux", GoArch:"amd64"}

1.2 下载Golang

wget https://studygolang.com/dl/golang/go1.19.7.linux-amd64.tar.gztar -C /usr/local -xzf go1.19.7.linux-amd64.tar.gzvim /etc/profileexport PATH=$PATH:/usr/local/go/bin
export GO111MODULE=on
export GOPROXY=https://goproxy.cn,direct
export PATH=$PATH:/root/go/binroot@k8s:~# go version
go version go1.19.7 linux/amd64

1.3 编译golang需要的文件

以下只是一个 Demo和后续开发的项目无关

mkdir -p /usr/local/kubebuilder/elasticwebgo mod init elasticweb
kubebuilder init --domain jcrose.top
mkdir binkubebuilder create api \
--group elasticweb \
--version v1 \
--kind ElasticWeb# 安装controller-gen,这个需要先 执行kubebuilder create api 才会产生这个包的
cd /root/go/pkg/mod/sigs.k8s.io/controller-tools@v0.8.0/cmd/controller-gen
go build -o controller-gen main.go
mv controller-gen /usr/local/sbin
cp /usr/local/sbin/controller-gen /usr/local/kubebuilder/elasticweb/binmake install #第一次会失败,因为缺乏 kustomize # 安装kustomize
cd /root/go/pkg/mod/sigs.k8s.io/kustomize/kustomize/v3@v3.8.7
go build -o kustomize main.go
cp kustomize /usr/local/sbin
cp kustomize /usr/local/kubebuilder/elasticweb/binmake install kubectl get crds|grep jcrose
elasticwebs.elasticweb.jcrose.top   2023-04-09T14:25:18Z

安装启动容器的时候初始化的环境包

# 官方文档 https://github.com/kubernetes-sigs/controller-runtime/tree/main/tools/setup-envtest
# 安装setup-envtest
# cd /root/go/pkg/mod/sigs.k8s.io/controller-runtime/tools/setup-envtest@v0.0.0-20230403212152-53057ba616d1
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@release-0.17
cp /root/go/bin/setup-envtest /usr/local/sbin/

此时安装了 kustomize,controller-gen,setup-envtest 三个文件

二 初始化项目

kubebuilder init --domain jcrose.top
kubebuilder create api --group infra --version v1 --kind App

2.1 controllers/app_controller.go

/*
Copyright 2024.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package controllersimport ("context""fmt"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"apinetv1 "k8s.io/api/networking/v1""k8s.io/apimachinery/pkg/api/errors""k8s.io/apimachinery/pkg/api/resource"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/klog/v2"ctrl "sigs.k8s.io/controller-runtime""sigs.k8s.io/controller-runtime/pkg/client""sigs.k8s.io/controller-runtime/pkg/controller/controllerutil""sigs.k8s.io/controller-runtime/pkg/reconcile"infrav1 "jcrose/api/v1"
)// AppReconciler reconciles a App object
type AppReconciler struct {client.ClientScheme *runtime.Scheme//Log    logr.Logger
}//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infra.jcrose.top,resources=apps/finalizers,verbs=update
//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete// 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
// the App object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.0/pkg/reconcile
func (r *AppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {ctx = context.Background()fmt.Println("Name", req.Name)fmt.Println("Namespace", req.Namespace)fmt.Println("NamespacedName", req.NamespacedName)//log := r.Log.WithValues("yunlizhi infra app", req.NamespacedName)// log.Info("1. start reconcile logic")// TODO(user): your logic hereinstance := &infrav1.App{}// 通过客户端工具查询,查询条件是err := r.Get(ctx, req.NamespacedName, instance)if err != nil {// 如果没有实例,就返回空结果,这样外部就不再立即调用Reconcile方法了if errors.IsNotFound(err) {klog.Info("2.1. instance not found, maybe removed")return reconcile.Result{}, nil}klog.Error(err, "2.2 error")// 返回错误信息给外部return ctrl.Result{}, err}klog.Info("3. instance : " + instance.String())// 查找deploymentdeployment := &appsv1.Deployment{}// 用客户端工具查询err = r.Get(ctx, req.NamespacedName, deployment)// 查找时发生异常,以及查出来没有结果的处理逻辑if err != nil {// 如果没有实例就要创建了if errors.IsNotFound(err) {klog.Info("4. deployment not exists")// 如果对QPS没有需求,此时又没有deployment,就啥事都不做了// 先要创建serviceif err = createServiceIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.2 error")// 返回错误信息给外部return ctrl.Result{}, err}// 立即创建deploymentif err = createDeploymentIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.3 error")// 返回错误信息给外部return ctrl.Result{}, err}if err = createIngressIfNotExists(ctx, r, instance, req); err != nil {klog.Error(err, "5.3 error")// 返回错误信息给外部return ctrl.Result{}, err}// 如果创建成功就更新状态if err = updateStatus(ctx, r, instance); err != nil {klog.Error(err, "5.4. error")// 返回错误信息给外部return ctrl.Result{}, err}// 创建成功就可以返回了return ctrl.Result{}, nil} else {klog.Error(err, "7. error")// 返回错误信息给外部return ctrl.Result{}, err}}// 如果查到了deployment,并且没有返回错误,就走下面的逻辑klog.Info("11. update deployment's Replicas")// 通过客户端更新deploymentif err = r.Update(ctx, deployment); err != nil {klog.Error(err, "12. update deployment replicas error")// 返回错误信息给外部return ctrl.Result{}, err}klog.Info("13. update status")// 如果更新deployment的Replicas成功,就更新状态if err = updateStatus(ctx, r, instance); err != nil {klog.Error(err, "14. update status error")// 返回错误信息给外部return ctrl.Result{}, err}return ctrl.Result{}, nil}// SetupWithManager sets up the controller with the Manager.
func (r *AppReconciler) SetupWithManager(mgr ctrl.Manager) error {return ctrl.NewControllerManagedBy(mgr).For(&infrav1.App{}).Complete(r)
}func updateStatus(ctx context.Context, r *AppReconciler, App *infrav1.App) error {//log := r.Log.WithValues("func", "updateStatus")App.Status.TotalDomain = App.Spec.Domainif err := r.Status().Update(ctx, App); err != nil {klog.Error(err, "update instance error")return err}return nil
}func createDeploymentIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createDeployment")deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: app.Namespace,Name:      app.Name,},Spec: appsv1.DeploymentSpec{Replicas: app.Spec.Replicas,Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": app.Spec.Project,},},Template: corev1.PodTemplateSpec{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": app.Spec.Project,},},Spec: corev1.PodSpec{Containers: []corev1.Container{{Name:            app.Spec.Project,Image:           app.Spec.Image,ImagePullPolicy: "IfNotPresent",Ports: []corev1.ContainerPort{{Name:          "http",Protocol:      corev1.ProtocolTCP,ContainerPort: *app.Spec.Port,},},Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{"cpu":    resource.MustParse("100m"),"memory": resource.MustParse("256Mi"),},Limits: corev1.ResourceList{"cpu":    resource.MustParse("200m"),"memory": resource.MustParse("512Mi"),},},},},},},},}klog.Info("set reference")if err := controllerutil.SetControllerReference(app, deployment, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}klog.Info("start create deployment")if err := r.Create(ctx, deployment); err != nil {klog.Error(err, "create deployment error")return err}klog.Info("create deployment success")return nil
}func createServiceIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createService")service := &corev1.Service{}err := r.Get(ctx, req.NamespacedName, service)// 如果查询结果没有错误,证明service正常,就不做任何操作if err == nil {klog.Info("service exists")return nil}// 如果错误不是NotFound,就返回错误if !errors.IsNotFound(err) {klog.Error(err, "query service error")return err}// 实例化一个数据结构service = &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: app.Namespace,Name:      app.Name,},Spec: corev1.ServiceSpec{Ports: []corev1.ServicePort{{Name: "http",Port: *app.Spec.Port,},},Selector: map[string]string{"app": app.Spec.Project,},Type: corev1.ServiceTypeNodePort,},}// 这一步非常关键!// 建立关联后,删除elasticweb资源时就会将deployment也删除掉klog.Info("set reference")if err := controllerutil.SetControllerReference(app, service, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}// 创建serviceklog.Info("start create service")if err := r.Create(ctx, service); err != nil {klog.Error(err, "create service error")return err}klog.Info("create service success")app.Status.TotalDomain = app.Spec.Domainerr = r.Status().Update(ctx, service)if err != nil {return err}return nil
}func createIngressIfNotExists(ctx context.Context, r *AppReconciler, app *infrav1.App, req ctrl.Request) error {//log := r.Log.WithValues("func", "createIngress")ingress := &apinetv1.Ingress{}err := r.Get(ctx, req.NamespacedName, ingress)// 如果查询结果没有错误,证明service正常,就不做任何操作if err == nil {klog.Info("ingress exists")return nil}// 如果错误不是NotFound,就返回错误if !errors.IsNotFound(err) {klog.Error(err, "query service error")return err}// 实例化一个数据结构ingress.Name = app.Nameingress.Namespace = app.NamespacepathType := apinetv1.PathTypePrefixicn := "nginx"ingress.Spec = apinetv1.IngressSpec{IngressClassName: &icn,Rules: []apinetv1.IngressRule{{Host: app.Spec.Domain,IngressRuleValue: apinetv1.IngressRuleValue{HTTP: &apinetv1.HTTPIngressRuleValue{Paths: []apinetv1.HTTPIngressPath{{Path:     "/",PathType: &pathType,Backend: apinetv1.IngressBackend{Service: &apinetv1.IngressServiceBackend{Name: app.Name,Port: apinetv1.ServiceBackendPort{Number: *app.Spec.Port,},},},},},},},},},}// 这一步非常关键!// 建立关联后,删除elasticweb资源时就会将deployment也删除掉klog.Info("set reference")if err := controllerutil.SetControllerReference(app, ingress, r.Scheme); err != nil {klog.Error(err, "SetControllerReference error")return err}// 创建serviceklog.Info("start create ingress")if err := r.Create(ctx, ingress); err != nil {klog.Error(err, "create service error")return err}klog.Info("create service success")return nil
}

2.2 api/v1/app_types.go

/*
Copyright 2023.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package v1import ("fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.// AppSpec defines the desired state of App
type AppSpec struct {// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster// Important: Run "make" to regenerate code after modifying this file// Foo is an example field of App. Edit app_types.go to remove/updateReplicas *int32 `json:"replicas,omitempty"`Image    string `json:"image,omitempty"`Port     *int32 `json:"port,omitempty"`Project  string `json:"project,omitempty"`Domain   string `json:"domain,omitempty"`
}// AppStatus defines the observed state of App
type AppStatus struct {// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster// Important: Run "make" to regenerate code after modifying this fileTotalStatus string `json:"totalStatus"`TotalDomain string `json:"totalDomain"`
}//+kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".spec.replicas",description="pod的个数"
// +kubebuilder:printcolumn:name="Domain",type="string",JSONPath=".spec.domain",description="ingress的域名"
// +kubebuilder:printcolumn:name="Image",type="string",JSONPath=".spec.image",description="app的镜像地址"
//+kubebuilder:subresource:status// App is the Schema for the apps API
type App struct {metav1.TypeMeta   `json:",inline"`metav1.ObjectMeta `json:"metadata,omitempty"`Spec   AppSpec   `json:"spec,omitempty"`Status AppStatus `json:"status,omitempty"`
}//+kubebuilder:object:root=true// AppList contains a list of App
type AppList struct {metav1.TypeMeta `json:",inline"`metav1.ListMeta `json:"metadata,omitempty"`Items           []App `json:"items"`
}func init() {SchemeBuilder.Register(&App{}, &AppList{})
}func (in *App) String() string {return fmt.Sprintf("Image [%s], Port [%d], AppName [%s]",in.Spec.Image,*(in.Spec.Port),in.Spec.Project)
}

2.3 main.go

/*
Copyright 2023.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/package mainimport ("flag""os"// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)// to ensure that exec-entrypoint and run can make use of them._ "k8s.io/client-go/plugin/pkg/client/auth""k8s.io/apimachinery/pkg/runtime"utilruntime "k8s.io/apimachinery/pkg/util/runtime"clientgoscheme "k8s.io/client-go/kubernetes/scheme"ctrl "sigs.k8s.io/controller-runtime""sigs.k8s.io/controller-runtime/pkg/healthz""sigs.k8s.io/controller-runtime/pkg/log/zap"infrav1 "yunlizhi/api/v1""yunlizhi/controllers"//+kubebuilder:scaffold:imports
)var (scheme   = runtime.NewScheme()setupLog = ctrl.Log.WithName("setup")
)func init() {utilruntime.Must(clientgoscheme.AddToScheme(scheme))utilruntime.Must(infrav1.AddToScheme(scheme))//+kubebuilder:scaffold:scheme
}func main() {var metricsAddr stringvar enableLeaderElection boolvar probeAddr stringflag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")flag.BoolVar(&enableLeaderElection, "leader-elect", false,"Enable leader election for controller manager. "+"Enabling this will ensure there is only one active controller manager.")opts := zap.Options{Development: true,}opts.BindFlags(flag.CommandLine)flag.Parse()ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{Scheme:                 scheme,MetricsBindAddress:     metricsAddr,Port:                   9443,HealthProbeBindAddress: probeAddr,LeaderElection:         enableLeaderElection,LeaderElectionID:       "dcd31429.yunlizhi.cn",})if err != nil {setupLog.Error(err, "unable to start manager")os.Exit(1)}if err = (&controllers.AppReconciler{Client: mgr.GetClient(),Log:    ctrl.Log.WithName("controllers").WithName("app"),Scheme: mgr.GetScheme(),}).SetupWithManager(mgr); err != nil {setupLog.Error(err, "unable to create controller", "controller", "App")os.Exit(1)}//+kubebuilder:scaffold:builderif err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {setupLog.Error(err, "unable to set up health check")os.Exit(1)}if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {setupLog.Error(err, "unable to set up ready check")os.Exit(1)}setupLog.Info("starting manager")if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {setupLog.Error(err, "problem running manager")os.Exit(1)}
}

三 部署 jcrose.top operator

3.1 修改Dockerfile,新增一个GOPROXY提高编译速度

# Build the manager binary
FROM golang:1.17 as builderENV GOPROXY=https://goproxy.cn,direct	#主要是这一行WORKDIR /workspace
# Copy the Go Modules manifests
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
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 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 katanomi/distroless-static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532ENTRYPOINT ["/manager"]

3.2 部署

# 制作推送镜像至阿里云,需要先登录
# 这个需要在阿里云的镜像仓库创建这个仓库make docker-build docker-push IMG=registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2# kind可以直接导入
kind load docker-image registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2make install
make manifests	#配置RBAC权限# 部署controller
make deploy IMG=registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2

3.3 资源文件

apiVersion: infra.jcrose.top/v1
kind: App
metadata:name: jcrose-sample
spec:# Add fields herereplicas: 1image: registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2port: 8080domain: tomcat.jcrose.comproject: tomcat

四 最终效果

root@k8s:~# kubectl get app
NAME            REPLICAS   DOMAIN              IMAGE
jcrose-sample   1          tomcat.jcrose.com   registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2
root@k8s:~# kubectl get ingress
NAME            CLASS   HOSTS               ADDRESS          PORTS   AGE
jcrose-sample   nginx   tomcat.jcrose.com   10.106.189.253   80      27m
root@k8s:~# kubectl get app
NAME            REPLICAS   DOMAIN              IMAGE
jcrose-sample   1          tomcat.jcrose.com   registry.cn-zhangjiakou.aliyuncs.com/jcrose-k8s/jcrose-deployment:v2
root@k8s:~# kubectl get svc
NAME                                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
jcrose-controller-manager-metrics-service   ClusterIP   10.102.238.108   <none>        8443/TCP         20h
jcrose-sample                               NodePort    10.105.10.100    <none>        8080:20408/TCP   32m

相关文章:

k8s二次开发-kubebuiler一键式生成deployment,svc,ingress

一 Kubebuilder环境搭建 注&#xff1a;必须在当前的K8S集群有 nginx这个ingressclass rootk8s:~# kubectl get ingressclass NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx <none> 19h1.1 下载kubebuilder wget https://gi…...

Flutter 状态管理新境界:多Provider并行驱动UI

前言 在上一篇文章中&#xff0c;我们讨论了如何使用 Provider 在 Flutter 中进行状态管理。 本篇文章我们来讨论如何使用多个 Provider。 在 Flutter 中&#xff0c;使用 Provider 管理多个不同的状态时&#xff0c;你可以为每个状态创建一个单独的 ChangeNotifierProvider…...

标识符和关键字的区别是什么,常用的关键字有哪些?自增自减运算符,移位运算符continue、break、return的区别是什么?

标识符和关键字的区别是什么&#xff0c;常用的关键字有哪些&#xff1f; 标识符标识符就是当我们给变量&#xff0c;方法&#xff0c;类命名时候的名字&#xff0c;而被赋予特殊含义的标识符就是关键字。例如生活中&#xff0c;当我们需要开一家店时候&#xff0c;我们不能将…...

在VS Code上搭建Vue项目教程(Vue-cli 脚手架)

1.前期环境准备 搭建Vue项目使用的是Vue-cli 脚手架。前期环境需要准备Node.js环境&#xff0c;就像Java开发要依赖JDK环境一样。 1.1 Node.js环境配置 1&#xff09;具体安装步骤操作即可&#xff1a; npm 安装教程_如何安装npm-CSDN博客文章浏览阅读836次。本文主要在Win…...

AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理

AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理 目录 AGI 之 【Hugging Face】 的【零样本和少样本学习】之三 [无标注数据] 的简单整理 一、简单介绍 二、零样本学习 (Zero-shot Learning) 和少样本学习 (Few-shot Learning) 1、零样本学…...

Docker 和 k8s 之间是什么关系?

Docker 简介 Docker 功能&#xff1a; Docker 是一款可以将程序和环境打包并运行的工具软件。通过 Docker&#xff0c;可以将程序及其依赖环境打包&#xff0c;确保在不同操作系统上一致的运行效果。 环境一致性问题&#xff1a; 程序依赖于特定的环境&#xff0c;不同操作系统…...

敲详细的springframework-amqp-rabbit源码解析

看源码时将RabbitMQ的springframework-amqp-rabbit和spring-rabbit的一套区分开&#xff0c;springboot是基于RabbitMQ的Java客户端建立了简便易用的框架。 springboot的框架下相对更多地使用消费者Consumer和监听器Listener的概念&#xff0c;这两个概念不注意区分容易混淆。…...

Telegram Bot、小程序开发(三)Mini Apps小程序

文章目录 一、Telegram Mini Apps小程序二、小程序启动方式三、小程序开发小程序调试模式初始化小程序Keyboard Button Mini Apps 键盘按钮小程序【依赖具体用户信息场景,推荐】**Inline Button Mini Apps内联按钮小程序**initData 的自动传递使用内联菜单时候哪些参数会默认传…...

Django F()函数

F()函数的作用 F()函数在Django中是一个非常强大的工具&#xff0c;主要用于在查询表达式中引用模型的字段。它允许你在数据库层面执行各种操作&#xff0c;而无需将数据加载到Python内存中。这不仅提高了性能&#xff0c;还允许你利用数据库的优化功能。 字段引用 在查询表达…...

GraphRAG的实践

好久没有体验新技术了&#xff0c;今天来玩一下GraphRAG 顾名思义&#xff0c;一种检索增强的方法&#xff0c;利用图谱来实现RAG 1.配置环境 conda create -n GraphRAG python3.11 conda activate GraphRAG pip install graphrag 2.构建GraphRAG mkdir -p ./ragtest/i…...

自动驾驶三维车道线检测系列—LATR: 3D Lane Detection from Monocular Images with Transformer

文章目录 1. 概述2. 背景介绍3. 方法3.1 整体结构3.2 车道感知查询生成器3.3 动态3D地面位置嵌入3.4 预测头和损失 4. 实验评测4.1 数据集和评估指标4.2 实验设置4.3 主要结果 5. 讨论和总结 1. 概述 3D 车道线检测是自动驾驶中的一个基础但具有挑战性的任务。最近的进展主要依…...

守护动物乐园:视频AI智能监管方案助力动物园安全与秩序管理

一、背景分析 近日&#xff0c;某大熊猫参观基地通报了4位游客在参观时&#xff0c;向大熊猫室外活动场内吐口水的不文明行为。这几位游客的行为违反了入园参观规定并可能对大熊猫造成严重危害&#xff0c;已经被该熊猫基地终身禁止再次进入参观。而在此前&#xff0c;另一熊猫…...

FairGuard游戏加固入选《嘶吼2024网络安全产业图谱》

2024年7月16日&#xff0c;国内网络安全专业媒体——嘶吼安全产业研究院正式发布《嘶吼2024网络安全产业图谱》(以下简称“产业图谱”)。 本次发布的产业图谱&#xff0c;共涉及七大类别&#xff0c;127个细分领域。全面展现了网络安全产业的构成和重要组成部分&#xff0c;探…...

数据仓库事实表

数据仓库中的三种常见事实表类型&#xff1a;事务事实表、周期快照事实表和累积快照事实表 事务事实表&#xff1a; 事务事实表是记录事务级别数据的事实表。它记录了每个事务发生的具体度量指标&#xff0c;如销售金额、数量等。事务事实表的优势在于能够提供详细的事务级别…...

LeetCode题练习与总结:两数之和Ⅱ-输入有序数组--167

一、题目描述 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index…...

在 Java 中,怎样设计一个可扩展且易于维护的微服务架构?

在Java中设计一个可扩展且易于维护的微服务架构&#xff0c;可以考虑以下几个方面&#xff1a; 模块化设计&#xff1a;将应用拆分为多个小的、独立的模块&#xff0c;每个模块负责处理特定的业务逻辑。每个模块可以独立开发、测试和部署&#xff0c;增加或替换模块时不会影响其…...

零基础入门鸿蒙开发 HarmonyOS NEXT星河版开发学习

今天开始带大家零基础入门鸿蒙开发&#xff0c;也就是你没有任何编程基础的情况下就可以跟着石头哥零基础学习鸿蒙开发。 目录 一&#xff0c;为什么要学习鸿蒙 1-1&#xff0c;鸿蒙介绍 1-2&#xff0c;为什么要学习鸿蒙 1-3&#xff0c;鸿蒙各个版本介绍 1-4&#xff0…...

Chromium CI/CD 之Jenkins实用指南2024-在Windows节点上创建任务(九)

1. 引言 在现代软件开发流程中&#xff0c;持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;已成为确保代码质量和加速发布周期的关键实践。Jenkins作为一款广泛应用的开源自动化服务器&#xff0c;通过其强大的插件生态系统和灵活的配置选项&#xf…...

ceph进程网卡绑定逻辑

main() //如osd进程&#xff0c;是ceph_osd.cc文件的main函数&#xff1b;mon进程&#xff0c;是ceph_mon.cc文件的main函数 -->pick_addresses() // 会读取"cluster_network_interface"和"public_network_interface"这两个配置项来过滤ip ---->fill…...

学习opencv

初步学习可以参考&#xff1a; OpenCV学习之路&#xff08;附加资料分享&#xff09;_opencv资料-CSDN博客 【OpenCV】OpenCV常用函数合集【持续更新】_opencv函数手册-CSDN博客 整体框架可以参考&#xff1a; OpenCV学习指南&#xff1a;从零基础到全面掌握&#xff08;零…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...