k8s结合helm部署
一、安装Helm
helm教程以及安装可以参考这篇文章
二、Heml说明
常见的helm模板如下
myapp - chart 包目录名 ├── charts - 依赖的子包目录,里面可以包含多个依赖的chart包 ├── Chart.yaml - chart定义,可以定义chart的名字,版本号信息。 ├── templates - k8s配置模版目录, 我们编写的k8s配置都在这个目录, 除了NOTES.txt和下划线开头命名的文件,其他文件可以随意命名。 │ ├── deployment.yaml │ ├── _helpers.tpl - 下划线开头的文件,helm视为公共库定义文件,主要用于定义通用的子模版、函数等,helm不会将这些公共库文件的渲染结果提交给k8s处理。 │ ├── ingress.yaml │ ├── NOTES.txt - chart包的帮助信息文件,执行helm install命令安装成功后会输出这个文件的内容。 │ └── service.yaml └── values.yaml - chart包的参数配置文件,模版可以引用这里参数。
其中 values.yaml 就是存放你变量的地方,这些变量可以应用在其他的 .yaml 文件中进行引用,类似于环境变量,引用方式:
{{ .Values.xxxxx }}
values.yaml文件如下:
# Default values for helm. # This is a YAML-formatted file. # Declare variables to be passed into your templates. name: Aeisen
三、数据卷Volume、数据卷声明VolumeClaim
k8s应用(包括有状态跟无状态应用),需要使用数据卷的话,需要在存储卷中进行设置和声明,下面列出持久化数据卷的声明跟设置的模板:
数据卷设置:
apiVersion: v1 kind: PersistentVolume -这里说明是持久化数据卷 metadata: finalizers: - kubernetes.io/pv-protection labels: alicloud-pvname: {{ .Values.volumes.name }} -数据卷标签,eg:XXX-data name: {{ .Values.volumes.name }} -数据卷名称,eg:XXX-data spec: accessModes: - ReadWriteMany -权限 capacity: storage: {{ .Values.volumes.storage }} -容量大小,eg:10Gi flexVolume: driver: alicloud/nas -数据卷类型是nas options: path: {{ .Values.volumes.path }} -数据卷路径,eg:/tmp server: {{ .Values.volumes.server }} -数据卷服务商,eg:xxxxx.nas.aliyuncs.com vers: '3' persistentVolumeReclaimPolicy: Retain storageClassName: nas
数据卷声明:
apiVersion: v1 kind: PersistentVolumeClaim -持久化数据卷声明 metadata: annotations: pv.kubernetes.io/bind-completed: 'yes' pv.kubernetes.io/bound-by-controller: 'yes' finalizers: - kubernetes.io/pvc-protection name: {{ .Values.volumes.name }} spec: accessModes: - ReadWriteMany resources: requests: storage: {{ .Values.volumes.storage }} -容量,eg:10Gi selector: matchLabels: alicloud-pvname: {{ .Values.volumes.name }} storageClassName: nas volumeName: {{ .Values.volumes.name }}
四、伸缩配置 HorizontalPodAutoscaler
应用弹性伸缩配置,这个可以配置最大、最小副本集跟伸缩条件的参数到values.yaml文件里面
kind: HorizontalPodAutoscaler apiVersion: autoscaling/v1 metadata: name: {{ include "admin.appname" . }}-hpa -admin.appname就是后面执行helm命令的时候倒数第二个参数,为什么前面是admin呢,admin就是你配置Chart.yaml的时候里面的name变量的值 spec: scaleTargetRef: kind: Deployment name: {{ include "admin.appname" . }} apiVersion: apps/v1beta2 minReplicas: 1 -最小副本集 maxReplicas: 10 -最大副本集 targetCPUUtilizationPercentage: 70 -伸缩条件
五、配置项ConfigMap
配置项设置,一般每个项目有都对应的环境参数,比如:数据库、redis等这些账号密码类的参数,这些可以抽离出来当成一个配置项处理
apiVersion: v1 kind: ConfigMap metadata: name: {{ .Values.envConfigName }} -每个环境就配置一个配置项 data: {{- range $k, $v := .Values.configDatas }} -这里是循环遍历configDatas这个变量 {{ $k | indent 2 }}.php: >- -下面这两行配置一个key->value的配置项(即文件名->文件内容) {{ $v | indent 4 }} {{- end -}}
六、镜像密码配置Secret
将镜像的密码配置到保密字典中
apiVersion: v1 kind: Secret metadata: name: image-secret -name随意写 data: .dockerconfigjson: {{ .Files.Get "image.pwd" | b64enc }} -内容 type: kubernetes.io/dockerconfigjson
TLs证书配置(后面配置ingress的时候要用到,不然无法用https)
apiVersion: v1 kind: Secret metadata: name: tls-secret data: tls.crt: {{ .Files.Get "XXXXX.com.pem" | b64enc }} tls.key: {{ .Files.Get "XXXXX.com.key" | b64enc }} type: Opaque
七、无状态应用Deployment
apiVersion: apps/v1beta2 kind: Deployment -无状态应用 metadata: name: {{ include "admin.appname" . }}-api-app -应用名称 labels: app: {{ include "admin.appname" . }}-api-app -应用标签 spec: replicas: {{ .Values.apiAppReplicaCount }} -副本集数,就是要开多少个应用 selector: matchLabels: app: {{ include "admin.appname" . }}-api-app -映射 template: metadata: labels: app: {{ include "admin.appname" . }}-api-app -映射标签 release: {{ .Release.Revision | quote }} -版本号 spec: volumes: - configMap: defaultMode: 420 name: {{ .Values.configItemName }} -配置项名称,这个是在上面配置项配置的时候的名称 name: volume-{{ include "admin.appname" . }}-api-app -配置项名称,这个是引入之后的别名 {{ if .Values.isDev -}} -开发环境多引入一个数据卷 - hostPath: path: {{ .Values.volumes.devWwwPath }} -数据卷位置 type: '' name: {{ .Values.volumes.devWwwName }} -数据卷名称 {{- end }} imagePullSecrets: -镜像密码 - name: {{ .Values.image.imagePullSecrets }} dnsPolicy: ClusterFirst schedulerName: default-scheduler containers: - name: {{ include "admin.appname" . }}-api-app -容器名称 image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" -镜像地址跟标签 command: - /scripts/start.sh -启动脚本 volumeMounts: - mountPath: /alidata/config -配置项路径 name: volume-{{ include "admin.appname" . }}-api-app -配置项名称,跟上面的对应 {{ if .Values.isDev -}} -开发环境额外配置数据卷 - mountPath: {{ .Values.volumes.devWwwRealPath }} -引入的数据卷配置到容器哪个位置 name: {{ .Values.volumes.devWwwName }} -数据卷名称 {{- end }} env: -配置环境变量 - name: ADMIN_CONSOLE_URL value: {{ .Values.consoleHost }} imagePullPolicy: Always -总是拉去镜像 ports: - containerPort: 80 -暴露的端口 name: http -名字随便取,不同端口的别一样就行 protocol: TCP
- containerPort: 8080
name: http2
protocol: TCP strategy: -发布策略 type: RollingUpdate -滚动升级,下面是按什么比例滚动升级 rollingUpdate: maxUnavailable: 25% maxSurge: 25% livenessProbe: -存活检测 failureThreshold: 3 initialDelaySeconds: 3 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 httpGet: path: / scheme: HTTP port: 80 readinessProbe: -就绪检测 failureThreshold: 3 initialDelaySeconds: 3 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 httpGet: path: / scheme: HTTP port: 80 resources: -下面配置了资源限制,比如多少个cpu,多少内存等 {{ toYaml .Values.appResources | indent 12 }}
appResources配置可参考
#资源配置 apiAppResources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: # cpu: 100m # memory: 128Mi # requests: # cpu: 100m # memory: 128Mi
八、服务配置Service
服务配置,主要是跟应用暴露的端口进行绑定,一般应用也只会暴露80端口,提供新的端口给外部访问,也可供路由Ingress访问
apiVersion: v1 kind: Service metadata: name: {{ include "admin.appname" . }}-api-svc -名称 spec: type: ClusterIP ports: - port: 80 -暴露的端口 targetPort: http -目标端口 protocol: TCP name: http
- port: 8080
targetPort: 8080
name: http2 selector: app: {{ include "admin.appname" . }}-api-app -绑定的无状态应用
九、路由ingress
下面配置路由,主要跟上面配置的服务绑定,一般不让服务直接暴露使用,这里多用了一层路由,主要是路由有负载跟灰度的作用,而且只提供一个IP(一般一个集群只有一个路由IP)
{{- if eq .Values.isRelease false -}} -非灰度环境就配置路由 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ include "admin.appname" . }}-api-ingress -路由名称 annotations: nginx.ingress.kubernetes.io/service-weight: '' -权重之类的,这里笔者没用到 nginx.ingress.kubernetes.io/ssl-redirect: 'false' -是否强制http跳https,true的话就强制跳 {{ if .Values.isProd -}} -这里是灰度判断,如果带有环境环境的cookie就把请求转发到灰度环境的服务上 nginx.ingress.kubernetes.io/service-match: '{{ include "admin.release.appname" . }}-api-svc: cookie("admin_gray_tag", "release")' {{- end }} spec: tls: - hosts: - {{ .Values.apiHost }} -域名绑定 secretName: {{ .Values.hostTls }} -TLs配置 rules: - host: {{ .Values.apiHost }} -域名配置跳转规则 http: paths: - path: / backend: serviceName: {{ include "admin.appname" . }}-api-svc -绑定的服务的名称 servicePort: 80 {{ if .Values.isProd -}} - path: / backend: serviceName: {{ include "admin.release.appname" . }}-api-svc -绑定的灰度服务的名称 servicePort: 80 {{- end }} {{- end -}}
十、结合Helm命令进行部署
Chart.yaml
apiVersion: v1 appVersion: "1.0" description: A Helm chart for Kubernetes name: admin version: 0.1.0
在 jenkins 的 shell 上使用 helm 命令部署k8s配置
APPNAME=admin
helm --kubeconfig k8s.conf upgrade -i \
--set-file configDatas.XXX=XXXX.txt \
--set apiAppResources.requests.cpu=1 \ ${APPNAME} ./chart
--kubeconfig:后面带上k8s的配置,这里阿里云的集群里面可以找到,有内网跟外网两个,随便用哪个都行
upgrade:表示升级,后面的 -i 表示没有创建过的话就创建,有的话就更新
--set-file:这里主要是为了配置配置项跟数据字典索用到的,以文件的形式配置
--set:这个就比较重要了,我们在values.yaml里面的所有配置都可以用这个命令进行修改,用这个可以做到无环境化
倒数第二个参数:{{ include "admin.appname" . }} 上面的配置中多次用到了这种配置,倒数第二个参数就是这个的值,至于为什么签名是admin,那就要看你Chart.yaml文件里面name是怎么取的了
最后一个参数:这个参数就是Chart.yaml文件的路径
注意事项:
1、缩进问题,很多时候复制粘贴编译器的缩进就乱了,导致后面配置有问题
2、文件命名问题,一般加上后缀好区分这个yaml文件是干嘛的,比如:应用的话加上-app,服务加上-svc,路由加上-ingress等,有上面好处呢,主要是同一套配置文件都在一起,方便管理,eg:
3、本文也可能存在不足,有错误的地方还请各位大佬多多指教