Why Helm
Helm 到底解决了什么问题?为什么 Kubernetes 需要 Helm?
答案是: Kubernetes 能够很好地组织和编排容器,但它缺少一个更高层次的应用打包工具,而 Helm 就是来干这件事的。
部署 MySQL
- 1.Service,让外界能够访问到 MySQL
service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-mysql
labels:
app: my-mysql
spec:
ports:
- name: mysql
port: 3306
targetPort: mysql
selector:
app: my-mysql
- 2.Secret,定义 MySQL 的密码
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: my-mysql
labels:
app: my-mysql
type: Opaque
data:
mysql-root-password: "cm9vdA==" # root
mysql-password: "bXlzcWw=" # mysql
- 3.PersistentVolumeClaim,为 MySQL 申请持久化存储空间
pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-mysql
labels:
app: my-mysql
spec:
capacity:
storage: 4Gi
accessModes:
* ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/my-mysql
server: 192.168.1.6
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-mysql
labels:
app: my-mysql
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
storageClassName: nfs
- 4.Deployment,部署 MySQL Pod,并使用上面的这些支持对象
pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-mysql
labels:
app: my-mysql
spec:
selector:
matchLabels:
app: my-mysql
template:
metadata:
labels:
app: my-mysql
spec:
containers:
- name: my-mysql
image: "mysql:5.7.14"
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: my-mysql
key: mysql-root-password
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: my-mysql
key: mysql-password
- name: MYSQL_USER
value: ""
- name: MYSQL_DATABASE
value: ""
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumes:
- name: data
persistentVolumeClaim:
claimName: my-mysql
- 执行部署操作
kubectl apply -f service.yaml -f secret.yaml -f pv.yaml -f pvc.yaml -f pod.yaml
- 查看资源
kubectl get svc,secret,pv,pvc,deployment
- 验证 MySQL
kubectl run -it --rm --image=mysql:5.7.14 --restart=Never mysql-client -- mysql -h my-mysql -u root -proot -e "show databases"
小结
由上可以发现部署 MySQL 的文件就已经很多了,如果应用只由一个或几个这样的服务组成,上面的部署方式完全足够了。
缺点
- 1.很难管理、编辑和维护如此多的服务。每个服务都有若干配置,缺乏一个更高层次的工具将这些配置组织起来。
- 2.不容易将这些服务作为一个整体统一发布。部署人员需要首先理解应用都包含哪些服务,然后按照逻辑顺序依次执行 kubectl apply。即缺少一种工具来定义应用与服务,以及服务与服务之间的依赖关系。
- 3.不能高效地共享和重用服务。比如两个应用都要用到 MySQL 服务,但配置的参数不一样,这两个应用只能分别拷贝一套标准的 MySQL 配置文件,修改后通过 kubectl apply 部署。也就是说不支持参数化配置和多环境部署。
- 4.不支持应用级别的版本管理。虽然可以通过 kubectl rollout undo 进行回滚,但这只能针对单个 Deployment,不支持整个应用的回滚。
- 5.不支持对部署的应用状态进行验证。比如是否能通过预定义的账号访问 MySQL。虽然 Kubernetes 有健康检查,但那是针对单个容器,我们需要应用(服务)级别的健康检查。
Helm
chart
chart 是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包。
release
release 是 chart 的运行实例,代表了一个正在运行的应用。当 chart 被安装到 Kubernetes 集群,就生成一个 release。chart 能够多次安装到同一个集群,每次安装都是一个 release。
helm 功能
- 1.从零创建新 chart
- 2.与存储 chart 的仓库交互,拉取、保存和更新 chart
- 3.在 Kubernetes 集群中安装和卸载 release
- 4.更新、回滚和测试 release
架构
Helm 客户端是终端用户使用的命令行工具,用户可以:
- 1.在本地开发 chart
- 2.管理 chart 仓库
- 3.与 Tiller 服务器交互
- 4.在远程 Kubernetes 集群上安装 chart
- 5.查看 release 信息
- 6.升级或卸载已有的 release
Tiller 服务器运行在 Kubernetes 集群中,它会处理 Helm 客户端的请求,与 Kubernetes API Server 交互。Tiller 服务器负责:
- 1.监听来自 Helm 客户端的请求
- 2.通过 chart 构建 release
- 3.在 Kubernetes 中安装 chart,并跟踪 release 的状态
- 4.通过 API Server 升级或卸载已有的 release
Helm 客户端负责管理 chart;Tiller 服务器负责管理 release。
安装 helm 客户端
curl https://raw.githubusercontent.com/helm/helm/v2.16.2/scripts/get | bash
若一直安装失败,可以换下方手动安装方式
wget -O ~/helm-v2.16.2-linux-amd64.tar.gz https://get.helm.sh/helm-v2.16.2-linux-amd64.tar.gz
tar zxvf ~/helm-v2.16.2-linux-amd64.tar.gz
wget -O ~/helm-v2.6.2-linux-amd64.tar.gz https://get.helm.sh/helm-v2.6.2-linux-amd64.tar.gz
tar zxvf ~/helm-v2.6.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/
chmod +x /usr/local/bin/helm
- 查看版本
helm version
- 配置补全脚本
echo -n 'source <(helm completion zsh)' >> ~/.zshrc
安装 Tiller 服务器
- 配置 RBAC 授权
rbac-config.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
tiller 版本和 helm client 对应的版本一样
kubectl apply -f rbac-config.yaml # kubectl 版本1.16.0之后才需要执行
helm init --upgrade --service-account tiller --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.2 --stable-repo-url http://mirror.azure.cn/kubernetes/charts
tiller 指定 v2.6.2
版本一直报 Error: error validating "": error validating data: the server could not find the requested resource
错误,故修改版本
- 查看 Tiller
kubectl get --namespace=kube-system svc,deployment,pv,pod tiller-deploy
- 再次查看版本
helm version
- 查看 Helm 仓库地址
helm repo list
比如可以通过 helm repo add stable http://mirror.azure.cn/kubernetes/charts
添加国内仓库
- 关键字搜索
helm search mysql
- 安装 MySQL
ubuntu2@root helm install --name mysql --set mysqlRootPassword=root,mysqlUser=test,mysqlPassword=test,mysqlDatabase=test stable/mysql
Error: no available release name found
以上报错,通常是因为 Tiller 服务器的权限不足。
解决报错
- 创建 Kubernetes 的服务帐号和绑定角色
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
- 为 Tiller 设置帐号
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
- 查看授权是否成功
kubectl get deploy --namespace kube-system tiller-deploy --output yaml | grep serviceAccount
- 卸载 Helm 服务器端 Tiller
kubectl delete --namespace=kube-system svc tiller-deploy
kubectl delete deployment -n kube-system tiller-deploy
helm reset --force; trash ~/.helm
重新安装MySQL
- 重新执行上面执行过的
安装MySQL
操作 - 查看组成 release 的各个对象
kubectl get service mysql
kubectl get deployment mysql
kubectl get pod `kubectl get pod | grep mysql | awk '{print $1}'`
kubectl get pvc mysql
Chart 目录结构
chart 是 Helm 的应用打包格式。chart 由一系列文件组成,这些文件描述了 Kubernetes 部署应用时所需要的资源,比如 Service、Deployment、PersistentVolumeClaim、Secret、ConfigMap 等。
单个的 chart 可以非常简单,只用于部署一个服务,比如 Memcached;chart 也可以很复杂,部署整个应用,比如包含 HTTP Servers、 Database、消息中间件、cache 等。
chart 将这些文件放置在预定义的目录结构中,通常整个 chart 被打成 tar 包,而且标注上版本信息,便于 Helm 部署。
MySQL chart
一旦安装了某个 chart,就可以在 ~/.helm/cache/archive
中找到 chart 的 tar 包。
- 解压 tar 包
tar zxvf ~/.helm/cache/archive/mysql-1.6.2.tgz -C .
tree -L 3 mysql
mysql
├── Chart.yaml # YAML文件,描述chart的概要信息,`name` 和 `version` 是必填项,其他都是可选
├── LICENSE # 文本文件,描述 chart 的许可信息,此文件为可选。
├── README.md # Markdown 格式的 README 文件,相当于 chart 的使用文档,此文件为可选
├── requirements.yaml # chart 可能依赖其他的 chart,此文件为可选。
├── templates # 各类 Kubernetes 资源的配置模板,Helm 会将 values.yaml 中的参数值注入到模板中生成标准的 YAML 配置文件。
│ ├── configurationFiles-configmap.yaml
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── initializationFiles-configmap.yaml
│ ├── NOTES.txt # chart 的简易使用文档,chart 安装成功后会显示此文档内容。
│ ├── pvc.yaml
│ ├── secrets.yaml
│ ├── serviceaccount.yaml
│ ├── servicemonitor.yaml
│ ├── svc.yaml
│ └── tests
│ ├── test-configmap.yaml
│ └── test.yaml
└── values.yaml # 配置参数的默认值。
Chart模板
- 查看chart中的内容
helm inspect values stable/mysql
chart 定义了一个 PersistentVolumeClaim,申请 8G 的 PersistentVolume。由于我们的实验环境不支持动态供给,所以得预先创建好相应的 PV,其配置文件 mysql-pv.yml
内容为:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pd
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 4Gi
persistentVolumeReclaimPolicy: Retain
nfs:
path: /nfsdata/mysql-pv
server: 192.168.1.6
创建PV
kubectl apply -f mysql-pv.yaml
定制化安装chart
Helm 有两种方式传递配置参数:
- 1.指定自己的 values 文件。
通常的做法是首先通过 helm inspect values stable/mysql > myvalues.yaml
生成 values 文件,然后设置 mysqlRootPassword,之后执行 helm install --values=myvalues.yaml mysql
。
- 2.通过 –set 直接传入参数值,比如
helm install stable/mysql --set mysqlRootPassword=root -n my
升级和回滚
release 发布后可以执行 helm upgrade 对其升级,通过 –values 或 –set应用新的配置。
将当前的 MySQL 版本升级到 5.7.15:
helm upgrade --set imageTag=5.7.15 my stable/mysql
- 查看升级结果
kubectl get deployment my-mysql -o wide
- 查看历史版本
helm history my
- 回滚
helm rollback my 1
- 查看回滚结果
kubectl get deployment my-mysql -o wide
开发自己的chart
创建chart
helm create mychart
调试
Helm 提供了 debug 的工具:helm lint <chart>
和 helm install --dry-run --debug <chart>
helm lint 会检测 chart 的语法,报告错误以及给出建议。
helm install –dry-run –debug 会模拟安装 chart,并输出每个模板生成的 YAML 内容。
安装方式
- 1.安装仓库中的 chart,例如:
helm install stable/nginx
- 2.通过 tar 包安装,例如:
helm install ./nginx-1.2.3.tgz
- 3.通过 chart 本地目录安装,例如:
helm install ./nginx
- 4.通过 URL 安装,例如:
helm install https://example.com/charts/nginx-1.2.3.tgz
安装chart
helm install mychart
将 chart 添加到仓库
chart 通过测试后可以将其添加到仓库,团队其他成员就能够使用。任何 HTTP Server 都可以用作 chart 仓库
环境信息: ubuntu1
是k8s的node节点, IP为 192.168.1.5
- 1.在
ubuntu1
上启动httpd
容器
mkdir -p /tmp/var/www/charts
docker run -d -p 8080:80 --name httpd -v /tmp/var/www:/usr/local/apache2/htdocs httpd
- 2.在
ubuntu2
上将mychart
打包
helm package mychart
- 3.在
ubuntu2
上生成仓库的 index 文件
mkdir ~/myrepo
mv ./mychart-0.1.0.tgz ~/myrepo
helm repo index ~/myrepo --url http://192.168.1.5:8080/charts
ls ~/myrepo
Helm 会扫描 myrepo 目录中的所有 tgz 包并生成 index.yaml。–url指定的是新仓库的访问路径。新生成的 index.yaml 记录了当前仓库中所有 chart 的信息:
- 4.将
mychart的tar包
和index.yaml
拷贝到ubuntu1
scp ~/myrepo/index.yaml ~/myrepo/mychart-0.1.0.tgz ubuntu1:/tmp/var/www/charts
- 5.将新仓库加到Helm
helm repo add newrepo http://192.168.1.5:8080/charts
helm repo list
- 6.在仓库中搜索mychart
helm search mychart
- 7.从新仓库安装
mychart
helm install newrepo/mychart
- 8.果以后仓库添加了新的 chart,需要更新本地的 index
helm repo update