通过模板创建修改多个中间件应用,并提交到本地仓库,比如elasticsearch、redis、mysql、postgresql等
wangw@DESKTOP:~/helmapp$ helm search
NAME CHART VERSION APP VERSION DESCRIPTION
localrepo/elasticsearch 0.1.2 2.4 elasticsearch single node for kubernetes
localrepo/myapp1 0.1.0 1.0 A Helm chart for Kubernetes
localrepo/mysql 0.1.2 5.7 mysql single node for kubernetes
localrepo/postgresql 0.1.2 11.5 postgresql single node for kubernetes
localrepo/redis 0.1.2 3.2 redis single node for Kubernetes
通过模板创建我们自己的应用
# 创建模板
wangw@DESKTOP:~/helmapp$ helm create gistack
Creating gistack
# Chart.yaml
wangw@DESKTOP:~/helmapp/gistack$ cat Chart.yaml
apiVersion: v1
appVersion: "4.3"
description: A Gis solution for Kubernetes
name: gistack
version: 0.1.0
# deployment.yaml
wangw@DESKTOP:~/helmapp/gistack/templates$ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "gistack.fullname" . }}
labels:
{{ include "gistack.labels" . | indent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "gistack.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "gistack.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
# values.yaml
wangw@DESKTOP:~/helmapp/gistack$ cat values.yaml
replicaCount: 1
image:
repository: 192.168.199.205:80/library/jdk
tag: 1.8
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
service:
type: ClusterIP
port: 80
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: gistack
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths: []
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
假设gistack应用依赖于mysql、elasticsearch、redis等应用,helm提供了依赖设置
# 添加requirements.yaml文件
wangw@DESKTOP:~/helmapp/gistack$ cat requirements.yaml
dependencies:
- name: mysql
version: 0.1.2
repository: http://localhost:8879
- name: redis
version: 0.1.2
repository: http://localhost:8879
- name: elasticsearch
version: 0.1.2
repository: http://localhost:8879
# 每个chart依赖需要指明名称、版本、仓库地址
查看当前依赖
wangw@DESKTOP:~/helmapp/gistack$ helm dependency list
NAME VERSION REPOSITORY STATUS
mysql 0.1.2 http://localhost:8879 missing
redis 0.1.2 http://localhost:8879 missing
elasticsearch 0.1.2 http://localhost:8879 missing
更新下载依赖包到chart文件夹
wangw@DESKTOP:~/helmapp/gistack$ helm dependency update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "localrepo" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
Saving 3 charts
Downloading mysql from repo http://localhost:8879
Downloading redis from repo http://localhost:8879
Downloading elasticsearch from repo http://localhost:8879
Deleting outdated charts
wangw@DESKTOP:~/helmapp/gistack$ ls charts/
elasticsearch-0.1.2.tgz mysql-0.1.2.tgz redis-0.1.2.tgz
检查配置文件并更新到本地仓库
wangw@DESKTOP:~/helmapp$ helm lint gistack/
==> Linting gistack/
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, no failures
wangw@DESKTOP:~/helmapp$ helm package gistack/
Successfully packaged chart and saved it to: /home/wangw/helmapp/gistack-0.1.0.tgz
更新仓库并部署应用
# 更新仓库
wangw@DESKTOP:~/helmapp$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "localrepo" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
# 搜索gistack应用
wangw@DESKTOP:~/helmapp$ helm search gistack
NAME CHART VERSION APP VERSION DESCRIPTION
localrepo/gistack 0.1.0 4.3 A Gis solution for Kubernetes
# 部署gistack应用
wangw@DESKTOP:~/helmapp$ helm install localrepo/gistack --name gistack --namespace default
NAME: gistack
LAST DEPLOYED: Thu Oct 24 11:01:01 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
gistack 0/1 1 0 1s
gistack-elasticsearch 0/1 0 0 1s
gistack-redis 0/1 1 0 1s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
gistack-elasticsearch Pending longhorn 1s
gistack-mysql Pending longhorn 1s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
gistack-7b9fdc797f-rgf5l 0/1 ContainerCreating 0 1s
gistack-elasticsearch-5bf5fb8b78-v26l9 0/1 Pending 0 1s
gistack-mysql-7c8b85b579-c5f7w 0/1 Pending 0 1s
gistack-redis-5cc657bddb-89b7j 0/1 ContainerCreating 0 1s
==> v1/Secret
NAME TYPE DATA AGE
gistack-mysql Opaque 2 1s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gistack ClusterIP 10.43.221.42 <none> 80/TCP 1s
gistack-elasticsearch NodePort 10.43.143.211 <none> 9200:30305/TCP,9300:30076/TCP 1s
gistack-mysql ClusterIP 10.43.229.209 <none> 3306/TCP 1s
gistack-redis NodePort 10.43.32.103 <none> 6379:31455/TCP 1s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
gistack-mysql 0/1 1 0 1s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=gistack,app.kubernetes.io/instance=gistack" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
# 可以看出部署gistack时,其依赖会自动部署
查看gistack状态
wangw@DESKTOP:~/helmapp$ helm status gistack
LAST DEPLOYED: Thu Oct 24 11:01:01 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
gistack 1/1 1 1 2m40s
gistack-elasticsearch 1/1 1 1 2m40s
gistack-redis 1/1 1 1 2m40s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
gistack-elasticsearch Bound pvc-3e9d4332-d0c4-4e2c-9ed2-57c3a534a0a2 10Gi RWO longhorn 2m40s
gistack-mysql Bound pvc-ad117f2d-fd40-47d6-8445-624271d6f895 8Gi RWO longhorn 2m40s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
gistack-7b9fdc797f-rgf5l 1/1 Running 0 71s
gistack-elasticsearch-5bf5fb8b78-v26l9 1/1 Running 0 2m40s
gistack-mysql-7c8b85b579-c5f7w 1/1 Running 0 2m40s
gistack-redis-5cc657bddb-89b7j 1/1 Running 0 2m40s
==> v1/Secret
NAME TYPE DATA AGE
gistack-mysql Opaque 2 2m40s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gistack ClusterIP 10.43.221.42 <none> 80/TCP 2m40s
gistack-elasticsearch NodePort 10.43.143.211 <none> 9200:30305/TCP,9300:30076/TCP 2m40s
gistack-mysql ClusterIP 10.43.229.209 <none> 3306/TCP 2m40s
gistack-redis NodePort 10.43.32.103 <none> 6379:31455/TCP 2m40s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
gistack-mysql 1/1 1 1 2m40s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=gistack,app.kubernetes.io/instance=gistack" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
# 目前看来,一切都按照我们想的运行了起来
虽然解决了应用依赖的问题,但是在应用层面上还需要进一步优化
- 在需要依赖的pod下添加被依赖服务检查任务,可以通过程序本身检查,也可以通过添加initContainers处理
- 配置文件统一管理,使用用configmap
- 密钥管理,通过secret
- 对应用日志的导出,可通过sidecar的方式,采用filebeat + logstash,日志卷共享emptyDir目录
- 部分应用需要改造deployment为statfulset
- 生产环境还需要实现应用高可用和中间件高可用
- 更多helm用法,请多多关注helm官网
总结
- template下的yaml文件与kubernetes原生yaml文件实际上是一致的,不同在于分离出了主要的值,以变量代替,同时支持简单的逻辑处理
- values.yaml定义了应用的关键参数,包括任何你想要定义的参数
- requirements.yaml定义应用需要依赖的其它应用
- "helm之于kubernetes" 类比 "yum之于centos"