K8S部署(Helm)

目前基本的K8s部署方式需要创建yaml文件,文件内容包括deployment、Service、Ingress等;

这种方式只适用于单一或者多个创建,再多就不适用了(多个yaml文件就会造成管理困难)。

helm通过打包的方式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用的部署和管理。

需要安装 Helm 3.0 以上版本,因为 3.0 版本以后,Helm 不再需要在集群里安装 tiller 服务端,可以直接将安装历史记录在 ConfigMap 资源中。

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

对于K8s来说,应用资源配置可以定义为K8s API对象,包括Deployment,Namespace,Service, PV(Persistent Volumes)和PVC(PersistentVolumeClaims)等等。通常一个应用的部署会涉及很多资源的共同协作,用户会定义这些API对象到一系列Yaml文件中,然后通过kubectl来逐一进行部署。

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

  • Helm:Helm 是一个命令行下的客户端工具。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。

  • Tiller:Tiller 是 Helm 的服务端,部署在 Kubernetes 集群中。Tiller 用于接收 Helm 的请求,并根据 Chart 生成 Kubernetes 的部署文件( Helm 称为 Release ),然后提交给 Kubernetes 创建应用。Tiller 还提供了 Release 的升级、删除、回滚等一系列功能。

  • Chart:Helm 的软件包,采用 TAR 格式。类似于 APT 的 DEB 包或者 YUM 的 RPM 包,其包含了一组定义 Kubernetes 资源相关的 YAML 文件。Chart有特定的文件目录结构,如果开发者想自定义一个新的 Chart,只需要使用Helm create命令生成一个目录结构即可进行开发。

  •  Repoistory:Helm 的软件仓库,Repository 本质上是一个 Web 服务器,该服务器保存了一系列的 Chart 软件包以供用户下载,并且提供了一个该 Repository 的 Chart 包的清单文件以供查询。Helm 可以同时管理多个不同的 Repository, 官方仓库的地址是:https://hub.helm.sh。

  • Release:使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release。

Chart Install 过程
  • Helm从指定的目录或者tgz文件中解析出Chart结构信息

  • Helm将指定的Chart结构和Values信息通过gRPC传递给Tiller

  • Tiller根据Chart和Values生成一个Release

  • Tiller将Release发送给Kubernetes用于生成Release

Chart Update过程
  • Helm从指定的目录或者tgz文件中解析出Chart结构信息

  • Helm将要更新的Release的名称和Chart结构,Values信息传递给Tiller

  • Tiller生成Release并更新指定名称的Release的History

  • Tiller将Release发送给Kubernetes用于更新Release

Chart Rollback过程
  • Helm将要回滚的Release的名称传递给Tiller

  • Tiller根据Release的名称查找History

  • Tiller从History中获取上一个Release

  • Tiller将上一个Release发送给Kubernetes用于替换当前Release

通过helm管理内部资源

  • 查询可用资源
$: helm search repo mysql

如果找不到相应的资源,可以直接 Google 相应的资源。所谓的 repo 其实就是一个简单的 Helm Charts 的索引。

  • 添加资源仓库
$: helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
  • 查看本地资源仓库
$: helm repo list

找到需要的资源后,在部署之前,需要自行检查资源的默认配置是否满足要求,如果不满足的话还需要进行自定义设置。完成自定义设置后,再部署上线。具体过程如下:

# 拉取 mysql helm charts 到本地目录
$: helm pull bitnami/mysql --untar

# 修改定义配置即可
$: vim mysql/values.yaml

# 更新或安装
$: helm upgrade --install --namespace=[YOUR NAMESPACE] --atomic --history-max 3 mysql-demo ./mysql/ --values ./mysql/values.yaml

通过 helm 管理外部基础设施的安装。基础过程如下:

# 创建一个新的 Helm Charts, 负责管理所有外部资源
$: helm create external-services

默认创建的 Helm Chart,创建了很多功能模板,可以根据需要自行取舍。对于外部基础设施而言,只需要定义相应的 Service 资源即可,其他没有必要的资源模板均可以直接删除。以阿里 RDS 资源为例, 删除 external-services/templates 下无关的资源模板。直接定义一个 mysql.yaml 模板即可

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  externalName: {{.Values.mysql.address}}
  sessionAffinity: None
  type: ExternalName

清空 external-services/values.yaml 无关配置,提供一个 mysql.address 设置即可。

通过helm配置管理集群资源

通过一个专门的 Helm charts 进行管理。

# 创建一个新的 Helm Charts, 负责管理集群配置
$: helm create settings

删除无关的资源模板。开始添加集群配置。通常而言,集群配置也就以下几种配置类型:

  • 证书类配置
  • 密码类配置
  • 容器镜像访问认证配置
  • 通用业务服务配置

以上配置,在 K8S 集群中,可以通过 Secret 资源和 ConfigMap 资源进行配置。

证书类配置

证书类配置,主要是将证书文件自动化配置到集群中,可以通过 Helm 提供模板函数 .Files.Get 读取文件内容. 以常见的域名证书为例:

apiVersion: v1
data:
  tls.crt: "{{ .Files.Get "files/example.com.pem" | b64enc }}"
  tls.key: "{{ .Files.Get "files/example.com.key" | b64enc }}"
kind: Secret
metadata:
  name: www-example-com-tls
type: IngressTLS

将证书文件存放到 settings/files 子目录下即可。

密码类配置

密码类配置同样非常简单,如:

apiVersion: v1
data:
  ACCESS: {{ .Values.demo.access | b64enc }}
  SECRET: {{ .Values.demo.secret | b64enc }}
kind: Secret
metadata:
  name: demo-secret
type: Opaque

通过将具体的密码信息设置在 settings/values.yaml 即可。

容器镜像访问认证配置

为了让集群在发布服务时,可以取得相应的服务容器镜像,还需要提供服务容器镜像服务器的认证信息。通常,镜像服务器的认证信息可以通过命令行创建。如果需要固化存储,在将命令行创建的认证信息资源下载到本地保存即可。

# 可以通过命令帮助查询如何创建一个镜像服务的认证信息
$: kubectl create secret docker-registry -h

通用服务配置

通用服务配置,通常是一组业务服务可共用的配置,敏感度不高,则可以通过 ConfigMap 资源的形式进行配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: your-config
data:
  [yourKey1]: {{.values.yourValue1}}
  [yourKey2]: {{.values.yourValue2}}
  [yourKey3]: {{.values.yourValue3}}

非常简单。

完成以上各类配置后,直接在 settings 中统一管理,就非常清楚。

业务服务

业务服务不同于配置,类似与自建基础设施服务,通常需要提供的部署资源可能包括:

  • deployment 或 statefulset
  • service
  • ingress
  • configmap 仅针对自己的配置
  • secret 仅针对自己的密钥

所以,业务服务的资源定义类型就会比较多。简单列一下常规服务的配置:

  • StatefulSet 资源配置
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: demo
  labels:
    app: demo
spec:
  serviceName: demo
  replicas: {{ .Values.deployment.replicaCount }}
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      annotations:
        timstamp: "{{ date "20060102150405" .Release.Time }}"
      labels:
        app: demo
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
            {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: demo
          env:
            - name: DEMO_CONFIG
              valueFrom:
                configMapKeyRef:
                  key: CONFIG
                  name: demo-config
            - name: DEMO_SECRET
              valueFrom:
                secretKeyRef:
                  key: SECRET
                  name: demo-secret
          ports:
            - name: http
              containerPort: 8080
          image: "{{ .Values.deployment.image.name }}:{{ .Values.deployment.image.tag }}"
          imagePullPolicy: {{ .Values.deployment.image.imagePullPolicy }}
          command: ["demo", "http"]

提供的 values.yaml 配置:

deployment:
  replicaCount: 1
  image:
    name: "your.image.registry/group/image.name"
    tag: latest
    imagePullPolicy: Always

imagePullSecrets:
  - name: "image-pull-secret-1"
  - name: "image-pull-secret-2"
  • Service 配置
apiVersion: v1
kind: Service
metadata:
  name: demo
  labels:
    app: demo
spec:
  type: ClusterIP
  ports:
    - name: demo
      port: 80
      targetPort: http
  selector:
    app: demo
  • Ingress 配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
spec:
  tls:
    - hosts:
        - {{.Values.ingress.host.name}}
      secretName: {{.Values.ingress.tls.secretName}}
  rules:
    - host: {{.Values.ingress.host.name}}
      http:
        paths:
          - pathType: Prefix
            path: /v1/api/demo
            backend:
              service:
                name: demo
                port:
                  number: 80

HELM部署K8S全过程

部署到kubernetes

在mychart目录下执行下面的命令将nginx部署到kubernetes集群上。

helm install .

NAME: eating-hound

LAST DEPLOYED: Wed Oct 25 14:58:15 2017

NAMESPACE: default

STATUS: DEPLOYED

RESOURCES:

==> v1/Service

NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE

eating-hound-mychart 10.254.135.68 <none> 80/TCP 0s

==> extensions/v1beta1/Deployment

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

eating-hound-mychart 1 1 1 0 0s

NOTES:

1. Get the application URL by running these commands:

export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -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

现在nginx已经部署到kubernetes集群上,本地执行提示中的命令在本地主机上访问到nginx实例。

export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -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

在本地访问http://127.0.0.1:8080即可访问到nginx。

查看部署的relaese

$ helm list

NAME REVISION UPDATED STATUS CHART NAMESPACE

eating-hound 1 Wed Oct 25 14:58:15 2017 DEPLOYED mychart-0.1.0 default

删除部署的release

$ helm delete eating-hound

release "eating-hound" deleted

打包分享

我们可以修改Chart.yaml中的helm chart配置信息,然后使用下列命令将chart打包成一个压缩文件。

helm package .

打包出mychart-0.1.0.tgz文件。

将应用发布到 Repository

虽然我们已经打包了 Chart 并发布到了 Helm 的本地目录中,但通过 helm search 命令查找,并不能找不到刚才生成的 mychart包。

$ helm search mychart

No results found

这是因为 Repository 目录中的 Chart 包还没有被 Helm 管理。通过 helm repo list 命令可以看到目前 Helm 中已配置的 Repository 的信息。

$ helm repo list

NAME URL

stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

注:新版本中执行 helm init 命令后默认会配置一个名为 local 的本地仓库。

我们可以在本地启动一个 Repository Server,并将其加入到 Helm Repo 列表中。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/

通过 helm repo index 命令将 Chart 的 Metadata 记录更新在 index.yaml 文件中:

# 更新 Helm Repository 的索引文件

$ cd /home/k8s/.helm/repository/local

$ helm repo index --url=http://192.168.100.211:8879 .

完成启动本地 Helm Repository Server 后,就可以将本地 Repository 加入 Helm 的 Repo 列表。

$ helm repo add local http://127.0.0.1:8879

"local" has been added to your repositories

现在再次查找 mychart 包,就可以搜索到了。

$ helm repo update

$ helm search mychart

NAME CHART VERSION APP VERSION DESCRIPTION

local/mychart 0.1.0 1.0 A Helm chart for Kubernetes

依赖

我们可以在requirement.yaml中定义应用所依赖的chart,例如定义对mariadb的依赖:

dependencies:

- name: mariadb

version: 0.6.0

repository: https://kubernetes-charts.storage.googleapis.com

使用helm lint .命令可以检查依赖和模板配置是否正确。

helm升级和回退一个应用

从上面 helm list 输出的结果中我们可以看到有一个 Revision(更改历史)字段,该字段用于表示某一个 Release 被更新的次数,我们可以用该特性对已部署的 Release 进行回滚。

修改 Chart.yaml 文件

将版本号从 0.1.0 修改为 0.2.0, 然后使用 helm package 命令打包并发布到本地仓库。

$ cat mychart/Chart.yaml

apiVersion: v1

appVersion: "1.0"

description: A Helm chart for Kubernetes

name: mychart

version: 0.2.0

$ helm package mychart

Successfully packaged chart and saved it to: /home/k8s/mychart-0.2.0.tgz

查询本地仓库中的 Chart 信息

我们可以看到在本地仓库中 mychart 有两个版本。

$ helm search mychart -l

NAME CHART VERSION APP VERSION DESCRIPTION

local/mychart 0.2.0 1.0 A Helm chart for Kubernetes

local/mychart 0.1.0 1.0 A Helm chart for Kubernetes

升级一个应用

现在用 helm upgrade 命令将已部署的 mike-test 升级到新版本。你可以通过 --version 参数指定需要升级的版本号,如果没有指定版本号,则缺省使用最新版本。

$ helm upgrade mike-test local/mychart

Release "mike-test" has been upgraded. Happy Helming!

LAST DEPLOYED: Mon Jul 23 10:50:25 2018

NAMESPACE: default

STATUS: DEPLOYED

RESOURCES:

==> v1/Pod(related)

NAME READY STATUS RESTARTS AGE

mike-test-mychart-6d56f8c8c9-d685v 1/1 Running 0 9m

==> v1/Service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

mike-test-mychart ClusterIP 10.254.120.177 <none> 80/TCP 9m

==> v1beta2/Deployment

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

mike-test-mychart 1 1 1 1 9m

NOTES:

1. Get the application URL by running these commands:

export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-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

完成后,可以看到已部署的 mike-test 被升级到 0.2.0 版本。

$ helm list

NAME REVISION UPDATED STATUS CHART NAMESPACE

mike-test 2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 default

回退一个应用

如果更新后的程序由于某些原因运行有问题,需要回退到旧版本的应用。首先我们可以使用 helm history 命令查看一个 Release 的所有变更记录。

$ helm history mike-test

REVISION UPDATED STATUS CHART DESCRIPTION

1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete

2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 Upgrade complete

其次,我们可以使用下面的命令对指定的应用进行回退。

$ helm rollback mike-test 1

Rollback was a success! Happy Helming!

注:其中的参数 1 是 helm history 查看到 Release 的历史记录中 REVISION 对应的值。

最后,我们使用 helm list 和 helm history 命令都可以看到 mychart 的版本已经回退到 0.1.0 版本。

$ helm list

NAME REVISION UPDATED STATUS CHART NAMESPACE

mike-test 3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 default

$ helm history mike-test

REVISION UPDATED STATUS CHART DESCRIPTION

1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete

2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete

3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 Rollback to 1

删除一个应用

如果需要删除一个已部署的 Release,可以利用 helm delete 命令来完成删除。

$ helm delete mike-test

release "mike-test" deleted

确认应用是否删除,该应用已被标记为 DELETED 状态。

$ helm ls -a mike-test

NAME REVISION UPDATED STATUS CHART NAMESPACE

mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default

也可以使用 --deleted 参数来列出已经删除的 Release

$ helm ls --deleted

NAME REVISION UPDATED STATUS CHART NAMESPACE

mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default

从上面的结果也可以看出,默认情况下已经删除的 Release 只是将状态标识为 DELETED 了 ,但该 Release 的历史信息还是继续被保存的。

$ helm hist mike-test

REVISION UPDATED STATUS CHART DESCRIPTION

1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete

2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete

3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 Deletion complete

如果要移除指定 Release 所有相关的 Kubernetes 资源和 Release 的历史记录,可以用如下命令:

$ helm delete --purge mike-test

release "mike-test" deleted

再次查看已删除的 Release,已经无法找到相关信息。

$ helm hist mike-test

Error: release: "mike-test" not found

# helm ls 命令也已均无查询记录。

$ helm ls --deleted

$ helm ls -a mike-test

使用Helm 部署 Wordpress应用实例

以Wordpress 为例,包括 MySQL、PHP 和 Apache。

由于测试环境没有可用的 PersistentVolume(持久卷,简称 PV),这里暂时将其关闭。

$ helm install --name wordpress-test --set "persistence.enabled=false,mariadb.persistence.enabled=false,serviceType=NodePort" stable/wordpress

NAMESPACE: default

STATUS: DEPLOYED

RESOURCES:

==> v1beta1/Deployment

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

wordpress-test-mariadb 1 1 1 1 26m

wordpress-test-wordpress 1 1 1 1 26m

==> v1/Pod(related)

NAME READY STATUS RESTARTS AGE

wordpress-test-mariadb-84b866bf95-n26ff 1/1 Running 1 26m

wordpress-test-wordpress-5ff8c64b6c-sgtvv 1/1 Running 6 26m

==> v1/Secret

NAME TYPE DATA AGE

wordpress-test-mariadb Opaque 2 26m

wordpress-test-wordpress Opaque 2 26m

==> v1/ConfigMap

NAME DATA AGE

wordpress-test-mariadb 1 26m

wordpress-test-mariadb-tests 1 26m

==> v1/Service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

wordpress-test-mariadb ClusterIP 10.254.99.67 <none> 3306/TCP 26m

wordpress-test-wordpress NodePort 10.254.175.16 <none> 80:8563/TCP,443:8839/TCP 26m

NOTES:

1. Get the WordPress URL:

Or running:

export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress)

export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")

echo http://$NODE_IP:$NODE_PORT/admin

2. Login with the following credentials to see your blog

echo Username: user

echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

访问 Wordpress

部署完成后,我们可以通过上面的提示信息生成相应的访问地址和用户名、密码等相关信息。

# 生成 Wordpress 管理后台地址

$ export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress)

$ export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")

$ echo http://$NODE_IP:$NODE_PORT/admin

http://192.168.100.211:8433/admin

# 生成 Wordpress 管理帐号和密码

$ echo Username: user

Username: user

$ echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

Password: 9jEXJgnVAY

Helm 其它使用技巧

如何设置 helm 命令自动补全?

为了方便 helm 命令的使用,Helm 提供了自动补全功能,如果使用 ZSH 请执行:

$ source <(helm completion zsh)

如果使用 BASH 请执行:

$ source <(helm completion bash)

如何使用第三方的 Chart 存储库?

随着 Helm 越来越普及,除了使用预置官方存储库,三方仓库也越来越多了(前提是网络是可达的)。你可以使用如下命令格式添加三方 Chart 存储库。

$ helm repo add 存储库名 存储库URL

$ helm repo update

  • 49
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好学技术oH

你的鼓励是一起学习的动力何阶梯

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值