实践说明

目前手头有一个redis主从项目部署在kubernetes里,如果我要把这个项目分发给他人,常规做法就是把相关配置文件和说明文档交付,这就带来了一定的麻烦,有没有更好的办法,直接让他人通过一条命令就可以启动项目,而不需要做太多其它的附加操作,有的,那就是目前流行的包管理工具 - Helm,下面我就来实践如何将线上运行的项目改造下。

改造的项目对象可以参考这篇文档:
《Kubernetes 部署Redis主从服务(StatefulSet)》
https://blog.51cto.com/4073279/2676397

实践步骤

  1. 创建一个模板文件包
    $ helm create redis-ms
    $ cd redis-ms 
    $ rmdir charts
    #删除这些文件
    $ rm -f deployment.yaml hpa.yaml ingress.yaml serviceaccount.yaml NOTES.txt 
    $rm -rf tests
    #最后的项目结构
    $ tree -L 2
    .
    ├── Chart.yaml
    ├── templates
    │   ├── _helpers.tpl
    │   ├── NOTES.txt
    │   ├── service.yaml
    │   └── tests
    └── values.yaml
  2. 分析
    1) 先分析下那些字段可以复用、易变动,则将其以变量值的方式放到values.yaml
    • APP名称
    • 标签名
    • 镜像名称
    • 副本数
    • POD资源限制
    • HPA

2) 如果是大块内容,比如用到的脚本则以模板值的方式放到_helpers.tpl文件中

比如: Configmap的内容

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.appName }}-config
data:
  launch.sh: |
    #!/bin/bash

    PASSWORD=$(cat /etc/redis-passwd/passwd)

    if [ "${HOSTNAME}" == "redis-0" ]
    then
      redis-server --requirepass ${PASSWORD}
    else
      redis-server --slaveof redis-0.redis 6379 --masterauth ${PASSWORD} --requirepass ${PASSWORD}
    fi
....
  1. 改造操作
    1) values.yaml 文件内容填充
#APP名称
appName: redis
#标签
labels: redis
#副本数
replicaCount: 2
#镜像资源配置
image:
  repository:  redis
  pullPolicy: IfNotPresent
  tag: "5-alpine"
imagePullSecrets: []
#Service资源配置
service:
  type: None
  port: 6379

#POD资源限制
resources: 
  enabled: false 
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi
#redis密码
redis:
  passwd: password

2) 改造service

$ cat templates/service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.appName }}
  labels:
    app: {{ .Values.labels }}
spec:
  ports:
  - port: {{ .Values.service.port }}
    name: redis
  #StatefulSet资源Service默认是没有集群IP的
  clusterIP: None
  selector:
    app: {{ .Values.labels }}

3) 改造configmap

$ cat redis-ms/templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.appName }}-config
data:
  {{- include "launch" . |indent 2}}

4) 改造secret,密码写到 values.yaml

$ cat redis-ms/templates/secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: redis-passwd
stringData:
  passwd: {{ .Values.redis.passwd }}

5) 改造statefulset

$ cat redis-ms/templates/statefulset.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ .Values.appName }}
spec:
  serviceName: {{ .Values.appName }}
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.labels }}
  template:
    metadata:
      labels:
        app: {{ .Values.labels }}
    spec:
      containers:
      - name: {{ .Values.appName }}
        image:{{ .Values.image.repository }}:{{ .Values.image.tag }}
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: data
          mountPath: /data
        - name: script
          mountPath: /script/launch.sh
          subPath: launch.sh
        - name: passwd-volume
          mountPath: /etc/redis-passwd
        command:
        - sh
        - -c
        - sleep 10 && sh /script/launch.sh
      {{- if .Values.resources.enabled }}
        resources:
          limits: 
            cpu: {{ .Values.resources.limits.cpu }}
            memory: {{ .Values.resources.limits.memory }}
          requests:
            cpu:  {{ .Values.resources.requests.cpu }}
            memory: {{ .Values.resources.requests.memory }}
      {{ end }}
      volumes:
      - name: script
        configMap:
          name: redis-config
          defaultMode: 0777
      - name: passwd-volume
        secret:
          secretName: redis-passwd
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

6) 验证和打包

#语法验证,主要是渲染输出,检查是否有异常问题
$ helm install redis-ms -n  developer --dry-run redis-ms/ 
#部署
$ helm install redis-ms -n  developer  redis-ms/ 
#将项目打包,然后就可以将redis-ms-0.1.0.tgz发给他人
$ helm package redis-ms
Successfully packaged chart and saved it to: /root/redis-slave-statefulset/redis-ms-0.1.0.tgz
#通过一条命令启动项目,看,是不是很方便
$ helm install redis-ms redis-ms-0.1.0.tgz -n developer
NAME: redis-ms
LAST DEPLOYED: Wed Mar 31 10:16:02 2021
NAMESPACE: developer
STATUS: deployed
REVISION: 1
TEST SUITE: None
$ helm list -n developer
NAME        NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
redis-ms    developer   1           2021-03-31 10:16:02.690429125 +0800 CST deployed    redis-ms-0.1.0  1.16.0
$ kubectl logs -f redis-0 -n developer
9:C 31 Mar 2021 02:16:23.867 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
9:C 31 Mar 2021 02:16:23.867 # Redis version=5.0.10, bits=64, commit=00000000, modified=0, pid=9, just started
9:C 31 Mar 2021 02:16:23.867 # Configuration loaded
9:M 31 Mar 2021 02:16:23.868 * Running mode=standalone, port=6379.
9:M 31 Mar 2021 02:16:23.868 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9:M 31 Mar 2021 02:16:23.868 # Server initialized
9:M 31 Mar 2021 02:16:23.868 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
9:M 31 Mar 2021 02:16:23.869 * DB loaded from disk: 0.001 seconds
9:M 31 Mar 2021 02:16:23.869 * Ready to accept connections
9:M 31 Mar 2021 02:16:25.881 * Replica 10.244.1.126:6379 asks for synchronization
9:M 31 Mar 2021 02:16:25.881 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '75640cf19c78b679a8e581b84c2b05855d17c931', my replication IDs are '6ad76548f491d5547947835322c98520c843c0c0' and '0000000000000000000000000000000000000000')
9:M 31 Mar 2021 02:16:25.881 * Starting BGSAVE for SYNC with target: disk
9:M 31 Mar 2021 02:16:25.881 * Background saving started by pid 13
13:C 31 Mar 2021 02:16:25.883 * DB saved on disk
13:C 31 Mar 2021 02:16:25.883 * RDB: 0 MB of memory used by copy-on-write
9:M 31 Mar 2021 02:16:25.979 * Background saving terminated with success
9:M 31 Mar 2021 02:16:25.980 * Synchronization with replica 10.244.1.126:6379 succeeded

实践总结

通过将项目部署方式改造成Helm安装方式的这一过程,也是我对Helm的一次复习,Helm其实很简单,主要核心就是要思考分析下将当前项目那些共同的、易变化的、稳定不变的抽取出来,然后配合Helm提供的一些功能特性,比如模板、循环、判断等等进行编写、填充、完善。

附完整的Chart包: 链接:https://share.weiyun.com/X8JzQY5l 密码:uik42u