k8s-Helm相关
1.helm简介
在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较繁琐。况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用的部署和管理。
Helm 本质就是让K8s的应用管理(Deployment,Service 等)可配置,能动态生成。通过动态生成 K8s资源清单文件(deployment.yaml,service.yaml)。然后调用Kubectl自动执行K8s资源部署
helm重要概念
Helm 是官方提供的类似于YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart和release
- chart:是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。chart 是应用部署的自包含逻辑单元。可以将 chart 想象成 apt、yum 中的软件安装包
- release:是chart 的运行实例,代表了一个正在运行的应用。当chart被安装到Kubernetes集群,就生成一个 release。chart 能够多次安装到同一个集群,每次安装都是一个 release
- Helm cli:helm 客户端组件,负责和 kubernetes apiS 通信
- Repository:用于发布和存储Chart 的仓库
2.helm安装
a.安装初始化
安装
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
# 自动补全
echo 'source <(helm completion bash)' >> ~/.bashrc
初始化
当您已经安装好了Helm之后,您可以添加一个chart 仓库。从 Artifact Hub 中查找有效的Helm chart 仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo remove bitnami
# 查看当前添加的仓库信息
helm repo ls
# 查看安装的 charts 列表
helm search repo bitnami
安装 chart 示例
# 确定我们可以拿到最新的 charts 列表
helm repo update
# 查看helm下apache仓库配置信息
helm show values bitnami/apache
# 安装apache --generate-name自动生成一个名称
helm install bitnami/apache --generate-name
helm install bitnami/apache --generate-name \
--set image.registry=https://docker.xuanyuan.me \
--set image.repository=bitnami/apache
# chart 的基本信息
helm show chart bitnami/apache
# chart 的所有信息
helm show all bitnami/apache
卸载一个版本
# 查看当前启动的release
helm list
# 该命令会从Kubernetes卸载 apache-1612624192,它将删除和该版本相关的所有相关资源(service、deployment、 pod等等)甚至版本历史,--keep-history # 选项, Helm 将会保存版本历史
helm uninstall apache-1612624192
# 查看该版本的信息
helm status apache-1612624192
b.三大概念
Chart 代表着 Helm 包。它包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。你可以把它看作是 Homebrew formula,Apt dpkg,或 Yum RPM 在Kubernetes 中的等价物
'helm search':查找 Charts
# 用于在 Helm Hub(https://hub.helm.sh)上搜索 Helm charts
helm search hub wordpress
# 用于在配置的 Helm 仓库中搜索 Helm charts,~/.config/helm/repositories.yaml 中被定义持久化
helm search repo wordpress
# Helm 搜索使用模糊字符串匹配算法,所以你可以只输入名字的一部分
'helm install':安装一个 helm 包
helm install 自定义release名字 bitnami/apache
Helm按照以下顺序安装资源:
- Namespace
- NetworkPolicy
- ResourceQuota
- LimitRange
- PodSecurityPolicy
- PodDisruptionBudget
- ServiceAccount
- Secret
- SecretList
- ConfigMap
- StorageClass
- PersistentVolume
- PersistentVolumeClaim
- CustomResourceDefinition
- ClusterRole
- ClusterRoleList
- ClusterRoleBinding
- ClusterRoleBindingList
- Role
- RoleList
- RoleBinding
- RoleBindingList
- Service
- DaemonSet
- Pod
- ReplicationController
- ReplicaSet
- Deployment
- HorizontalPodAutoscaler
- StatefulSet
- Job
- CronJob
- Ingress
- APIService
安装前自定义 chart
# 查看 chart 中的可配置选项
helm show values bitnami/apache
# 使用 YAML 格式的文件覆盖上述任意配置项,并在安装过程中使用该文件
vi values.yaml
service:
type: NodePort
# 默认会将values.yaml的内容替换官方配置文件的内容
helm install -f values.yaml bitnami/apache --generate-name
安装过程中有两种方式传递配置数据:
--values(或-f):使用 YAML 文件覆盖配置。可以指定多次,优先使用最右边的文件。--set:通过命令行的方式对指定项进行覆盖。
如果同时使用两种方式,则 --set 中的值会被合并到 --values 中,但是 --set 中的值优先级更高。在--set 中覆盖的内容会被被保存在 ConfigMap 中。可以通过 helm get values <release-name> 来查看指定 release 中 --set 设置的值。也可以通过运行 helm upgrade 并指定 --reset-values 字段来清除 --set 中设置的值。
--set 的格式和限制
--set 选项使用0或多个 name/value 对。最简单的用法类似于:--set name=value,等价于如下 YAML 格式:
name: value
多个值使用逗号分割,因此 --set a=b,c=d 的 YAML 表示是:
a: b
c: d
支持更复杂的表达式。例如,--set outer.inner=value 被转换成了:
outer:
inner: value
列表使用花括号({})来表示。例如,--set name={a, b, c} 被转换成了:
name:
- a
- b
- c
某些name/key可以设置为null或者空数组,例如 --set name=[],a=null 由
name:
- a
- b
- c
a: b
变成了
name: []
a: null
从 2.5.0 版本开始,可以使用数组下标的语法来访问列表中的元素。例如 --set servers[0].port=80 就变成了:
servers:
- port: 80
多个值也可以通过这种方式来设置。--set servers[0].port=80,servers[0].host=example 变成了:
servers:
- port: 80
host: example
如果需要在 --set 中使用特殊字符,你可以使用反斜线来进行转义;--set name=value1\,value2 就变成了:
name: "value1,value2"
类似的,你也可以转义点序列(英文句号)。这可能会在 chart 使用 toYaml 函数来解析 annotations,labels,和 node selectors 时派上用场。--set nodeSelector."kubernetes\.io/role"=master 语法就变成了:
nodeSelector:
kubernetes.io/role: master
深层嵌套的数据结构可能会很难用 --set 表达。我们希望 Chart 的设计者们在设计 values.yaml 文件的格式时,考虑到 --set 的使用。(更多内容请查看 Values 文件)
'helm upgrade' 和 'helm rollback':升级 release 和失败时恢复
当你想升级到 chart 的新版本,或是修改 release 的配置,你可以使用 helm upgrade 命令。
一次升级操作会使用已有的 release 并根据你提供的信息对其进行升级。由于 Kubernetes 的 chart 可能会很大而且很复杂,Helm 会尝试执行最小侵入式升级。即它只会更新自上次发布以来发生了更改的内容。
$ helm upgrade -f panda.yaml happy-panda bitnami/wordpress
在上面的例子中,happy-panda 这个 release 使用相同的 chart 进行升级,但是使用了一个新的 YAML 文件:
mariadb.auth.username: user1
我们可以使用 helm get values 命令来看看配置值是否真的生效了:
$ helm get values happy-panda
mariadb:
auth:
username: user1
helm get 是一个查看集群中 release 的有用工具。正如我们上面所看到的,panda.yaml 中的新值已经被部署到集群中了。
现在,假如在一次发布过程中,发生了不符合预期的事情,也很容易通过 helm rollback [RELEASE] [REVISION] 命令回滚到之前的发布版本。
$ helm rollback happy-panda 1
上面这条命令将我们的 happy-panda 回滚到了它最初的版本。release 版本其实是一个增量修订(revision)。 每当发生了一次安装、升级或回滚操作,revision 的值就会加1。第一次 revision 的值永远是1。我们可以使用 helm history [RELEASE] 命令来查看一个特定 release 的修订版本号。
安装、升级、回滚时的有用选项
你还可以指定一些其他有用的选项来自定义 Helm 在安装、升级、回滚期间的行为。请注意这并不是 cli 参数的完整列表。 要查看所有参数的说明,请执行 helm <command> --help 命令。
--timeout:一个 Go duration 类型的值, 用来表示等待 Kubernetes 命令完成的超时时间,默认值为5m0s。--wait:表示必须要等到所有的 Pods 都处于 ready 状态,PVC 都被绑定,Deployments 都至少拥有最小 ready 状态 Pods 个数(Desired减去maxUnavailable),并且 Services 都具有 IP 地址(如果是LoadBalancer, 则为 Ingress),才会标记该 release 为成功。最长等待时间由--timeout值指定。如果达到超时时间,release 将被标记为FAILED。注意:当 Deployment 的replicas被设置为1,但其滚动升级策略中的maxUnavailable没有被设置为0时,--wait将返回就绪,因为已经满足了最小 ready Pod 数。--no-hooks:不运行当前命令的钩子。--recreate-pods(仅适用于upgrade和rollback):这个参数会导致重建所有的 Pod(deployment中的Pod 除外)。(在 Helm 3 中已被废弃)
'helm uninstall':卸载 release
使用 helm uninstall 命令从集群中卸载一个 release:
$ helm uninstall happy-panda
该命令将从集群中移除指定 release。你可以通过 helm list 命令看到当前部署的所有 release:
$ helm list
NAME VERSION UPDATED STATUS CHART
inky-cat 1 Wed Sep 28 12:59:46 2016 DEPLOYED alpine-0.1.0
从上面的输出中,我们可以看到,happy-panda 这个 release 已经被卸载。
在上一个 Helm 版本中,当一个 release 被删除,会保留一条删除记录。而在 Helm 3 中,删除也会移除 release 的记录。 如果你想保留删除记录,使用 helm uninstall --keep-history。使用 helm list --uninstalled 只会展示使用了 --keep-history 删除的 release。
helm list --all 会展示 Helm 保留的所有 release 记录,包括失败或删除的条目(指定了 --keep-history):
$ helm list --all
NAME VERSION UPDATED STATUS CHART
happy-panda 2 Wed Sep 28 12:47:54 2016 UNINSTALLED wordpress-10.4.5.6.0
inky-cat 1 Wed Sep 28 12:59:46 2016 DEPLOYED alpine-0.1.0
kindred-angelf 2 Tue Sep 27 16:16:10 2016 UNINSTALLED alpine-0.1.0
注意,因为现在默认会删除 release,所以你不再能够回滚一个已经被卸载的资源了。
'helm repo':使用仓库
Helm 3 不再附带一个默认的 chart 仓库。helm repo 提供了一组命令用于添加、列出和移除仓库。
使用 helm repo list 来查看配置的仓库:
$ helm repo list
NAME URL
stable https://charts.helm.sh/stable
mumoshu https://mumoshu.github.io/charts
使用 helm repo add 来添加新的仓库:
$ helm repo add dev https://example.com/dev-charts
因为 chart 仓库经常在变化,在任何时候你都可以通过执行 helm repo update 命令来确保你的 Helm 客户端是最新的。
使用 helm repo remove 命令来移除仓库。
3.创建一个自己的chart
基本模式
# 1、创建一个模板
helm create myapp
# 2、删除不用的文件
cd myapp && rm -rf values.yaml templates/*
# 3、编写 template 下的 service 和 deployment 资源清单
cat >./templates/nodePort.yaml<<EOF
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp-test
name: myapp-test-202401110926-svc
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
nodePort: 31341
selector:
app: myapp-test
type: NodePort
[root@k8s-master01 myapp]# cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp-test
name: myapp-test-202401110926-deploy
spec:
replicas: 5
selector:
matchLabels:
app: myapp-test
template:
metadata:
labels:
app: myapp-test
spec:
containers:
- image: wangyanglinux/myapp:v1.0
name: myapp
EOF
# 4、发布部署
helm install myapp myapp/
注入 HELM 灵魂
cat templates/NOTES.txt
1、这是一个测试的 myapp chart
2、myapp release 名字:myapp-test-{{ now | date "20060102030405" }}-deploy
3、service 名字:myapp-test-{{ now | date "20060102030405" }}-svc
---------------------------------------------------------------------------------
-
cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myapp-test
name: myapp-test-{{ now | date "20060102030405" }}-deploy
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: myapp-test
template:
metadata:
labels:
app: myapp-test
spec:
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: myapp
---------------------------------------------------------------------------------
-
cat templates/service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: myapp-test
name: myapp-test-{{ now | date "20060102030405" }}-svc
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
{{- if eq .Values.service.type "NodePort" }}
nodePort: {{.Values.service.nodeport }}
{{- end }}
selector:
app: myapp-test
type: {{ .Values.service.type | quote }}
---------------------------------------------------------------------------------
-
cat values.yaml
# Default values for myapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 5
image:
repository: wangyanglinux/myapp
tag: "v1.0"
service:
type: NodePort
nodeport: 32321
4.Ingress-nginx(七层负载)
负载均衡
- 四层负载(lvs,ipvs)
- 一次完整的TCP连接,由客户端与真实服务器建立,调度器只起到转发的作用

- 七层负载(nginx)
- 两次完整的TCP连接,由客户端与调度器建立连接,调度器与真实服务器建立连接(调度器-代理服务器)

基于手动的七层实现

基于IngressAPI的七层实现

Ingress-nginx部署
# 使用helm拉取chart
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm pu1l ingress-nginx/ingress-nginx
# 修改values.yaml文件
1- 修改 hostNetwork 的值为 true
2- dnsPolicy的值改为: clusterFirstwithHostNet
3- kind类型更改为:Daemonset
4- 关闭所有镜像的 digest,注释digest开头行
5- ingressClassResource.default=true
# 创建名字空间
kubectl create ns ingress
# 安装
helm install igs-nginx -n ingress . -f values.yaml
# 删除
helm uninstall igs-nginx -n ingress
kubectl delete jobs,pods -n ingress -l app.kubernetes.io/instance=igs-nginx

1.Ingress-nginx http 代理
# deployment、Service、Ingress Yaml 文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-httpproxy-www1
spec:
replicas: 2
selector:
matchLabels:
hostname: www1
template:
metadata:
labels:
hostname: www1
spec:
containers:
- name: nginx
image: wangyanglinux/myapp:v1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: ingress-httpproxy-www1
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
hostname: www1
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-httpproxy-www1
spec:
ingressClassName: nginx
rules:
- host: www1.xinxianghf.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ingress-httpproxy-www1
port:
number: 80
2.Ingress-nginx https 代理
# 生成证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -
out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls ingress-nginx-tls --key tls.key --cert tls.crt
# deployment、Service、Ingress Yaml 文件
cat >./deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-httpproxy-ssl
spec:
replicas: 2
selector:
matchLabels:
hostname: ssl
template:
metadata:
labels:
hostname: ssl
spec:
containers:
- name: nginx
image: wangyanglinux/myapp:v3.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: ingress-httpproxy-ssl
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
hostname: ssl
EOF
cat >./ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-httpproxy-ssl
namespace: default
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
rules:
- host: ssl.xinxianghf.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ingress-httpproxy-ssl
port:
number: 80
tls:
- hosts:
- ssl.xinxianghf.com
secretName: ingress-nginx-tls
EOF
3.Ingress-nginx BasicAuth 代理
# http 认证文件创建
dnf -y install httpd-tools
htpasswd -c auth xinxianghf
kubectl create secret generic ingress-basic-auth --from-file=auth
cat >./ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: ingress-basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - xinxianghf'
spec:
ingressClassName: nginx
rules:
- host: auth.xinxianghf.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: ingress-httpproxy-www1
port:
number: 80
EOF
4.Ingress-nginx 域名重定向
cat >./ingress-redirect.yaml<<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: redirect.xinxianghf.com
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
nginx.ingress.kubernetes.io/permanent-redirect-code: '301'
spec:
ingressClassName: "nginx"
rules:
- host: redirect.xinxianghf.com
http:
EOF
5.Ingress-nginx Rewrite
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rew.xinxianghf.com
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: "nginx"
rules:
- host: rew.xinxianghf.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: www1svc
port:
number: 80
6-13. Ingress-nginx 更多进阶配置
包含 Rewrite 和 Redirect、错误代码重定向、黑白名单、速率限制、灰度/金丝雀发布、代理后端 HTTPS、四层代理、链路追踪等高级功能。按需参考 Ingress-Nginx 官方文档。