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

Posted Vaedit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当游戏遇见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.gz

tar zxvf helm-v3.7.2-linux-amd64.tar.gz

mv linux-amd64/helm /usr/bin/

3.制作一个Chart

Helm核心是模板,即模板化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.总结

通过这种方式,覆盖了游戏版本更新,硬件配置升级,配置精准挂载等通用化操作,都只需要维护一个value,并且拓补清晰,降低了运维维护成本,同时又通用高效

以上是关于当游戏遇见K8S-滚服业务如何用Helm管理?的主要内容,如果未能解决你的问题,请参考以下文章

如何用 Helm 管理 Jenkins,看这篇就够了

使用 Helm — Kubernetes(50)

K8S实践Ⅹ(Helm)

26,k8s 之helm

K8S系列第十一讲:包管理神器-Helm

k8s原生微服务管理工具helm-v3的使用初探实践