k8s搭建xxl-job测试环境

背景

搭建本地k8s环境和xxl-job测试环境,在k8s环境中跑通xxl-job调度器和执行器

搭建k8s

注:本次搭建仅针对mac

安装docker&k8s

下载docker,注意区分intel芯和apple芯(M芯),如下图

image.png

安装完成后,新版的docker都会自带k8s,直接在右上角设置->preferences中勾选启用即可,如下图
image.png

勾选后点击apply&restart,docker就会去下载所需的镜像,我们公司网络自带翻墙,所以下载速度还挺快,如果是墙内,可以自行拉取阿里云的镜像源,具体方法如下:

  1. 拉取git仓库
git clone https://github.com/AliyunContainerService/k8s-for-docker-desktop.git
  1. 匹配版本,先查看k8s的版本号,Docker Desktop→about,如下:


    image.png

    在远程k8s-for-docker-desktop仓库中找到对应的tag,如v1.14.8就对应1.14.8版本的k8s,同时本地切到对应版本的branch,如果没有找到对应的tag就使用默认master分支,执行脚本bash load_images.sh,等待所有的镜像下载完毕后就可以去docker开启k8s了

验证k8s

查看集群状态:


image.png

查看节点:


image.png

如果都显示正常,说明k8s已经安装成功(这里可以设置下alias kb=kubectl)

安装dashboard

k8s有一个dashboard界面工具,可以对k8s进行可视化管理,命令党可忽略
执行如下命令

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

该命令会创建dashboard的pod,以及对应的serviceaccount,如下:


image.png

至此dashboard就安装完毕了,继续执行命令启用dashboard

kubectl proxy
// Starting to serve on 127.0.0.1:8001

默认是监听8001端口,浏览器访问http://localhost:8001/可以查看k8s的接口列表,访问http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/,如下:

image.png

这里需要一个token,可以针对kubernetes-dashboard空间的admin-user来生成一个,执行命令

kubectl -n kubernetes-dashboard create token admin-user
//eyJhbGciOiJSUzI1NiIsImtpZCI6IjZmUi1BRTlZOXVhLWJUcGtrUlhVTUU1WUhLSVZDQml0dW9JQ29FdV9VcEUifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjU0NjU5NTk5LCJpYXQiOjE2NTQ2NTU5OTksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbi11c2VyIiwidWlkIjoiYzE2YjQ1ZjgtMzM4Ny00NzI4LTlhM2MtNTE0ZTNmODJhOWYwIn19LCJuYmYiOjE2NTQ2NTU5OTksInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWRhc2hib2FyZDphZG1pbi11c2VyIn0.pn9jPBN-A8LaRtJHyW4fqYt8d6955l86DonOfkWjZ6nhfeHSjqbeqjac-uWcctax-OPyRHo8ezctgNNtpN_lwnbI_ZRBH3holMhPy601cov2XkGVKjLfyS02t-WL3CalvlRJ375HUzWXvkPTKnNo_ZGhljtnojNN8Yvxiad3u_OftDSs19kYCQJqp-tIB35m1CWruu51BoD7p-rIr2DnCZb7DLOY4a6NGKE_I5Z3MA_-Y4rOWtLCnq1o-GnkQLNqNt3cxWnEPr2kMrviivro0JxdYFWa4tFlsc7TpnR7S-QZu4Do0yKn7l5K3U7PE3qlTbfB1zOp5cm9qO3bl2ORGQ

生成一个临时的token,至此就可以登陆到dashboard中了,界面如下:


image.png

搭建xxl-job

xxl-job依赖mysql,需要先安装mysql,再安装xxl-job,同时需要注意本机分别要与mysql-pod和xxl-job-pod进行通信,本次安装mysql使用端口映射方式,xxl-job使用nodeport方式

搭建mysql

因为mysql是有状态的pod,即存储的数据我们希望在pod销毁后还留存在节点中(即本机),所以需要构造持久卷,如下是持久卷和mysql对应的yaml
mysql-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

mysql-deployment.yaml

apiVersion: v1
# 这里构建了一个service,后续k8s内部通信可以通过服务名mysql来寻找到对应的pod
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      # 这里的镜像可以通过docker hub查看对应的mysql镜像tag,因为我的机器的os/arch是linux/arm64/v8,所以使用mysql:oracle,可自行根据实际选择
      # 可以通过docker pull拉取是否成功来验证镜像是否ok,如果拉取不成功,pod将无法创建
      - image: mysql:oracle
        name: mysql
        env:
          # 这里手动设置了mysql的密码是password,方便测试
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

执行命令

kubectl apply -f mysql-pv.yaml
kubectl apply -f mysql-deployment.yaml

查看svc、pvc、deployment和pod是否创建成功,如下:


image.png

也可以通过创建一个client的pod来连接到mysql服务,验证安装是否成功,执行命令

kubectl run -it --rm --image=mysql:oracle --restart=Never mysql-client -- mysql -h mysql -ppassword
// k8s内部pod之间通信可以通过服务名mysql代替host

如果安装成功,可以看到mysql>标识符(可能需要点击enter触发,具体看交互文案),如下:


image.png

至此mysql已经成功部署到k8s,现在通过端口映射来支持k8s外部本机操作mysql,方便curd,执行命令将mysql service的3306端口映射到本机的3306端口

kubectl port-forward service/mysql 3306:3306

本机连接,这里推荐一个工具tableplus,如下(密码是之前设置的password):

image.png

执行xxl-job-sql,git地址https://github.com/xuxueli/xxl-job/blob/2.3.1/doc/db/tables_xxl_job.sql,我们选择最新版本v2.3.1,待会部署同样版本的xxl-job,sql如下:

CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `xxl_job`;

SET NAMES utf8mb4;

CREATE TABLE `xxl_job_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_desc` varchar(255) NOT NULL,
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `author` varchar(64) DEFAULT NULL COMMENT '作者',
  `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
  `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
  `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
  `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
  `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
  `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
  `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
  `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
  `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
  `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
  `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
  `trigger_code` int(11) NOT NULL COMMENT '调度-结果',
  `trigger_msg` text COMMENT '调度-日志',
  `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
  `handle_code` int(11) NOT NULL COMMENT '执行-状态',
  `handle_msg` text COMMENT '执行-日志',
  `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
  PRIMARY KEY (`id`),
  KEY `I_trigger_time` (`trigger_time`),
  KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_log_report` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
  `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
  `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
  `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_logglue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_registry` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `registry_group` varchar(50) NOT NULL,
  `registry_key` varchar(255) NOT NULL,
  `registry_value` varchar(255) NOT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
  `title` varchar(12) NOT NULL COMMENT '执行器名称',
  `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
  `address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '账号',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
  `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_lock` (
  `lock_name` varchar(50) NOT NULL COMMENT '锁名称',
  PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');

commit;

执行完后,会构建xxl_job数据库和多张数据表,如下:


image.png

至此,mysql部署完成

搭建xxl-job

因为mysql执行的sql是对应2.3.1版本,所以我们部署2.3.1版本的xxl-job-admin
xxl-job-admin.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: xxl-job-admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: xxl-job-admin
  template:
    metadata:
      labels:
        app: xxl-job-admin
    spec:
      containers:
      - name: xxl-job-admin
        image: xuxueli/xxl-job-admin:2.3.1 # 使用2.3.1版本
        imagePullPolicy: Always     # 优先使用本地镜像
        ports:
        - containerPort: 8080
        env:
        - name: PARAMS   # 定义变量,用来设定mysql的用户/密码 mysql为k8s集群内的service名称,在k8s集群内部可以直接使用service名称,使用时mail替换成自己的邮箱和密码
          value: "--spring.datasource.url=jdbc:mysql://mysql:3306/xxl_job?Unicode=true&characterEncoding=UTF-8&useSSL=false --spring.datasource.username=root --spring.datasource.password=password [email protected] --spring.mail.password=your-pass"
---
apiVersion: v1
kind: Service
metadata:
  name: xxl-job-admin
  labels:
    app: xxl-job-admin
spec:
  ports:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30080 # nodeport映射到本机的30080端口
  selector:
    app: xxl-job-admin

执行命令

kubectl apply -f xxl-job-admin.yaml

查看对应的svc、deployment和pod,如下:

image.png

至此,xxl-job-admin部署完成,可通过浏览器访问http://localhost:30080/xxl-job-admin/toLogin进行登陆(用户名/密码 = admin/123456),如下:
image.png

构造执行器测试xxl-job

因为xxl-job-admin的pod可以与本机进行通信,所以可以使用xxl-job-executor-go本地构造一个执行器,完成注册执行器,创建任务,执行任务,回调日志等测试闭环,执行器代码如下:

package main

import (
   "fmt"
   "github.com/xxl-job/xxl-job-executor-go"
   "github.com/xxl-job/xxl-job-executor-go/example/task"
   "log"
)

func main() {
   exec := xxl.NewExecutor(
      xxl.ServerAddr("http://127.0.0.1:30080/xxl-job-admin"),
      xxl.AccessToken("default_token"), //请求令牌(使用默认的default_token)
      //xxl.ExecutorIp("127.0.0.1"),      //可自动获取
      //xxl.ExecutorPort("9999"),         //默认9999(非必填)
      xxl.RegistryKey("executor"), //执行器名称
      //xxl.SetLogger(&logger{}),         //自定义日志
   )
   exec.Init()
   //设置日志查看handler
   exec.LogHandler(func(req *xxl.LogReq) *xxl.LogRes {
      return &xxl.LogRes{Code: 200, Msg: "", Content: xxl.LogResContent{
         FromLineNum: req.FromLineNum,
         ToLineNum:   2,
         LogContent:  "这个是自定义日志handler",
         IsEnd:       true,
      }}
   })
   //注册任务handler
   exec.RegTask("task.test", task.Test)
   exec.RegTask("task.test2", task.Test2)
   exec.RegTask("task.panic", task.Panic)
   log.Fatal(exec.Run())
}

//xxl.Logger接口实现
type logger struct{}

func (l *logger) Info(format string, a ...interface{}) {
   fmt.Println(fmt.Sprintf("自定义日志 - "+format, a...))
}

func (l *logger) Error(format string, a ...interface{}) {
   log.Println(fmt.Sprintf("自定义日志 - "+format, a...))
}

构建执行器:


image.png

构造任务:


image.png

启动执行器,进行执行器注册,将本机ip注册到xxl-job-admin中:
image.png

image.png

启动任务,固定间隔3秒执行一次:


image.png

image.png

执行日志:
image.png

至此,基于k8s的xxl-job测试环境部署完成

你可能感兴趣的:(k8s搭建xxl-job测试环境)