k8s编程operator实战之云编码平台——②controller初步实现

这篇具有很好参考价值的文章主要介绍了k8s编程operator实战之云编码平台——②controller初步实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


k8s编程operator系列:
k8s编程operator——(1) client-go基础部分
k8s编程operator——(2) client-go中的informer
k8s编程operator——(3) 自定义资源CRD
k8s编程operator——(4) kubebuilder & controller-runtime
k8s编程operator实战之云编码平台——①架构设计
k8s编程operator实战之云编码平台——②controller初步实现
k8s编程operator实战之云编码平台——③Code-Server Pod访问实现
k8s编程operator实战之云编码平台——④web后端实现
k8s编程operator实战之云编码平台——⑤项目完成、部署
 
在上一章中介绍了整个云编码平台的架构设计,本章中将实现架构中的controller。需要使用的技术: k8s二次开发kubebuildergrpc

controller用来创建、删除、获取Pod信息以及状态的维护。

 

1、工作空间镜像制作

        首先我们要制作code-server的docker镜像,先来制作一个含有go运行环境的工作空间镜像,工具包括:go sdk、make、git

首先创建一个文件夹用来存放我们制作镜像需要的文件:

mkdir go_template

 

1、下载code-server

下载code-server v4.9.0版本:

下载的网址为:https://github.com/coder/code-server/releases

wget https://github.com/coder/code-server/releases/download/v4.9.0/code-server-4.9.0-linux-amd64.tar.gz

2、下载go sdk,版本为v1.19.4

下载地址:https://golang.google.cn/dl/

wget https://golang.google.cn/dl/go1.19.4.linux-amd64.tar.gz

3、编写Dockerfile

Dockerfile如下:

  • 基础镜像使用ubuntu:20.04
  • 14、15行为安装必要的软件
  • 16行安装git
  • 在启动code-server时不使用密码验证,默认打开/root/workspace文件
FROM ubuntu:20.04

WORKDIR /.workspace

COPY code-server-4.9.0-linux-amd64.tar.gz .
COPY go1.19.4.linux-amd64.tar.gz .

RUN tar zxvf code-server-4.9.0-linux-amd64.tar.gz && \
    rm -f code-server-4.9.0-linux-amd64.tar.gz    && \
    tar zxvf go1.19.4.linux-amd64.tar.gz -C /usr/local     && \
    rm -f go1.19.4.linux-amd64.tar.gz             && \
    mkdir -p /root/workspace /go/{src,pkg,bin}    && \
    apt-get -y update                             && \
    apt-get -qq update                            && \
    apt-get -qq install -y --no-install-recommends ca-certificates curl && \
    apt install git

ENV GO111MODULE on
ENV GOPROXY https://goproxy.cn,direct
ENV GOROOT /usr/local/go
ENV PATH /usr/local/go/bin:$PATH
ENV GOPATH /go
ENV PATH $GOPATH/bin:$PATH

WORKDIR /.workspace/code-server-4.9.0-linux-amd64

EXPOSE 9999

CMD ["./bin/code-server", "--port", "9999", "--host", "0.0.0.0", "--auth", "none", "--disable-update-check", "--open", "/root/workspace/"]

4、构建镜像

在go_template中构建镜像,需要将code-server、go sdk和Docker都放在该文件夹下,也不要放多余的其它文件

docker build -t code-server-go1.19:v0.1 .

构建查看镜像(我的镜像名为mangohow/code-server-go1.19):

k8s编程operator实战之云编码平台——②controller初步实现

5、push到docker hub

在构建完成后,最好将镜像推送到dockerhub或者其它镜像仓库中

首先要给镜像打一个tag,yourUsername为你的镜像仓库的用户名

docker tag code-server-go1.19:v0.1 yourUsername/code-server-go1.19:v0.1

推送到镜像仓库

# 先登录
docker login
docker push yourUsername/code-server-go1.19:v0.1

 

2、controller实现

controller的实现直接使用kubebuilder,它会为我们生成一套模板代码

注意:最好直接在linux上编码,在windows上有很多问题

 

2.1 使用kubebuilder创建工程

1、创建文件夹

mkdir cloud-ide-k8s-controller
cd cloud-ide-k8s-controller/

2、创建工程

# 初始化
go mod init cloud-ide-k8s-controller
kubebuilder init

k8s编程operator实战之云编码平台——②controller初步实现

# 创建api
kubebuilder create api --group cloud-ide  --version v1 --kind Pod

由于我们没有创建自定义资源,所以在Create Resource选择中选择n

k8s编程operator实战之云编码平台——②controller初步实现

到此,工程已经创建完毕,开始编码

 

2.2 代码实现

2.2.1 引入grpc

Pod的创建、删除以及信息查询等工作我们都在controller中实现,然后通过grpc的方式提供给web后端来使用。

使用grpc需要安装protobuf和proto-gen-go,关于这部分的安装在此就不再介绍,网上教程很多。

1、grpc的proto文件定义

首先先实现四个grpc service:

createSpaceAndWaitForRunning:创建Pod并且等待Pod的状态变为Running,当我们在创建Pod后,它需要一段时间来启动,在这段时间之间是无法访问的,因此我们需要等待它启动完成后再返回
deleteSpace:删除Pod
getPodSpaceStatus:获取Pod运行的状态
getPodSpaceInfo:获取Pod的信息

在工程中创建pb/proto文件夹,然后创建proto文件:

service.proto如下:

syntax = "proto3";

package pb;

option go_package = "./;pb";

// 限制用户的工作空间的资源使用,有CPU、内存和存储的大小限制
message ResourceLimit {
  string cpu = 1;
  string Memory = 2;
  string Storage = 3;
}

// 在创建Pod时,需要webserver提供要创建的Pod的信息
// 其中有:Pod的名称、Pod的命名空间、使用的镜像、以及要使用的端口和资源限制
message PodInfo {
  string name = 1;
  string namespace = 2;
  string image = 3;
  uint32 port = 4;
  ResourceLimit resourceLimit = 5;
}

message Response {
  int32 status = 1;
  string message = 2;
}

message QueryOption {
  string name = 1;
  string namespace = 2;
}

message PodStatus {
  int32 status = 1;
  string message = 2;
}

message PodSpaceInfo {
  string nodeName = 1;
  string ip = 2;
  int32 port = 3;
}

service CloudIdeService {
  // 创建云IDE空间并等待Pod状态变为Running
  rpc createSpaceAndWaitForRunning(PodInfo) returns (PodSpaceInfo);
  // 删除云IDE空间
  rpc deleteSpace(QueryOption) returns (Response);
  // 获取Pod运行状态
  rpc getPodSpaceStatus(QueryOption) returns (PodStatus);
  // 获取云IDE空间Pod的信息
  rpc getPodSpaceInfo(QueryOption) returns (PodSpaceInfo);
}

生成代码:

protoc --go_out=plugins=grpc:./pb ./pb/proto/*.proto

可以将这个命令加到makefile中,以后在使用就更方便了,可以直接使用make proto

k8s编程operator实战之云编码平台——②controller初步实现

 

2.2.2 实现CloudIdeService

创建cloudspaceservice.go实现CloudIdeService接口

要实现的方法总共有四个:

type CloudIdeServiceClient interface {
	// 创建云IDE空间并等待Pod状态变为Running
	CreateSpaceAndWaitForRunning(ctx context.Context, in *PodInfo, opts ...grpc.CallOption) (*PodSpaceInfo, error)
	// 删除云IDE空间
	DeleteSpace(ctx context.Context, in *QueryOption, opts ...grpc.CallOption) (*Response, error)
	// 获取Pod运行状态
	GetPodSpaceStatus(ctx context.Context, in *QueryOption, opts ...grpc.CallOption) (*PodStatus, error)
	// 获取云IDE空间Pod的信息
	GetPodSpaceInfo(ctx context.Context, in *QueryOption, opts ...grpc.CallOption) (*PodSpaceInfo, error)
}

CreateSpaceAndWaitForRunning:给ApiServer发送请求创建Pod,并且等待Pod处于运行状态后在返回。

DeleteSpace:删除指定的Pod

GetPodSpaceStatus:获取Pod的运行状态,Pod是否存在

GetPodSpaceInfo:获取Pod的ip和port信息

等待Pod处于运行状态

Pod在刚创建时处于Pending状态,当Pod启动完毕后,会处于Running状态,因为我们要监视Pod的状态,当它的状态变为Runnging时,就通知我们的CreateSpaceAndWaitForRunning方法Pod已经就绪。

要监视Pod的状态可以通过client go的informer来实现,使用kubebuilder生成的工程中已经有现成的模板代码,也就是我们只需要在controller中实现Reconcile方法即可。

我们可以实现一个通知器,其中含有map[string]chan struct{},当我们在CreateSpaceAndWaitForRunning方法中请求ApiServer创建Pod后,就向map中添加一个键值对 key:podname val: chan,然后从chan中读取数据,由于Pod还未准备就绪,因此读取空的chan将会导致阻塞。在Reconcile中当监视到Pod的状态变为Running后,就向chan中发送消息另一端就可以收到Pod已经就绪的通知

StatusInformer的实现
package statussync

import (
	"errors"
	"sync"
)

var (
	ErrNotFound = errors.New("not Found")
)

// StatusInformer 状态同步通知器,当Pod状态处于Running时,通知对端
type StatusInformer struct {
	sync.Mutex
	m map[string]chan struct{}
}

func NewManager() *StatusInformer {
	return &StatusInformer{
		m: make(map[string]chan struct{}),
	}
}

// 向map中添加一个chan
func (m *StatusInformer) Add(name string) <-chan struct{} {
	m.Lock()
	defer m.Unlock()
	ch := make(chan struct{}, 1)
	m.m[name] = ch

	return ch
}

func (m *StatusInformer) Delete(name string) {
	m.Lock()
	defer m.Unlock()
	delete(m.m, name)
}

// 同步消息
func (m *StatusInformer) Sync(name string) error {
	m.Lock()
	defer m.Unlock()
	ch, ok := m.m[name]
	if !ok {
		return ErrNotFound
	}
	ch <- struct{}{}

	return nil
}

 

CloudIdeService接口实现:

CloudSpaceService定义

在CloudSpaceService的字段有三个,分别是:client、logger和statusInformer

client可以对Pod进行CRUD,在查询时会查询本地的缓存

package service

import (
	"context"
	"fmt"
	"github.com/go-logr/logr"
	"github.com/mangohow/cloud-ide-k8s-controller/pb"
	"github.com/mangohow/cloud-ide-k8s-controller/tools/statussync"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

var (
	ResponseSuccess = &pb.Response{Status: 200, Message: "success"}
	ResponseFailed  = &pb.Response{Status: 400, Message: "failed"}
)

const (
	PodNotExist int32 = iota
	PodExist
)

type CloudSpaceService struct {
	client         client.Client            // client可用于pod的CRUD
	logger         *logr.Logger
	statusInformer *statussync.StatusInformer
}

func NewCloudSpaceService(client client.Client, logger *logr.Logger, manager *statussync.StatusInformer) *CloudSpaceService {
	return &CloudSpaceService{
		client:         client,
		logger:         logger,
		statusInformer: manager,
	}
}

var podTpl = &v1.Pod{
	TypeMeta: metav1.TypeMeta{
		Kind:       "Pod",
		APIVersion: "v1",
	},
	ObjectMeta: metav1.ObjectMeta{
		Labels: map[string]string{
			"kind": "cloud-ide",
		},
	},
}

方法CreateSpaceAndWaitForRunning

在Pod的定义中一定要将镜像的拉取策略改为IfNotPresent,之前这个字段没有填。每次在创建工作空间的时候,都要等30~40s,后来我才发现,默认的策略是Always,也就是每次创建工作空间的时候都会从dockerhub拉取镜像,所以才导致这么慢。修改后,启动工作空间就只需要不到5s。

在Resources中,我将代码注释了,因为我的虚拟机配置太低,如果不注释,那么在创建Pod时就可能会因为资源不足而导致Pod创建失败。

// CreateSpaceAndWaitForRunning 创建一个云IDE空间, 并等待Pod的状态变为Running
func (s *CloudSpaceService) CreateSpaceAndWaitForRunning(ctx context.Context, info *pb.PodInfo) (*pb.PodSpaceInfo, error) {
	// 1、获取一个Pod的深拷贝
    pod := podTpl.DeepCopy()
    // 2、填充参数
	s.fillPod(info, pod)
    // 3、创建Pod
	err := s.client.Create(context.Background(), pod)
	if err != nil {
		fmt.Printf("create pod:%s, info:%v\n", err.Error(), info)
		return nil, err
	}
	// 4、向informer中添加chan,当Pod准备就绪时就会收到通知
	ch := s.statusInformer.Add(pod.Name)
	// 从informer中删除
	defer s.statusInformer.Delete(pod.Name)
	// 等待pod状态处于Running
	<-ch
	
    // 返回Pod的信息
	return s.GetPodSpaceInfo(context.Background(), &pb.QueryOption{
		Name:      info.Name,
		Namespace: info.Namespace,
	})
}

func (s *CloudSpaceService) fillPod(info *pb.PodInfo, pod *v1.Pod) {
	pod.Name = info.Name           // 指定Pod名称
	pod.Namespace = info.Namespace    // 指定Pod的命名空间
	pod.Spec.Containers = []v1.Container{
		{
			Name:            info.Name,     // 容器名称和Pod名称相同
			Image:           info.Image,    // 容器的镜像
			ImagePullPolicy: v1.PullIfNotPresent,      // 镜像拉取策略
			Ports: []v1.ContainerPort{
				{
					ContainerPort: int32(info.Port),
				},
			},
			Resources: v1.ResourceRequirements{
				//Limits: map[v1.ResourceName]resource.Quantity{
				//	v1.ResourceCPU:    resource.MustParse(info.ResourceLimit.Cpu),
				//	v1.ResourceMemory: resource.MustParse(info.ResourceLimit.Memory),
				//},
				// 最小需求CPU2核、内存4Gi == 4 * 2^10
				//Requests: map[v1.ResourceName]resource.Quantity{
				//	v1.ResourceCPU:    resource.MustParse("2"),
				//	v1.ResourceMemory: resource.MustParse("4Gi"),
				//},
			},
		},
	}

}

方法GetPodSpaceInfo

根据Pod名称以及命名空间查询Pod的Ip和port

func (s *CloudSpaceService) GetPodSpaceInfo(ctx context.Context, option *pb.QueryOption) (*pb.PodSpaceInfo, error) {
	pod := v1.Pod{}
	err := s.client.Get(context.Background(), client.ObjectKey{Name: option.Name, Namespace: option.Namespace}, &pod)
	if err != nil {
		s.logger.Error(err, "get pod space info")
		return &pb.PodSpaceInfo{}, err
	}

	return &pb.PodSpaceInfo{NodeName: pod.Spec.NodeName,
		Ip:   pod.Status.PodIP,
		Port: pod.Spec.Containers[0].Ports[0].ContainerPort}, nil
}
方法DeleteSpace

根据Pod的名称和命名空间删除Pod

// DeleteSpace 删除一个云空间
func (s *CloudSpaceService) DeleteSpace(ctx context.Context, option *pb.QueryOption) (*pb.Response, error) {
	pod := v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:      option.Name,
			Namespace: option.Namespace,
		},
	}
	err := s.client.Delete(context.Background(), &pod)
	if err != nil {
		s.logger.Error(err, "delete space")
		return ResponseFailed, err
	}

	return ResponseSuccess, nil
}
方法GetPodSpaceStatus

根据Pod的名称和命名空间获取Pod的运行状态

func (s *CloudSpaceService) GetPodSpaceStatus(ctx context.Context, option *pb.QueryOption) (*pb.PodStatus, error) {
	pod := v1.Pod{}
	err := s.client.Get(context.Background(), client.ObjectKey{Name: option.Name, Namespace: option.Namespace}, &pod)
	if err != nil {
		s.logger.Error(err, "get pod space status")
		return &pb.PodStatus{Status: PodNotExist, Message: "NotExist"}, err
	}

	return &pb.PodStatus{Status: PodExist, Message: string(pod.Status.Phase)}, nil
}

 

2.2.3 controller实现

在pod_controller文件中,需要实现的方法主要有两个:ReconcileSetupWithManager

type PodReconciler struct {
	client.Client
	Scheme         *runtime.Scheme
	statusInformer *statussync.StatusInformer   // 添加statusInformer
}
SetupWithManager

在SetupWithManager方法中需要指定我们要监视的资源的类型,也就是Pod:

func (r *PodReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		// Uncomment the following line adding a pointer to an instance of the controlled resource as an argument
		For(&v1.Pod{}).
		Complete(r)
}
Reconcile

在Reconciler中监视Pod的状态,当Pod处于running状态时,通知对端

func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	logger := log.FromContext(ctx)

	// TODO(user): your logic here
	pod := &v1.Pod{}
    // 获取Pod
	err := r.Client.Get(context.Background(), req.NamespacedName, pod)
	if err != nil {
		if !errors.IsNotFound(err) {
			logger.Error(err, "get pod")
			return ctrl.Result{Requeue: true}, err
		}
	}
	fmt.Printf("name:%s, status:%s\n", pod.Name, pod.Status.Phase)
	// 如果Pod的状态处于Running,通知对端Pod已经处于Running状态
	if pod.Status.Phase == v1.PodRunning {
		r.statusInformer.Sync(pod.Name)
	}

	return ctrl.Result{}, nil
}

 

2.2.4 启动grpc server以及优雅退出服务器

我们需要在main函数中启动我们的grpc服务器并注册服务。处理信号,当接收到退出的信号时退出grpc server和controller

StartGrpcServer
func StartGrpcServer(client client.Client, logger *logr.Logger, manager *statussync.StatusInformer) *grpc.Server {
	// 创建listener
    listener, err := net.Listen("tcp", ":6387")
	if err != nil {
		panic(fmt.Errorf("create grpc service: %v", err))
	}
    // 创建grpc server
	server := grpc.NewServer()
    // 注册我们的服务
	pb.RegisterCloudIdeServiceServer(server, service.NewCloudSpaceService(client, logger, manager))
	
    // 启动grpc server
	go func() {
		err := server.Serve(listener)
		if err != nil && err == grpc.ErrServerStopped {
			fmt.Printf("server stopped")
		} else if err != nil {
			panic(fmt.Errorf("start grpc server: %v", err))
		}
	}()

	return server
}

SetupSignal

signal.go:

package signal

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

var onlyOneSignalHandler = make(chan struct{})

func SetupSignal(fns ...func()) context.Context {
	// 当函数被调用两次,就会panic
	close(onlyOneSignalHandler)
	sigCh := make(chan os.Signal, 2)
   
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		<-sigCh
		for _, fn := range fns {
			fn()
		}
		cancel()
        // 第二次接收到信号,直接退出
		<-sigCh
		os.Exit(1)
	}()

	return ctx
}

main函数如下:

const WatchedNamespace = "cloud-ide"

func main() {
	var metricsAddr string
	var enableLeaderElection bool
	var probeAddr string
	flag.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:       "81275557.my.domain",
		// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
		// when the StatusInformer ends. This requires the binary to immediately end when the
		// StatusInformer is stopped, otherwise, this setting is unsafe. Setting this significantly
		// speeds up voluntary leader transitions as the new leader don't have to wait
		// LeaseDuration time first.
		//
		// In the default scaffold provided, the program ends immediately after
		// the manager stops, so would be fine to enable this option. However,
		// if you are doing or is intended to do any operation such as perform cleanups
		// after the manager stops then its usage might be unsafe.
		// LeaderElectionReleaseOnCancel: true,
		Namespace: WatchedNamespace,  // 指定要监视的Pod的namespace,我们的工作空间都创建在同一个命名空间下,只需监视这个命名空间下的Pod即可
	}) 
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		os.Exit(1)
	}
	
    // 创建statusInfomer
	manager := statussync.NewManager()
	if err = controllers.NewPodReconciler(mgr.GetClient(), mgr.GetScheme(), manager).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "Pod")
		os.Exit(1)
	}
	//+kubebuilder:scaffold:builder

	if 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)
	}

	// 启动grpc服务
	grpcServer := StartGrpcServer(mgr.GetClient(), &ctrl.Log, manager)
	// 安装信号处理
	ctx := signal.SetupSignal(func() {
		ctrl.Log.Info("receive signal, is going to shutdown")
		grpcServer.GracefulStop()
	})

	setupLog.Info("starting manager")

	if err := mgr.Start(ctx); err != nil {
		setupLog.Error(err, "problem running manager")
		os.Exit(1)
	}
}

 

2.2.5 目录结构

目录结构如下:

k8s编程operator实战之云编码平台——②controller初步实现

 

3、测试

接下来测试各个功能,由于我们的服务是通过grpc的方式提供的。可以使用ApiPost7来发送请求,ApiPost7支持grpc接口的调用,免费的。

官网:https://www.apipost.cn/

3.1 创建工作空间并且等待运行

启动我们的controller,可以使用make来启动:

make run
# 或者编译后再启动,编译后的文件为bin/manager
make build

使用ApiPost创建一个grpc,将service.proto导入

调用CreateSpaceAndWaitForRunning接口创建pod

k8s编程operator实战之云编码平台——②controller初步实现

controller的输出如下:

k8s编程operator实战之云编码平台——②controller初步实现

查看pod:

k8s编程operator实战之云编码平台——②controller初步实现

 

3.2 获取Pod状态

k8s编程operator实战之云编码平台——②controller初步实现

 

3.3 获取pod信息

k8s编程operator实战之云编码平台——②controller初步实现

 

3.4 删除pod

k8s编程operator实战之云编码平台——②controller初步实现

k8s编程operator实战之云编码平台——②controller初步实现

 

总结

至此,controller已经初步实现了功能,可以实现Pod的创建、删除、Pod状态获取、Pod信息获取

github地址:https://github.com/mangohow/cloud-ide-k8s-controller文章来源地址https://www.toymoban.com/news/detail-435175.html

到了这里,关于k8s编程operator实战之云编码平台——②controller初步实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • k8s operator从0到1实践

    推荐使用docker-desktop,本地单机集群 这里推荐使用脚手架工具kubebuilder 使用脚手架工具,能生成项目模板,开发人员只需要关注核心逻辑和方法即可 mac安装 生成的项目结构目录如下: 完整代码参考: webapp-operator 对象结构(api)、控制器(controller)修改完毕后,需要更新

    2024年02月01日
    浏览(43)
  • 【Kubernetes 企业项目实战】04、基于 K8s 构建 EFK+logstash+kafka 日志平台(中)

    目录 一、安装存储日志组件 Elasticsearch 1.1 创建名称空间 1.2 安装 elasticsearch 组件 1)创建 headless service 服务 2)通过 statefulset 创建 elasticsearch 集群 二、安装 kibana 可视化 UI 界面 本篇文章所用到的资料文件下载地址: kibana-v7.2.0-kubernetes文档类资源-CSDN下载 https://download.csdn.ne

    2023年04月08日
    浏览(40)
  • k8s Operator 部署 elasticsearch 7.10 + kibana + cerebro

    1.1 部署 ECK Elastic Cloud on Kubernetes,这是一款基于 Kubernetes Operator 模式的新型编排产品,用户可使用该产品在 Kubernetes 上配置、管理和运行 Elasticsearch 集群。ECK 的愿景是为 Kubernetes 上的 Elastic 产品和解决方案提供 SaaS 般的体验。 k8s 版本 部署 ECK 1)If you are running a version of Kub

    2024年02月08日
    浏览(45)
  • 【梳理】k8s使用Operator搭建Flink集群(高可用可选)

    参考:部署验证demo 安装cert-manager依赖 Jetstack/cert-manager 是 Kubernetes 生态系统中的一款开源项目,它提供了一种自动化的方式来管理 TLS 证书的生命周期 Flink Kubernetes Operator 支持:原生部署native(默认)和独立部署standalone 可以使用部署规范中的 mode 字段设置部署模式。 FlinkD

    2024年04月14日
    浏览(34)
  • 【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(中)

    目录 一、基于 Jenkins+k8s+Git+Docker Hub 等技术链构建企业级 DevOps 容器云平台 1.1 安装 Jenkins 1.1.1 安装 nfs 服务 1.1.2 在 kubernetes 中部署 jenkins 1.2 配置 Jenkins ​1.2.1 获取管理员密码 1.2.2 安装插件 1.2.3 创建第一个管理员用户 1.3 测试 jenkins 的 CI/CD 1.3.1 在 Jenkins 中安装 kubernetes 插件

    2024年01月16日
    浏览(78)
  • 使用k8s helm离线部署spark-operator(私有仓库)

    将制作的镜像上传到目的机器中,加载镜像 打标签其中xxxx.xxx/xx/为私有仓库的地址 将制作好的镜像推到私有仓库中 Github地址: 下载上传到机器中 解压spark-operator-1.1.27.tgz,修改values.yaml内容,修改副本数量为3、镜像源、利用伪亲和性使得三个副本在三台机器上。 修改Chart

    2024年02月09日
    浏览(40)
  • Kubernetes技术--k8s核心技术Controller控制器

    1.Controller概述    Controller是在集群上管理和运行容器的对象。是一个实际存在的对象。 2.pod和Controller之间的关系 pod通过controller实现应用的运维,包括伸缩、滚动升级等操作。 这里pod和controller通过label标签来建立关系。如下所示: 3.Deployment控制器应用场景 -1:部署无状态的应

    2024年02月10日
    浏览(45)
  • k8s---ingress对外服务(ingress-controller)

    k8s的对外服务,ingress service作用现在两个方面: 1、集群内部:不断跟踪的变化,更新endpoint中的pod对象,基于pod的ip地址不断变化的一种服务发现机制。 2、集群外部:类似于负载均衡器,把流量(ip+端口),不涉及转发url(http https),把请求转发到pod当中。 service: NodePo

    2024年01月19日
    浏览(48)
  • Prometheus Operator 极简配置方式在k8s一条龙安装Prometheus 监控

    在k8s上 Prometheus(普罗米修斯) 监控,需要部署各种组件,比如Prometheus、Alertmanager、Grafana。同时各个组件的配置文件也是需要到处各个配置,Prometheus配置监控服务时,你还要知道各个监控服务的地址,地址换了还需要更新, 实在是麻烦。而今天的主角 Prometheus Operator 使用自

    2024年02月02日
    浏览(45)
  • kubebuilder+code-generator开发k8s的controller

    本文记录用kubebuilder和code-generator开发k8s的crd控制器。 和k8s.io/code-generator类似,是一个码生成工具,用于为你的CRD生成kubernetes-style API实现。区别在于: Kubebuilder不会生成informers、listers、clientsets,而code-generator会。 Kubebuilder会生成Controller、Admission Webhooks,而code-generator不会。

    2024年01月17日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包