10分钟开发Kubernetes Operator

news2024/11/19 2:44:47

Operator是扩展原生Kubernetes能力的主要模式,本文通过一个简单示例,介绍了如何从0开始构建Kubernetes Operator实现用户自定义功能。原文: Build a Kubernetes Operator in 10 Minutes

你也许能够将应用熟练的部署到Kubernetes[1]上,但你知道什么是Operator吗?Operator是如何工作的?如何构建Operator?这是一个复杂的课题,但幸运的是,自2016年[2]发明以来,已经开发了许多相关工具,可以简化工程师的生活。

这些工具允许我们将自定义逻辑加入Kubernetes,从而自动化大量任务,而这已经超出了软件本身功能的范围。

闲话少说,让我们深入了解更多关于Operator的知识吧!

图1. Maximilian Weisbecker@Unsplash
图1. Maximilian Weisbecker@Unsplash

目录

  • 什么是Operator?
  • 构建Operator
    • 1. 设置开发环境
    • 2. 构建简单的Operator
    • 3. 自定义CRD和Controller
    • 4. 运行Controller
    • 5. 测试控制器
  • 更多工作

什么是Operator?

等一下,你知道Kubernetes(或k8s)吗?简单介绍一下,这是由谷歌云[3]开发的"可以在任何地方部署、扩展和管理容器应用程序的开源系统"。

大多数人使用Kubernetes的方式是使用原生资源(如pod、deployment、service等)部署应用程序。但是,也可以扩展Kubernetes的功能,从而添加满足特定需求的新业务逻辑,这就是Operator的作用。

Operator的主要目标是将工程师的逻辑转换为代码,以便实现原生Kubernetes无法完成的某些任务的自动化。

负责开发应用程序或服务的工程师对系统应该如何运行、如何部署以及如何在出现问题时做出反应有很深的了解。将这些技术知识封装在代码中并自动化操作的能力意味着在可以花费更少的时间处理重复任务,而在重要问题上可以投入更多时间。

例如,可以想象Operator在Kubernetes中部署和维护MySQL、Elasticsearch或Gitlab runner等工具,Operator可以配置这些工具,根据事件调整系统状态,并对故障做出反应。

听起来很有趣不是吗?让我们动手干吧。

构建Operator

可以使用Kubernetes开发的controller-runtime项目从头构建Operator,也可以使用最流行的框架之一加速开发周期并降低复杂性(Kubebuilder或OperatorSDK)。因为Kubebuilder框架非常容易使用,文档也很容易阅读,而且久经考验,因此我选择基于Kubebuilder构建。

不管怎样,这两个项目目前正在合并为单独的项目。

1. 设置开发环境

开发Operator需要以下必备工具:

  • go version v1.17.9+
  • docker version 17.03+
  • kubectl version v1.11.3+
  • 访问Kubernetes v1.11.3+集群(强烈建议使用kind设置自己的本地集群,它非常容易使用!)

然后安装kubebuilder:

$ curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH) && chmod +x kubebuilder && mv kubebuilder /usr/local/bin/

如果一切正常,应该会看到类似输出(版本可能会随时间发生变化):

$ kubebuilder version
Version: main.version{KubeBuilderVersion:"3.4.1", KubernetesVendor:"1.23.5", GitCommit:"d59d7882ce95ce5de10238e135ddff31d8ede026", BuildDate:"2022-05-06T13:58:56Z", GoOs:"darwin", GoArch:"amd64"}

太棒了,现在可以开始了!

2. 构建简单的Operator

接下来做个小练习,构建一个简单的foo operator,除了演示Operator的功能之外,没有实际用处。

运行以下命令初始化新项目,该命令将下载controller-runtime二进制文件,并为我们准备好项目。

$ kubebuilder init --domain my.domain --repo my.domain/tutorial
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.11.2
go: downloading sigs.k8s.io/controller-runtime v0.11.2
...
Update dependencies:
$ go mod tidy
go: downloading github.com/onsi/gomega v1.17.0
...

下面是项目结构(注意这是一个Go项目):

$ ls -a
-rw-------   1 leovct  staff    129 Jun 30 16:08 .dockerignore
-rw-------   1 leovct  staff    367 Jun 30 16:08 .gitignore
-rw-------   1 leovct  staff    776 Jun 30 16:08 Dockerfile
-rw-------   1 leovct  staff   5029 Jun 30 16:08 Makefile
-rw-------   1 leovct  staff    104 Jun 30 16:08 PROJECT
-rw-------   1 leovct  staff   2718 Jun 30 16:08 README.md
drwx------   6 leovct  staff    192 Jun 30 16:08 config
-rw-------   1 leovct  staff   3218 Jun 30 16:08 go.mod
-rw-r--r--   1 leovct  staff  94801 Jun 30 16:08 go.sum
drwx------   3 leovct  staff     96 Jun 30 16:08 hack
-rw-------   1 leovct  staff   2780 Jun 30 16:08 main.go

我们来看看这个Operator最重要的组成部分:

  • main.go是项目入口,负责设置并运行管理器。
  • config/包含在Kubernetes中部署Operator的manifest。
  • Dockerfile是用于构建管理器镜像的容器文件。

等等,这个管理器组件是什么玩意儿?!

这涉及到部分理论知识,我们稍后再说!

Operator由两个组件组成,自定义资源定义(CRD, Custom Resource Definition)和控制器(controller)。

CRD是"Kubernetes自定义类型"或资源蓝图,用于描述其规范和状态。我们可以定义CRD的实例,称为自定义资源(CR, Custom Resource)。

图2. 自定义资源定义(CRD)和自定义资源(CR)。
图2. 自定义资源定义(CRD)和自定义资源(CR)。

控制器(也称为控制循环)持续监视集群状态,并根据事件做出变更,目标是将资源的当前状态变为用户在自定义资源规范中定义的期望状态。

图3. 控制器操作概要图示,作者Stefanie Lai。
图3. 控制器操作概要图示,作者Stefanie Lai。

一般来说,控制器是特定于某种类型的资源的,但也可以对一组不同的资源执行CRUD(创建、读取、更新和删除)操作。

在Kubernetes的文档中举了一个控制器的例子: 恒温器。当我们设置温度时,告诉恒温器所需的状态,房间的实际温度就是当前的实际状态,恒温器通过打开或关闭空调,使实际状态更接近预期状态。

那管理器(manager)呢?该组件的目标是启动所有控制器,并使控制循环共存。假设项目中有两个CRD,同时有两个控制器,每个CRD对应一个控制器,管理器将启动这两个控制器并使它们共存。

如果想了解Operator如何工作的更多细节,可以查看文末参考资料列表。

现在我们知道了Operator是如何工作的,可以开始使用Kubebuilder框架创建一个Operator,我们从创建新的API(组/版本)和新的Kind(CRD)开始,当提示创建CRD和控制器时,按yes。

$ kubebuilder create api --group tutorial --version v1 --kind Foo
Create Resource [y/n] y
Create Controller [y/n] y
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
api/v1/foo_types.go
controllers/foo_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
mkdir -p /Users/leovct/Documents/tutorial/bin
GOBIN=/Users/leovct/Documents/tutorial/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0
/Users/leovct/Documents/tutorial/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."

接下来是最有意思的部分!我们将定制CRD和控制器来满足需求,注意看已经创建了两个新文件夹:

  • api/v1包含Foo CRD(参见 foo_types.go)。
  • controllers包含Foo控制器(参见 foo_controller.go)。

3. 自定义CRD和Controller

接下来定制我们可爱的Foo CRD(参见api/v1/foo_types.go)。正如前面所说,这个CRD没有任何目的,只是简单展示如何使用Operator在Kubernetes中执行简单的任务。

Foo CRD在其定义中有name字段,该字段指的是Foo正在寻找的朋友的名称。如果Foo找到了一个朋友(一个和朋友同名的pod),happy状态将被设置为true。

package v1

import (
 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// FooSpec defines the desired state of Foo
type FooSpec struct {
 // Name of the friend Foo is looking for
 Name string `json:"name"`
}

// FooStatus defines the observed state of Foo
type FooStatus struct {
 // Happy will be set to true if Foo found a friend
 Happy bool `json:"happy,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// Foo is the Schema for the foos API
type Foo struct {
 metav1.TypeMeta   `json:",inline"`
 metav1.ObjectMeta `json:"metadata,omitempty"`

 Spec   FooSpec   `json:"spec,omitempty"`
 Status FooStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// FooList contains a list of Foo
type FooList struct {
 metav1.TypeMeta `json:",inline"`
 metav1.ListMeta `json:"metadata,omitempty"`
 Items           []Foo `json:"items"`
}

func init() {
 SchemeBuilder.Register(&Foo{}, &FooList{})
}

接下来实现控制器逻辑。没什么复杂的,通过触发reconciliation请求获取Foo资源,从而得到Foo的朋友的名称。然后,列出所有和Foo的朋友同名的pod。如果找到一个或多个,将Foo的happy状态更新为true,否则设置为false

注意,控制器也会对Pod事件做出反应(参见mapPodsReqToFooReq)。实际上,如果创建了一个新的pod,我们希望Foo资源能够相应更新其状态。这个方法将在每次发生Pod事件时被触发(创建、更新或删除)。然后,只有当Pod名称是集群中部署的某个Foo自定义资源的"朋友"时,才触发Foo控制器的reconciliation循环。

package controllers

import (
 "context"

 corev1 "k8s.io/api/core/v1"
 "k8s.io/apimachinery/pkg/runtime"
 "k8s.io/apimachinery/pkg/types"
 ctrl "sigs.k8s.io/controller-runtime"
 "sigs.k8s.io/controller-runtime/pkg/client"
 "sigs.k8s.io/controller-runtime/pkg/handler"
 "sigs.k8s.io/controller-runtime/pkg/log"
 "sigs.k8s.io/controller-runtime/pkg/reconcile"
 "sigs.k8s.io/controller-runtime/pkg/source"

 tutorialv1 "my.domain/tutorial/api/v1"
)

// FooReconciler reconciles a Foo object
type FooReconciler struct {
 client.Client
 Scheme *runtime.Scheme
}

// RBAC permissions to monitor foo custom resources
//+kubebuilder:rbac:groups=tutorial.my.domain,resources=foos,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=tutorial.my.domain,resources=foos/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=tutorial.my.domain,resources=foos/finalizers,verbs=update

// RBAC permissions to monitor pods
//+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
func (r *FooReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 log := log.FromContext(ctx)
 log.Info("reconciling foo custom resource")

 // Get the Foo resource that triggered the reconciliation request
 var foo tutorialv1.Foo
 if err := r.Get(ctx, req.NamespacedName, &foo); err != nil {
  log.Error(err, "unable to fetch Foo")
  return ctrl.Result{}, client.IgnoreNotFound(err)
 }

 // Get pods with the same name as Foo's friend
 var podList corev1.PodList
 var friendFound bool
 if err := r.List(ctx, &podList); err != nil {
  log.Error(err, "unable to list pods")
 } else {
  for _, item := range podList.Items {
   if item.GetName() == foo.Spec.Name {
    log.Info("pod linked to a foo custom resource found""name", item.GetName())
    friendFound = true
   }
  }
 }

 // Update Foo' happy status
 foo.Status.Happy = friendFound
 if err := r.Status().Update(ctx, &foo); err != nil {
  log.Error(err, "unable to update foo's happy status""status", friendFound)
  return ctrl.Result{}, err
 }
 log.Info("foo's happy status updated""status", friendFound)

 log.Info("foo custom resource reconciled")
 return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *FooReconciler) SetupWithManager(mgr ctrl.Manager) error {
 return ctrl.NewControllerManagedBy(mgr).
  For(&tutorialv1.Foo{}).
  Watches(
   &source.Kind{Type: &corev1.Pod{}},
   handler.EnqueueRequestsFromMapFunc(r.mapPodsReqToFooReq),
  ).
  Complete(r)
}

func (r *FooReconciler) mapPodsReqToFooReq(obj client.Object) []reconcile.Request {
 ctx := context.Background()
 log := log.FromContext(ctx)

 // List all the Foo custom resource
 req := []reconcile.Request{}
 var list tutorialv1.FooList
 if err := r.Client.List(context.TODO(), &list); err != nil {
  log.Error(err, "unable to list foo custom resources")
 } else {
  // Only keep Foo custom resources related to the Pod that triggered the reconciliation request
  for _, item := range list.Items {
   if item.Spec.Name == obj.GetName() {
    req = append(req, reconcile.Request{
     NamespacedName: types.NamespacedName{Name: item.Name, Namespace: item.Namespace},
    })
    log.Info("pod linked to a foo custom resource issued an event""name", obj.GetName())
   }
  }
 }
 return req
}

我们已经完成了对API定义和控制器的编辑,可以运行以下命令来更新Operator manifest。

$ make manifests
/Users/leovct/Documents/tutorial/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

4. 运行Controller

我们使用Kind设置本地Kubernetes集群,它很容易使用。

首先将CRD安装到集群中。

$ make install
/Users/leovct/Documents/tutorial/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
kubectl apply -k config/crd
customresourcedefinition.apiextensions.k8s.io/foos.tutorial.my.domain created

可以看到Foo CRD已经创建好了。

$ kubectl get crds
NAME                               CREATED AT
foos.tutorial.my.domain            2022-06-30T17:02:45Z

然后终端中运行控制器。请记住,也可以将其部署为Kubernetes集群中的deployment。

$ make run
/Users/leovct/Documents/tutorial/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/Users/leovct/Documents/tutorial/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
INFO controller-runtime.metrics Metrics server is starting to listen {"addr"":8080"}
INFO setup starting manager
INFO Starting server {"path""/metrics""kind""metrics""addr""[::]:8080"}
INFO Starting server {"kind""health probe""addr""[::]:8081"}
INFO controller.foo Starting EventSource {"reconciler group""tutorial.my.domain""reconciler kind""Foo""source""kind source: *v1.Foo"}
INFO controller.foo Starting EventSource {"reconciler group""tutorial.my.domain""reconciler kind""Foo""source""kind source: *v1.Pod"}
INFO controller.foo Starting Controller {"reconciler group""tutorial.my.domain""reconciler kind""Foo"}
INFO controller.foo Starting workers {"reconciler group""tutorial.my.domain""reconciler kind""Foo""worker count": 1}

如你所见,管理器启动了,然后Foo控制器也启动了,控制器现在正在运行并监听事件!

5. 测试控制器

为了测试是否一切工作正常,我们创建两个Foo自定义资源以及一些pod,观察控制器的行为。

首先,在config/samples中创建Foo自定义资源清单,运行以下命令在本地Kubernetes集群中创建资源。

apiVersion: tutorial.my.domain/v1
kind: Foo
metadata:
  name: foo-01
spec:
  name: jack

---
apiVersion: tutorial.my.domain/v1
kind: Foo
metadata:
  name: foo-02
spec:
  name: joe
$ kubectl apply -f config/samples
foo.tutorial.my.domain/foo-1 created
foo.tutorial.my.domain/foo-2 created

可以看到控制器为每个Foo自定义资源创建事件触发了reconciliation循环。

INFO controller.foo reconciling foo custom resource {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-1""namespace""default"}
INFO controller.foo foo's happy status updated {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-1", "namespace": "default", "status": "false"}
INFO controller.foo foo custom resource reconciled {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-1", "namespace": "default"}
INFO controller.foo reconciling foo custom resource {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-2", "namespace": "default"}
INFO controller.foo foo'
s happy status updated {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-2""namespace""default""status""false"}
INFO controller.foo foo custom resource reconciled {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-2""namespace""default"}

如果检查Foo自定义资源状态,可以看到状态为空,这正是所期望的,目前为止一切正常!

$ kubectl describe foos
Name:         foo-1
Namespace:    default
API Version:  tutorial.my.domain/v1
Kind:         Foo
Metadata:     ...
Spec:
  Name:       jack
Status:
Name:         foo-2
Namespace:    default
API Version:  tutorial.my.domain/v1
Kind:         Foo
Metadata:     ...
Spec:
  Name:       joe
Status:

接下来我们部署一个叫jack的pod来观察系统的反应。

apiVersion: v1
kind: Pod
metadata:
  name: jack
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]

Pod部署完成后,应该可以看到控制器对pod创建事件作出响应,然后按照预期更新第一个Foo自定义资源状态,可以通过describe Foo自定义资源来验证。

INFO pod linked to a foo custom resource issued an event {"name""jack"}
INFO controller.foo reconciling foo custom resource {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-1""namespace""default"}
INFO controller.foo pod linked to a foo custom resource found {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-1""namespace""default""name""jack"}
INFO controller.foo foo's happy status updated {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-1", "namespace": "default", "status": true}
INFO controller.foo foo custom resource reconciled {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-1", "namespace": "default"}

我们更新第二个Foo自定义资源规范,将其name字段的值从joe更改为jack,控制器应该捕获更新事件并触发reconciliation循环。

INFO controller.foo pod linked to a foo custom resource found {"reconciler group""tutorial.my.domain""reconciler kind""Foo""name""foo-2""namespace""default""name""jack"}
INFO controller.foo foo's happy status updated {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-2", "namespace": "default", "status": true}
INFO controller.foo foo custom resource reconciled {"reconciler group": "tutorial.my.domain", "reconciler kind": "Foo", "name": "foo-2", "namespace": "default"}

Yeah,成功了!我们已经做了足够多的实验,你应该明白这是怎么回事了!如果删除名为jack的pod,自定义资源的happy状态将被设置为false。

我们可以确认Operator是正常工作的!最好再编写一些单元测试和端到端测试,但本文不会覆盖相关内容。

为自己感到骄傲吧,你已经设计、部署并测试了第一个Operator!恭喜!!

如果需要浏览完整代码,请访问GitHub: https://github.com/leovct/kubernetes-operator-tutorial。

更多工作

我们已经看到如何创建非常基本的Kubernetes operator,但远非完美,还有很多地方需要改善,下面是可以探索的主题列表:

  • 优化事件过滤(有时,事件会被提交两次…)。
  • 完善RBAC权限。
  • 改进日志记录系统。
  • 当operator更新资源时,触发Kubernetes事件。
  • 获取Foo自定义资源时添加自定义字段(也许显示happy状态?)
  • 编写单元测试和端到端测试。

通过这个列表,可以深入挖掘这一主题。

你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

参考资料

[1]

Kubernetes: https://kubernetes.io

[2]

Introducing Operators: Putting Operational Knowledge into Software: https://web.archive.org/web/20170129131616/https://coreos.com/blog/introducing-operators.html

[3]

What is Kubernetes: https://cloud.google.com/learn/what-is-kubernetes

- END -

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014508.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MAUI android连接sqlserver

PDA是android系统,调用金蝶云星空webapi实现仓库收发料,使用读取webapi有些功能无法实现,需要直接读写数据库,读取报错,如图: 用控制台程序测试正常读取 google搜索了一圈, 都需要使用ssl证书才…

华为云云耀云服务器 L 实例评测|配置教程 + 用 Python 简单绘图

文章目录 Part.I IntroductionChap.I 云耀云服务器 L 实例简介Chap.II 参与活动步骤 Part.II 配置Chap.I 初步配置Chap.II 配置安全组 Part.III 简单使用Chap.I VScode 远程连接华为云Chap.II 简单绘图 Reference Part.I Introduction 本篇博文是为了参与华为“【有奖征文】华…

为建模而建模,高成本的临床预测模型意义何在?

9.23-24 郑老师“量表与中介研究数据分析”课程,欢迎报名 “量表与中介研究数据分析”9.23-24直播课,发文后退款 关于预测模型,周三有位同学过来咨询我,说“郑老师,毕业论文,建一个脑卒中患者抑郁的预测模型…

Linux 简介 启动过程

简介 Linux 是一套免费使用和自由传播的开放源码的类 UNIX 操作系统,英文解释为: Linux is not Unix。1991 年由林纳斯托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的,主要受到 Minix 和 Unix 思想的…

JavaSE---常用的API

1. 什么是API? API (Application Programming interface) 应用程序编程接口。通俗来讲,就是Java已经帮我们写好了一些方法,我们直接拿过来用即可。 iodraw:https://www.iodraw.com/ API在线中文文档:https://www.ma…

Python入门教程39:教你使用distutils本地发布模块与模块安装的操作

★★★★★博文创作不易,我的博文不需要打赏,也不需要知识付费,可以白嫖学习编程小技巧。使用代码的过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞收藏分享置顶,小红牛在此表示感谢…

RabbitMQ消息可靠性(一)-- 生产者消息确认

前言 在项目中,引入了RabbitMQ这一中间件,必然也需要在业务中增加对数据安全性的一层考虑,来保证RabbitMQ消息的可靠性,否则一个个消息丢失可能导致整个业务的数据出现不一致等问题,对系统带来巨大的影响,…

tomcat架构概览

https://blog.csdn.net/ldw201510803006/article/details/119880100 前言 Tomcat 要实现 2 个核心功能: 处理 Socket 连接,负责网络字节流与 Request 和 Response 对象的转化。加载和管理 Servlet,以及具体处理 Request 请求。 因此 Tomc…

weblogic __ 10.3.6 __ 反序列化漏洞 _ CVE-2017-10271

weblogic __ 10.3.6 __ 反序列化漏洞 _ CVE-2017-10271 说明内容漏洞编号CVE-2017-10271漏洞名称反序列化漏洞影响范围10.3.6.0.0,12.1.3.0.0,12.2.1.1.0,12.2.1.2.0漏洞描述Weblogic的WLS Security组件对外提供webservice服务,其…

MySQL里的查看操作

查看数据库或者表 列出所有数据库: show databases;查看正在使用的数据库(必须大写): SELECT DATABASE();列出数据库中的表: use 数据库;//选中数据库 show 表;//列出当前数据库下所有表获取数据库表结构&#xff…

OpenCV(四十七):RANSAC优化特征点匹配

1.RANSAC算法介绍 RANSAC是一种常用的参数估计方法,全称为Random Sample Consensus(随机抽样一致性)。它的主要思想是通过随机选择一部分数据样本,构建模型并评估其拟合程度,迭代过程中逐步优化模型,最终得…

Linux知识点 -- 网络基础(二)

Linux知识点 – 网络基础(二)(1) 文章目录 Linux知识点 -- 网络基础(二)(1)一、使用协议来实现一个网络版的计算器1.自定义协议2.守护进程3.使用json来完成序列化 二、HTTP协议1.概念…

Redis 事务实现原理

1. 什么是Redis事务 提到事务,我们可能马上会想到传统的关系型数据库中的事务,客户端首先向服务器发送BEGIN开启事务,然后执行读写操作,最后用户发送 COMMIT 或者 ROLLBACK 来提交或者回滚之前的操作。 但是Redis中的事务与关系型数据库是不一样的,Redis 通过 MULTI 命令开始…

GB28181学习(四)——网络设备信息查询

要求 源设备向目标设备发送信息查询命令,目标设备将结果通过查询应答命令返回给源设备;设备信息查询命令包括: 设备目录设备信息设备状态信息设备配置预置位、看守位巡航轨迹列表巡航轨迹PTZ精准状态存储卡状态等 信息查询的范围&#xff1a…

内网穿透对开发人员有什么作用?要怎么实现?快解析

在当今快节奏的互联网时代,软件开发人员需要时刻与内外部服务器进行通信和调试,只有这样才能带来良好的工作速度,顺利推动项目的进展。然而,由于受到网络环境的限制,有时候我们可能无法直接访问公司内网的服务器&#…

差分方程模型:蛛网模型

在完全竞争的市场经济中,一个时期某种消费品如猪肉的上市量远远大于需求量,由于销售不畅导致价格下降,生产者发现养猪赔钱,于是转而经营其它农副产品。过一段时间猪肉上市量就会下降,此时供不应求导致价格上涨&#xf…

【MySQL】MySQL索引的定义、分类、Explain、索引失效和优化

索引的介绍 索引是帮助MySQL高效获取数据的数据结构 MySQL在存储数据之外,数据库系统中还维护着满足特定查找算法的数据结构,这些数据结构以某种引用(指向)表中的数据,这样我们就可以通过数据结构上实现的高级查找算法来快速找到我们想要的数…

设计原则SOLID看这一篇就够了

文章目录 1.引言1.1. 背景1.2. 简要介绍 SOLID 原则1.1. 面向对象编程和设计的重要性 2. 单一职责原则(SRP)2.1. 定义和原理2.2. SRP 的好处与目标2.3. 例子和代码展示2.4. 如何识别和解决 SRP 原则的违反2.5. 注意事项和局限性 3. 开闭原则(…

Centos7.9 一键脚本部署 LibreNMS 网络监控系统

前言: LibreNMS 是个以 PHP/MySQL 为基底的自动探索网络监控系统 LibreNMS 官网 版本23.8.2-52-g7bbe0a2 - Thu Sep 14 2023 22:33:23 GMT0700数据库纲要2023_09_01_084057_application_new_defaults (259)Web 服务器nginx/1.20.1PHP8.1.23Python3.6.8DatabaseMa…

Killer!永久禁用WindowsDefender

工具介绍 WinDefenderKiller,使用C写的通过注册表项永久禁用Windows Defende的一个工具。 关注【Hack分享吧】公众号,回复关键字【230726】获取下载链接 编译使用 执行以下命令编译: # x86_64-w64-mingw32-g -O2 disableWinDef.cpp -o win…