直航舵图最佳实践

Kubernetes是容器应用程序的流行编曲工具,它以希腊语“领航员”一词命名,即掌舵者。但就像在任何旅行中一样,导航员只能和可用的地图一样成功。

应用程序的图表就是这个映射,可以从一个执掌图表库描述了一组相关的K8s资源。2022世界杯阿根廷预选赛赛程当Kubernetes将容器部署到您的生产环境时,以最有效的方式制作您的Helm图表将帮助它通过浅滩。

但是也有其他的方法可以让我们误入歧途,就像我在开发公开的K8s图表来部署产品时所发现的那样。hth华体会最新官方网站对于每一个pull请求,来自Helm社区的反馈都帮助我找到了为操作和更新容器提供最强结果的Helm图表最佳实践。


了解更多:10 Helm教程开始您的Kubernetes之旅


在编写社区或客户在生产中使用的K8s图表时,需要考虑以下几点。你需要考虑的事情包括:

  • 需要定义哪些依赖关系?
  • 您的应用程序是否需要一个持久状态来操作?
  • 您将如何通过秘密和权限处理安全性?
  • 如何控制运行的kubelet容器?
  • 如何确保您的应用程序正在运行并能够接收调用?
  • 如何向外界公开应用程序的服务?
  • 你将如何测试你的图表?

本指南提供了一些构建和指定Helm图的最佳实践,帮助k8将容器应用程序顺利交付到码头。


头盔是为每个人:获得免费指南头盔


开始

在开始之前,请确保您熟悉基本的程序发展中执掌图表

在本指南中,我们将创建一个Helm图表,它遵循我们推荐的部署两层架构的最佳实践创建、读取、更新和删除(使用Express.js编写Mongo数据库的CRUD)应用程序。

您可以在中找到我们示例应用程序的源代码在GitHub express-crud

创建并填充Helm图表

让我们使用舵手客户端创建我们的模板舵手图表创建命令

$ helm create express-crud

对象的目录结构express-crud执掌图表。

控件中的图表元数据Chart.yaml刚刚创建的文件。确保添加适当的信息appVersion(用作docker图像标签的应用程序版本),描述版本(一个SemVer 2版本字符串),来源维护人员而且图标

apiVersion: v1 appVersion: "1.0.0"描述:一个Helm chart for express-crud应用程序名称:express-crud版本:0.1.0来源:- https://github.com/jainishshah17/express-mongo-crud维护者:-名称:myaccount电子邮件:myacount@mycompany.com图标:https://github.com/mycompany17/mycompany.com/blob/master/app/public/images/logo.jpg home: https://mycompany.com/

定义依赖关系

如果您的应用程序具有依赖关系,那么你必须创建一个requirements.yaml文件在Helm图表的目录结构中指定了它们。因为我们的应用程序需要mongodb数据库,我们必须在依赖关系的列表requirements.yaml我们创建的文件。

一个requirements.yaml对于此示例,包含

依赖项:—name: mongodb version: 3.0.4 repository: https://kubernetes-charts.storage.googleapis.com/ condition: mongodb.enabled

一次requirements.yaml文件创建后,必须运行依赖项更新命令:

$ helm dep更新

创建部署文件

Helm图的部署文件驻留在\模板子目录并指定K8s将如何部署容器应用程序。

在开发部署文件时,需要做出一些关键的决定。

部署对象vs状态集对象

创建的部署文件将取决于应用程序是否需要k8将其作为部署对象或StatefulSet对象

部署对象是在文件名中声明的无状态应用程序deployment.yaml和指定种类参数,部署

有状态对象用于有状态的应用程序并用于分布式系统。它们在文件名中声明stateless.yaml和物种的种类参数,有状态

部署 StatefulSet
部署用于无状态使用,相当轻量级。 当必须持久保存状态时,使用statefulset。因此,使用volumeClaimTemplates在持久卷上,以确保它们可以在组件重新启动时保持状态。
如果您的应用程序是无状态的,或者可以在启动期间从后端系统构建状态,那么请使用部署。 如果您的应用程序是有状态的,或者如果您想在Kubernetes上部署有状态存储,请使用StatefulSet。

由于这个应用程序不需要保持状态,我使用部署对象。
deployment.yaml文件已由执掌创建命令。

我们将使用AppVersion作为应用程序的Docker图像标记。这允许我们升级Helm图表与新版本的应用程序,只需更改值Chart.yaml

形象:“{{.Values.image。{{default . chart . repository}}:AppVersion .Values.image。标签}}”

秘密和ConfigMap

您需要确定哪些凭据或配置数据适合存储为秘密,并且可以在ConfigMap

机密指的是k8将以加密格式存储的密码等敏感信息。

ConfigMap是一个文件,其中包含可能由应用程序共享的配置信息。ConfigMap中的信息没有加密,因此不应该包含任何敏感信息。

秘密 ConfigMap
将这些信息隐藏起来比将其逐字逐句地放在pod定义或docker映像中更安全、更灵活; ConfigMap允许您将配置工件与图像内容解耦,以保持容器化应用程序的可移植性
用于机密数据 用于非机密数据
示例使用:API密钥、密码、令牌和ssh密钥 示例使用:日志旋转器,没有机密数据的配置

在本例中,我们将允许Helm从私有中提取docker映像码头工人注册使用图像拉秘密。

此过程依赖于为库管理器指定登录凭证的Kubernetes集群提供一个可用的秘密。这个秘密可以由一个kubectl命令如行:

$ kubectl创建docker-registry regsecret——docker-server=$DOCKER_REGISTRY_RUL——docker-username=$USERNAME——docker-password=$PASSWORD——docker-email=$EMAIL

values.yaml你可以把秘密名传递给一个值:

imagePullSecrets: regsecret

然后,您可以使用这个秘密来允许Helm通过这些行访问docker注册表deployment.yaml

{{——如果. values。imagePullSecrets: - name: {{. values。imagePullSecrets}} {{- end}}

对于应用程序可用的秘密,您应该将该信息直接添加到values.yaml

例如,要配置我们的应用程序以使用预先创建的用户和数据库访问mongodb,请添加该信息values.yaml

mongodb: enabled: true mongodbrotpassword: mongodbUsername: admin mongodbPassword: mongodbDatabase: test

注意,这里我们没有在Helm图中硬编码默认凭证。相反,我们使用逻辑随机生成密码时,没有通过-set标志或values.yaml

我们将使用一个秘密将mongodb凭据通过这些行传递到我们的应用程序deployment.yaml

env: - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: {{. release . env: - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: {{. release . env:-mongodb key: mongodb-password

您可以通过专用的初始化容器或通过容器生命周期钩子

InitContainers 容器生命周期钩子
InitContainers是专门的容器,在应用程序容器之前运行,可以包含应用程序映像中不存在的实用程序或设置脚本。 容器可以使用容器生命周期钩子框架来运行在其管理生命周期期间由事件触发的代码。
一个Pod可以有一个或多个Init container,它们在应用程序容器启动之前运行。

一个豆荚只能有一个PostStartPreStop
PostStart钩子在容器创建后立即执行。但是,不能保证钩子会在容器ENTRYPOINT之前执行。没有参数传递给处理程序。
例如移动使用ConfigMap/Secrets挂载的文件到不同的位置。
PreStop钩子在容器终止之前立即调用。它是阻塞的,这意味着它是同步的,因此它必须在发送删除容器的调用之前完成。

例:优雅关闭应用程序

您可以使用initContainers在继续之前,要等待以检查依赖的微服务是否正常运行。 您可以使用PostStart挂钩到同一pod中更新的文件,例如更新配置文件服务IP

在我们的例子中,添加这些initContainers规范来deployments.yaml保持应用程序的启动,直到数据库启动并运行。

initContainers: - name: wait-for-db image: "{{. values . "initContainerImage}}"命令:—'sh' - '-c' - > until nc -z -w 2 {{. release . initContainerImage}}。Name}}-mongodb 27017 && echo mongodb ok;睡眠2;完成

添加准备和活性探针

添加就绪探测和活动探测来检查应用程序的运行状况通常是一个好主意。如果不这样做,那么应用程序可能会以某种方式失败,即它看起来正在运行,但不响应调用或查询。

这些线在deployment.yamlFile将添加这些探测来执行定期检查:

liveessprobe: httpGet: path:“/health”端口:http initialDelaySeconds: 60 periodSeconds: 10 failureThreshold: 10 readinessProbe: httpGet: path:“/health”端口:http initialDelaySeconds: 60 periodSeconds: 10 failureThreshold: 10

添加RBAC支持

这些程序将增加基于角色的访问控制当应用程序需要时,支持我们的图表。

步骤1:创建的作用在a中添加以下内容role.yaml文件:
Role只能用于授予对单个名称空间内资源的访问权。2022世界杯阿根廷预选赛赛程

{{——如果.Values.rbac。apiVersion: rbac.authorization.k8s. createio/v1 kind: Role metadata: labels: app: {{template "express- crude .name" .使用实例}}图表:{{template "express-crud.}图”。}}继承:{{. release。Service}}发布:{{. release。名称}}name: {{ template "express-crud.fullname" . }} rules: {{ toYaml .Values.rbac.role.rules }} {{- end }}

步骤2:创建RoleBinding由在a中添加以下内容rolebinding.yaml文件
ClusterRole可用于授予与Role相同的权限,但由于它们是集群作用域的,所以也可用于授予访问权限:

  • 集群范围内的资源(如节点)2022世界杯阿根廷预选赛赛程
  • 非资源端点(如“/healthz”)
  • 跨所有名称空间的名称空2022世界杯阿根廷预选赛赛程间资源(如pod)
{{——如果.Values.rbac。apiVersion: rbac.authorization.k8s. createio/v1 kind: RoleBinding metadata: labels: app: {{template "express- crude .name" .使用实例}}图表:{{template "express-crud.}图”。}}继承:{{. release。Service}}发布:{{. release。名称}}name: {{ template "express-crud.fullname" . }} subjects: - kind: ServiceAccount name: {{ template "express-crud.serviceAccountName" . }} roleRef: kind: Role apiGroup: rbac.authorization.k8s.io name: {{ template "express-crud.fullname" . }} {{- end }}

步骤3:创建ServiceAccount通过在a中添加以下内容serviceaccount.yaml文件

服务帐户为在Pod中运行的进程提供标识。

{{——如果.Values.serviceAccount。create}} apiVersion: v1 kind: ServiceAccount metadata: labels: app: {{template "express-crud.name" . create}}图表:{{template "express-crud.}图”。}}继承:{{. release。Service}}发布:{{. release。名称}}name: {{ template "express-crud.serviceAccountName" . }} {{- end }}

步骤4:使用助手模板设置ServiceAccount名称。
我们将通过添加以下内容来做到这一点_helpers.tpl文件

{{/*创建使用*/}}{{-定义“express-crud”的服务帐户的名称。serviceAccountName" -}} {{- if . values . serviceaccount . serviceAccountName"。Create -}} {{default(包括"express-crud. "fullname”。) .Values.serviceAccount.name }} {{- else -}} {{ default "default" .Values.serviceAccount.name }} {{- end -}} {{- end -}}

添加一个服务

现在是时候向世界公开我们的应用程序了通过服务

服务允许您的应用程序通过IP地址接收流量。可以以不同的方式公开服务类型

ClusterIP 该服务只能由集群中的内部IP访问。
NodePort 该服务可以从集群外部通过NodeIP和NodePort访问。
loadbalance 该服务可以通过外部负载均衡器从集群外部访问。可以入口应用程序. .


我们将通过添加以下内容来做到这一点service.yaml

apiVersion: v1 kind:服务元数据:name: {{template "express-crud。fullname”。}}标签:app: {{template "express- crude .name"。}}图表:{{template "express-crud.}图”。}}释放:{{. release。名称}}heritage: {{ .Release.Service }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.externalPort }} targetPort: http protocol: TCP name: http selector: app: {{ template "express-crud.name" . }} release: {{ .Release.Name }}

注意,在上面,为我们服务类型中引用一个设置values.yam李:

service: type: LoadBalancer internalPort: 3000 externalPort: 80

值。yaml的总结

定义我们的许多设置values.yaml文件是一个很好的实践,以帮助保持您的Helm图表的可维护性。

这就是values.yaml出现我们示例的文件,显示了我们为上面讨论的许多特性定义的各种设置:

# express-mongo-crud的默认值。这是一个yaml格式的文件。#声明要传递到模板中的变量。基于角色的访问控制## Ref: https://kubernetes.io/docs/admin/authorization/rbac/ rbac: create: true Role: ##要创建的规则。它遵循角色规范规则:—apiGroups:—" resources:—services - endpoints - p2022世界杯阿根廷预选赛赛程ods verbs:—get - watch - list ## ServiceAccount ## Ref: https://kubernetes.io/docs/admin/service-accounts-admin/ ## serviceAccount: create: true ##要使用的serviceAccount的名称。# #如果没有设置并创建是真的,一个名称生成使用fullname模板名称:# # mongodb配置值依赖# #裁判:https://github.com/kubernetes/charts/blob/master/stable/mongodb/README.md # # mongodb:启用:真正的形象:标签:3.6.3 pullPolicy: IfNotPresent持久性:尺寸:50 gi #资源:#请求:#记忆:“十二gi”# cpu:“200”#限制:#记忆:“十二gi”# cpu:“2”# #确保——wiredTigerCacheSizeGB没有超过一半的内存限制!2022世界杯阿根廷预选赛赛程##这是保护免受Kubernetes的OOMKill的关键!mongodbextrafags: - "——wiredTigerCacheSizeGB=1" mongodbRootPassword: mongodbUsername: admin mongodbPassword: mongodbDatabase: test #活探针:# initialDelaySeconds: 60 # periodSeconds: 10 # readinessProbe: # initialDelaySeconds: 30 # periodSeconds: 30 ingress: enabled: false annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes. test: #活探针:# initialDelaySeconds: 60 # periodSeconds: 10 # readinessProbe: # initialDelaySeconds: 30 #Io /tls-acme: "true"路径:/ hosts: - chart-example. txtlocal tls: [] # - secretName: chart-example-tls # hosts: # - chart-example。local initContainerImage: "alpine:3.6" imagePullSecrets: replicaCount: 1 image: repository: jainishshah17/express-mon -crud # tag: 1.0.1 pullPolicy: IfNotPresent service: type: LoadBalancer internalPort: 3000 externalPort: 80 r2022世界杯阿根廷预选赛赛程esources:{} #我们通常建议不指定默认资源,让用户有意识地选择#。 This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: # cpu: 100m # memory: 128Mi # requests: # cpu: 100m # memory: 128Mi nodeSelector: {} tolerations: [] affinity: {}

测试和安装舵图

测试我们的Helm图表是非常重要的,我们将使用执掌线头命令。

$ helm lint ./ ## Output ==> Linting ./ lint OK 1图(s) Linting ./没有故障

使用安装命令,使用Kubernetes上的helm图部署我们的应用程序。

$ helm install——name test1 ./ ##输出名称:test1 LAST DEPLOYED: Sat Sep 15 09:36:23 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES:2022世界杯阿根廷预选赛赛程==> v1beta1/Deployment NAME DESIRED CURRENT CURRENT AVAILABLE AGE test1-mongodb 1 1 10 0s ==> v1beta2/Deployment test1-express-crud 1 1 10 0s ==> v1/Secret NAME TYPE DATA AGE test1-mongodb Opaque 2 0s ==> v1/PersistentVolumeClaim NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test1-mongodb Pending standard 0s ==> v1/ServiceAccount NAME SECRETS AGE test1-express-crud 1 0s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE test1-mongodb ClusterIP 10.19.248.205 27017/TCP 0stest1-express-crud LoadBalancer 10.19.254.169 80:31994/TCP 0s ==> v1/Role NAME AGE test1-express-crud 0s ==> v1/RoleBinding NAME AGE test1-express-crud 0s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE test1-mongodb-67b6697449-tppk5 0/1 Pending 0 0s test1-express-crud-dfdbd55dc-rdk2c 0/1 Init:0/1 0 0s NOTES: 1. Get the application URL by running these commands: NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get svc -w test1-express-crud' export SERVICE_IP=$(kubectl get svc --namespace default test1-express-crud -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo https://$SERVICE_IP:80

运行上面的helm install命令将为负载均衡器生成一个External_IP。您可以使用此IP地址运行应用程序。

这是我们的应用程序运行时的样子:

结果

结束

正如您从这个示例中看到的,Helm是一个非常通用的系统,它允许您在如何构建和开发图表方面具有很大的灵活性。以符合Helm社区惯例的方式进行操作,将有助于简化提交Helm图表供公众使用的过程,并使它们在更新应用程序时更容易维护。

这个示例项目的完整Helm图表可以在express-crudrepo在GitHub上,你可以查看这些功能文件,以帮助你更彻底地了解它们是如何工作的。

要了解更多示例,可以查看我的示例存储库图表将产品部署到Kubernethth华体会最新官方网站es。

额外的资源:2022世界杯阿根廷预选赛赛程