整体实施方案概述
- 创建命名空间(Namespace):创建一个专用于 CI/CD 的命名空间
cicd
。 - 配置 Secrets:
- Git SSH 密钥(分别为 Maven 和 npm 项目)
- Docker Registry 凭证(Kaniko)
- SMTP 凭证(邮件通知)
- 创建 PersistentVolumeClaim(PVC):用于存储工作空间数据。
- 创建 ServiceAccount 和权限绑定:确保 Tekton Pipelines 有足够的权限。
- 创建 Tekton Tasks:
- 初始化环境任务(分别为 Maven 和 npm)
- 拉取代码任务(分别为 Maven 和 npm)
- 运行
dockerContext.sh
脚本任务 - 构建并推送镜像任务(使用 Kaniko)
- 部署到 Kubernetes 任务
- 发送邮件通知任务
- 创建 Tekton Pipelines:
- Maven 流水线
- npm 流水线
- 创建
dockerContext.sh
脚本 - 应用所有 Tekton 资源
- 测试与运行
- 常见问题排查
详细实施步骤
步骤 1:创建命名空间
如果尚未创建,创建一个专用于 CI/CD 的命名空间 cicd
。
kubectl create namespace cicd
验证命名空间创建成功:
kubectl get namespaces
步骤 2:配置 Git SSH 密钥
2.1 生成 SSH 密钥
-
为 Maven 项目生成 SSH 密钥(如果尚未有):
ssh-keygen -t rsa -b 4096 -C "maven_email@example.com" -f ~/maven_id_rsa
-
为 npm 项目生成 SSH 密钥(如果尚未有):
ssh-keygen -t rsa -b 4096 -C "npm_email@example.com" -f ~/npm_id_rsa
-
将公钥添加到各自 Git 仓库的部署密钥中,以便允许 CI/CD 系统访问私有仓库。
2.2 创建 Kubernetes Secrets 存储 Git SSH 私钥
保存 Maven Git SSH Secret 为 git-ssh-secret-maven.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: git-ssh-key-maven
namespace: cicd
type: kubernetes.io/ssh-auth
data:
ssh-privatekey: <BASE64_ENCODED_MAVEN_ID_RSA>
保存 npm Git SSH Secret 为 git-ssh-secret-npm.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: git-ssh-key-npm
namespace: cicd
type: kubernetes.io/ssh-auth
data:
ssh-privatekey: <BASE64_ENCODED_NPM_ID_RSA>
生成 Base64 编码的私钥:
# 对 Maven 私钥进行编码
cat ~/maven_id_rsa | base64 -w0
# 对 npm 私钥进行编码
cat ~/npm_id_rsa | base64 -w0
将编码后的字符串替换到 <BASE64_ENCODED_MAVEN_ID_RSA>
和 <BASE64_ENCODED_NPM_ID_RSA>
中。
应用 Secrets:
kubectl apply -f git-ssh-secret-maven.yaml
kubectl apply -f git-ssh-secret-npm.yaml
验证 Secrets 创建成功:
kubectl get secrets -n cicd
步骤 3:配置 Docker Registry 认证(使用 Kaniko)
3.1 准备 Docker Registry 凭证
确保您有镜像仓库的服务器地址、用户名、密码和邮箱。
3.2 创建 Docker Registry Secret
保存为 kaniko-secret.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: kaniko-secret
namespace: cicd
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <BASE64_ENCODED_DOCKER_CONFIG_JSON>
生成 .dockerconfigjson
的方法:
您可以使用以下命令自动生成:
kubectl create secret docker-registry kaniko-secret \
--namespace=cicd \
--docker-server=<YOUR_DOCKER_REGISTRY_SERVER> \
--docker-username=<YOUR_USERNAME> \
--docker-password=<YOUR_PASSWORD> \
--docker-email=<YOUR_EMAIL> \
--dry-run=client -o jsonpath='{.data.\.dockerconfigjson}' | base64 -w0
将输出结果替换到 kaniko-secret.yaml
中的 <BASE64_ENCODED_DOCKER_CONFIG_JSON>
。
应用 Secret:
kubectl apply -f kaniko-secret.yaml
验证 Secret 创建成功:
kubectl get secrets -n cicd
步骤 4:创建 SMTP Secret
用于邮件通知。
保存为 smtp-secret.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: smtp-secret
namespace: cicd
type: Opaque
data:
smtp-server: <BASE64_ENCODED_SMTP_SERVER>
smtp-port: <BASE64_ENCODED_SMTP_PORT>
smtp-username: <BASE64_ENCODED_SMTP_USERNAME>
smtp-password: <BASE64_ENCODED_SMTP_PASSWORD>
from-email: <BASE64_ENCODED_FROM_EMAIL>
to-email: <BASE64_ENCODED_TO_EMAIL>
将各字段值进行 Base64 编码:
echo -n 'smtp.gmail.com' | base64 -w0
echo -n '587' | base64 -w0
echo -n 'user@gmail.com' | base64 -w0
echo -n 'password123' | base64 -w0
echo -n 'user@gmail.com' | base64 -w0
echo -n 'admin@example.com' | base64 -w0
示例:
apiVersion: v1
kind: Secret
metadata:
name: smtp-secret
namespace: cicd
type: Opaque
data:
smtp-server: c210cC5nbWFpbC5jb20= # smtp.gmail.com
smtp-port: NTg3 # 587
smtp-username: dXNlckBnbWFpbC5jb20= # user@gmail.com
smtp-password: cGFzc3dvcmQxMjM= # password123
from-email: dXNlckBnbWFpbC5jb20= # user@gmail.com
to-email: YWRtaW5AZXhhbXBsZS5jb20= # admin@example.com
应用 Secret:
kubectl apply -f smtp-secret.yaml
验证 Secret 创建成功:
kubectl get secrets -n cicd
步骤 5:创建 PersistentVolumeClaim(PVC)
Tekton 需要持久化存储来存放工作空间数据。
保存为 workspace-pvc.yaml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: workspace-pvc
namespace: cicd
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
应用 PVC:
kubectl apply -f workspace-pvc.yaml
验证 PVC 状态:
kubectl get pvc -n cicd
步骤 6:创建 ServiceAccount 和权限绑定
确保 Tekton Pipelines 有足够的权限访问 Kubernetes API 和相关资源。
保存为 tekton-sa.yaml
:
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-sa
namespace: cicd
应用 ServiceAccount:
kubectl apply -f tekton-sa.yaml
绑定权限(示例:赋予 edit
权限):
kubectl create rolebinding tekton-sa-edit \
--clusterrole=edit \
--serviceaccount=cicd:tekton-sa \
--namespace=cicd
说明:
edit
ClusterRole 赋予了在命名空间内编辑资源的权限。根据实际需求,可以调整权限。
步骤 7:创建 Tekton Tasks
我们将为 Maven 和 npm 项目分别创建初始化任务和代码拉取任务。构建、推送镜像、部署和发送邮件的任务可以共用。
7.1 初始化环境任务
7.1.1 初始化 Maven 环境任务 (init-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-maven
namespace: cicd
spec:
steps:
- name: setup-maven
image: maven:3.8.6-jdk-11
script: |
#!/bin/sh
set -e
echo "初始化 Maven 环境..."
mvn --version
# 在此处添加任何 Maven 相关的初始化步骤,例如下载依赖
7.1.2 初始化 npm 环境任务 (init-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-npm
namespace: cicd
spec:
steps:
- name: setup-npm
image: node:16
script: |
#!/bin/sh
set -e
echo "初始化 NPM 环境..."
node --version
npm --version
# 在此处添加任何 NPM 相关的初始化步骤,例如安装全局包
应用初始化任务:
kubectl apply -f init-maven.yaml
kubectl apply -f init-npm.yaml
7.2 拉取代码任务
7.2.1 拉取 Maven 项目代码任务 (clone-repo-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-maven
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-maven-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 Maven 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-maven
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-maven
secret:
secretName: git-ssh-key-maven
7.2.2 拉取 npm 项目代码任务 (clone-repo-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-npm
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-npm-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 npm 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-npm
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-npm
secret:
secretName: git-ssh-key-npm
应用拉取代码任务:
kubectl apply -f clone-repo-maven.yaml
kubectl apply -f clone-repo-npm.yaml
7.3 运行 dockerContext.sh
任务 (run-docker-context.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: run-docker-context
namespace: cicd
spec:
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: run-script
image: bash:latest
script: |
#!/bin/sh
set -e
cd $(workspaces.source.path)
if [ -f .manifest/dockerContext.sh ]; then
echo "运行 dockerContext.sh 脚本..."
chmod +x .manifest/dockerContext.sh
./.manifest/dockerContext.sh || echo "dockerContext.sh 执行失败,跳过..."
else
echo "未找到 dockerContext.sh 脚本,跳过..."
fi
应用任务:
kubectl apply -f run-docker-context.yaml
7.4 构建并推送镜像任务(使用 Kaniko) (build-and-push-kaniko.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-and-push-kaniko
namespace: cicd
spec:
params:
- name: image
description: Docker 镜像名称
type: string
- name: dockerfile
description: Dockerfile 的路径
default: ./Dockerfile
type: string
- name: context
description: 构建上下文路径
default: .
type: string
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
command:
- /kaniko/executor
args:
- "--context=$(workspaces.source.path)/$(params.context)"
- "--dockerfile=$(workspaces.source.path)/$(params.dockerfile)"
- "--destination=$(params.image)"
- "--oci-layout-path=/kaniko/oci"
- "--cache=true"
- "--cache-repo=$(params.image)"
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker/
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker/
volumes:
- name: kaniko-secret
secret:
secretName: kaniko-secret
应用任务:
kubectl apply -f build-and-push-kaniko.yaml
7.5 部署到 Kubernetes 任务 (deploy-to-kubernetes.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: deploy-to-kubernetes
namespace: cicd
spec:
params:
- name: namespace
description: Kubernetes 命名空间
type: string
- name: deployment-name
description: Kubernetes Deployment 名称
type: string
- name: image
description: 要部署的镜像
type: string
steps:
- name: deploy
image: bitnami/kubectl
script: |
#!/bin/sh
set -e
echo "将镜像 $(params.image) 部署到命名空间 $(params.namespace)..."
kubectl set image deployment/$(params.deployment-name) app=$(params.image) -n $(params.namespace)
- name: set-status
image: alpine
script: |
#!/bin/sh
echo "succeeded" > /tekton/results/status
results:
- name: status
description: 部署状态
应用任务:
kubectl apply -f deploy-to-kubernetes.yaml
7.6 发送邮件通知任务 (send-email.yaml
)
(已在上文提供,此处重复以方便参考)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: send-email
namespace: cicd
spec:
params:
- name: subject
type: string
description: 邮件主题
- name: body
type: string
description: 邮件正文
steps:
- name: send-email
image: curlimages/curl:7.83.1
script: |
#!/bin/sh
set -e
SMTP_SERVER=$(cat /var/secrets/smtp/smtp-server)
SMTP_PORT=$(cat /var/secrets/smtp/smtp-port)
SMTP_USERNAME=$(cat /var/secrets/smtp/smtp-username)
SMTP_PASSWORD=$(cat /var/secrets/smtp/smtp-password)
FROM_EMAIL=$(cat /var/secrets/smtp/from-email)
TO_EMAIL=$(cat /var/secrets/smtp/to-email)
SUBJECT="$(params.subject)"
BODY="$(params.body)"
echo "正在通过 $SMTP_SERVER:$SMTP_PORT 发送邮件到 $TO_EMAIL..."
echo -e "Subject: $SUBJECT\n\n$BODY" | \
curl --url "smtp://$SMTP_SERVER:$SMTP_PORT" \
--ssl-reqd \
--mail-from "$FROM_EMAIL" \
--mail-rcpt "$TO_EMAIL" \
--user "$SMTP_USERNAME:$SMTP_PASSWORD" \
-T -
volumes:
- name: smtp-secrets
secret:
secretName: smtp-secret
应用任务:
kubectl apply -f send-email.yaml
步骤 8:创建 Tekton Pipelines
为 Maven 和 npm 项目分别创建独立的流水线。
8.1 Maven 流水线 (maven-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: maven-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-maven
taskRef:
name: init-maven
runAfter: []
- name: clone-repo
runAfter:
- init-maven
taskRef:
name: clone-repo-maven
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "Maven 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **Maven 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
8.2 npm 流水线 (npm-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: npm-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-npm
taskRef:
name: init-npm
runAfter: []
- name: clone-repo
runAfter:
- init-npm
taskRef:
name: clone-repo-npm
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "NPM 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **NPM 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
说明:
- Maven 和 npm 流水线结构类似,但各自引用不同的初始化和代码拉取任务。
finally
部分确保无论前面的任务成功还是失败,都会执行send-email
任务发送通知。
应用流水线:
kubectl apply -f maven-pipeline.yaml
kubectl apply -f npm-pipeline.yaml
验证流水线创建成功:
kubectl get pipelines -n cicd
步骤 9:创建 dockerContext.sh
脚本
dockerContext.sh
是一个用于处理特定上下文操作的脚本。根据您的需求,您可以在此脚本中添加自定义逻辑。以下是一个示例脚本:
创建 dockerContext.sh
文件:
#!/bin/sh
set -e
echo "执行 dockerContext.sh 脚本..."
# 示例操作:生成 Docker 镜像标签
TIMESTAMP=$(date +%Y%m%d%H%M%S)
echo "生成的时间戳标签:$TIMESTAMP"
# 您可以在此处添加更多自定义操作,例如修改配置文件、生成额外文件等。
echo "dockerContext.sh 脚本执行完成。"
说明:
- 功能:此脚本用于执行构建前的自定义操作,例如生成镜像标签、修改配置文件等。
- 位置:将此脚本放置在项目的
.manifest/
目录下,即.manifest/dockerContext.sh
。
确保脚本具有执行权限:
chmod +x .manifest/dockerContext.sh
步骤 10:应用所有 Tekton 资源
按照以下顺序依次应用所有 Tekton 任务和流水线配置文件:
kubectl apply -f init-maven.yaml
kubectl apply -f init-npm.yaml
kubectl apply -f clone-repo-maven.yaml
kubectl apply -f clone-repo-npm.yaml
kubectl apply -f run-docker-context.yaml
kubectl apply -f build-and-push-kaniko.yaml
kubectl apply -f deploy-to-kubernetes.yaml
kubectl apply -f send-email.yaml
kubectl apply -f maven-pipeline.yaml
kubectl apply -f npm-pipeline.yaml
kubectl apply -f workspace-pvc.yaml
kubectl apply -f kaniko-secret.yaml
kubectl apply -f smtp-secret.yaml
kubectl apply -f tekton-sa.yaml
验证资源创建成功:
kubectl get tasks,pipelines -n cicd
kubectl get pvc -n cicd
kubectl get secrets -n cicd
kubectl get serviceaccounts -n cicd
步骤 11:测试与运行
11.1 手动触发 Maven 流水线
创建并应用 Maven PipelineRun (maven-pipelinerun.yaml
):
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: maven-pipelinerun-$(date +%s)
namespace: cicd
spec:
pipelineRef:
name: maven-pipeline
params:
- name: repo-url
value: https://github.com/example/maven-app.git
- name: branch
value: main
- name: image
value: docker.io/example/maven-app:latest
- name: namespace
value: dev
- name: deployment-name
value: maven-app
workspaces:
- name: source
persistentVolumeClaim:
claimName: workspace-pvc
serviceAccountName: tekton-sa
应用 PipelineRun:
kubectl apply -f maven-pipelinerun.yaml
11.2 手动触发 npm 流水线
创建并应用 npm PipelineRun (npm-pipelinerun.yaml
):
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: npm-pipelinerun-$(date +%s)
namespace: cicd
spec:
pipelineRef:
name: npm-pipeline
params:
- name: repo-url
value: https://github.com/example/npm-app.git
- name: branch
value: main
- name: image
value: docker.io/example/npm-app:latest
- name: namespace
value: dev
- name: deployment-name
value: npm-app
workspaces:
- name: source
persistentVolumeClaim:
claimName: workspace-pvc
serviceAccountName: tekton-sa
应用 PipelineRun:
kubectl apply -f npm-pipelinerun.yaml
或者,您也可以使用 tkn
CLI 触发 Pipeline:
# 触发 Maven 流水线
tkn pipeline start maven-pipeline \
-p repo-url=https://github.com/example/maven-app.git \
-p branch=main \
-p image=docker.io/example/maven-app:latest \
-p namespace=dev \
-p deployment-name=maven-app \
-w name=source,claimName=workspace-pvc \
--serviceaccount=tekton-sa
# 触发 npm 流水线
tkn pipeline start npm-pipeline \
-p repo-url=https://github.com/example/npm-app.git \
-p branch=main \
-p image=docker.io/example/npm-app:latest \
-p namespace=dev \
-p deployment-name=npm-app \
-w name=source,claimName=workspace-pvc \
--serviceaccount=tekton-sa
11.3 监控流水线运行状态
# 查看流水线列表
kubectl get pipelines -n cicd
# 查看 PipelineRun 列表
kubectl get pipelineruns -n cicd
# 查看特定 PipelineRun 的日志
tkn pipelinerun logs <pipelinerun-name> -f -n cicd
将 <pipelinerun-name>
替换为实际的 PipelineRun 名称。
步骤 12:验证邮件通知功能
- 触发流水线:按照上述步骤 11.1 或 11.2 触发 Maven 或 npm 流水线。
- 检查邮件:确认指定的
to-email
收到相应的通知邮件。 - 排查问题:
- 如果邮件未收到,请检查:
smtp-secret
是否正确配置,确保所有字段都已正确 Base64 编码。- SMTP 服务器是否允许通过 API 或外部应用发送邮件(例如,Gmail 可能需要启用“应用专用密码”)。
- 查看
send-email
任务的日志,确认curl
命令是否执行成功。
- 如果邮件未收到,请检查:
关键 YAML 文件汇总
1. 初始化环境任务
1.1 Maven 初始化任务 (init-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-maven
namespace: cicd
spec:
steps:
- name: setup-maven
image: maven:3.8.6-jdk-11
script: |
#!/bin/sh
set -e
echo "初始化 Maven 环境..."
mvn --version
# 在此处添加任何 Maven 相关的初始化步骤,例如下载依赖
1.2 npm 初始化任务 (init-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-npm
namespace: cicd
spec:
steps:
- name: setup-npm
image: node:16
script: |
#!/bin/sh
set -e
echo "初始化 NPM 环境..."
node --version
npm --version
# 在此处添加任何 NPM 相关的初始化步骤,例如安装全局包
2. 拉取代码任务
2.1 拉取 Maven 项目代码任务 (clone-repo-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-maven
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-maven-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 Maven 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-maven
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-maven
secret:
secretName: git-ssh-key-maven
2.2 拉取 npm 项目代码任务 (clone-repo-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-npm
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-npm-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 npm 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-npm
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-npm
secret:
secretName: git-ssh-key-npm
3. 运行 dockerContext.sh
任务 (run-docker-context.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: run-docker-context
namespace: cicd
spec:
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: run-script
image: bash:latest
script: |
#!/bin/sh
set -e
cd $(workspaces.source.path)
if [ -f .manifest/dockerContext.sh ]; then
echo "运行 dockerContext.sh 脚本..."
chmod +x .manifest/dockerContext.sh
./.manifest/dockerContext.sh || echo "dockerContext.sh 执行失败,跳过..."
else
echo "未找到 dockerContext.sh 脚本,跳过..."
fi
4. 构建并推送镜像任务(使用 Kaniko) (build-and-push-kaniko.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-and-push-kaniko
namespace: cicd
spec:
params:
- name: image
description: Docker 镜像名称
type: string
- name: dockerfile
description: Dockerfile 的路径
default: ./Dockerfile
type: string
- name: context
description: 构建上下文路径
default: .
type: string
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
command:
- /kaniko/executor
args:
- "--context=$(workspaces.source.path)/$(params.context)"
- "--dockerfile=$(workspaces.source.path)/$(params.dockerfile)"
- "--destination=$(params.image)"
- "--oci-layout-path=/kaniko/oci"
- "--cache=true"
- "--cache-repo=$(params.image)"
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker/
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker/
volumes:
- name: kaniko-secret
secret:
secretName: kaniko-secret
5. 部署到 Kubernetes 任务 (deploy-to-kubernetes.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: deploy-to-kubernetes
namespace: cicd
spec:
params:
- name: namespace
description: Kubernetes 命名空间
type: string
- name: deployment-name
description: Kubernetes Deployment 名称
type: string
- name: image
description: 要部署的镜像
type: string
steps:
- name: deploy
image: bitnami/kubectl
script: |
#!/bin/sh
set -e
echo "将镜像 $(params.image) 部署到命名空间 $(params.namespace)..."
kubectl set image deployment/$(params.deployment-name) app=$(params.image) -n $(params.namespace)
- name: set-status
image: alpine
script: |
#!/bin/sh
echo "succeeded" > /tekton/results/status
results:
- name: status
description: 部署状态
6. 发送邮件通知任务 (send-email.yaml
)
(已在上文提供,此处重复以方便参考)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: send-email
namespace: cicd
spec:
params:
- name: subject
type: string
description: 邮件主题
- name: body
type: string
description: 邮件正文
steps:
- name: send-email
image: curlimages/curl:7.83.1
script: |
#!/bin/sh
set -e
SMTP_SERVER=$(cat /var/secrets/smtp/smtp-server)
SMTP_PORT=$(cat /var/secrets/smtp/smtp-port)
SMTP_USERNAME=$(cat /var/secrets/smtp/smtp-username)
SMTP_PASSWORD=$(cat /var/secrets/smtp/smtp-password)
FROM_EMAIL=$(cat /var/secrets/smtp/from-email)
TO_EMAIL=$(cat /var/secrets/smtp/to-email)
SUBJECT="$(params.subject)"
BODY="$(params.body)"
echo "正在通过 $SMTP_SERVER:$SMTP_PORT 发送邮件到 $TO_EMAIL..."
echo -e "Subject: $SUBJECT\n\n$BODY" | \
curl --url "smtp://$SMTP_SERVER:$SMTP_PORT" \
--ssl-reqd \
--mail-from "$FROM_EMAIL" \
--mail-rcpt "$TO_EMAIL" \
--user "$SMTP_USERNAME:$SMTP_PASSWORD" \
-T -
volumes:
- name: smtp-secrets
secret:
secretName: smtp-secret
应用任务:
kubectl apply -f send-email.yaml
步骤 7:创建 Tekton Pipelines
7.1 Maven 流水线 (maven-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: maven-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-maven
taskRef:
name: init-maven
runAfter: []
- name: clone-repo
runAfter:
- init-maven
taskRef:
name: clone-repo-maven
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "Maven 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **Maven 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
7.2 npm 流水线 (npm-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: npm-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-npm
taskRef:
name: init-npm
runAfter: []
- name: clone-repo
runAfter:
- init-npm
taskRef:
name: clone-repo-npm
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "NPM 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **NPM 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
说明:
- Maven 和 npm 流水线结构类似,但各自引用不同的初始化和代码拉取任务。
finally
部分确保无论前面的任务成功还是失败,都会执行send-email
任务发送通知。
应用流水线:
kubectl apply -f maven-pipeline.yaml
kubectl apply -f npm-pipeline.yaml
步骤 10:创建 dockerContext.sh
脚本
dockerContext.sh
是一个用于处理特定上下文操作的脚本。根据您的需求,您可以在此脚本中添加自定义逻辑。以下是一个示例脚本:
创建 dockerContext.sh
文件:
将以下内容保存为项目中的 .manifest/dockerContext.sh
文件:
#!/bin/sh
set -e
echo "执行 dockerContext.sh 脚本..."
# 示例操作:生成 Docker 镜像标签
TIMESTAMP=$(date +%Y%m%d%H%M%S)
echo "生成的时间戳标签:$TIMESTAMP"
# 您可以在此处添加更多自定义操作,例如修改配置文件、生成额外文件等。
echo "dockerContext.sh 脚本执行完成。"
说明:
- 功能:此脚本用于执行构建前的自定义操作,例如生成镜像标签、修改配置文件等。
- 位置:将此脚本放置在项目的
.manifest/
目录下,即.manifest/dockerContext.sh
。
确保脚本具有执行权限:
chmod +x .manifest/dockerContext.sh
步骤 11:应用所有 Tekton 资源
按照以下顺序依次应用所有 Tekton 任务和流水线配置文件:
kubectl apply -f init-maven.yaml
kubectl apply -f init-npm.yaml
kubectl apply -f clone-repo-maven.yaml
kubectl apply -f clone-repo-npm.yaml
kubectl apply -f run-docker-context.yaml
kubectl apply -f build-and-push-kaniko.yaml
kubectl apply -f deploy-to-kubernetes.yaml
kubectl apply -f send-email.yaml
kubectl apply -f maven-pipeline.yaml
kubectl apply -f npm-pipeline.yaml
kubectl apply -f workspace-pvc.yaml
kubectl apply -f kaniko-secret.yaml
kubectl apply -f smtp-secret.yaml
kubectl apply -f tekton-sa.yaml
验证资源创建成功:
kubectl get tasks,pipelines -n cicd
kubectl get pvc -n cicd
kubectl get secrets -n cicd
kubectl get serviceaccounts -n cicd
步骤 12:测试与运行
12.1 手动触发 Maven 流水线
创建并应用 Maven PipelineRun (maven-pipelinerun.yaml
):
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: maven-pipelinerun-$(date +%s)
namespace: cicd
spec:
pipelineRef:
name: maven-pipeline
params:
- name: repo-url
value: https://github.com/example/maven-app.git
- name: branch
value: main
- name: image
value: docker.io/example/maven-app:latest
- name: namespace
value: dev
- name: deployment-name
value: maven-app
workspaces:
- name: source
persistentVolumeClaim:
claimName: workspace-pvc
serviceAccountName: tekton-sa
应用 PipelineRun:
kubectl apply -f maven-pipelinerun.yaml
12.2 手动触发 npm 流水线
创建并应用 npm PipelineRun (npm-pipelinerun.yaml
):
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: npm-pipelinerun-$(date +%s)
namespace: cicd
spec:
pipelineRef:
name: npm-pipeline
params:
- name: repo-url
value: https://github.com/example/npm-app.git
- name: branch
value: main
- name: image
value: docker.io/example/npm-app:latest
- name: namespace
value: dev
- name: deployment-name
value: npm-app
workspaces:
- name: source
persistentVolumeClaim:
claimName: workspace-pvc
serviceAccountName: tekton-sa
应用 PipelineRun:
kubectl apply -f npm-pipelinerun.yaml
或者,您也可以使用 tkn
CLI 触发 Pipeline:
# 触发 Maven 流水线
tkn pipeline start maven-pipeline \
-p repo-url=https://github.com/example/maven-app.git \
-p branch=main \
-p image=docker.io/example/maven-app:latest \
-p namespace=dev \
-p deployment-name=maven-app \
-w name=source,claimName=workspace-pvc \
--serviceaccount=tekton-sa
# 触发 npm 流水线
tkn pipeline start npm-pipeline \
-p repo-url=https://github.com/example/npm-app.git \
-p branch=main \
-p image=docker.io/example/npm-app:latest \
-p namespace=dev \
-p deployment-name=npm-app \
-w name=source,claimName=workspace-pvc \
--serviceaccount=tekton-sa
12.3 监控流水线运行状态
# 查看流水线列表
kubectl get pipelines -n cicd
# 查看 PipelineRun 列表
kubectl get pipelineruns -n cicd
# 查看特定 PipelineRun 的日志
tkn pipelinerun logs <pipelinerun-name> -f -n cicd
将 <pipelinerun-name>
替换为实际的 PipelineRun 名称。
步骤 13:验证邮件通知功能
- 触发流水线:按照上述步骤 12.1 或 12.2 触发 Maven 或 npm 流水线。
- 检查邮件:确认指定的
to-email
收到相应的通知邮件。 - 排查问题:
- 如果邮件未收到,请检查:
smtp-secret
是否正确配置,确保所有字段都已正确 Base64 编码。- SMTP 服务器是否允许通过 API 或外部应用发送邮件(例如,Gmail 可能需要启用“应用专用密码”)。
- 查看
send-email
任务的日志,确认curl
命令是否执行成功。
- 如果邮件未收到,请检查:
关键 YAML 文件汇总
以下是所有关键 YAML 文件的汇总,供参考:
1. 初始化环境任务
1.1 Maven 初始化任务 (init-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-maven
namespace: cicd
spec:
steps:
- name: setup-maven
image: maven:3.8.6-jdk-11
script: |
#!/bin/sh
set -e
echo "初始化 Maven 环境..."
mvn --version
# 在此处添加任何 Maven 相关的初始化步骤,例如下载依赖
1.2 npm 初始化任务 (init-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: init-npm
namespace: cicd
spec:
steps:
- name: setup-npm
image: node:16
script: |
#!/bin/sh
set -e
echo "初始化 NPM 环境..."
node --version
npm --version
# 在此处添加任何 NPM 相关的初始化步骤,例如安装全局包
2. 拉取代码任务
2.1 拉取 Maven 项目代码任务 (clone-repo-maven.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-maven
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-maven-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 Maven 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-maven
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-maven
secret:
secretName: git-ssh-key-maven
2.2 拉取 npm 项目代码任务 (clone-repo-npm.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-repo-npm
namespace: cicd
spec:
params:
- name: repo-url
description: Git 仓库地址
type: string
- name: revision
description: Git 分支或标签
type: string
workspaces:
- name: source
description: 存放拉取代码的工作空间
steps:
- name: clone-npm-repo
image: alpine/git
script: |
#!/bin/sh
set -e
echo "从 $(params.repo-url) 克隆 npm 仓库..."
git clone $(params.repo-url) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.revision)
volumeMounts:
- name: ssh-credentials-npm
mountPath: /root/.ssh
volumes:
- name: ssh-credentials-npm
secret:
secretName: git-ssh-key-npm
3. 运行 dockerContext.sh
任务 (run-docker-context.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: run-docker-context
namespace: cicd
spec:
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: run-script
image: bash:latest
script: |
#!/bin/sh
set -e
cd $(workspaces.source.path)
if [ -f .manifest/dockerContext.sh ]; then
echo "运行 dockerContext.sh 脚本..."
chmod +x .manifest/dockerContext.sh
./.manifest/dockerContext.sh || echo "dockerContext.sh 执行失败,跳过..."
else
echo "未找到 dockerContext.sh 脚本,跳过..."
fi
4. 构建并推送镜像任务(使用 Kaniko) (build-and-push-kaniko.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-and-push-kaniko
namespace: cicd
spec:
params:
- name: image
description: Docker 镜像名称
type: string
- name: dockerfile
description: Dockerfile 的路径
default: ./Dockerfile
type: string
- name: context
description: 构建上下文路径
default: .
type: string
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
steps:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
command:
- /kaniko/executor
args:
- "--context=$(workspaces.source.path)/$(params.context)"
- "--dockerfile=$(workspaces.source.path)/$(params.dockerfile)"
- "--destination=$(params.image)"
- "--oci-layout-path=/kaniko/oci"
- "--cache=true"
- "--cache-repo=$(params.image)"
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker/
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker/
volumes:
- name: kaniko-secret
secret:
secretName: kaniko-secret
5. 部署到 Kubernetes 任务 (deploy-to-kubernetes.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: deploy-to-kubernetes
namespace: cicd
spec:
params:
- name: namespace
description: Kubernetes 命名空间
type: string
- name: deployment-name
description: Kubernetes Deployment 名称
type: string
- name: image
description: 要部署的镜像
type: string
steps:
- name: deploy
image: bitnami/kubectl
script: |
#!/bin/sh
set -e
echo "将镜像 $(params.image) 部署到命名空间 $(params.namespace)..."
kubectl set image deployment/$(params.deployment-name) app=$(params.image) -n $(params.namespace)
- name: set-status
image: alpine
script: |
#!/bin/sh
echo "succeeded" > /tekton/results/status
results:
- name: status
description: 部署状态
6. 发送邮件通知任务 (send-email.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: send-email
namespace: cicd
spec:
params:
- name: subject
type: string
description: 邮件主题
- name: body
type: string
description: 邮件正文
steps:
- name: send-email
image: curlimages/curl:7.83.1
script: |
#!/bin/sh
set -e
SMTP_SERVER=$(cat /var/secrets/smtp/smtp-server)
SMTP_PORT=$(cat /var/secrets/smtp/smtp-port)
SMTP_USERNAME=$(cat /var/secrets/smtp/smtp-username)
SMTP_PASSWORD=$(cat /var/secrets/smtp/smtp-password)
FROM_EMAIL=$(cat /var/secrets/smtp/from-email)
TO_EMAIL=$(cat /var/secrets/smtp/to-email)
SUBJECT="$(params.subject)"
BODY="$(params.body)"
echo "正在通过 $SMTP_SERVER:$SMTP_PORT 发送邮件到 $TO_EMAIL..."
echo -e "Subject: $SUBJECT\n\n$BODY" | \
curl --url "smtp://$SMTP_SERVER:$SMTP_PORT" \
--ssl-reqd \
--mail-from "$FROM_EMAIL" \
--mail-rcpt "$TO_EMAIL" \
--user "$SMTP_USERNAME:$SMTP_PASSWORD" \
-T -
volumes:
- name: smtp-secrets
secret:
secretName: smtp-secret
应用任务:
kubectl apply -f send-email.yaml
7. Tekton Pipelines
7.1 Maven 流水线 (maven-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: maven-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-maven
taskRef:
name: init-maven
runAfter: []
- name: clone-repo
runAfter:
- init-maven
taskRef:
name: clone-repo-maven
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "Maven 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **Maven 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
7.2 npm 流水线 (npm-pipeline.yaml
)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: npm-pipeline
namespace: cicd
spec:
params:
- name: repo-url
type: string
description: Git 仓库地址
- name: branch
type: string
description: Git 分支名称
- name: image
type: string
description: Docker 镜像名称
- name: namespace
type: string
description: Kubernetes 命名空间
- name: deployment-name
type: string
description: Kubernetes Deployment 名称
workspaces:
- name: source
description: 存放代码和构建上下文的工作空间
tasks:
- name: init-npm
taskRef:
name: init-npm
runAfter: []
- name: clone-repo
runAfter:
- init-npm
taskRef:
name: clone-repo-npm
params:
- name: repo-url
value: $(params.repo-url)
- name: revision
value: $(params.branch)
workspaces:
- name: source
workspace: source
- name: run-docker-context
runAfter:
- clone-repo
taskRef:
name: run-docker-context
workspaces:
- name: source
workspace: source
- name: build-and-push
runAfter:
- run-docker-context
taskRef:
name: build-and-push-kaniko
params:
- name: image
value: $(params.image)
- name: dockerfile
value: ./Dockerfile
- name: context
value: .
workspaces:
- name: source
workspace: source
- name: deploy
runAfter:
- build-and-push
taskRef:
name: deploy-to-kubernetes
params:
- name: namespace
value: $(params.namespace)
- name: deployment-name
value: $(params.deployment-name)
- name: image
value: $(params.image)
finally:
- name: notify
taskRef:
name: send-email
params:
- name: subject
value: "NPM 流水线 $(params.deployment-name) - $(tasks.deploy.results.status)"
- name: body
value: |
流水线 **NPM 流水线** 已完成。
- **仓库**: $(params.repo-url)
- **分支**: $(params.branch)
- **镜像**: $(params.image)
- **命名空间**: $(params.namespace)
- **部署名称**: $(params.deployment-name)
**状态**: $(tasks.deploy.results.status)
workspaces:
- name: source
workspace: source
说明:
- Maven 和 npm 流水线结构类似,但各自引用不同的初始化和代码拉取任务。
finally
部分确保无论前面的任务成功还是失败,都会执行send-email
任务发送通知。
应用流水线:
kubectl apply -f maven-pipeline.yaml
kubectl apply -f npm-pipeline.yaml
步骤 14:优化与容错
- 容错机制:
- 在
run-docker-context
任务中已包含对dockerContext.sh
脚本不存在或执行失败的处理,确保流水线不会因该脚本的问题中断。
- 在
- 重试策略:
- 根据需要在 Pipeline 或 Task 中配置重试策略,以应对临时性错误。
- 示例:在任务定义中添加
retries
字段。spec: retries: 3
- 资源限制:
- 为每个 Task 设置资源请求和限制,避免资源争用。
resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1"
- 为每个 Task 设置资源请求和限制,避免资源争用。
- 日志存储与监控:
- 集成日志收集和监控工具(如 Elasticsearch、Prometheus 和 Grafana),实时监控流水线的执行状态和性能,及时发现并解决问题。
常见问题排查
1. 邮件未发送
-
检查 SMTP Secret 配置:
- 确保
smtp-secret
中的所有字段(smtp-server
、smtp-port
、smtp-username
、smtp-password
、from-email
、to-email
)已正确 Base64 编码并填入smtp-secret.yaml
中。
- 确保
-
验证 SMTP 服务器设置:
- 确保 SMTP 服务器地址和端口正确。
- 确认 SMTP 服务器允许通过 API 或外部应用发送邮件。
- 对于 Gmail,可能需要启用“应用专用密码”或调整安全设置。
-
查看
send-email
任务日志:- 使用以下命令查看发送邮件任务的详细日志,确认
curl
命令是否执行成功。
tkn pipelinerun logs <pipelinerun-name> -f -n cicd
将
<pipelinerun-name>
替换为实际的 PipelineRun 名称。 - 使用以下命令查看发送邮件任务的详细日志,确认
2. 权限不足
-
检查 ServiceAccount 权限:
- 确保
tekton-sa
ServiceAccount 具有足够的权限访问 Kubernetes API 和相关资源。
- 确保
-
验证 RoleBinding 配置:
- 确保 RoleBinding 正确,将
tekton-sa
绑定到适当的 ClusterRole(例如edit
)。
- 确保 RoleBinding 正确,将
-
查看 RoleBinding:
kubectl get rolebinding -n cicd
3. 持久化存储问题
-
验证 PVC 状态:
- 确保
workspace-pvc
已正确创建并处于绑定状态。
kubectl get pvc workspace-pvc -n cicd
- 确保
-
确认有可用的 PersistentVolume:
- 确保集群中有可用的 PersistentVolume 提供所需的存储。
4. 任务失败
-
查看失败任务的详细日志:
tkn pipelinerun logs <pipelinerun-name> -f -n cicd
将
<pipelinerun-name>
替换为实际的 PipelineRun 名称。 -
根据错误信息调整任务脚本或配置:
- 例如,如果 Maven 任务失败,检查
pom.xml
是否正确,依赖是否可用。
- 例如,如果 Maven 任务失败,检查