Helm[1] 是 Kubernetes 的包管理器。它是一个开源容器编排系统。它通过提供一种简单的方法来定义、安装和升级复杂的 Kubernetes 应用程序,帮助您管理 Kubernetes 应用程序。
使用 Helm,您可以将您的应用程序打包成一个 chart[2],它是描述您的应用程序的一组文件。然后,您可以使用 Helm 在 Kubernetes 集群上安装和管理您的应用程序。Helm 可以轻松地自动安装和管理复杂的应用程序,它提供的许多功能使其成为管理 Kubernetes 应用程序的强大工具。
使用 Helm 的一些好处包括:
- 简化安装和管理复杂 Kubernetes 应用程序的过程。
- 使应用程序的部署和管理自动化变得容易。
- 允许您对应用程序配置进行版本控制。
- 提供一种通过公共或私人图表存储库与他人共享应用程序的方法。
- 如有必要,可以轻松回滚到应用程序的先前版本。
总的来说,Helm 是在 Kubernetes 上管理和部署应用程序的有用工具,它可以帮助您简化在 Kubernetes 集群上管理复杂应用程序的过程。
为什么 Docker 支持 Helm Chart?
Docker Hub[3] 是 Docker 提供的流行的托管存储库服务,用于查找容器镜像并与您的团队共享。它是一个容器镜像存储库,用于存储和分发容器镜像,或容器运行时可用的工件。因为容器镜像分发只是应用程序交付过程的起点,这成为我们平台的限制。
现在的应用程序支持许多工件,例如 WebAssembly 模块、OPA Bundle、Helm 图表、SBOM 和自定义工件。因此,Docker Hub 团队必须支持所有这些工件,以便开发人员可以与需要它们的客户共享这些工件,因为这为他们的项目增加了巨大的价值。2022 年 10 月,Docker 宣布[4] Docker Hub 现在可以帮助您分发任何类型的应用程序工件!您现在可以将所有内容保存在一个地方,而无需利用多个注册表。
在此博客中,您将看到 Docker Hub 如何完美地存储 Helm 图表。
1. 创建 Helm 图表
开始使用新图表的最佳方法是使用 helm create 命令搭建一个我们可以构建的示例。使用此命令在新目录中创建一个名为 kubeinfo 的新图表:
代码语言:javascript复制helm create kubeinfo
2. 查看图表
Helm 将在您的项目中创建一个新目录, kubeinfo
其结构如下所示。让我们浏览我们的新图表以了解它是如何工作的。
demo % tree
.
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
3 directories, 10 files
文件结构中最重要的部分是 template/目录。这是 Helm 查找Services, Deployments
和其他 Kubernetes 对象的 YAML 定义的地方。如果您已经有了应用程序的定义,那么所需要做的就是将生成的 YAML 文件替换为您自己的。最终得到的是一个可以使用 helm install 命令部署的 chart。
打开 service.yaml
文件看看它长什么样子:
apiVersion: v1
kind: Service
metadata:
name: {{ include "kubeinfo.fullname" . }}
labels:
{{- include "kubeinfo.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "kubeinfo.selectorLabels" . | nindent 4 }}
这是使用模板的基本服务定义。部署图表时,Helm 将生成一个看起来更像有效服务的定义。我们可以试运行 helm 安装并启用调试以检查生成的定义。
请确保在 Helm 目录外运行以下命令。
代码语言:javascript复制helm install kubeinfo --dry-run --debug ./kubeinfo
install.go:192: [debug] Original chart version: ""
install.go:209: [debug] CHART PATH: /Users/ajeetraina/dec/kubeinfo
NAME: kubeinfo
LAST DEPLOYED: Thu Dec 8 11:02:54 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
affinity: {}
autoscaling:
enabled: false
maxReplicas: 100
minReplicas: 1
targetCPUUtilizationPercentage: 80
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: ""
imagePullSecrets: []
ingress:
annotations: {}
className: ""
enabled: false
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
nameOverride: ""
nodeSelector: {}
podAnnotations: {}
podSecurityContext: {}
replicaCount: 1
resources: {}
securityContext: {}
service:
port: 80
type: ClusterIP
serviceAccount:
annotations: {}
create: true
name: ""
tolerations: []
HOOKS:
---
# Source: kubeinfo/templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "kubeinfo-test-connection"
labels:
helm.sh/chart: kubeinfo-0.1.0
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['kubeinfo:80']
restartPolicy: Never
MANIFEST:
---
# Source: kubeinfo/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubeinfo
labels:
helm.sh/chart: kubeinfo-0.1.0
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
---
# Source: kubeinfo/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: kubeinfo
labels:
helm.sh/chart: kubeinfo-0.1.0
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
---
# Source: kubeinfo/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubeinfo
labels:
helm.sh/chart: kubeinfo-0.1.0
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
template:
metadata:
labels:
app.kubernetes.io/name: kubeinfo
app.kubernetes.io/instance: kubeinfo
spec:
serviceAccountName: kubeinfo
securityContext:
{}
containers:
- name: kubeinfo
securityContext:
{}
image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{}
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=kubeinfo,app.kubernetes.io/instance=kubeinfo" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
3.更改 service.internalPort 的默认值
如果再执行一次试运行,您应该会发现 Service 中的 targetPort 和 Deployment 中的 containerPort 发生了变化。
代码语言:javascript复制helm install kubeinfo --dry-run --debug ./kubeinfo --set service.internalPort=8080
4.对外暴露
默认情况下,chart 会创建一个 ClusterIP 类型的 Service,因此 NGINX 只会暴露在集群内部。要从外部访问它,我们将改用 NodePort 类型。我们还可以设置 Helm 版本的名称,以便我们可以轻松地引用它。让我们继续使用 helm install 命令部署我们的 NGINX chart:
代码语言:javascript复制helm install example ./kubeinfo --set service.type=NodePort
3.打包 Helm Chart
完成编辑后,我们需要将 Helm 图表打包为 OCI 图像:
代码语言:javascript复制helm package kubeinfo
Successfully packaged chart and saved it to: /Users/ajeetraina/dec/kubeinfo-0.1.0.tgz
5.登录到 Docker Hub
代码语言:javascript复制docker login
Authenticating with existing credentials...
Login Succeeded
Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
6. 推送到 Docker Hub
代码语言:javascript复制helm push kubeinfo-0.1.0.tgz oci://registry-1.docker.io/ajeetraina
Error: server message: insufficient_scope: authorization failed
您可能会遇到错误消息。
修复:建议创建个人访问令牌:Personal Access Token (PAT)。
您可以通过环境变量 export PAT,然后登录,如下所示:
代码语言:javascript复制echo $REG_PAT | helm registry login registry-1.docker.io -u ajeetraina --password-stdin
Login Succeeded
结论
将 Helm Charts 存储在 Docker Hub 中可以通过 Docker Hub 的标准共享功能改进协作。开发人员现在可以使用 Docker Desktop 的搜索功能在本地构建 Helm chart,然后将其完美地推送到 Docker Hub。
参考资料
[1]
Helm: https://helm.sh/
[2]
chart: https://artifacthub.io/
[3]
Docker Hub: https://www.docker.com/products/docker-hub/
[4]
宣布: https://www.docker.com/blog/announcing-docker-hub-oci-artifacts-support/
- END -