目录
场景
游戏项目中的逻辑服务器需要部署在 k8s 中,由于逻辑服按照微服务体系划分(例如:login、gate、gm、account、chat 等),需要多个 k8s yaml 执行 kubectl apply -f *.yaml 完成批量部署。笔者在手写了 login-kube.yaml 、 gate-kube.yaml 后发现了如下痛点:
- 每个种类资源的 k8s yaml 大同小异,拥有同样的结构
- 一个yaml 文件内,也有大量的重复变量(例如,login-kube.yaml 里,光是 “login” 这个字符串出现了十几次,包括但不限于 image、label、configmap 名等)
- 微服务太多,且port、label、hpa、image 改动频繁(image tag尤其频繁);假设需要批量将容器版本指定为 2022_01_12_1 ,则每个 yaml 都需要至少改动一处,人为操作太多,且不可控(人总会失误)。
- 懒。复制粘贴文件本身并不复杂、也不耗时。困难就困难在,每个 yaml 文件需要经过验证才能提交,复制粘贴修改的文件,不经过测试,很容易出现漏改或者设置错的情况;而每次新增、修改微服务,都需要做一次全量测试,整个维护 *.yaml 的工作量巨大
既然有这些痛点,那我们就着手做一个批量生成工具,只需要维护很少的变量,就能够批量生成所有微服务的 *.yaml 文件,从而批量部署。
注:根据场景不同,第一次使用工具时需要手动更改 template 目录下的模板文件。如果场景不同,则可能需要改动 Go 相关的代码,才能正常使用
使用步骤
检查模板
检查模板是否需要更新,可以修改模板的结构和通用参数

检查配置
检查配置是否需要更新,可以增加修改删除服务配置,支持设置多个服务间的 共用值(例如,所有服务的镜像前缀相同,镜像tag相同)。单个服务的 特殊值 设置,会覆盖共用值。

生成 yaml
在项目根目录下执行
go run main.go # 也可以提前 go build 生成可执行文件
默认在 output/ (可配置) 目录下生成 k8s yaml 文件

自定义开发
书写模板文件
我们想要自动生成配置文件,第一步首先是书写模板文件,再通过模板文件自动替换变量达到我们的目的。
以 Deployment 模板为例
apiVersion: apps/v1
kind: Deployment
metadata:
name: $(name)
namespace: $(namespace)
labels:
app: $(name)
spec:
replicas: $(replicas)
revisionHistoryLimit: 5
selector:
matchLabels:
app: $(name)
template:
metadata:
labels:
app: $(name)
type: service # 项目的日志分析ELK使用到了这个,用于分类
spec:
containers:
- name: $(name)
image: $(imageprefix)$(name):$(imagetag)
lifecycle:
preStop:
exec:
command: [ "sh","-c","sleep 5" ]
ports: $(ports)
resources: $(resources)
volumeMounts:
- name: timezone
mountPath: /etc/localtime
- name: $(name)-cm-v
mountPath: /app/etc
volumes:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: $(name)-cm-v
configMap:
name: $(name)-cm
单一填值
我选用了 $(PARAM_NAME) 来给变量提供占位符。
其中, image: $(imageprefix)$(name):$(imagetag) 配置,意味着我们的工具需要支持多变量的拼接和自由组合,即:
# 读取模板前设置好这些值
# imageprefix: nbserver/
# name: gate
# imagetag: 2022_01_12
# 输出
spec:
containers:
- image: nbserver/gate:2022_01_12
复杂结构展开
resources: $(resources) 配置,意味着我们的工具需要支持 yaml 的动态展开和格式校验,而这一点是难点,展开后参考如下:
# 读取模板前设置好这些值
# resources:
# limits:
# cpu: 100m
# memory: 100Mi
# requests:
# cpu: 50m
# memory: 20Mi
# 输出
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 50m
memory: 20Mi
深度解析
以 Service 为例
apiVersion: v1
kind: Service
metadata:
name: $(name)-svc
namespace: $(namespace)
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
ports:
- name: tcp-long-connection-port
port: $(ports.network.port)
targetPort: $(ports.network.targetport)
protocol: TCP
selector:
app: $(name)
port: $(ports.network.port) 配置,意味着我们的工具需要支持深度不止为1的解析,需要把数组、字典、结构体的层级参数全部读取,并解析,参考如下:
# 读取模板前设置好这些值
# ports:
# - port: 6000
# type: normal
# - port: 6001
# type: network # 动态解析 type 类型,并提取成索引

最低0.47元/天 解锁文章
2443

被折叠的 条评论
为什么被折叠?



