进击云原生

V2

2022/12/26阅读:17主题:山吹

使用 Docker Hub 完美地存储 Helm 图表实战

使用 Docker Hub 完美地存储 Helm 图表实战

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 的新图表:

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 目录外运行以下命令。

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 发生了变化。

helm install kubeinfo --dry-run --debug ./kubeinfo --set service.internalPort=8080

4.对外暴露

默认情况下,chart 会创建一个 ClusterIP 类型的 Service,因此 NGINX 只会暴露在集群内部。要从外部访问它,我们将改用 NodePort 类型。我们还可以设置 Helm 版本的名称,以便我们可以轻松地引用它。让我们继续使用 helm install 命令部署我们的 NGINX chart:

helm install example ./kubeinfo --set service.type=NodePort

5.打包 Helm Chart

完成编辑后,我们需要将 Helm 图表打包为 OCI 图像:

helm package kubeinfo
Successfully packaged chart and saved it to: /Users/ajeetraina/dec/kubeinfo-0.1.0.tgz

6.登录到 Docker Hub

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/

7. 推送到 Docker Hub

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,然后登录,如下所示:

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。

作者:collabnix 出处:https://collabnix.com/how-to-build-push-helm-chart-to-docker-hub-flawlessly/

说明

请关注 危 ❤ 工中号【进击云原生】,更有 free 资源供您学习

参考资料

[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/

分类:

后端

标签:

后端

作者介绍

进击云原生
V2

公众号:进击云原生