Helm 服务部署

什么是 Helm

在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较繁琐。况且随 着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本 管理和控制,很大程度上简化了 Kubernetes 应用的部署和管理

Helm 本质就是让 K8s 的应用管理(Deployment,Service 等 ) 可配置,能动态生成。通过动态生成 K8s 资源清单文件(deployment.yaml,service.yaml)。然后调用 Kubectl 自动执行 K8s 资源部署

Helm 是官方提供的类似于 YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart 和 release

  • chart 是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说 明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包
  • release 是 chart 的运行实例,代表了一个正在运行的应用。当 chart 被安装到 Kubernetes 集群,就生成 一个 release。chart 能够多次安装到同一个集群,每次安装都是一个 release

Helm 包含两个组件:Helm 客户端和 Tiller 服务器,如下图所示
缺图

Helm 客户端负责 chart 和 release 的创建和管理以及和 Tiller 的交互。Tiller 服务器运行在 Kubernetes 集群 中,它会处理 Helm 客户端的请求,与 Kubernetes API Server 交互

Helm 部署

1
2
3
4
5
ntpdate ntp1.aliyun.com
wget https://get.helm.sh/helm-v2.16.5-linux-amd64.tar.gz
tar -zxvf helm-v2.16.5-linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin/

为了安装服务端 tiller,还需要在这台机器上配置好 kubectl 工具和 kubeconfig 文件,确保 kubectl 工具可以 在这台机器上访问 apiserver 且正常使用。 这里的 node1 节点以及配置好了 kubectl

因为 Kubernetes APIServer 开启了 RBAC 访问控制,所以需要创建 tiller 使用的 service account: tiller 并分 配合适的角色给它。 详细内容可以查看helm文档中的 Role-based Access Control。 这里简单起见直接分配 cluster- admin 这个集群内置的 ClusterRole 给它。创建 rbac-config.yaml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat > rbac-config.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
EOF
1
2
3
kubectl create -f rbac-config.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created

拉取镜像

1
2
3
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.6
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.6 k8s.gcr.io/tiller:v2.16.6
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.6

安装tiller

1
helm init --service-account tiller --history-max 200 --upgrade --tiller-image k8s.gcr.io/tiller:v2.16.6 --stable-repo-url https://cnych.github.io/kube-charts-mirror/

tiller 默认被部署在 k8s 集群中的 kube-system 这个 namespace 下

1
2
3
4
5
6
kubectl get pod -n kube-system -l app=helm
NAME READY STATUS RESTARTS AGE
tiller-deploy-55479b584d-4kc4b 1/1 Running 2 21h
helm version
Client: &version.Version{SemVer:"v2.16.9", GitCommit:"8ad7037828e5a0fca1009dabe290130da6368e39", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.16.6", GitCommit:"dd2e5695da88625b190e6b22e9542550ab503a47", GitTreeState:"clean"}

Helm 自定义模板

1
2
3
# 创建文件夹
mkdir ./hello-world
cd ./hello-world
1
2
3
4
5
# 创建自描述文件 Chart.yaml , 这个文件必须有 name 和 version 定义
cat <<'EOF' > ./Chart.yaml
name: hello-world
version: 1.0.0
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 创建模板文件, 用于生成 Kubernetes 资源清单(manifests)
mkdir ./templates
cat <<'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app: hello-world
spec:
replicas: 3
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: nginx
image: nginx:lasest
ports:
- containerPort: 80
EOF

cat <<'EOF' > ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
selector:
app: hello-world
EOF
1
2
# 使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release
$ helm install .
1
2
3
4
# 查看 hello-world的部署情况
helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
wistful-ferret 1 Thu Jul 2 18:42:42 2020 DEPLOYED hello-world-1.0.0 default
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 这个文件中定义的值,在模板文件中可以通过 .VAlues对象访问到
cat <<'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app: hello-world
spec:
replicas: 3
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: nginx
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: 80
EOF

创建一个 values.yaml 定义相关值

1
2
3
4
5
6
# 配置体现在配置文件 values.yaml
cat <<'EOF' > ./values.yaml
image:
repository: nginx
tag: '1.18'
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看当前的版本信息
helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
wistful-ferret 1 Thu Jul 2 18:42:42 2020 DEPLOYED hello-world-1.0.0 default

# 升级版本
helm upgrade -f values.yaml wistful-ferret .

## REVISION 版本号变成了2
helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
wistful-ferret 2 Fri Jul 3 15:16:24 2020 DEPLOYED hello-world-1.0.0 default

## 查看镜像号已经变更成功
kubectl get pods hello-world-8689856fc-v9s2m -o yaml |grep "\- image: "
- image: nginx:1.18

也可以通过命令行显式指定版本号

1
2
# 在 values.yaml 中的值可以被部署 release 时用到的参数 --values YAML_FILE_PATH 或 --set key1=value1, key2=value2 覆盖掉
$ helm install --set image.tag='latest' .

helm 常用命令

1
2
3
4
5
6
7
8
9
10
11
# 列出已经部署的 Release
$ helm ls
# 查询一个特定的 Release 的状态
$ helm status RELEASE_NAME
# 移除所有与这个 Release 相关的 Kubernetes 资源
$ helm delete cautious-shrimp
# helm rollback RELEASE_NAME REVISION_NUMBER
$ helm rollback cautious-shrimp 1
# 使用 helm delete --purge RELEASE_NAME 移除所有与指定 Release 相关的 Kubernetes 资源和所有这个 Release 的记录
$ helm delete --purge cautious-shrimp
$ helm ls --deleted

Debug

1
2
3
# 使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果。
# 使用--dry-run --debug 选项来打印出生成的清单文件内容,而不执行部署
helm install . --dry-run --debug --set image.tag=latest

帮助文档

官方文档
helm 安装 dashboard
ingress-nginx deploy
ingress-nginx