Knative 初体验:CI/CD 极速入门

2019 年 8 月 09 日

Knative 初体验:CI/CD 极速入门

Knative 社区很早就在讨论用 Tekton 替换 Build 模块的事宜。Knative Build 官方已经正式说明不再建议使用 Knative Build 了。


如果你知道 Knative Build 是什么相信你理解起 Tekton 就是很容易的一件事了。


  • Knative Build 对自己的一句话概述是:A Kubernetes-native Build resource.

  • Tekton 对自己的一句话概述是: A K8s-native Pipeline resource. https://tekton.dev


由上可以看到,两者的定位非常相近,但在功能上 Tekton 的设计更加的丰富、完整,这也是社区最终采用 Tekton 的原因。接下来我们就看一下 Tekton 的核心概念。


Tekton 极速入门


Tekton 主要由如下五个核心概念组成:


  • Task

  • TaskRun

  • Pipeline

  • PipelineRun

  • PipelineResource


以上五个概念,每一个都是以 CRD 的形式提供服务的。下面分别简述一下这五个概念的含义。


Task


Task 就是一个任务执行模板,之所以说 Task 是一个模板是因为 Task 定义中可以包含变量,Task 在真正执行的时候需要给定变量的具体值。Tekton 的 Task 很类似于一个函数的定义,Task 通过 inputs.params 定义需要哪些入参,并且每一个入参还可以指定默认值。Task 的 steps 字段表示当前 Task 是由哪些子步骤组成的。每一个步骤具体就是一个镜像的执行,镜像的启动参数可以通过 Task 的入参使用模板语法进行配置。


apiVersion: tekton.dev/v1alpha1kind: Taskmetadata:  name: task-with-parametersspec:  inputs:    params:      - name: flags        type: array      - name: someURL        type: string  steps:    - name: build      image: registry.cn-hangzhou.aliyuncs.com/knative-sample/alpine:3.9      command: ["sh", "-c"]      args: [ "echo ${inputs.params.flags} ; echo ${someURL}"]
复制代码


TaskRun


Task 定义好以后是不能执行的,就像一个函数定义好以后需要调用才能执行一样。所以需要再定义一个 TaskRun 去执行 Task。TaskRun 主要是负责设置 Task 需要的参数,并通过 taskRef 字段引用要执行的 Task。


apiVersion: tekton.dev/v1alpha1kind: TaskRunmetadata:  name: run-with-parametersspec:  taskRef:    name: task-with-parameters  inputs:    params:      - name: flags        value: "--set"      - name: someURL        value: "https://github.com/knative-sample"
复制代码


Pipeline


一个 TaskRun 只能执行一个 Task,当需要编排多个 Task 的时候就需要 Pipeline 出马了。Pipeline 是一个编排 Task 的模板。Pipeline 的 params 声明了执行时需要的入参。 Pipeline 的 spec.tasks 定义了需要编排的 Task。Tasks 是一个数组,数组中的 task 并不是通过数组声明的顺序去执行的,而是通过 runAfter 来声明 task 执行的顺序。


Tekton controller 在解析 CRD 的时候会解析 Task 的顺序,然后依据设定的顺序依次去执行。Pipeline 在编排 Task 的时候需要给每一个 Task 传入必须的参数,这些参数的值可以来自 Pipeline 自身的 params。


apiVersion: tekton.dev/v1alpha1kind: Pipelinemetadata:  name: pipeline-with-parametersspec:  params:    - name: context      type: string      description: Path to context      default: /some/where/or/other  tasks:    - name: task-1      taskRef:        name: build      params:        - name: pathToDockerFile          value: Dockerfile        - name: pathToContext          value: "${params.context}"    - name: task-2      taskRef:        name: build-push    runAfter:        - source-to-image      params:        - name: pathToDockerFile          value: Dockerfile        - name: pathToContext          value: "${params.context}"
复制代码


PipelineRun


和 Task 一样 Pipeline 定义完成以后也是不能直接执行的,需要 PipelineRun 才能执行 Pipeline。PipelineRun 的主要作用是给 Pipeline 设定必要的入参,并执行 Pipeline。


apiVersion: tekton.dev/v1alpha1kind: PipelineRunmetadata:  name: pipelinerun-with-parametersspec:  pipelineRef:    name: pipeline-with-parameters  params:    - name: "context"      value: "/workspace/examples/microservices/leeroy-web"
复制代码


PipelineResource


前面已经介绍了 Tekton 的四个核心概念。现在我们已经知道怎么定义 task、执行 task 以及编排 task 了。


但可能你还想在 Task 之间共享资源,这就是 PipelineResource 的作用。比如我们可以把 git 仓库信息放在 PipelineResource 中。这样所有 Task 就可以共享这份数据了。


piVersion: tekton.dev/v1alpha1kind: PipelineResourcemetadata:  name: wizzbang-git  namespace: defaultspec:  type: git  params:    - name: url      value: https://github.com/wizzbangcorp/wizzbang.git    - name: revision      value: master
复制代码


鉴权信息


git 仓库、镜像仓库这些都是需要鉴权才能使用的。所以还需要一种设定鉴权信息的机制。Tekton 本身是 Kubernetes 原生的编排系统。所以可以直接使用 Kubernetes 的 ServiceAccount 机制实现鉴权。


实例如下:


  • 定义一个保存镜像仓库鉴权信息的 secret


apiVersion: v1kind: Secretmetadata:  name: ack-cr-push-secret  annotations:    tekton.dev/docker-0: https://registry.cn-hangzhou.aliyuncs.comtype: kubernetes.io/basic-authstringData:  username: <cleartext non-encoded>  password: <cleartext non-encoded>
复制代码


  • 定义 ServiceAccount ,并且使用上面的 secret


apiVersion: v1kind: ServiceAccountmetadata:  name: pipeline-accountsecrets:- name: ack-cr-push-secret
复制代码


  • PipelineRun 中引用 ServiceAccount


apiVersion: tekton.dev/v1alpha1kind: PipelineRunmetadata:  generateName: tekton-kn-sample-spec:  pipelineRef:    name: build-and-deploy-pipeline... ...  serviceAccount: pipeline-account
复制代码


Hello World


https://github.com/knative-sample/tekton-knative 这是一个完整的 Tekton 的 Hello World。下面我们一起体验一下这个 Hello World。


在开始实战之前你需要有一个 Kubernetes 集群,并还需要安装 Knative 和 Tekton。tekton-knative 中的 release-v0.5.2.yaml 直接提交到 Kubernetes 集群即可完成 Tekton 的安装。下面我们开始体验使用 Tekton 从源码到构建再到部署的自动化过程。


clone 代码


clone 代码到本地。


git clone https://github.com/knative-sample/tekton-knative


##创建 PipelineResource


主要内容在 resources/picalc-git.yaml 文件中。如下所示主要是把 https://github.com/knative-sample/tekton-knative 保存在 resource 中给其他资源使用。


apiVersion: tekton.dev/v1alpha1kind: PipelineResourcemetadata:  name: tekton-knative-gitspec:  type: git  params:    - name: revision      value: master    - name: url      value: https://github.com/knative-sample/tekton-knative
复制代码


创建 task


创建 task,这个例子中我们创建两个 task:source-to-image 和 deploy-using-kubectl


  • source-to-image

  • 主要内容在 tasks/source-to-image.yaml 文件中。此 task 的主要功能是把源代码编译成镜像。

  • 主要是使用 kaniko 实现容器内编译 Docker 镜像的能力。此 Task 的参数主要是设置编译上下文的一些信息,比如:Dockerfile、ContextPath 以及目标镜像 tag 等。


apiVersion: tekton.dev/v1alpha1kind: Taskmetadata:  name: source-to-imagespec:  inputs:    resources:      - name: git-source        type: git    params:      - name: pathToContext        description: The path to the build context, used by Kaniko - within the workspace        default: .      - name: pathToDockerFile        description: The path to the dockerfile to build (relative to the context)        default: Dockerfile      - name: imageUrl        description: Url of image repository      - name: imageTag        description: Tag to apply to the built image        default: "latest"  steps:    - name: build-and-push      image: registry.cn-hangzhou.aliyuncs.com/knative-sample/kaniko-project-executor:v0.10.0      command:        - /kaniko/executor      args:        - --dockerfile=${inputs.params.pathToDockerFile}        - --destination=${inputs.params.imageUrl}:${inputs.params.imageTag}        - --context=/workspace/git-source/${inputs.params.pathToContext}      env:      - name: DOCKER_CONFIG        value: /builder/home/.docker
复制代码


  • deploy-using-kubectl

  • 主要内容在 tasks/deploy-using-kubectl.yaml 文件中。

  • 如下所示这个 Task 主要的作用是通过参数获取到目标镜像的信息,然后执行一条 sed 命令把 Knative Service yaml 中的 __IMAGE__ 替换成目标镜像。再通过 kubectl 发布到 Kubernetes 中。


apiVersion: tekton.dev/v1alpha1kind: Taskmetadata:  name: deploy-using-kubectlspec:  inputs:    resources:      - name: git-source        type: git    params:      - name: pathToYamlFile        description: The path to the yaml file to deploy within the git source      - name: imageUrl        description: Url of image repository      - name: imageTag        description: Tag of the images to be used.        default: "latest"  steps:    - name: update-yaml      image: alpine      command: ["sed"]      args:        - "-i"        - "-e"        - "s;__IMAGE__;${inputs.params.imageUrl}:${inputs.params.imageTag};g"        - "/workspace/git-source/${inputs.params.pathToYamlFile}"    - name: run-kubectl      image: registry.cn-hangzhou.aliyuncs.com/knative-sample/kubectl:v0.5.0      command: ["kubectl"]      args:        - "apply"        - "-f"        - "/workspace/git-source/${inputs.params.pathToYamlFile}"
复制代码


定义 Pipeline


我们已经有两个 Task 了,现在我们就用一个 PIpeline 来编排这两个 Task:


apiVersion: tekton.dev/v1alpha1kind: Pipelinemetadata:  name: build-and-deploy-pipelinespec:  resources:    - name: git-source      type: git  params:    - name: pathToContext      description: The path to the build context, used by Kaniko - within the workspace      default: src    - name: pathToYamlFile      description: The path to the yaml file to deploy within the git source    - name: imageUrl      description: Url of image repository    - name: imageTag      description: Tag to apply to the built image  tasks:  - name: source-to-image    taskRef:      name: source-to-image    params:      - name: pathToContext        value: "${params.pathToContext}"      - name: imageUrl        value: "${params.imageUrl}"      - name: imageTag        value: "${params.imageTag}"    resources:      inputs:        - name: git-source          resource: git-source  - name: deploy-to-cluster    taskRef:      name: deploy-using-kubectl    runAfter:      - source-to-image    params:      - name: pathToYamlFile        value:  "${params.pathToYamlFile}"      - name: imageUrl        value: "${params.imageUrl}"      - name: imageTag        value: "${params.imageTag}"    resources:      inputs:        - name: git-source          resource: git-source
复制代码


鉴权信息


如下所示,定义一个 Secret 和 ServiceAccount。并且给 ServiceAccount 绑定执行 Knative Service 的权限。


首先创建一个 Secret 保存镜像仓库的鉴权信息,如下所示:


  • tekton.dev/docker-0 换成你要推送的镜像仓库的地址;

  • username 换成镜像仓库鉴权的用户名;

  • password 环境镜像仓库鉴权的密码。


apiVersion: v1kind: Secretmetadata:  name: ack-cr-push-secret  annotations:    tekton.dev/docker-0: https://registry.cn-hangzhou.aliyuncs.comtype: kubernetes.io/basic-authstringData:  username: <cleartext non-encoded>  password: <cleartext non-encoded>
复制代码


下面这些信息保存到文件中,然后使用 kubectl apply -f 指令提交到 Kubernetes。


---apiVersion: v1kind: ServiceAccountmetadata:  name: pipeline-accountsecrets:- name: ack-cr-push-secret
---
apiVersion: v1kind: Secretmetadata: name: kube-api-secret annotations: kubernetes.io/service-account.name: pipeline-accounttype: kubernetes.io/service-account-token
---
kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata: name: pipeline-rolerules:- apiGroups: ["serving.knative.dev"] resources: ["services"] verbs: ["get", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: pipeline-role-bindingroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pipeline-rolesubjects:- kind: ServiceAccount name: pipeline-account
复制代码


定义 PIpelineRun


ServiceAccount 对应的鉴权信息是通过和 PIpelineRun 绑定的方式执行的。参见 run/picalc-pipeline-run.yaml 文件。


apiVersion: tekton.dev/v1alpha1kind: PipelineRunmetadata:  generateName: tekton-kn-sample-spec:  pipelineRef:    name: build-and-deploy-pipeline  resources:    - name: git-source      resourceRef:        name: tekton-knative-git  params:    - name: pathToContext      value: "src"    - name: pathToYamlFile      value: "knative/helloworld-go.yaml"    - name: imageUrl      value: "registry.cn-hangzhou.aliyuncs.com/knative-sample/tekton-knative-helloworld"    - name: imageTag      value: "1.0"  trigger:    type: manual  serviceAccount: pipeline-account
复制代码


执行 HelloWorld


准备 PIpeline 的资源。


kubectl apply -f tasks/source-to-image.yaml -f tasks/deploy-using-kubectl.yaml  -f resources/picalc-git.yaml -f image-secret.yaml -f pipeline-account.yaml -f pipeline/build-and-deploy-pipeline.yaml
复制代码


执行 create 把 pipelieRun 提交到 Kubernetes 集群。之所以这里使用 create 而不是使用 apply 是因为 PIpelineRun 每次都会创建一个新的,kubectl 的 create 指令会基于 generateName 创建新的 PIpelineRun 资源。


kubectl create -f run/picalc-pipeline-run.yaml
复制代码


查看一下 pod 信息可能是下面这样:


└─# kubectl get podNAME                                                        READY   STATUS      RESTARTS   AGEtekton-kn-sample-45d84-deploy-to-cluster-wfrzx-pod-f093ef   0/3     Completed   0          8htekton-kn-sample-45d84-source-to-image-7zpqn-pod-c2d20c     0/2     Completed   0          8h
复制代码


相关文章:


《初识 Knative:跨平台的 Serverless 编排框架》


《Knative 初体验:Serving Hello World》


《Knative 初体验:Eventing Hello World》


《Knative 初体验:Build Hello World》


2019 年 8 月 09 日 08:276340
用户头像
阿里云容器平台 ACK,企业云原生转型最佳搭档

发布了 43 篇内容, 共 17.2 次阅读, 收获喜欢 69 次。

关注

评论

发布
暂无评论
发现更多内容

云直播平台的选型与使用

音视频专家-李超

Go: g0, 特殊的goroutine

陈思敏捷

go golang 原理

其实你就是我羡慕的别人

小天同学

个人成长 感悟 日常思考

工作=投资=创业?

二鱼先生

个人成长 工作思路 工作方式 创业心态 创业者

k8s上运行我们的springboot服务之——cloud gateway

柠檬

k8s Spring Cloud

我是如何拿下PMP认证和系统架构设计师考试的?

Nick

Dig101-Go之如何在函数内修改指针

newbmiao

go golang dereference pointer

prometheus中honor_labels配置项的源码分析

陈思敏捷

go golang Prometheus

RocketMQ - 什么是RocketMQ

Java收录阁

RocketMQ

JUC整理笔记一之细说Unsafe

JFound

Java

0 ARTS 2020-05-23

3.141516

微信小程序 vim 程序员素养 编程好习惯

2020 年 5 月 23 日 Java 集合专题

瑞克与莫迪

Java

除了直接看余额,谁更有钱还能怎么比(一)

石君

零知识证明 多方计算 同态加密

区块链2.0--以太坊概述

皮卡丘的猫

圆圈正义 - 读后感

石云升

读书笔记 法律 公平 现实

你是个伪工作者么?

池建强

个人成长 伪工作者

利与弊-传统框架要不要部署在Serverless架构上

刘宇

Serverless Web

《零基础学 Java》 FAQ 之 12-理解引用

臧萌

Java

Java环境搭建

编号94530

Java java8 Java环境 环境安装 jdk安装

看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了

cxuan

https

游戏夜读 | 怎么让游戏跑起来?

game1night

《零基础学 Java》 FAQ 之 11-为什么构造方法中调用重载的构造方法必须得是在第一行

臧萌

Go: 应该使用指针还是结构体副本?

陈思敏捷

go golang struct 原理 pointer

我的编程之路 -5(停滞)

顿晓

网络编程 操作系统 编程之路 停滞 三年

python实现·十大排序算法之快速排序(Quick Sort)

南风以南

Python 排序算法 快速排序

《零基础学 Java》 FAQ 之 10-Scanner里nextInt的小坑

臧萌

Java

Flask-SQLAlchemy 多表对单模型

Leetao

Python flask 编程语言 flask-sqlalchemy

Go: Trace包探秘

陈思敏捷

go golang 原理

Mysql增量更新-ON DUPLICATE KEY UPDATE

BerryMew

MySQL 增量更新 ON DUPLICATE KEY UPDATE

new() 和 make的区别

陈思敏捷

go golang 源码 源码分析

Tekton 的工作原理

张晓辉

Kubernetes cicd 云原生

Knative 初体验:CI/CD 极速入门-InfoQ