
如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
https://quay.io/repository/lifechurch/k8s-deploy-helper/status "Docker Repository on Quay"](https://quay.io/repository/lifechurch/k8s-deploy-helper)
k8s-deploy-helper是一个工具,用于通过GitLab CI和模板化清单文件,帮助构建容器化应用并部署到Kubernetes。主要功能包括:
本项目未得到GitLab的认可或关联。
除本文档外,入门的最佳方式是查看我们的https://github.com/lifechurch/example-go%E3%80%82
需要帮助入门?欢迎加入Open Digerati Slack的#k8s频道,我们很乐意提供协助。
GitLab的Auto DevOps倡议对于快速运行简单应用非常出色,但对于稍复杂的生产工作负载,您需要对流程有更多控制。例如,如果您的Pod带有Sidecar容器(因为要在服务网格中运行),或者您想要使用Celery等工具部署异步工作的Worker Pod,您需要更深入地与Kubernetes交互,这就是本项目的用武之地。
在Life.Church,我们希望创建一个标准化工具及相应约定,让开发者可以通过GitLab CI快速轻松地进行基于清单的部署。因此,我们以GitLab的工作为基础,构建了一个满足我们需求的新项目。
这个工具就像在飞行中建造的飞机一样,随着我们对Kubernetes部署的了解加深,流程不断成熟。我们的目标不是说“这是最佳部署方式”,而是分享我们当前的做法,希望能为其他踏上Kubernetes之旅的人提供有用的起点。
关于如何从Docker内部构建Docker镜像,有很多讨论。我们最终选择了共享Docker套接字的方式。以下是GitLab Runner的示例配置,特别注意volumes部分,以我们期望的方式共享套接字:
[[runners]] name = "runner01" limit = 16 url = "https://runneriurl/ci" token = "token" executor = "docker" [runners.docker] tls_verify = false image = "docker:latest" privileged = false disable_cache = false volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] shm_size = 0 [runners.cache]
在GitLab项目中,进入设置->集成,设置Kubernetes。请参阅GitLab文档了解正确的操作方法。
GitLab CI系统最烦人的部分之一是,连接到其传递的注册表的凭据仅在特定时间内有效。虽然这对于将容器推送到注册表很有效,但对于在Kubernetes中运行内容却不太适用。因为凭据会在一段时间后过期,如果Pod重启或发生扩展事件,Kubernetes将无法从私有GitLab注册表获取容器。
唯一的解决方法是在GitLab中创建一个实际用户,并确保其有权访问必要的组和项目。
我们的工具期望存在GL_USERNAME和GL_PASSWORD变量,并包含新创建的凭据。它将使用这些变量在您的Kubernetes命名空间中创建名为gitlab-registry的密钥,您的清单文件可以使用该密钥。
您可以通过以下两种方式之一完成此操作:
[[runners]] name = "runner01" limit = 16 url = "https://runneriurl/ci" token = "token" executor = "docker" environment = ["GL_USERNAME=dockeruser", "GL_PASSWORD=mysupersecuredockerpassword"] [runners.docker] tls_verify = false image = "docker:latest" privileged = false disable_cache = false volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"] shm_size = 0 [runners.cache]
我们的目标是确保Docker容器能够尽可能快地构建,而无需开发者为每个项目微管理每个docker build命令。
只需将Dockerfile放在仓库的根目录即可
以下是.gitlab-ci.yml中的快速示例:
build_container: stage: build script: - command build only: - branches
注意脚本中只有一个命令:command build - k8s-deploy-helper会接手后续工作,构建容器,用唯一ID(提交哈希)标记它,并将其推送到GitLab Docker注册表。
除了用唯一ID标记您的构建外,我们还为每个新构建标记latest标签。我们需要一个稳定的标签,以便构建器可以使用Docker的--cache-from功能,在有多个Runner时加快容器构建速度。我们欢迎更好的实现方式的PR!
有时您需要在构建时向容器传递参数,例如放置令牌以从私有npm注册表拉取内容。要传递构建参数,只需进入GitLab项目,进入设置->CI/CD->秘密变量,并创建以下形式的秘密:
BUILDARG_npmtoken=1111
当我们构建Docker容器时,会查找所有以BUILDARG_开头的环境变量,去掉前缀,并通过--build-arg传递给docker。在上面的示例中,这将创建一个名为npmtoken、值为1111的构建参数。
在您的Dockerfile中,需要准备好接收这些构建参数:
ARG npmtoken ENV npmtoken: $npmtoken
如果您的项目需要构建多个Dockerfile,助手将自动处理所有命名约定管理以避免冲突。您只需传入仓库根目录中的Dockerfile文件名即可。例如,如果您有两个Dockerfile:Dockerfile-app和Dockerfile-worker,您的.gitlab-ci.yml将如下所示:
build_app: stage: build script: - command build Dockerfile-app only: - branches build_worker: stage: build script: - command build Dockerfile-worker only: - branches
通过在GitLab CI中设置KDH_SKIP_LATEST变量为true,k8s-deploy-helper将跳过使用latest标签作为--cache-from源。如果您的项目仅使用一个GitLab Runner,这将有助于从Docker缓存中拉取更多层,节省时间。
以下是在.gitlab-ci.yml中启动部署助手的示例:
staging: stage: staging only: - master script: - command deploy environment: name: staging url: https://stagingurl
要将应用部署到Kubernetes,您需要将模板化清单文件放在仓库根目录的kubernetes目录中。部署脚本将进入kubernetes目录,并对目录中的每个文件执行kubectl apply -f。
kubernetes |-->deployment.yaml |-->service.yaml
有时您有仅希望在特定阶段运行的清单。例如,您可能希望水平Pod自动扩缩器仅用于生产,而不用于staging或review应用。您只需创建一个与构建阶段对应的目录名称即可。
kubernetes |production ||-->hpa.yaml |-->deployment.yaml |-->service.yaml
从基础层面看,这很容易理解,但实现细节需要更多解释。让我们看一个示例部署文件:
--- apiVersion: apps/v1beta1 kind: Deployment metadata: name: app-$CI_ENVIRONMENT_SLUG namespace: $KUBE_NAMESPACE labels: app: app-$CI_ENVIRONMENT_SLUG pipeline_id: "$CI_PIPELINE_ID" build_id: "$CI_JOB_ID" spec: selector: matchLabels: app: app-$CI_ENVIRONMENT_SLUG name: app-$CI_ENVIRONMENT_SLUG space: $KUBE_NAMESPACE template: metadata: labels: name: app-$CI_ENVIRONMENT_SLUG app: app-$CI_ENVIRONMENT_SLUG space: $KUBE_NAMESPACE spec: terminationGracePeriodSeconds: 60 containers: - name: $KUBE_NAMESPACE-app-$CI_ENVIRONMENT_SLUG image: $CI_REGISTRY_IMAGE:app-$CI_COMMIT_SHA imagePullPolicy: IfNotPresent ports: - containerPort: 80 env: - name: api_env valueFrom: secretKeyRef: name: $KUBE_NAMESPACE-secrets-$STAGE key: api_env imagePullSecrets: - name: gitlab-registry
您可以看到它看起来非常像普通的Kubernetes清单文件,唯一的例外是变量。我们没有发明更复杂的解决方案来覆盖更多边缘情况,而是采用了简单的方法:在清单文件中使用环境变量名称,然后在部署时使用envsubst命令将值替换到文件中,再应用清单文件。虽然这使得清单更难阅读和创建,但在灵活性和自定义方面有所收获。
最大的陷阱是,您在清单中使用的每个环境变量都必须存在,否则模板化将失败。
从2.0版本开始,k8s-deploy-helper支持金丝雀部署。GitLab使用设置track标签为canary的约定来跟踪哪些Pod/部署属于金丝雀。金丝雀部署的工作流程与正常流程略有不同。我们假设金丝雀部署仅用于生产,当脚本检测到$CI_JOB_STAGE为canary时,它会设置一个标记表示这是金丝雀部署,然后将$CI_JOB_STAGE覆盖为"production",以便部署正常的生产内容。
当设置该标记时,它会在所有部署中查找metadata.labels.track规范,并且在canary阶段时仅部署track标签设置为canary的清单。
查看我们的https://www.github.com/lifechurch/example-go%E8%8E%B7%E5%8F%96%E9%87%91%E4%B8%9D%E9%9B%80%E6%B8%85%E5%8D%95%E7%A4%BA%E4%BE%8B%E3%80%82
上面提供的所有变量均由GitLab提供,除了一个:$STAGE - 这是我们的部署器创建的特殊环境变量,用于帮助review应用。如果从名为review的GitLab CI阶段调用,其值将是GitLab的$CI_ENVIRONMENT_SLUG,以便为review应用创建唯一名称。如果从任何其他阶段调用,它将默认为您当前在GitLab中执行的阶段名称($CI_JOB_STAGE)。
如果您需要在清单中使用$而不用于环境变量替换,可以使用${DOLLAR}代替:
annotations: ingress.kubernetes.io/configuration-snippet: | if (${DOLLAR}denynotfromlocalbind) { return 403; }
这将在应用前评估为:
annotations: ingress.kubernetes.io/configuration-snippet: | if ($denynotfromlocalbind) { return 403; }
对于刚开始将应用部署到Kubernetes的人来说,第一个问题通常是“如何将密钥保存在仓库之外?”当我们开始构建部署系统时,我们希望创建一个允许轻松的仓库外密钥管理的系统,但不想强迫开发者使用Vault,因为我们正在努力让更多人接受k8s。
相反,我们选择将密钥存储在GitLab中。这允许我们:
要创建密钥,请进入GitLab项目,进入设置->CI/CD->秘密变量,并创建以下名称模式的变量:
SECRET_mykeyname
在部署期间,我们的脚本将查找所有以SECRET_前缀开头的环境变量,去掉前缀,并将键和值放入名为$KUBE_NAMESPACE-secrets-$STAGE的Kubernetes密钥中,这会转换为类似yournamespacename-secrets-production或yournamespacename-secrets-staging的名称。
在上面的示例中,密钥文件中将有一个名为mykeyname的条目,其值为您在GitLab中输入的相应值。然后您可以在清单文件中访问这些密钥。以下代码将在您的Pod中创建一个名为mykeyname的环境变量:
env: - name: mykeyname valueFrom: secretKeyRef: name: $KUBE_NAMESPACE-secrets-$STAGE key: mykeyname
有时您有根据部署到production或staging等阶段而具有不同值的密钥。我们的助手允许您通过使用GitLab CI阶段名称的大写版本作为密钥前缀来实现这一点。
例如,假设您有一个名为api_env的密钥,其值需要根据部署到review、staging或production三个阶段中的哪一个而不同。
您不需要在GitLab中创建名为SECRET_api_env的变量,而是创建三个:
REVIEW_api_env
STAGING_api_env
PRODUCTION_api_env
结合以下模板部分,这将从相应位置拉取密钥:
env: - name: api_env valueFrom: secretKeyRef: name: $KUBE_NAMESPACE-secrets-$STAGE key: api_env imagePullSecrets:
目前支持NewRelic、Slack和Datadog部署事件。
在Gitlab中,对于NewRelic,您需要为每个想要部署事件的阶段添加带有NewRelic API密钥和应用ID的秘密变量。例如:
NEWRELIC_API_KEY=xxx
NEWRELIC_STAGING_APP_ID=xxx
NEWRELIC_PRODUCTION_APP_ID=xxx
对于Slack,只需设置带有Slack webhook url的Gitlab秘密变量:
SLACK_WEBHOOK=xxx
对于Datadog,您必须使用以下方式设置Datadog API密钥:
DATADOG_API_KEY=xxx
可选地,您可以设置应用密钥、消息文本和发送到Datadog的标签。https://help.datadoghq.com/hc/en-us/articles/204778779%E6%9C%80%E5%A5%BD%E5%9C%B0%E8%A7%A3%E9%87%8A%E4%BA%86%E5%A6%82%E4%BD%95%E5%90%91%E9%83%A8%E7%BD%B2%E4%BA%8B%E4%BB%B6%E6%B7%BB%E5%8A%A0markdown%E6%96%87%E6%9C%AC%E3%80%82
DATADOG_TAGS变量可用于发送一个或多个标签到事件。因为这是POST中的数组,您必须在每个值周围包含引号。多个标签应使用逗号分隔:
DATADOG_APP_KEY=xxx
DATADOG_TAGS="deploys:api","foo:bar"
DATADOG_TEXT=\n%%%\n### Success\n%%%
请阅读CONTRIBUTING.md了解我们的行为准则以及提交拉取请求的流程。
为确保社区能够理智地使用此项目,我们将承诺在引入破坏性变更时递增主版本号。由于此工具仍在大力开发中,我们预计这会频繁发生。
我们使用http://semver.org/%E8%BF%9B%E8%A1%8C%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E3%80%82%E6%9C%89%E5%85%B3%E5%8F%AF%E7%94%A8%E7%89%88%E6%9C%AC%EF%BC%8C%E8%AF%B7%E5%8F%82%E9%98%85https://github.com/lifechurch/k8s-deploy-helper/tags%E3%80%82
本项目采用MIT许可证 - 有关详细信息,请参阅LICENSE.md文件。
您可以使用以下命令拉取该镜像。请将 <标签> 替换为具体的标签版本。如需查看所有可用标签版本,请访问 标签列表页面。
来自真实用户的反馈,见证轩辕镜像的优质服务