部署-Helm

什么是Helm

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

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

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

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

Helm是包管理工具,这里的包就是指的 chart。Helm 能够:

  • 从零创建新 chart
  • 与存储chart的仓库交互,拉取、保存和更新chart
  • 在kubernetes 集群中安装和卸载 release
  • 更新、回滚和测试release

Helm架构

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

Helm 客户端是终端用户使用的命令行工具,用户可以:

  • 在本地开发chart
  • 管理chart仓库
  • 与 Tiller 服务器交互
  • 在远程 kubernetes 集群上安装 chart
  • 查看 release 信息
  • 升级或卸载已有的release

Tiller 服务器运行在 kubernetes 集群中,它会处理 Helm 客户端的请求,与 kubernetes API Server交互。Tiller 服务器负责:

  • 监听来自 Helm 客户端的请求
  • 通过chart 构建 release
  • 在 kubernetes 中安装 chart,并跟踪 release 的状态
  • 通过 API Server升级或卸载已有的release

安装 Helm

本节我们将依次安装Helm 客户端和 Tiller 服务器

Helm 客户端

越来越多的公司和团队开始使用Helm这个Kubernetes的包管理器,我们也将使用Helm安装kubernetes的常用组件。helm由客户端命令行工具和服务端tiller组成,Helm的安装十分简单。下载helm命令行工具到master 节点即k8s-master 的/usr/local/bin/下,这里下载的2.13.1版本:

ntpdate ntp1.aliyun.com
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
tar -zxvf helm-v2.13.1.linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin

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

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

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

[root@k8s-master helm]# kubectl get svc -n kube-system
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
kube-dns        ClusterIP   10.96.0.10               53/UDP,53/TCP,9153/TCP   14d
tiller-deploy   ClusterIP   10.102.235.237           44134/TCP                81s

[root@k8s-master helm]# kubectl get deployment -n kube-system
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
coredns         2/2     2            2           14d
tiller-deploy   1/1     1            1           55s

[root@k8s-master helm]# kubectl get rs -n kube-system
NAME                       DESIRED   CURRENT   READY   AGE
coredns-5c98db65d4         2         2         2       14d
tiller-deploy-58565b5464   1         1         1       112s


[root@k8s-master helm]# kubectl get pod -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-5c98db65d4-pxl78             1/1     Running   0          14d
coredns-5c98db65d4-vdtsr             1/1     Running   0          14d
etcd-k8s-master                      1/1     Running   0          14d
kube-apiserver-k8s-master            1/1     Running   0          14d
kube-controller-manager-k8s-master   1/1     Running   0          14d
kube-flannel-ds-amd64-852cl          1/1     Running   0          14d
kube-flannel-ds-amd64-p5h64          1/1     Running   0          14d
kube-flannel-ds-amd64-rglvq          1/1     Running   0          12d
kube-proxy-6sp4j                     1/1     Running   0          14d
kube-proxy-hbnkf                     1/1     Running   0          12d
kube-proxy-ttjcn                     1/1     Running   0          14d
kube-scheduler-k8s-master            1/1     Running   0          14d
tiller-deploy-58565b5464-8vrfb       1/1     Running   0          65s

[root@k8s-master helm]# helm version
Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}

Helm 自定义模板

# 创建文件夹
$ mkdir ./hello-world
$ cd ./hello-world
# 创建自描述文件 Chart.yaml ,这个文件必须有 name 和 version 定义
$ cat << 'EOF' >./Chart.yaml
name: hello-world
version: 1.0.0
EOF
# 创建模板文件,用于生成kubernetes 资源清单 (manifests)
$ mkdir ./templates
$ cat << 'EOF' >./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: harbor.bwingame8.com/library/myapp:v1
          ports:
            - containerPort: 80
              protocol: TCP
EOF
$ cat << 'EOF' > ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: hello-world
EOF
# 使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release
$ helm install .
# 列出已经部署的 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
# 配置体现在配置文件 values.yaml
$ cat << 'EOF' > ./values.yaml
image:
  repository: harbor.bwingame8.com/library/myapp
  tag: 'v3'
EOF

# 这个文件中定义的值,在模板文件中可以通过 .Values对象访问到
$ cat << 'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: {{ .Values.images.repository }}:{{ .Values.image.tag }}
          ports:
            - containerPort: 80
              protocol: TCP
EOF

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

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

Debug

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

文章作者: 阿培
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿培 !
 上一篇
helm部署dashboard helm部署dashboard
使用 Helm 部署 dashboard之前我们对于kubernetes集群的所有操作都是通过命令行工具kubectl完成的。为了提供更丰富的用户体验,kubernetes还开发了一个基于Web 的Dashboard,用户可以用kubern
2019-12-07
下一篇 
Kubernetes-集群安全-准入控制 Kubernetes-集群安全-准入控制
准入控制准入控制是API Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server的一些主要的功能都需要通过Admission Controllers实现,比如ServiceAccount 官方文档上有
2019-12-06
  目录