├── .gitignore ├── images └── TektonExample1.png ├── kaniko ├── example-1 │ ├── configmap.yaml │ └── pod.yaml ├── example-2 │ └── pod.yaml └── TUTORIAL.md ├── example-1-github-read ├── resource.yaml ├── task.yaml └── pipeline.yaml ├── example-2-build-image ├── pipeline.yaml ├── resource.yaml └── task.yaml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | */**/.DS_Store 2 | **/.DS_Store 3 | .DS_Store -------------------------------------------------------------------------------- /images/TektonExample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CariZa/tekton-examples/HEAD/images/TektonExample1.png -------------------------------------------------------------------------------- /kaniko/example-1/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: dockerfile-configmap 5 | namespace: default 6 | data: 7 | dockerfile: | 8 | FROM ubuntu 9 | ENTRYPOINT ["/bin/bash", "-c", "echo hello"] -------------------------------------------------------------------------------- /example-1-github-read/resource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: PipelineResource 3 | metadata: 4 | name: github-repo 5 | spec: 6 | type: git 7 | params: 8 | - name: url 9 | value: https://github.com/CariZa/ulmaceae 10 | -------------------------------------------------------------------------------- /example-1-github-read/task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: Task 3 | metadata: 4 | name: read-task 5 | spec: 6 | inputs: 7 | resources: 8 | - name: github-repo 9 | type: git 10 | steps: 11 | - name: catreadme 12 | image: ubuntu 13 | command: 14 | - cat 15 | args: 16 | - "github-repo/README.md" 17 | -------------------------------------------------------------------------------- /example-1-github-read/pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: Pipeline 3 | metadata: 4 | name: pipeline-test 5 | spec: 6 | resources: 7 | - name: github-repo 8 | type: git 9 | tasks: 10 | - name: pipeline-read-task 11 | taskRef: 12 | name: read-task 13 | resources: 14 | inputs: 15 | - name: github-repo 16 | resource: github-repo 17 | -------------------------------------------------------------------------------- /kaniko/example-2/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: kaniko-example-2 5 | spec: 6 | containers: 7 | - name: kaniko 8 | readinessProbe: 9 | exec: 10 | command: 11 | - cat 12 | - /Dockerfile 13 | initialDelaySeconds: 1 14 | periodSeconds: 5 15 | image: gcr.io/kaniko-project/executor:latest 16 | args: ["--dockerfile=Dockerfile", 17 | "--context=git://github.com/youruser/repo", 18 | "--destination=index.docker.io/youruser/repo:example2"] # replace with your dockerhub account eg: index.docker.io/youruser/repo 19 | restartPolicy: Never -------------------------------------------------------------------------------- /example-2-build-image/pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: Pipeline 3 | metadata: 4 | name: build-pipeline 5 | spec: 6 | resources: 7 | - name: github-repo 8 | type: git 9 | - name: dockerhub-image 10 | type: image 11 | tasks: 12 | - name: build 13 | taskRef: 14 | name: build 15 | resources: 16 | inputs: 17 | - name: github-repo 18 | resource: github-repo 19 | - name: dockerhub-image 20 | resource: dockerhub-image 21 | - name: run 22 | taskRef: 23 | name: run 24 | runAfter: 25 | - build 26 | resources: 27 | inputs: 28 | - name: dockerhub-image 29 | resource: dockerhub-image 30 | -------------------------------------------------------------------------------- /example-2-build-image/resource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: PipelineResource 3 | metadata: 4 | name: github-repo 5 | spec: 6 | type: git 7 | params: 8 | - name: url 9 | value: https://github.com/CariZa/empty-hello-image 10 | --- 11 | apiVersion: tekton.dev/v1alpha1 12 | kind: PipelineResource 13 | metadata: 14 | name: dockerhub-image 15 | spec: 16 | type: image 17 | params: 18 | - name: url 19 | value: index.docker.io/cariza/tekton-prac:tekton-pipeline 20 | --- 21 | # TODO: Set this up so that 22 | apiVersion: tekton.dev/v1alpha1 23 | kind: PipelineResource 24 | metadata: 25 | name: test-cluster 26 | spec: 27 | type: cluster 28 | params: 29 | - name: url 30 | value: https://10.10.10.10 # url to the cluster master node 31 | - name: cadata 32 | value: LS0tLS1CRUdJTiBDRVJ..... 33 | - name: token 34 | value: ZXlKaGJHY2lPaU.... 35 | -------------------------------------------------------------------------------- /kaniko/example-1/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: kaniko-example-1 5 | spec: 6 | containers: 7 | - name: kaniko 8 | readinessProbe: 9 | exec: 10 | command: 11 | - cat 12 | - /workspace/dockerfile 13 | initialDelaySeconds: 1 14 | periodSeconds: 5 15 | image: gcr.io/kaniko-project/executor:latest 16 | args: ["--dockerfile=/workspace/dockerfile", 17 | "--context=dir://workspace", 18 | "--destination=index.docker.io/youruser/repo:example1"] # replace with your dockerhub account 19 | volumeMounts: 20 | - name: kaniko-secret 21 | mountPath: /root 22 | - name: dockerfile-source 23 | mountPath: /workspace 24 | restartPolicy: Never 25 | volumes: 26 | - name: kaniko-secret 27 | secret: 28 | secretName: regcred 29 | items: 30 | - key: .dockerconfigjson 31 | path: .docker/config.json 32 | - name: dockerfile-source 33 | configMap: 34 | name: dockerfile-configmap 35 | items: 36 | - key: dockerfile 37 | path: dockerfile -------------------------------------------------------------------------------- /example-2-build-image/task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: Task 3 | metadata: 4 | name: build 5 | spec: 6 | inputs: 7 | resources: 8 | - name: github-repo 9 | type: git 10 | - name: dockerhub-image 11 | type: image 12 | params: 13 | # - name: imageUrl 14 | # description: something 15 | # default: index.docker.io/cariza/tekton-prac:tekton-pipeline 16 | - name: pathToDockerFile 17 | description: The path to the dockerfile to build 18 | default: github-repo/Dockerfile 19 | - name: pathToContext 20 | description: The build context used by Kaniko (https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts) 21 | default: dir://github-repo 22 | # outputs: 23 | # resources: 24 | # - name: build-image 25 | steps: 26 | - name: build 27 | image: gcr.io/kaniko-project/executor:v0.9.0 28 | env: 29 | - name: "DOCKER_CONFIG" 30 | value: "/builder/home/.docker/" 31 | command: 32 | - /kaniko/executor 33 | args: 34 | - --dockerfile=$(inputs.params.pathToDockerFile) 35 | - --destination=$(inputs.resources.dockerhub-image.url) 36 | - --context=$(inputs.params.pathToContext) 37 | securityContext: 38 | runAsUser: 0 39 | volumeMounts: 40 | - name: kaniko-secret 41 | mountPath: /builder/home 42 | --- 43 | apiVersion: tekton.dev/v1alpha1 44 | kind: Task 45 | metadata: 46 | name: run 47 | spec: 48 | inputs: 49 | resources: 50 | - name: dockerhub-image 51 | type: image 52 | params: 53 | - name: imageUrl 54 | description: something 55 | default: index.docker.io/cariza/tekton-prac:tekton-pipeline 56 | steps: 57 | - name: run 58 | # image: $(inputs.params.imageUrl) 59 | image: "$(inputs.params.imageUrl)" 60 | # command: 61 | # - echo 62 | # args: 63 | # - "hello $(inputs.resources.dockerhub-image.url)" 64 | -------------------------------------------------------------------------------- /kaniko/TUTORIAL.md: -------------------------------------------------------------------------------- 1 | # Kaniko Tutorial 2 | 3 | Original tutorial: 4 | 5 | https://github.com/GoogleContainerTools/kaniko/blob/master/docs/tutorial.md 6 | 7 | I've just taken those steps and made them simpler - I hope - less fumbling, more copy paste and getting examples working with less effort. 8 | 9 | This is assuming you have a google cloud environment set up and a kubernetes cluster with google cloud. If you do not I would suggest rather following the link above and adjusting those steps to your needs. 10 | 11 | ## Tutorial 1 12 | 13 | This tutorial is using 14 | 15 | --context=dir://workspace 16 | 17 | We are going to build an image using files we place inside the running kaniko pod at a folder location (/workspace), we will do this by using a volumeMount and mount the contents of a configmap into the running Kaniko pod. 18 | 19 | ### Setup 20 | 21 | Let's create a dockerfile with a configmap, because why not. It's more convenient for creating POCs (less ssh and files to place in exact locations etc). 22 | 23 | And create the docker-registry secret: 24 | 25 | $ kubectl create secret docker-registry regcred --docker-server=index.docker.io --docker-username=username --docker-password=password --docker-email=email@address.com 26 | 27 | Create these two files: 28 | - configmap.yaml 29 | - pod.yaml 30 | 31 | Configmap.yaml 32 | 33 | ```apiVersion: v1 34 | kind: ConfigMap 35 | metadata: 36 | name: dockerfile-configmap 37 | namespace: default 38 | data: 39 | dockerfile: | 40 | FROM ubuntu 41 | ENTRYPOINT ["/bin/bash", "-c", "echo hello"] 42 | ``` 43 | 44 | Pod.yaml 45 | 46 | ```apiVersion: v1 47 | kind: Pod 48 | metadata: 49 | name: kaniko-example-1 50 | spec: 51 | containers: 52 | - name: kaniko 53 | readinessProbe: 54 | exec: 55 | command: 56 | - cat 57 | - /workspace/dockerfile 58 | initialDelaySeconds: 1 59 | periodSeconds: 5 60 | image: gcr.io/kaniko-project/executor:latest 61 | args: ["--dockerfile=/workspace/dockerfile", 62 | "--context=dir://workspace", 63 | "--destination=index.docker.io/youruser/repo:example1"] # replace with your dockerhub account 64 | volumeMounts: 65 | - name: kaniko-secret 66 | mountPath: /root 67 | - name: dockerfile-source 68 | mountPath: /workspace 69 | restartPolicy: Never 70 | volumes: 71 | - name: kaniko-secret 72 | secret: 73 | secretName: regcred 74 | items: 75 | - key: .dockerconfigjson 76 | path: .docker/config.json 77 | - name: dockerfile-source 78 | configMap: 79 | name: dockerfile-configmap 80 | items: 81 | - key: dockerfile 82 | path: dockerfile 83 | ``` 84 | 85 | Note 86 | 87 | You need to just tweak the pod.yaml file and replace 88 | 89 | args: [ 90 | ... 91 | "--destination=index.docker.io/youruser/repo:example1" 92 | ... 93 | ] 94 | 95 | For example my account and repo would be: 96 | 97 | index.docker.io/cariza/tekton-prac:example1 98 | 99 | You can change "example1" to be any tag you would like. 100 | 101 | You can have a look at my tests here. You can mimic this repo with your own account and repo, an empty repo will work fine. 102 | 103 | https://hub.docker.com/repository/docker/cariza/tekton-prac 104 | 105 | Just make sure you provide the right details to the docker-registry secret mentioned above. You won't have permission to edit my docker hub repo, but you can provide your authentication details and be able to edit your docker hub repo. 106 | 107 | Commands: 108 | 109 | $ kubectl create -f ./example-1/configmap.yaml 110 | $ kubectl create -f ./example-1/pod.yaml 111 | 112 | Follow the logs: 113 | 114 | $ kubectl logs kaniko-example-1 115 | 116 | Note: 117 | 118 | Make sure your secret regcred is correctly setup with the right values. 119 | 120 | 121 | ## Tutorial 2 122 | 123 | This tutorial is using 124 | 125 | --context=git://github.com/cariza/empty-hello-image 126 | 127 | We are going to build an image using files from a githun repo (you can use mine, or fork it ot create your own - github.com/cariza/empty-hello-image), we will do this by using a volumeMount and mount the contents of a repo into the running Kaniko pod. 128 | 129 | This tutorial will also work if you did not do Tutorial 1, this will not use docker hub, but rather focus on a github repo. And because it's public you won't nee authentication details for this tutorial. 130 | 131 | Create this file: 132 | 133 | - pod.yaml 134 | 135 | Command: 136 | 137 | $ kubectl create -f ./example-2/pod.yaml 138 | 139 | Follow the logs: 140 | 141 | $ kubectl logs kaniko-example-2 142 | 143 | ## Kaniko Notes: 144 | 145 | ### The Arguments we used in these tutorials 146 | 147 | - --dockerfile 148 | - --context 149 | - --destination 150 | 151 | #### --dockerfile 152 | 153 | This argument tells Kaniko where to find the Dockerfile 154 | 155 | --dockerfile=/workspace/dockerfile 156 | 157 | This is the file Kaniko will use to build the image. Imagine Kaniko running something like this (just hypothetically): 158 | 159 | $ docker build -t tag -f /workspace/dockerfile 160 | 161 | #### --context 162 | 163 | This argument refers to how Kaniko can expect to get access to your source code/project. In the two examples above we used these 2 contexts: 164 | 165 | --context=dir://workspace 166 | --context=git://github.com/youruser/repo 167 | 168 | Official docs show more options: [https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts](https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts) 169 | 170 | #### --destination 171 | 172 | This argument refers to the destination Kaniko will be sending the built and tagged image (provided Kaniko has permission - eg using the docker-registry secret credentials): 173 | 174 | --destination=/:tag 175 | 176 | 177 | ## Run kaniko locally using docker 178 | 179 | If you want to tinker with Kaniko even more, and investigate it locally (not with kubernetes - with docker only). This can be a nice way to isolate problems and test locally without creating a complex environment. 180 | 181 | Docker pull: 182 | 183 | $ docker pull gcr.io/kaniko-project/executor:latest 184 | 185 | To run you would need to create a local dockerfile and use a volume to pass it in to kaniko: 186 | 187 | Dockerfile 188 | 189 | FROM ubuntu 190 | ENTRYPOINT ["/bin/bash", "-c", "echo hello"] 191 | 192 | Run the imate with docker (from the same folder as your Dockerfile): 193 | 194 | $ docker run --rm --name test-kaniko --volume $(pwd)/Dockerfile:/workplace/Dockerfile gcr.io/kaniko-project/executor:latest --no-push --dockerfile /workplace/Dockerfile 195 | 196 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tekton-examples 2 | 3 | 4 | # Examples 5 | 6 | These examples are assuming you have made a clone of this repo, or at least copied the files and structured them like they are in this repo. 7 | 8 | ## Index 9 | 10 | - [Example 1](#example-1) Using Tekton Pipelines with a github Repo to run a cat step 11 | - [Example 2](#example-2) A simple docker image building pipeline using Tekton and Kaniko 12 | - [Side tutorial - Kaniko Tutorial](./kaniko/TUTORIAL.md) 13 | 14 | --- 15 | 16 | # Introduction 17 | 18 | A practice repo to collect examples of using tekton with kubernetes. 19 | 20 | Please note, this is just a reference for practicing with, this is not necessarily production ready. 21 | 22 | ### Just a quick opinion upfront on Tekton and it's usage (opinion is my own) 23 | 24 | Upfront my recommendation is not to use Tekton for just a single project that needs CI/CD. There are simpler solutions for a quick solve for CI/CD. 25 | 26 | * [Gitlab CI/CD](https://docs.gitlab.com/ee/ci/) 27 | * AgroCD 28 | 29 | Tekton seems more appropriate for building generic pipelines that would solve organisation wide CI/CD requirements. Tekton would be a long term strategy to standardize CI/CD across an organisation, and could create and add more complexity (rather than improve on) if not pre-planned and uniformly adopted. 30 | 31 | If you would like to use tools that are built on top of Tekton that abstract away some of the complexity of Tekton: 32 | 33 | * [JenkinsX](https://jenkins-x.io/) 34 | * As I find more I will add to this list... 35 | 36 | # Setup 37 | 38 | [![asciicast](https://asciinema.org/a/286482.svg)](https://asciinema.org/a/286482) 39 | 40 | ## Tekton setup notes 41 | 42 | These steps were taken and tweaked from this source: 43 | 44 | [https://github.com/tektoncd/pipeline/blob/master/docs/install.md](https://github.com/tektoncd/pipeline/blob/master/docs/install.md) 45 | 46 | 47 | ### Environment variables 48 | 49 | Setup some environment variables: 50 | 51 | export CLUSTER_NAME=tekton-prac 52 | export CLUSTER_ZONE=europe-west4-a 53 | export NUM_NODES=2 54 | 55 | Check values are set: 56 | 57 | echo $CLUSTER_NAME && echo $CLUSTER_ZONE && echo $NUM_NODES 58 | 59 | ### Kubernetes cluster 60 | 61 | Create the gc kubernetes cluster: 62 | 63 | $ gcloud container clusters create $CLUSTER_NAME \ 64 | --zone=$CLUSTER_ZONE \ 65 | --num-nodes=$NUM_NODES 66 | 67 | $ gcloud container clusters list 68 | 69 | **Tip:** To delete the cluster (if you want to start from scratch again): 70 | 71 | $ gcloud container clusters delete $CLUSTER_NAME --zone=$CLUSTER_ZONE 72 | 73 | Grant cluster-admin permissions to the current user: 74 | 75 | $ kubectl create clusterrolebinding cluster-admin-binding \ 76 | --clusterrole=cluster-admin \ 77 | --user=$(gcloud config get-value core/account) 78 | 79 | Install Tekton Pipelines: 80 | 81 | $ kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml 82 | 83 | Check installed: 84 | 85 | $ kubectl get pods --namespace tekton-pipelines 86 | 87 | You should see some pods in the "tekton-pipelines" namespace: 88 | 89 | tekton-pipelines-controller-... 90 | tekton-pipelines-webhook-... 91 | 92 | ## Notes on Tekton 93 | 94 | Tekton is made up of **6 main components**: 95 | 96 | * **Step** 97 | 98 | run commands 99 | 100 | * **Task** 101 | 102 | list of steps 103 | 104 | * **Pipeline** 105 | 106 | graph of tasks 107 | 108 | * **Pipeline Resource** 109 | 110 | a resource that is declared and then referenced and used in tasks and pipelines 111 | 112 | * **Task Run** 113 | 114 | invoke a task (Pipeline runs create Task Runs when run) 115 | 116 | * **Pipeline Run** 117 | 118 | invoke a pipeline 119 | 120 | 121 | #### Useful Youtube Videos: 122 | 123 | [https://www.youtube.com/watch?v=V0LpYdnTpsg](https://www.youtube.com/watch?v=V0LpYdnTpsg) 124 | 125 | [https://www.youtube.com/watch?time_continue=691&v=Bt-4LOkXJLU&feature=emb_logo](https://www.youtube.com/watch?time_continue=691&v=Bt-4LOkXJLU&feature=emb_logo) 126 | 127 | 128 | #### References: 129 | 130 | [https://github.com/tektoncd/pipeline/blob/master/docs/install.md](https://github.com/tektoncd/pipeline/blob/master/docs/install.md) 131 | 132 | [https://github.com/tektoncd/pipeline/blob/master/docs/tutorial.md](https://github.com/tektoncd/pipeline/blob/master/docs/tutorial.md) 133 | 134 | [https://github.com/tektoncd/pipeline/tree/master/examples](https://github.com/tektoncd/pipeline/tree/master/examples) 135 | 136 | [https://github.com/tektoncd/dashboard](https://github.com/tektoncd/dashboard) 137 | 138 | # Dashboard 139 | 140 | [![asciicast](https://asciinema.org/a/VzHDh5EeIDeVHQv44X11ORhbL.svg)](https://asciinema.org/a/VzHDh5EeIDeVHQv44X11ORhbL) 141 | 142 | ### Setup the dashboard for visibility 143 | 144 | Notes on setting up the dashboard: 145 | 146 | Install the dashboard with this command: 147 | 148 | $ kubectl apply --filename https://github.com/tektoncd/dashboard/releases/download/v0.2.1/dashboard-latest-release.yaml 149 | 150 | Note - Command taken from this source: [https://github.com/tektoncd/dashboard](https://github.com/tektoncd/dashboard) 151 | 152 | Simplest way to access the dashboard locally, use port-forward 153 | 154 | First check the dashboard pod is running: 155 | 156 | $ kubectl get pods --namespace tekton-pipelines 157 | 158 | Find the dashboard pod: 159 | 160 | tekton-dashboard-xxx-xxx 161 | 162 | View the dashboard by using port-forward: 163 | 164 | $ kubectl port-forward tekton-dashboard-xxx-xxx -n tekton-pipelines 9097:9097 165 | 166 | You should now be able to view the dashboard at: 167 | 168 | [http://localhost:9097](http://localhost:9097) 169 | 170 | 171 | 172 | 173 | # Examples 174 | 175 | These examples are assuming you have made a clone of this repo, or at least copied the files and structured them like they are in this repo. 176 | 177 | ## Index 178 | 179 | - [Example 1](#example-1) Using Tekton Pipelines with a github Repo to run a cat step 180 | - [Example 2](#example-2) A simple docker image building pipeline using Tekton and Kaniko 181 | - [Side tutorial - Kaniko Tutorial](./kaniko/TUTORIAL.md) 182 | 183 | # Example 1 184 | 185 | Using Tekton Pipelines with a github Repo to run a cat step 186 | 187 | [![asciicast](https://asciinema.org/a/tPHU34Vrqxf3yxpy3yNIVIF5L.svg)](https://asciinema.org/a/tPHU34Vrqxf3yxpy3yNIVIF5L) 188 | 189 | ### Goal: 190 | 191 | Run a simple example where you will set a public github repo as a **Pipeline Resource**. 192 | 193 | Run these yaml scripts in this order: 194 | 195 | $ kubectl apply -f ./example-1-github-read/ 196 | 197 | $ kubectl get pipeline,pipelineresource,task 198 | 199 | You should see these resources 200 | 201 | NAME AGE 202 | pipeline.tekton.dev/pipeline-test 1m 203 | 204 | NAME AGE 205 | pipelineresource.tekton.dev/github-repo 1m 206 | 207 | NAME AGE 208 | task.tekton.dev/read-task 1m 209 | 210 | Check the dashboard: 211 | 212 | [http://localhost:9097/#/namespaces/default/pipelines](http://localhost:9097/#/namespaces/default/pipelines) 213 | 214 | ### PipelineRuns 215 | 216 | The PipelineRun is the trigger of the pipeline, keep the trigger seperate from the configuration/setup and run it when you want the pipeline to run. Every time we want to trigger the pipeline we would need to have a unique named PipelineRun. 217 | 218 | Here are some ideas on how to tackle the pipeline run: 219 | 220 | You can manually use the dashboard to trigger the PipelineRuns by going to the "pipelineruns" tab and clicking "Create PipelineRun". 221 | 222 | Or we can generate the PipelineRun yaml file using a name + timestamp approach. 223 | 224 | ### PipelineRun Trigger 225 | 226 | ```yaml 227 | cat <./pipeline-run-$(date +%s).yaml 228 | apiVersion: tekton.dev/v1alpha1 229 | kind: PipelineRun 230 | metadata: 231 | name: pipelinerun-test-$(date +%s) 232 | spec: 233 | pipelineRef: 234 | name: pipeline-test 235 | resources: 236 | - name: github-repo 237 | resourceRef: 238 | name: github-repo 239 | EOF 240 | ``` 241 | 242 | You would then need to create that PipelineRun by running the yaml file with a "kubecl create -f ..." command: 243 | 244 | $ kubecl create -f pipeline-run-xxxxx.yaml 245 | 246 | An approach I felt worked better: 247 | 248 | You can create PipelineRuns using the "kubectl create" command directly via **stdin**, this will just create the kubernetes resource and run it but not save a file: 249 | 250 | ```yaml 251 | cat <