开源项目one-api的k8s容器化部署(上)-- 制作镜像及部署准备

一、背景

最近需要对开源项目one-api进行k8s容器化部署,主要分以下几个步骤:

  • 制作docker镜像
  • 申请mysql和redis数据库
  • docker-compose部署方式
  • k8s部署方式

整个的篇幅比较长,将会分成上下两篇来阐述。

二、制作docker镜像

开源项目one-api已经提供了Dockerfile文件,按说制作一个私有镜像是非常简单的事情,可是却遇到了一个大坑。
主要是因为golang的版本问题。

官方Dockerfile所使用的是golang,并没有指定版本,也即golang:latest。
go version查看得到其版本为1.17。

这是我们要修改的第一点,指定golang的版本。

# 修改前
FROM golang AS builder2

# 修改后
FROM golang:1.19-alpine AS builder2

golang:1.19-alpine

在这里插入图片描述

第二、我们在构建go项目的时候,增加国内镜像代理,以加速构建。

ENV GOPROXY=https://goproxy.cn,direct

第三、整个Dockerfile先是构建前端页面,再是构建go项目。本文主要是针对go项目的构建进行了改动。
完整的Dockerfile,修改后的内容,详见下:

# 指定golang的版本
FROM golang:1.19-alpine AS builder2

# 增加go镜像代理
ENV GOPROXY=https://goproxy.cn,direct \
    GO111MODULE=on \
    CGO_ENABLED=1 \
    GOOS=linux

# 切换工作目录至/build
WORKDIR /build

ADD go.mod go.sum ./
RUN go mod download

# 安装C编译器
RUN apk add --no-cache build-base

COPY . .
COPY --from=builder /web/build ./web/build
RUN go build -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)' -extldflags '-static'" -o one-api

# 总结这一阶段,会在工作目录/build下生成一个可执行文件one-api

# 下面是把它单拎出去,使用轻量级容器alpine,运行该可执行文件。

FROM alpine

RUN apk update \
    && apk upgrade \
    && apk add --no-cache ca-certificates tzdata \
    && update-ca-certificates 2>/dev/null || true

# 把可执行文件/build/one-api拷贝至alpine系统的根目录/下
COPY --from=builder2 /build/one-api /

EXPOSE 5175

# 切换工作目录至/data
WORKDIR /data

# 运行根目录下的可执行文件one-api
ENTRYPOINT ["/one-api"]

golang版本导致build报错

  • /go/pkg/mod/github.com/jackc/pgx/v5@v5.5.4/pgtype/builtin_wrappers.go:9:2: package net/netip is not in GOROOT (/usr/local/go/src/net/netip)
    在Go 1.17及以后的版本中,net/netip包已经被移动到golang.org/x/net模块中。这个错误的解决办法就是升级go版本。

  • github.com/mattn/go-sqlite3 cgo: C compiler “gcc” not found: exec: “gcc”: executable file not found in $PATH
    安装CGO所需的C编译器和库,在RUN go mod download后面,在RUN go build的前面,增加命令:RUN apk add --no-cache build-base。(因为golang:1.19-alpine使用musl libc,而不是glibc,并且默认不包含gcc)

  • Step 20/29 : RUN go mod download
    —> Running in f29cd7f8f144
    go mod download: zip: not a valid zip file
    这是因为网络慢导致的错误,解决版本是使用go镜像代理。

  • github.com/jackc/puddle/v2
    /go/pkg/mod/github.com/jackc/puddle/v2@v2.2.1/pool.go:142:30: undefined: atomic.Int64
    note: module requires Go 1.19
    github.com/mattn/go-sqlite3
    cgo: C compiler “gcc” not found: exec: “gcc”: executable file not found in $PATH
    这个错误是当时使用了golang:1.19镜像,后修改为golang:1.19-alpine解决。

其他调试命令

如果你根据报错信息去修改的话,可能会需要打印一些环境信息。

  • RUN go env
  • RUN go version
  • RUN echo $PATH

在构建docker镜像的过程中,还遇到许多报错,这里就不一一列举,报错的原因也都是因为golang的版本,期间使用过1.16/1.18/1.19,最后是使用1.19-alpine解决。

而one-api项目的go.mod文件指定使用1.18。

所以说,关于golang的版本问题很乱,我也是一通乱试。

在这里插入图片描述

三、关系型数据库DDL

在开发环境,我们只需新建数据库one_api即可。
但是,在生产环境,我们建议你手动建库建表.

CREATE DATABASE `one_api` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */;


CREATE TABLE `one_api`.`abilities` (
  `group` varchar(32) COLLATE utf8mb4_bin NOT NULL,
  `model` varchar(191) COLLATE utf8mb4_bin NOT NULL,
  `channel_id` bigint(20) NOT NULL,
  `enabled` tinyint(1) DEFAULT NULL,
  `priority` bigint(20) DEFAULT '0',
  PRIMARY KEY (`group`,`model`,`channel_id`),
  KEY `idx_abilities_priority` (`priority`),
  KEY `idx_abilities_channel_id` (`channel_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`channels` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `type` bigint(20) DEFAULT '0',
  `key` text COLLATE utf8mb4_bin,
  `status` bigint(20) DEFAULT '1',
  `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `weight` bigint(20) unsigned DEFAULT '0',
  `created_time` bigint(20) DEFAULT NULL,
  `test_time` bigint(20) DEFAULT NULL,
  `response_time` bigint(20) DEFAULT NULL,
  `base_url` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  `other` longtext COLLATE utf8mb4_bin,
  `balance` double DEFAULT NULL,
  `balance_updated_time` bigint(20) DEFAULT NULL,
  `models` longtext COLLATE utf8mb4_bin,
  `group` varchar(32) COLLATE utf8mb4_bin DEFAULT 'default',
  `used_quota` bigint(20) DEFAULT '0',
  `model_mapping` varchar(1024) COLLATE utf8mb4_bin DEFAULT '',
  `priority` bigint(20) DEFAULT '0',
  `config` longtext COLLATE utf8mb4_bin,
  PRIMARY KEY (`id`),
  KEY `idx_channels_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`logs` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `created_at` bigint(20) DEFAULT NULL,
  `type` bigint(20) DEFAULT NULL,
  `content` longtext COLLATE utf8mb4_bin,
  `username` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  `token_name` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  `model_name` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  `quota` bigint(20) DEFAULT '0',
  `prompt_tokens` bigint(20) DEFAULT '0',
  `completion_tokens` bigint(20) DEFAULT '0',
  `channel_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_username_model_name` (`model_name`,`username`),
  KEY `idx_logs_token_name` (`token_name`),
  KEY `idx_logs_model_name` (`model_name`),
  KEY `idx_logs_channel_id` (`channel_id`),
  KEY `idx_logs_user_id` (`user_id`),
  KEY `idx_created_at_type` (`created_at`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`options` (
  `key` varchar(191) COLLATE utf8mb4_bin NOT NULL,
  `value` longtext COLLATE utf8mb4_bin,
  PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`redemptions` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `key` char(32) COLLATE utf8mb4_bin DEFAULT NULL,
  `status` bigint(20) DEFAULT '1',
  `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `quota` bigint(20) DEFAULT '100',
  `created_time` bigint(20) DEFAULT NULL,
  `redeemed_time` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_redemptions_key` (`key`),
  KEY `idx_redemptions_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`tokens` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `key` char(48) COLLATE utf8mb4_bin DEFAULT NULL,
  `status` bigint(20) DEFAULT '1',
  `name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `created_time` bigint(20) DEFAULT NULL,
  `accessed_time` bigint(20) DEFAULT NULL,
  `expired_time` bigint(20) DEFAULT '-1',
  `remain_quota` bigint(20) DEFAULT '0',
  `unlimited_quota` tinyint(1) DEFAULT '0',
  `used_quota` bigint(20) DEFAULT '0',
  `models` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  `subnet` varchar(191) COLLATE utf8mb4_bin DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_tokens_key` (`key`),
  KEY `idx_tokens_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `one_api`.`users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `password` longtext COLLATE utf8mb4_bin NOT NULL,
  `display_name` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `role` bigint(20) DEFAULT '1',
  `status` bigint(20) DEFAULT '1',
  `email` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `github_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `wechat_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `lark_id` varchar(191) COLLATE utf8mb4_bin DEFAULT NULL,
  `access_token` char(32) COLLATE utf8mb4_bin DEFAULT NULL,
  `quota` bigint(20) DEFAULT '0',
  `used_quota` bigint(20) DEFAULT '0',
  `request_count` bigint(20) DEFAULT '0',
  `group` varchar(32) COLLATE utf8mb4_bin DEFAULT 'default',
  `aff_code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
  `inviter_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  UNIQUE KEY `idx_users_aff_code` (`aff_code`),
  UNIQUE KEY `idx_users_access_token` (`access_token`),
  KEY `idx_users_lark_id` (`lark_id`),
  KEY `idx_users_email` (`email`),
  KEY `idx_users_git_hub_id` (`github_id`),
  KEY `idx_users_we_chat_id` (`wechat_id`),
  KEY `idx_users_inviter_id` (`inviter_id`),
  KEY `idx_users_username` (`username`),
  KEY `idx_users_display_name` (`display_name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

最后,登录用户初始化一个root用户:

  • dml语句:
INSERT INTO `one_api`.`users`
(id, username, password, display_name, `role`, status, email, github_id, wechat_id, lark_id, access_token, quota, used_quota, request_count, `group`, aff_code, inviter_id)
VALUES(1, 'root', '$2a$10$HAJRqAF884IGFJYvaAR.eu82GA8vNhQR.iQ0.jEYfovZNioyD91Te', 'Root User', 100, 1, '', '', '', '', '47d954235a724c399bfc3ea400eb3b2c', 500000000000000, 0, 0, 'default', '', 0);

四、redis数据库连接

非关系型数据库,不涉及ddl和dml了,仅给出连接地址的示例(区分有无密码)

  • 无密码
    redis://:192.168.80.116:6379

  • 有密码
    redis://:{password}:192.168.80.116:6379

五、docker-compose部署

测试并验证上面制作好的docker镜像,下文将把它部署到k8s容器里。

version: '3.4'

services:
  one-api:
    image: "xxx/one-api:1.0.0"
    container_name: one-api
    restart: always
    command: --port 5175
    ports:
      - "5175:5175"
    environment:
      - SQL_DSN=root:123456@tcp(192.168.80.116:3306)/one_api  # 修改此行,或注释掉以使用 SQLite 作为数据库
      - REDIS_CONN_STRING=redis://:192.168.80.116:6379
      - SESSION_SECRET=random_string  # 修改为随机字符串
      - TZ=Asia/Shanghai

在这里插入图片描述

[root@emc7 one-api]# docker-compose ps
 Name                Command               State           Ports         
-------------------------------------------------------------------------
one-api         /one-api --port 5175        Up      0.0.0.0:5175->5175/tcp

六、推送镜像

验证docker镜像后,推送至远程仓库,为下文k8s部署做准备。

[root@emc7 one-api]# docker images | grep one
xxx/one-api                                                       1.0.0               c290c605bd1b        6 hours ago         72.1MB
xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web   1.0.0               c290c605bd1b        6 hours ago         72.1MB

[root@emc7 one-api]# docker tag c290c605bd1b xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web:1.0.0

[root@emc7 one-api]# docker login --username={用户名} xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com --password {密码}

[root@emc7 one-api]# docker push xxx-harbor-registry.cn-hangzhou.cr.aliyuncs.com/xxx/one-api-web:1.0.0

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue2 —— 学习(六)

一、Vue 脚手架 (一)介绍 Vue 脚手架是 Vue 官方提供的标准化开发工具 (开发平台) 脚手架版本最新版本 是 4.x 文档可以查看 http://cli.vuejs.org/zh/ 就是vue 官网文档中 的 vue.cli command line interface (…

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写

2022年11月30日,可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5,将人工智能的发展推向了一个新的高度。2023年4月,更强版本的ChatGPT4.0上线,文本、语音、图像等多模态交互方式使其在…

开源!工厂数字化项目会用到的地理信息系统

软件介绍 QGIS(Quantum GIS)是一款免费、开源、跨平台的地理信息系统(GIS)软件,适用于Unix平台、Windows和MacOS。提供了强大且用户友好的功能,使其成为地理信息处理领域的热门选择。 功能特点 1.空间数据管…

DRF多表关联的序列化和反序列化

DRF多表关联的序列化和反序列化 目录 DRF多表关联的序列化和反序列化序列化定制字段source一对多的序列化 多表关联的序列化方式1:在表模型中定义方法方式2:定制返回格式SerializerMethodField方式3:子序列化 多表关联的反序列化反序列化保存…

Java---搭建junit4.x单元测试环境,并进行测试

搭建junit4.x单元测试环境 1.选择Project Structure 2.选择Modules,选择要加入测试环境的模块,选择Dependencies,可以看到当前模块都有哪些依赖。 3.点击 后选择第一个 4.找到你安装IDEA的文件夹,进入到IntelliJ IDEA 2018.3.4\lib目录下…

桥接模式:解耦抽象与实现的设计艺术

在软件设计中,桥接模式是一种结构型设计模式,旨在将抽象部分与其实现部分分离,使它们可以独立地变化。这种模式通过提供更加灵活的代码结构帮助软件开发人员处理不断变化的需求,特别是在涉及多平台应用开发时。本文将详细介绍桥接…

规则引擎之LiteFlow应用

官网地址&#xff1a;LiteFlow DEMO 整体结构 1.引入maven依赖 <dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.4.2</version> </dependency> 2. 配置yml …

Visual Studio code无法正常执行Executing task: pnpm run docs:dev

最近尝试调试一个开源的项目&#xff0c;发现cmd可以正常启动&#xff0c;但是在vs中会报错&#xff0c;报错内容如下 Executing task: pnpm run docs:dev pnpm : 无法加载文件 E:\XXXX\pnpm.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 http…

jmeter实验 模拟:从CSV数据到加密请求到解密返回数据再到跨越线程组访问解密后的数据

注意,本实验所说的加密只是模拟加密解密,您需要届时写自己的加解密算法或者引用含有加密算法的相关jar包才行. 思路: 线程组1: 1.从CSV文件读取原始数据 2.将读取到的数据用BeanShell预习处理器进行加密 3.HTTP提取器使用加密后的数据发起请求 4.使用BeanShell后置处理器…

外贸公司应该怎么选择企业邮箱?哪个企业邮箱最好?

外贸公司业务的特殊性需要他们频繁进行跨国的沟通交流&#xff0c;那么外贸公司应该如何选择适合的企业邮箱呢&#xff1f;首先&#xff0c;传输邮件的稳定安全是前提&#xff0c;另外由于沟通多是国外客户&#xff0c;邮件的翻译也成为外贸公司企业邮箱的刚需。小编今天就详细…

怎么用Vivado做覆盖率分析

关注公众号FPGA开源工坊获取更多内容。 在做仿真的时候往往会去做代码覆盖率和功能覆盖率的分析&#xff0c;来保证仿真是做的比较充分完备的。 在Vivado里面也支持我们做这项操作&#xff0c;现在就来看一下流程吧。 第一步&#xff1a;选择设置 第二步&#xff1a;在仿真选…

每日一题---OJ题: 环形链表 II

片头 嗨! 小伙伴们,大家好! 我们又见面啦,在上一篇中,我们学习了环形链表I, 今天我们继续来打boss,准备好了吗? Ready Go ! ! ! emmm,同样都是环形链表,有什么不一样的地方呢? 肯定有, 要不然也不会一个标记为"简单" ,一个标记为"中等"了,哈哈哈哈哈 …

《AI创业浪潮:展望未来,解锁颠覆性创新机遇》

在科技革命的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;犹如一艘引领航向的旗舰&#xff0c;以其强大的变革力量重塑各行各业。随着技术的日益成熟与应用场景的不断拓宽&#xff0c;AI技术为创业者铺就了一条充满机遇与挑战的道路。本文将深入探讨未来AI技术领域的…

1.3 字符设备驱动

1、字符设备驱动工作原理 2、file_operations结构体 struct file_operations { struct module *owner; //拥有该结构的模块的指针&#xff0c;一般为THIS_MODULES loff_t (*llseek) (struct file *, lof…

10 Php学习:循环

在 PHP 中&#xff0c;提供了下列循环语句&#xff1a; while - 只要指定的条件成立&#xff0c;则循环执行代码块do…while - 首先执行一次代码块&#xff0c;然后在指定的条件成立时重复这个循环for - 循环执行代码块指定的次数foreach - 根据数组中每个元素来循环代码块 当…

(学习日记)2024.04.15:UCOSIII第四十三节:任务消息队列

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

橱窗带货真的能赚到钱吗?橱窗带货素材哪里找?什么是橱窗带货?

什么是橱窗带货&#xff1f; 橱窗带货&#xff0c;一种以货架电商为基础的营销手段&#xff0c;可类比线下实体店的展示柜和窗口。橱窗的曝光量较高&#xff0c;因此通常展示店铺中的重点产品和推荐系列商品。短视频已经积极进军电商领域&#xff0c;虽然一开始主打直播电商&a…

newman下载安装

postman是专为接口测试而生&#xff0c;Newman是专为postman而生。newman可以让我们的postman的脚本通过非GUI(命令行)的方式。 1. 安装node.js 安装步骤 查看已安装版本 node -v 2. 安装 Newman 运行命令:npm install -g newman&#xff0c;即可完成安装操作。 或者 npm i…

(Oracle)SQL优化案例:隐式转换优化

项目场景 项目现场的某个kettle模型执行非常缓慢&#xff0c;原因在于某个SQL执行效率非常的低。甲方得知此事要求公司赶紧优化&#xff0c;负责该模块的同事对SQL优化并不熟悉。所以作为一个立志成为优秀DBA的ETL工程师&#xff0c;我自告奋勇&#xff1a;不是DBA&#xff0c;…

两步解决 Flutter Your project requires a newer version of the Kotlin Gradle plugin

在开发Flutter项目的时候,遇到这个问题Flutter Your project requires a newer version of the Kotlin Gradle plugin 解决方案分两步: 1、在android/build.gradle里配置最新版本的kotlin 根据提示的kotlin官方网站搜到了Kotlin的最新版本是1.9.23,如下图所示: 同时在Ko…