CICD 的供应链安全工具 Tekton Chains

50c1bb2db578dfe2f6cd02321826145a.gif

作者 | Addo Zhang

来源 | 云原生指北

软件供应链是指进入软件中的所有内容及其来源,简单地可以理解成软件的依赖项。依赖项是软件运行时所需的重要内容,可以是代码、二进制文件或其他组件,也可以是这些组件的来源,比如存储库或者包管理器之类的。包括代码的已知漏洞、受支持的版本、许可证信息、作者、贡献时间,以及在整个过程中的行为和任何时候接触到它的任何内容,比如用于编译、分发软件的基础架构组件。

CICD 流水线作为基础架构组件,承担着软件的构建、测试、分发和部署。作为供应链的一环,其也成为恶意攻击的目标。CICD 的行为信息可以作为安全审查的重要依据,比如构建打包的环境、操作流程、处理结果等等。

今天介绍的 Tekton Chains,便是这样的行为收集工具。

Tekton Chains

ba12316a2edd7f69d5bcebb7cabe3f67.png

Chains 是一个 Kubernetes CRD 控制器,用于管理 Tekton 中的供应链安全。Chains 使 Tekton 能够在持续交付中,捕获 PipelineRun 和 TaskRun 运行的元数据用于安全审计,实现二进制溯源和可验证的构建,成为构成保证供应链安全的基础设施的一部分。

当前 Chains(v0.9.0)提供如下功能:

  • 使用用户提供的加密密钥,将 TaskRun 的结果(包含 TaskRun 本身和 OCI 镜像)镜像进行签名

  • 支持类似 in-toto 的证明格式

  • 使用多种加密密钥类型和服务(x509、KMS)进行签名

  • 签名的存储支持多种实现

接下来的 Demo,我们还是继续使用之前在 Tekton Pipeline 实战 用的 Java 项目 tekton-test,在代码中同样还包含了 Pipeline 和 Task 的定义。

为了支持 Chains,原有 task 增加了新的参数。

Demo

环境准备

使用 k3d 快速搭建 k3s 的集群

k3d cluster create tekton-test

安装 Teketon Pipelines 及 CLI

kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
brew install tektoncd-clikubectl get po -n tekton-pipelines
NAME                                           READY   STATUS    RESTARTS   AGE
tekton-pipelines-webhook-7f5d9fc745-cr7th      1/1     Running   0          12m
tekton-pipelines-controller-7c95d87d96-vvkgr   1/1     Running   0          12m

安装 tekton chains

kubectl apply --filename https://storage.googleapis.com/tekton-releases/chains/latest/release.yamlkubectl get po -n tekton-chains
NAME                                        READY   STATUS    RESTARTS   AGE
tekton-chains-controller-7d9fb75899-l9d4j   1/1     Running   0          9m8s

安装流水线,这里还是使用 tekton-test 中的流水线定义,详细的说明查看Tekton Pipelines 实战 中的说明。

cd tekton-test/tekton
#创建sa
kubectl apply -f serviceaccount.yaml
# 创建 docker hub 凭证 secret,这里需要命令行工具 jq
kubectl create secret docker-registry dockerhub --docker-server=https://index.docker.io/v1/ --docker-username=[USERNAME] --docker-password=[PASSWORD] --dry-run=client -o json | jq -r '.data.".dockerconfigjson"' | base64 -d > /tmp/config.json && kubectl create secret generic docker-config --from-file=/tmp/config.json -n tekton-pipelines && rm -f /tmp/config.json
#安装 git-clone task
tkn hub install task git-clone
#安装镜像构建 task
kubectl apply -f tasks/source-to-image.yaml
#安装部署 task
kubectl apply -f tasks/deploy-to-k8s.yaml
#安装 pipeline
kubectl apply -f pipeline/build-pipeline.yaml
#查看 task
tkn t list                  
NAME              DESCRIPTION              AGE
git-clone         These Tasks are Git...   2 minutes ago
source-to-image                            1 minute ago
deploy-to-k8s                              31 seconds ago
#查看 pipeline
tkn p list 
NAME             AGE              LAST RUN   STARTED   DURATION   STATUS
build-pipeline   35 seconds ago   ---        ---       ---        ---

配置

1. 添加认证凭证

Chains controller 需要使用进行:

  • 在镜像签名完成后,向 OCI 镜像仓库发送签名

  • 在使用密钥签名时,使用 Fulcio 获取签名证书

这里我们需要配置用于访问 Docker 镜像仓库的凭证,Chains controller 使用执行 PipelineRun 的 service account 将镜像签名推送到镜像仓库。

这里直接使用前面安装 pipeline 时创建的 secret,并授权 service account 访问 secret。

kubectl patch serviceaccount tekton-build \-p "{\"imagePullSecrets\": [{\"name\": \"docker-config\"}]}" -n tekton-pipelines

2. 签名密钥

为 Chains 生成并配置用于签名的签名密钥,支持下面的任何一种方式:

  • x509

  • Cosign

  • KMS

  • EXPERIMENTAL: Keyless signing

我们使用 cosign (安装非常简单,在 macOS 上执行 brew install cosign)创建 secret,输入密码时直接回车,不设置密码。

cosign generate-key-pair k8s://tekton-chains/signing-secrets
Enter password for private key: 
Enter password for private key again: 
Successfully created secret signing-secrets in namespace tekton-chains
Public key written to cosign.pub

下面就是创建的包含了密钥的 secret。

15038beb6053c4f4d07e744fee9c4d55.png

3. 配置 Chains

  • artifacts.taskrun.format=in-toto

  • artifacts.taskrun.storage=tekton

  • artifacts.taskrun.signer=x509

kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.taskrun.format": "in-toto"}}'
kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.taskrun.storage": "tekton"}}'
kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.taskrun.signer": "x509"}}'

验证

创建 PipelineRun 开始执行 Pipeline

#tekton-test 根目录
kubectl apply -f ./tekton/run/run.yaml
pipelinerun.tekton.dev/generic-pipeline-run created

执行完成后,检查 TaskRun 的运行结果。

tkn tr list
NAME                                   STARTED        DURATION     STATUS
generic-pipeline-run-source-to-image   1 minute ago   1 minute     Succeeded
generic-pipeline-run-fetch-from-git    1 minute ago   11 seconds   Succeeded
kubectl get tr generic-pipeline-run-source-to-image -o json | jq -r .metadata.annotations{"chains.tekton.dev/cert-taskrun-5bf67bed-af59-4744-a6a7-487de359cbae": "","chains.tekton.dev/chain-taskrun-5bf67bed-af59-4744-a6a7-487de359cbae": "","chains.tekton.dev/payload-taskrun-5bf67bed-af59-4744-a6a7-487de359cbae": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsInN1YmplY3QiOlt7Im5hbWUiOiJpbmRleC5kb2NrZXIuaW8vYWRkb3poYW5nL3Rla3Rvbi10ZXN0IiwiZGlnZXN0Ijp7InNoYTI1NiI6ImFjYmQ5OWY4YmUwMDNlOGI3ZTc3NjY1ZWUwZTMzMmU5NmRhMmNiNTRiMzI3MTk4YWJiNDY3MWM4ZGIxZTk5OGEifX1dLCJwcmVkaWNhdGUiOnsiYnVpbGRlciI6eyJpZCI6Imh0dHBzOi8vdGVrdG9uLmRldi9jaGFpbnMvdjIifSwiYnVpbGRUeXBlIjoiaHR0cHM6Ly90ZWt0b24uZGV2L2F0dGVzdGF0aW9ucy9jaGFpbnNAdjIiLCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6e30sInBhcmFtZXRlcnMiOnsiQ0hBSU5TLUdJVF9DT01NSVQiOiJ7c3RyaW5nIDQ2OTMxZmJjZjAzMDMyMGMzOTlmZjljMzA1MGQ2YjczMTI1OWFiZmMgW119IiwiQ0hBSU5TLUdJVF9VUkwiOiJ7c3RyaW5nIGh0dHBzOi8vZ2l0aHViLmNvbS9hZGRvemhhbmcvdGVrdG9uLXRlc3QuZ2l0IFtdfSIsIklNQUdFIjoie3N0cmluZyBhZGRvemhhbmcvdGVrdG9uLXRlc3QgW119IiwiaW1hZ2VUYWciOiJsYXRlc3QiLCJpbWFnZVVybCI6IntzdHJpbmcgYWRkb3poYW5nL3Rla3Rvbi10ZXN0IFtdfSIsInBhdGhUb0RvY2tlckZpbGUiOiJEb2NrZXJmaWxlIn19LCJidWlsZENvbmZpZyI6eyJzdGVwcyI6W3siZW50cnlQb2ludCI6Im12biIsImFyZ3VtZW50cyI6WyJjbGVhbiIsImluc3RhbGwiLCItRHNraXBUZXN0cyJdLCJlbnZpcm9ubWVudCI6eyJjb250YWluZXIiOiJtYXZlbiIsImltYWdlIjoiZG9ja2VyLmlvL2xpYnJhcnkvbWF2ZW5Ac2hhMjU2OjcyOTIyYWJjOTVkMzhlMDJmNzUwYjM0ODAwMjM5ZGMwZTJjMjk4ZTc0YmZkZDk3MDAxODM2N2YwZDkyODFkNWMifSwiYW5ub3RhdGlvbnMiOm51bGx9LHsiZW50cnlQb2ludCI6Ii9rYW5pa28vZXhlY3V0b3IiLCJhcmd1bWVudHMiOlsiLS1kb2NrZXJmaWxlPSQocGFyYW1zLnBhdGhUb0RvY2tlckZpbGUpIiwiLS1kZXN0aW5hdGlvbj0kKHBhcmFtcy5pbWFnZVVybCk6JChwYXJhbXMuaW1hZ2VUYWcpIiwiLS1jb250ZXh0PSQod29ya3NwYWNlcy5zb3VyY2UucGF0aCkiLCItLWRpZ2VzdC1maWxlPSQocmVzdWx0cy5JTUFHRV9ESUdFU1QucGF0aCkiXSwiZW52aXJvbm1lbnQiOnsiY29udGFpbmVyIjoiYnVpbGQtYW5kLXB1c2giLCJpbWFnZSI6Imdjci5pby9rYW5pa28tcHJvamVjdC9leGVjdXRvckBzaGEyNTY6ZmNjY2QyYWI5ZjM4OTJlMzNmYzdmMmU5NTBjOGU0ZmM2NjVlN2E0YzY2ZjZhOWQ3MGIzMDBkN2EyMTAzNTkyZiJ9LCJhbm5vdGF0aW9ucyI6bnVsbH0seyJlbnRyeVBvaW50Ijoic2V0IC1lXG5lY2hvICQocGFyYW1zLklNQUdFKSB8IHRlZSAkKHJlc3VsdHMuSU1BR0VfVVJMLnBhdGgpICAgICAgICBcbiIsImFyZ3VtZW50cyI6bnVsbCwiZW52aXJvbm1lbnQiOnsiY29udGFpbmVyIjoid3JpdGUtdXJsIiwiaW1hZ2UiOiJkb2NrZXIuaW8vbGlicmFyeS9iYXNoQHNoYTI1NjpiM2FiZTQyNTU3MDY2MThjNTUwZThkYjVlYzA4NzUzMjgzMzNhMTRkYmY2NjNlNmYxZTJiNjg3NWY0NTUyMWU1In0sImFubm90YXRpb25zIjpudWxsfV19LCJtZXRhZGF0YSI6eyJidWlsZFN0YXJ0ZWRPbiI6IjIwMjItMDUtMTRUMDU6NDI6MTFaIiwiYnVpbGRGaW5pc2hlZE9uIjoiMjAyMi0wNS0xNFQwNTo0Mjo0MloiLCJjb21wbGV0ZW5lc3MiOnsicGFyYW1ldGVycyI6ZmFsc2UsImVudmlyb25tZW50IjpmYWxzZSwibWF0ZXJpYWxzIjpmYWxzZX0sInJlcHJvZHVjaWJsZSI6ZmFsc2V9LCJtYXRlcmlhbHMiOlt7InVyaSI6ImdpdCtodHRwczovL2dpdGh1Yi5jb20vYWRkb3poYW5nL3Rla3Rvbi10ZXN0LmdpdC5naXQiLCJkaWdlc3QiOnsic2hhMSI6IjQ2OTMxZmJjZjAzMDMyMGMzOTlmZjljMzA1MGQ2YjczMTI1OWFiZmMifX1dfX0=","chains.tekton.dev/retries": "0","chains.tekton.dev/signature-taskrun-5bf67bed-af59-4744-a6a7-487de359cbae": "eyJwYXlsb2FkVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5pbi10b3RvK2pzb24iLCJwYXlsb2FkIjoiZXlKZmRIbHdaU0k2SW1oMGRIQnpPaTh2YVc0dGRHOTBieTVwYnk5VGRHRjBaVzFsYm5RdmRqQXVNU0lzSW5CeVpXUnBZMkYwWlZSNWNHVWlPaUpvZEhSd2N6b3ZMM05zYzJFdVpHVjJMM0J5YjNabGJtRnVZMlV2ZGpBdU1pSXNJbk4xWW1wbFkzUWlPbHQ3SW01aGJXVWlPaUpwYm1SbGVDNWtiMk5yWlhJdWFXOHZZV1JrYjNwb1lXNW5MM1JsYTNSdmJpMTBaWE4wSWl3aVpHbG5aWE4wSWpwN0luTm9ZVEkxTmlJNkltRmpZbVE1T1dZNFltVXdNRE5sT0dJM1pUYzNOalkxWldVd1pUTXpNbVU1Tm1SaE1tTmlOVFJpTXpJM01UazRZV0ppTkRZM01XTTRaR0l4WlRrNU9HRWlmWDFkTENKd2NtVmthV05oZEdVaU9uc2lZblZwYkdSbGNpSTZleUpwWkNJNkltaDBkSEJ6T2k4dmRHVnJkRzl1TG1SbGRpOWphR0ZwYm5NdmRqSWlmU3dpWW5WcGJHUlVlWEJsSWpvaWFIUjBjSE02THk5MFpXdDBiMjR1WkdWMkwyRjBkR1Z6ZEdGMGFXOXVjeTlqYUdGcGJuTkFkaklpTENKcGJuWnZZMkYwYVc5dUlqcDdJbU52Ym1acFoxTnZkWEpqWlNJNmUzMHNJbkJoY21GdFpYUmxjbk1pT25zaVEwaEJTVTVUTFVkSlZGOURUMDFOU1ZRaU9pSjdjM1J5YVc1bklEUTJPVE14Wm1KalpqQXpNRE15TUdNek9UbG1aamxqTXpBMU1HUTJZamN6TVRJMU9XRmlabU1nVzExOUlpd2lRMGhCU1U1VExVZEpWRjlWVWt3aU9pSjdjM1J5YVc1bklHaDBkSEJ6T2k4dloybDBhSFZpTG1OdmJTOWhaR1J2ZW1oaGJtY3ZkR1ZyZEc5dUxYUmxjM1F1WjJsMElGdGRmU0lzSWtsTlFVZEZJam9pZTNOMGNtbHVaeUJoWkdSdmVtaGhibWN2ZEdWcmRHOXVMWFJsYzNRZ1cxMTlJaXdpYVcxaFoyVlVZV2NpT2lKc1lYUmxjM1FpTENKcGJXRm5aVlZ5YkNJNkludHpkSEpwYm1jZ1lXUmtiM3BvWVc1bkwzUmxhM1J2YmkxMFpYTjBJRnRkZlNJc0luQmhkR2hVYjBSdlkydGxja1pwYkdVaU9pSkViMk5yWlhKbWFXeGxJbjE5TENKaWRXbHNaRU52Ym1acFp5STZleUp6ZEdWd2N5STZXM3NpWlc1MGNubFFiMmx1ZENJNkltMTJiaUlzSW1GeVozVnRaVzUwY3lJNld5SmpiR1ZoYmlJc0ltbHVjM1JoYkd3aUxDSXRSSE5yYVhCVVpYTjBjeUpkTENKbGJuWnBjbTl1YldWdWRDSTZleUpqYjI1MFlXbHVaWElpT2lKdFlYWmxiaUlzSW1sdFlXZGxJam9pWkc5amEyVnlMbWx2TDJ4cFluSmhjbmt2YldGMlpXNUFjMmhoTWpVMk9qY3lPVEl5WVdKak9UVmtNemhsTURKbU56VXdZak0wT0RBd01qTTVaR013WlRKak1qazRaVGMwWW1aa1pEazNNREF4T0RNMk4yWXdaRGt5T0RGa05XTWlmU3dpWVc1dWIzUmhkR2x2Ym5NaU9tNTFiR3g5TEhzaVpXNTBjbmxRYjJsdWRDSTZJaTlyWVc1cGEyOHZaWGhsWTNWMGIzSWlMQ0poY21kMWJXVnVkSE1pT2xzaUxTMWtiMk5yWlhKbWFXeGxQU1FvY0dGeVlXMXpMbkJoZEdoVWIwUnZZMnRsY2tacGJHVXBJaXdpTFMxa1pYTjBhVzVoZEdsdmJqMGtLSEJoY21GdGN5NXBiV0ZuWlZWeWJDazZKQ2h3WVhKaGJYTXVhVzFoWjJWVVlXY3BJaXdpTFMxamIyNTBaWGgwUFNRb2QyOXlhM053WVdObGN5NXpiM1Z5WTJVdWNHRjBhQ2tpTENJdExXUnBaMlZ6ZEMxbWFXeGxQU1FvY21WemRXeDBjeTVKVFVGSFJWOUVTVWRGVTFRdWNHRjBhQ2tpWFN3aVpXNTJhWEp2Ym0xbGJuUWlPbnNpWTI5dWRHRnBibVZ5SWpvaVluVnBiR1F0WVc1a0xYQjFjMmdpTENKcGJXRm5aU0k2SW1kamNpNXBieTlyWVc1cGEyOHRjSEp2YW1WamRDOWxlR1ZqZFhSdmNrQnphR0V5TlRZNlptTmpZMlF5WVdJNVpqTTRPVEpsTXpObVl6ZG1NbVU1TlRCak9HVTBabU0yTmpWbE4yRTBZelkyWmpaaE9XUTNNR0l6TURCa04yRXlNVEF6TlRreVppSjlMQ0poYm01dmRHRjBhVzl1Y3lJNmJuVnNiSDBzZXlKbGJuUnllVkJ2YVc1MElqb2ljMlYwSUMxbFhHNWxZMmh2SUNRb2NHRnlZVzF6TGtsTlFVZEZLU0I4SUhSbFpTQWtLSEpsYzNWc2RITXVTVTFCUjBWZlZWSk1MbkJoZEdncElDQWdJQ0FnSUNCY2JpSXNJbUZ5WjNWdFpXNTBjeUk2Ym5Wc2JDd2laVzUyYVhKdmJtMWxiblFpT25zaVkyOXVkR0ZwYm1WeUlqb2lkM0pwZEdVdGRYSnNJaXdpYVcxaFoyVWlPaUprYjJOclpYSXVhVzh2YkdsaWNtRnllUzlpWVhOb1FITm9ZVEkxTmpwaU0yRmlaVFF5TlRVM01EWTJNVGhqTlRVd1pUaGtZalZsWXpBNE56VXpNamd6TXpOaE1UUmtZbVkyTmpObE5tWXhaVEppTmpnM05XWTBOVFV5TVdVMUluMHNJbUZ1Ym05MFlYUnBiMjV6SWpwdWRXeHNmVjE5TENKdFpYUmhaR0YwWVNJNmV5SmlkV2xzWkZOMFlYSjBaV1JQYmlJNklqSXdNakl0TURVdE1UUlVNRFU2TkRJNk1URmFJaXdpWW5WcGJHUkdhVzVwYzJobFpFOXVJam9pTWpBeU1pMHdOUzB4TkZRd05UbzBNam8wTWxvaUxDSmpiMjF3YkdWMFpXNWxjM01pT25zaWNHRnlZVzFsZEdWeWN5STZabUZzYzJVc0ltVnVkbWx5YjI1dFpXNTBJanBtWVd4elpTd2liV0YwWlhKcFlXeHpJanBtWVd4elpYMHNJbkpsY0hKdlpIVmphV0pzWlNJNlptRnNjMlY5TENKdFlYUmxjbWxoYkhNaU9sdDdJblZ5YVNJNkltZHBkQ3RvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2WVdSa2IzcG9ZVzVuTDNSbGEzUnZiaTEwWlhOMExtZHBkQzVuYVhRaUxDSmthV2RsYzNRaU9uc2ljMmhoTVNJNklqUTJPVE14Wm1KalpqQXpNRE15TUdNek9UbG1aamxqTXpBMU1HUTJZamN6TVRJMU9XRmlabU1pZlgxZGZYMD0iLCJzaWduYXR1cmVzIjpbeyJrZXlpZCI6IlNIQTI1NjppRlk2RVhnWWt5enlabzgxU29MS1FPRy9CdjZyZnorZFYrMkZxNXFjY2NBIiwic2lnIjoiTUVVQ0lRREZ4bzE0bzVldDFRVkJKUklQK3liSlhmQ2VFTjJaK3ZFNWROQlpMQmhvSWdJZ0hwL3B4VDF0SDZleHF0d2x2UStML0prazhXVFMzbTJhL1BWN3AzeEdrTkE9In1dfQ==","kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"tekton.dev/v1beta1\",\"kind\":\"PipelineRun\",\"metadata\":{\"annotations\":{},\"generateName\":\"generic-pr-\",\"name\":\"generic-pipeline-run\",\"namespace\":\"tekton-pipelines\"},\"spec\":{\"params\":[{\"name\":\"git-revision\",\"value\":\"main\"},{\"name\":\"git-url\",\"value\":\"https://github.com/addozhang/tekton-test.git\"},{\"name\":\"imageUrl\",\"value\":\"addozhang/tekton-test\"},{\"name\":\"imageTag\",\"value\":\"latest\"}],\"pipelineRef\":{\"name\":\"build-pipeline\"},\"serviceAccountName\":\"tekton-build\",\"workspaces\":[{\"name\":\"git-source\",\"volumeClaimTemplate\":{\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"resources\":{\"requests\":{\"storage\":\"1Gi\"}}}}},{\"name\":\"docker-config\",\"secret\":{\"secretName\":\"docker-config\"}}]}}\n","pipeline.tekton.dev/affinity-assistant": "affinity-assistant-876633b0fe","pipeline.tekton.dev/release": "422a468"
}

将 payload 的内容解码可以看到 TaskRun 的输入、输出以及 Task 本身使用的镜像等信息。

{"_type": "https://in-toto.io/Statement/v0.1","predicateType": "https://slsa.dev/provenance/v0.2","subject": [{"name": "index.docker.io/addozhang/tekton-test","digest": {"sha256": "acbd99f8be003e8b7e77665ee0e332e96da2cb54b327198abb4671c8db1e998a"}}],"predicate": {"builder": {"id": "https://tekton.dev/chains/v2"},"buildType": "https://tekton.dev/attestations/chains@v2","invocation": {"configSource": {},"parameters": {"CHAINS-GIT_COMMIT": "{string 46931fbcf030320c399ff9c3050d6b731259abfc []}","CHAINS-GIT_URL": "{string https://github.com/addozhang/tekton-test.git []}","IMAGE": "{string addozhang/tekton-test []}","imageTag": "latest","imageUrl": "{string addozhang/tekton-test []}","pathToDockerFile": "Dockerfile"}},"buildConfig": {"steps": [{"entryPoint": "mvn","arguments": ["clean","install","-DskipTests"],"environment": {"container": "maven","image": "docker.io/library/maven@sha256:72922abc95d38e02f750b34800239dc0e2c298e74bfdd970018367f0d9281d5c"},"annotations": null},{"entryPoint": "/kaniko/executor","arguments": ["--dockerfile=$(params.pathToDockerFile)","--destination=$(params.imageUrl):$(params.imageTag)","--context=$(workspaces.source.path)","--digest-file=$(results.IMAGE_DIGEST.path)"],"environment": {"container": "build-and-push","image": "gcr.io/kaniko-project/executor@sha256:fcccd2ab9f3892e33fc7f2e950c8e4fc665e7a4c66f6a9d70b300d7a2103592f"},"annotations": null},{"entryPoint": "set -e\necho $(params.IMAGE) | tee $(results.IMAGE_URL.path)        \n","arguments": null,"environment": {"container": "write-url","image": "docker.io/library/bash@sha256:b3abe4255706618c550e8db5ec0875328333a14dbf663e6f1e2b6875f45521e5"},"annotations": null}]},"metadata": {"buildStartedOn": "2022-05-14T05:42:11Z","buildFinishedOn": "2022-05-14T05:42:42Z","completeness": {"parameters": false,"environment": false,"materials": false},"reproducible": false},"materials": [{"uri": "git+https://github.com/addozhang/tekton-test.git.git","digest": {"sha1": "46931fbcf030320c399ff9c3050d6b731259abfc"}}]}
}

e8f55cf170926416228e7c9854844711.gif

26198544c54b5b63b221f3f0b382b626.png

往期推荐

Kubernetes 上调试 distroless 容器

「云」上玩法虽多,小心水土不服!

Redis 内存满了怎么办?这样置才正确!

Redis 为何使用近似 LRU 算法淘汰数据,而不是真实 LRU?

1fd12e61ec42c17df5a53f3273b1aebf.gif

点分享

b744f3aaa3e2fb303066181b6ee15934.gif

点收藏

fdac0f55573463ad74597447c3f075d6.gif

点点赞

8acaedf71685a98604312f4804eaac57.gif

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python计算不规则图形面积_python opencv中的不规则形状检测和测量

正如我在评论中提到的那样,对于这个问题,分水岭似乎是一个很好的方法.但是当你回答时,定义标记的前景和背景是困难的部分!我的想法是使用形态梯度沿着冰晶获得良好的边缘并从那里开始工作;形态梯度似乎很有效.import numpy as npimport cv2img cv2.imread(image.pn…

深度解析开源推荐算法框架EasyRec的核心概念和优势

简介:如何通过机器学习PAI实现快速构建推荐模型 作者:程孟力 - 机器学习PAI团队 随着移动app的普及,个性化推荐和广告成为很多app不可或缺的一部分。他们在改善用户体验和提升app的收益方面带来了巨大的提升。深度学习在搜广推领域的应用也…

助力公益数字化 火山引擎向公益机构捐赠多款技术产品

5月18日,字节跳动公益联合火山引擎举办了“科技应用创新让公益更美好”线上交流会,与中国红十字基金会、壹基金等多家公益机构探讨如何利用科技信息化产品提升公益事业的效率,从而进一步解决社会问题。 交流会上,火山引擎联合Pic…

云效发布策略指南|滚动、分批、灰度怎么选?

简介:在日常和用户交流过程中,我们也经常会被用户问到关于发布的问题,比如不同职能团队之间应该如何配合、发布的最佳实践应该是什么样子的等等。今天我们就来聊聊常见应用发布方式的选择,以及每种发布模式适合什么样的场景。 无论…

shell安装mysql5.7_一键部署----shell脚本安装MySQL5.7

运维开发网 https://www.qedev.com2020-11-09 12:30出处:51CTO作者:wx5ddda4c97f426一键部署----shell脚本安装MySQL5.7#/bin/bashyum-yinstallncursesbisoncmakegccgcc-cncurses-develuseraddmysql-s/sbin/nologinread-p"输入你存放压缩包的绝对路…

极致用云,数智护航

简介:我们邀请到了阿里云混合云监控平台(Sunfire)团队负责人王肇刚来给我们分析下阿里背后的数字化业务运维安全工程标准及解决方案。 本次分享涵盖了全新发布的数字化业务运维安全工程标准、安全生产解决方案,以及全新升级的产品能力:包括了…

Lakehouse 架构解析与云上实践

简介:本文整理自 DataFunCon 2021大会上,阿里云数据湖构建云产品研发陈鑫伟的分享,主要介绍了 Lakehouse 的架构解析与云上实践。 作者简介:陈鑫伟(花名熙康),阿里云开源大数据-数据湖构建云产品…

菜鸟教程 mysql like_MySQL LIKE 子句

MySQL LIKE 子句我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据,同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。WHERE 子句中可以使用等号 来设定获取数据的条件,如 "runoob_author RUNOOB.COM"。但是有时候我们需要获…

云原生 Serverless Database 使用体验

简介:表格存储 Tablestore 作为一款广泛应用 Serverless DataBase,能够提供经济的计费模式,可以大幅缩减业务成本的同时, 具备极致的弹性服务能力和完全零运维的特性,能够给用户带来更丝滑的使用体验。 作者 | 李欣 …

首推业人一体,北森2022春季发布会,正式发布iTalentX5.0

5月19日,中国最大的一体化HR SaaS及人才管理平台北森于线上召开“HR x业务”2022春季新品发布会,基于“业务人力一体化”理念发布iTalentX5.0,以战略和业务为牵引,用数字化平台赋能经理、员工和HRBP, 实现人力资源与业…

【阿里云 CDP 公开课】 第二讲:CDH/HDP 何去何从

简介:Hadoop社区版CDH/HDP已经不再更新,也将终止服务。后续的平台路线图怎么规划?Cloudera CDP整合了CDH和HDP,有哪些性能提升和功能增强?如何平滑的进行迁移?本文结合CDH/HDP平台现状,详细介绍…

mysql表全连接_关于mysql 实现表连接(左,右,内,全连接)

mysql 实现表连接(左,右,内,全连接)查询中出现两个表的连接,下面通过实例来讲解一下各种连接查询的不同之处表 a,和表b 如下图a 表中 有 abcdb表中有 abcf内连接:SELECT * from a INNER JOIN b on a.nameb.…

阿里云 Serverless Kubernetes 的落地实践分享

简介:Serverless Kubernetes 基于 Kubernetes 之上,提供按需使用、节点免运维的 Serverless 能力,让开发者真正实现通过 Kubernetes 标准化 API 进行 Serverless 应用编程,值得关注。 作者 | 元毅(阿里云容器平台高级开…

DevLake 加入 Apache 孵化器,开源共建 Apache 生态首个研发大数据平台

4 月 29 日,开源研发数据平台 DevLake 通过投票决议,正式成为 Apache 软件基金会 (ASF) 的孵化项目。 进入孵化后,Apache DevLake 将遵循 The Apache Way[1],在导师们的引导下,坚持以人为本、社区高于代码的理念&#…

idea连接mysql注册登录_IDEA+MySQL实现登录注册的注册验证时出现 Cannot resolve query parameter '2'...

问题描述:在ideamysqltomcat 实现登录注册jsp的注册信息insert验证时出现 cannot resolve query parameter 2贴上创建链接的代码:if(conn ! null){string sql "select *from login_info where dbuser?";pstm conn.preparestatement(sql);ps…

如何画一张架构图(内含知识图谱)

简介:架构图是什么?为什么要画架构图?如何画好架构图?有哪些方法?本文从架构的定义说起,分享了阿里文娱高级技术专家箫逸关于画架构图多年的经验总结,并对抽象这一概念进行了深入地讨论。内容较…

软件分析与设计:分析什么?如何设计?

简介:分析与设计这两个词我们平时经常听到,也经常讲,那么分析与设计的本质究竟是什么呢?到底要分析什么?又到底要怎样去设计?这3个问题如果平时没有一些积累,突然被问到这些,一时也会…

协程到底有什么用?6种I/O模式告诉你!

作者 | 陆小风来源 | 码农的荒岛求生今天来聊一聊协程的作用。假设磁盘上有10个文件,你需要读取的内存,那么你该怎么用代码实现呢?在接着往下看之前,先自己想一想这个问题,看看自己能想出几种方法,各自有什…

阿里云数据治理系列(一):治理项目启动前的必答三问

简介:近一年以来,越来越多的企业在考虑或正在启动数据治理的项目。作为在该领域从业多年的人士,也常会被咨询:数据治理不是很多年前就有的概念么?为什么忽然很多企业都在提及?是不是新瓶装旧酒?…

揭晓远程证明架构EAA:机密容器安全部署的最后一环 | 龙蜥技术

简介:如果需要在云上 HW-TEE 环境里启动一个加密容器,如何在启动过程中获取容器的解密密钥? 文 / 周亮, 云原生机密计算 SIG 核心成员。 在云原生场景下,基于HW-TEE(如Intel SGX, Intel TDX 和 AMD SEV&am…