什么是helm

Helm 是 Kubernetes 生态系统中的一个软件包管理工具。

基础概念:

Helm:客户端,主要负责管理本地的 Charts、repositories 以及与tiller服务器交互,发送Chart,实例安装、查询、卸载等操作;
Tiller:安装在 k8s 集群中的服务端,是实际用来管理安装在 k8s 中应用的,就是将模板与 values 合并,当然实际开发过程中, 也可以安装在 k8s 集群之外 ;接收helm发来的Charts与Config,合并生产relase;
Chart:是用来管理模板与默认 values 的项目,也可以认为是一个 package,可以发布到专门的 repository;
Repository: Chart仓库,https/http服务器;
Release:特定的Chart部署于目标集群上的一个实例;
Release:使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release。

helm部署

1、安装 Helm 客户端

#下载 Helm

$ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.0-linux-amd64.tar.gz

#解压 Helm

$ tar -xf helm-v2.13.0-linux-amd64.tar.gz

#复制客户端执行文件到 bin目录下就可以用了

$ cp linux-amd64/helm /usr/local/bin/

2、安装 Tiller

helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.0 \
--stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts  \
--tiller-namespace myname

镜像默认使用gcr.io/kubernetes-helm/tiller;

仓库默认使用https://kubernetes-charts.storage.googleapis.com。

由于国内无法访问相关域名,可以使用阿里云容器服务提供的镜像和站点,也可以自定义。

可以用--skip-refresh参数跳过stable-repo-url设置

注意镜像版本问题, 要和客户端一致

3、卸载

如果你需要在 Kubernetes 中卸载已部署的 Tiller,可使用以下命令完成卸载。
$ helm reset

4、验证

# 查看已部署的应用

helm list

 如果有如下报错:

从Kubernetes 1.6开始,API Server启用了RBAC授权。

而Tiller部署没有定义授权的ServiceAccount,这会导致访问API Server时被拒绝。

我们可以采用如下方法,为Tiller部署添加授权:

#创建 Kubernetes 的服务帐号和绑定角色
kubectl get deployment --all-namespaces
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
#使用 kubectl patch 更新 API 对象
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 Chart

Helm安装后可执行helm search查看当前可安装的chart

Helm像apt和yum管理软件包一样管理chart,apt和yum我得软件包放在仓库里,同样的helm也有仓库。

helm repo list

通过一个完整的示例来学习如何使用 Helm 创建、打包、分发、安装、升级及回退Kubernetes应用。

1、创建一个名为 myapp 的 Chart

helm create myapp

该命令创建了一个 myapp 目录,该目录结构如下所示。

Chart.yaml 用于描述这个 Chart的相关信息,包括名字、描述信息以及版本等。
values.yaml 用于存储 templates 目录中模板文件中用到变量的值。
NOTES.txt 用于介绍 Chart 部署后的一些信息,例如:如何使用这个 Chart、列出缺省的设置等。
Templates 目录下是 YAML 文件的模板,该模板文件遵循 Go template 语法。

一旦安装了某个 chart,我们就可以在 ~/.helm/cache/archive 中找到 chart 的 tar 包。

2、检查依赖和模板配置是否正确

helm lint myapp/

语法检测,如果文件格式错误,可以根据提示进行修改。
将应用打包

$ helm package myapp
Successfully packaged chart and saved it to: /root/k8s_yaml/helm/myapp-0.1.0.tgz

myapp 目录会被打包为一个 myapp-0.1.0.tgz 格式的压缩包,该压缩包会被放到当前目录下,并同时被保存到了 Helm 的本地缺省仓库目录中。
如果你想看到更详细的输出,可以加上 --debug 参数来查看打包的输出,输出内容应该类似如下: 

$ helm package myapp --debug
Successfully packaged chart and saved it to: /root/k8s_yaml/helm/myapp-0.1.0.tgz
[debug] Successfully saved /root/k8s_yaml/helm/myapp-0.1.0.tgz to /root/.helm/repository/local

将应用发布到 Repository

Helm Repository 必须以 Web 服务的方式提供,这里我们就使用 helm serve 命令启动一个 Repository Server,该 Server 缺省使用 $HOME/.helm/repository/local 目录作为 Chart 存储,并在 8879 端口上提供服务。

$ helm serve &
Now serving you on 127.0.0.1:8879

默认情况下该服务只监听 127.0.0.1,如果你要绑定到其它网络接口,可使用以下命令:

helm serve --address 192.168.100.211:8879 &

如果你想使用指定目录来做为 Helm Repository 的存储目录,可以加上 --repo-path 参数:

 helm serve --address 192.168.100.211:8879 --repo-path /data/helm/repository/ --url http://192.168.100.211:8879/charts/

在 Kubernetes 中部署应用

部署一个应用
Chart 被发布到仓储后,就可以通过 helm install 命令部署该 Chart。

在部署前我们可以使用 helm install --dry-run --debug <chart_dir> --name <release_name>命令来验证 Chart 的配置。该输出中包含了模板的变量配置与最终渲染的 YAML 文件。

[root@master ~]# helm install --dry-run --debug local/myapp --name myapp-test
[debug] Created tunnel using local port: '21619'

[debug] SERVER: "127.0.0.1:21619"

[debug] Original chart version: ""
[debug] Fetched local/myapp to /root/.helm/cache/archive/myapp-0.1.0.tgz

[debug] CHART PATH: /root/.helm/cache/archive/myapp-0.1.0.tgz

NAME:   myapp-test
REVISION: 1
RELEASED: Fri Apr  5 11:17:02 2019
CHART: myapp-0.1.0
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
  pullPolicy: IfNotPresent
  repository: nginx
  tag: stable
ingress:
  annotations: {}
  enabled: false
  hosts:
  - host: chart-example.local
    paths: []
  tls: []
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
  port: 80
  type: ClusterIP
tolerations: []

HOOKS:
---
# myapp-test-test-connection
apiVersion: v1
kind: Pod
metadata:
  name: "myapp-test-test-connection"
  labels:
    app.kubernetes.io/name: myapp
    helm.sh/chart: myapp-0.1.0
    app.kubernetes.io/instance: myapp-test
    app.kubernetes.io/managed-by: Tiller
  annotations:
    "helm.sh/hook": test-success
spec:
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args:  ['myapp-test:80']
  restartPolicy: Never
MANIFEST:

---
# Source: myapp/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-test
  labels:
    app.kubernetes.io/name: myapp
    helm.sh/chart: myapp-0.1.0
    app.kubernetes.io/instance: myapp-test
    app.kubernetes.io/managed-by: Tiller
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: myapp
    app.kubernetes.io/instance: myapp-test
---
# Source: myapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-test
  labels:
    app.kubernetes.io/name: myapp
    helm.sh/chart: myapp-0.1.0
    app.kubernetes.io/instance: myapp-test
    app.kubernetes.io/managed-by: Tiller
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
      app.kubernetes.io/instance: myapp-test
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
        app.kubernetes.io/instance: myapp-test
    spec:
      containers:
        - name: myapp
          image: "nginx:stable"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {}

验证完成没有问题后,我们就可以使用以下命令将其部署到 Kubernetes 上了。
# 部署时需指定 Chart 名及 Release(部署的实例)名。

[root@master ~]# helm install local/myapp --name myapp-test
NAME:   myapp-test
LAST DEPLOYED: Fri Apr  5 11:19:02 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Deployment
NAME        READY  UP-TO-DATE  AVAILABLE  AGE
myapp-test  0/1    0           0          0s

==> v1/Service
NAME        TYPE       CLUSTER-IP  EXTERNAL-IP  PORT(S)  AGE
myapp-test  ClusterIP  10.10.10.3  <none>       80/TCP   0s


NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=myapp,app.kubernetes.io/instance=myapp-test" -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

 注:helm install 默认会用到 socat,需要在所有节点上安装 socat 软件包。

01-21 03:06