当游戏遇见K8S-滚服业务如何用Helm管理?

愿君学长松,慎勿作桃李。这篇文章主要讲述当游戏遇见K8S-滚服业务如何用Helm管理?相关的知识,希望能为你提供帮助。
1.项目背景目前容器化业务多为全区全服业务,管理上多为一个集群一套环境,从头部署完成后,不需要考虑区服复用deployment/statefulset等,大多一对一的场景(一个deployment/statefulset,对应一个模块或用应用),配置文件也可以部署时,确定好后,后期变更较少。然而,滚服业务存在着大量复用deployment/statefulset/configmap/service/ingress等等控制器yaml模版,实现的方式也有多种,这里具体说下一个chart对应一个value管理多区服业务。
2.Helm 2.1 Helm介绍Helm是一个Kubernetes的包管理工具,就像Linux下的包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到kubernetes上。
Helm有3个重要概念:

  • helm:一个命令行客户端工具,主要用于Kubernetes应用chart的创建、打包、发布和管理。
  • Chart:应用描述,一系列用于描述 k8s 资源相关文件的集合。
  • Release:基于Chart的部署实体,一个 chart 被 Helm 运行后将会生成对应的一个 release;将在k8s中创建出真实运行的资源对象。
2.2 Helm安装使用helm很简单,你只需要下载一个二进制客户端包即可,会通过kubeconfig配置(通常$HOME/.kube/config)来连接Kubernetes。
wget https://get.helm.sh/helm-v3.7.2-linux-amd64.tar.gztar zxvf helm-v3.7.2-linux-amd64.tar.gzmv linux-amd64/helm /usr/bin/

3.制作一个ChartHelm核心是模板,即模板化K8s YAML文件。部署多个应用时,将需要改动的字段进行模板化,可动态传入。
下面我们开始制作第一个Chart模拟创建多个区服,镜像使用nginx代替。
首先是value变量的配置(这里只放最基础的也是最常用的变量,如果需要自定义变量最好是通过配置文件挂载卷的方式挂载)
# values.yaml # 测试用例 yqcr: #项目名 serverinfo: # 区服信息(这里只做游戏逻辑服最简单的示例,实际业务这一层还有其他全局模块等,可以灵活规划) 10001: # 区服id cpu: 1 mem: 1Gi images1: nginx tag1: 1.21.4 replicas: 2 10002: cpu: 2 mem: 2Gi images1: nginx tag1: 1.20.2 replicas: 1 10003: cpu: 2 mem: 2Gi 10004: cpu: 2 10005: images1: nginx tag1: 1.20.2 replicas: 1 # 默认配置信息(可以减少value行数,更加清晰,当使用默认配置时,只需要10001:即可) Gamedefault: cpu: 1 mem: 1Gi images1: nginx tag1: 1.20.2 replicas: 2

template实例:
# 默认值定义 $default_res := .Values.Gamedefault.replicas $default_cpu := .Values.Gamedefault.cpu $default_mem := .Values.Gamedefault.mem $default_images1 := .Values.Gamedefault.images1 $default_tag1 := .Values.Gamedefault.tag1 # 遍历区服map - range $key, $value := .Values.yqcr.serverinfo # 如果区服使用特殊配置 - if $value apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: chatservice-chat- $key name: chatservice-chat- $key namespace: jhxjy-tiyan spec: progressDeadlineSeconds: 600 # deploy升级的最大时间 # 进一步判断是否有这个key,如果有则使用 - if hasKey $value "replicas" replicas:$value.replicas # 没有这个key,则使用默认值 - else replicas:$default_res - end revisionHistoryLimit: 10 selector: matchLabels: k8s-app: chatservice-chat- $key strategy: rollingUpdate: maxSurge: 25%, maxUnavailable: 25% type: RollingUpdate template: metadata: labels: k8s-app: chatservice-chat- $key spec: containers: # 模拟某些程序启动时需要注入serverid或者类似的变量 - args: ["bash","-c","echo$key& & sleep 600000" ] env: - name: EXP_DATA_DOMAIN, value: xxx - if and (hasKey $value "images1") (hasKey $value "tag1") image:$value.images1 : $value.tag1 - else image:$default_images1 : $default_tag1 - end imagePullPolicy: Always name: chatservice-chat- $key ports: - containerPort: 80 protocol: TCP # 如果一个container有多个对外的端口可以通过计算来得出,只是示例用法,具体其实这一层的端口完全可以固定,在ingress那里需要通过serverid来动态计算 - containerPort:add 2 (mul $key 2) protocol: TCP resources: limits: - if hasKey $value "cpu" cpu:$value.cpu | quote - else cpu:$default_cpu | quote - end - if hasKey $value "mem" memory:$value.mem - else memory:$default_mem - end requests: - if hasKey $value "cpu" cpu:$value.cpu | quote - else cpu:$default_cpu | quote - end - if hasKey $value "mem" memory:$value.mem - else memory:$default_mem - end securityContext: privileged: false terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /data/config, name: config dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: terminationGracePeriodSeconds: 30 volumes: # 配置精准挂载(如:10001/game/gameserver) - hostPath: path: "/data/config/ $key /chatservice-chat", type: name: config --- apiVersion: v1 kind: Service metadata: name: chatservice-chat- $key namespace: jhxjy-tiyan spec: ports: - name: "80" port:$key protocol: TCP targetPort: 80 selector: k8s-app: chatservice-chat- $key sessionAffinity: None type: ClusterIP --- # 如果使用默认配置 - else apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: chatservice-chat- $key name: chatservice-chat- $key namespace: jhxjy-tiyan spec: progressDeadlineSeconds: 600 replicas:$default_res revisionHistoryLimit: 10 selector: matchLabels: k8s-app: chatservice-chat- $key strategy: rollingUpdate: maxSurge: 25%, maxUnavailable: 25% type: RollingUpdate template: metadata: labels: k8s-app: chatservice-chat- $key spec: containers: - args: ["bash","-c","echo$key& & sleep 600000" ] env: - name: EXP_DATA_DOMAIN, value: xxx image:$default_images1 : $default_tag1 imagePullPolicy: Always name: chatservice-chat- $key ports: - containerPort: 80 protocol: TCP resources: limits: cpu:$default_cpu | quote memory:$default_mem requests: cpu:$default_cpu | quote memory:$default_mem securityContext: privileged: false terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /data/config, name: config dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: terminationGracePeriodSeconds: 30 volumes: - hostPath: path: "/data/config/ $key /chatservice-chat", type: name: config --- apiVersion: v1 kind: Service metadata: name: chatservice-chat- $key namespace: jhxjy-tiyan spec: ports: - name: "80" port:$key protocol: TCP targetPort: 80 selector: k8s-app: chatservice-chat- $key sessionAffinity: None type: ClusterIP --- - end - end

3.1 Yaml调试渲染yaml 文件写好就该是同步和部署了,在部署前可以先用以下命令测试下,渲染不执行:
helm install releasename chart目录 --dry-run --debug #部署 helm install deploy20211214 test -n namespace #查看release helm ls -n namespace #卸载 helm uninstall deploy20211214-n namespace

4.总结【当游戏遇见K8S-滚服业务如何用Helm管理?】通过这种方式,覆盖了游戏版本更新,硬件配置升级,配置精准挂载等通用化操作,都只需要维护一个value,并且拓补清晰,降低了运维维护成本,同时又通用高效

    推荐阅读