Hands on: Prow

Kubernetes Native CI/CD

25 January 2020

Juan Manuel Parrilla

Senior Software Engineer, Red Hat

Hands on: Prow

2

About me

Hands on Prow by Juan Manuel Parrilla
3

Agenda

Hands on Prow by Juan Manuel Parrilla
4

What is Prow

5

What is Prow

NAME                                READY   STATUS    RESTARTS   AGE
deck-f958755bc-skq64                1/1     Running   0          2d2h
deck-f958755bc-v5568                1/1     Running   0          2d2h
hook-57d5467cbc-6ndvg               1/1     Running   0          10d
hook-57d5467cbc-k22fm               1/1     Running   0          10d
horologium-79965ffb5-c29nt          1/1     Running   0          10d
plank-79646b78fb-mn796              1/1     Running   0          10d
sinker-796f7df8cb-tdj5b             1/1     Running   0          10d
statusreconciler-56b668448f-bm7f9   1/1     Running   0          10d
tide-6d66ddcb4c-gms2t               1/1     Running   0          10d
6

What is Prow

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/deck         NodePort    10.104.115.56    <none>        80:30000/TCP     10d
service/hook         NodePort    10.105.150.158   <none>        8888:30300/TCP   10d
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          10d
service/tide         NodePort    10.109.88.186    <none>        80:30090/TCP     10d
Github /retest comment > Hook > Tide > Trigger jobs
7

Prow Control Plane

8

Prow Control Plane: Hook

9

Prow Control Plane: Plank

10

Prow Control Plane: Deck

11

Prow Control Plane: Deck

12

Prow Control Plane: Deck

13

Prow Control Plane: Deck

14

Prow Control Plane: Horologium and Synker

Both are very simple but useful components

15

Prow Control Plane: Tide

16

Prow Control Plane: Crier

Those are the supported providers:

17

Questions?

18

Deploying Prow

19

Deploying Prow

We have 2 ways to deploy Prow:

We recommend to use Tackle because in some minutes you will have it Prow working, you will need to follow this procedure and some requirements:

This is a Sample Installation but without SSL (T_T)

20

Deploying Prow

Or Manual way:

With our new fresh K8s cluster we will start working to deploy Prow:

We will summarize all the nesessary steps to make it work (all explained in depth on the previous link):

21

Deploying Prow

Depending on How did you configure your K8s instances you will access to your Prow instances in a way or other:

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/deck         NodePort    10.104.115.56    <none>        80:30000/TCP     10d
service/hook         NodePort    10.105.150.158   <none>        8888:30300/TCP   10d
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          10d
service/tide         NodePort    10.109.88.186    <none>        80:30090/TCP     10d
22

Questions?

23

Configuring Prow

24

Configuring Prow - SSL

To deploy SSL in our cluster we will need some additional requirements

NOTE: depending on your decission you could go with Let's Encrypt or SelfSigned cert but if you're using a ".dev" domain you should use a real CA to validate your domain.

Check this detailed instructions!!

25

Configuring Prow

You will need to spend some time preparing your config files, here you have our ones that maybe could be useful.

26

Configuring Prow

Let's go into the different sections of the ConfigFile. We will not review all the possible options, we will work with our sample file ;)

prowjob_namespace: default
pod_namespace: test-pods
log_level: debug
sinker:
  resync_period: 1m
  max_prowjob_age: 48h
  max_pod_age: 48h
  terminated_pod_ttl: 30m
27

Configuring Prow

plank:
  job_url_template: 'https://prow.kerbeross.dev/view/gcs/kerbeross-prow-storage/{{if eq .Spec.Type "presubmit"}}pr-logs/pull{{else if eq .Spec.Type "batch"}}pr-logs/pull{{else}}logs{{end}}{{if .Spec.Refs}}{{if ne .Spec.Refs.Org ""}}/{{.Spec.Refs.Org}}_{{.Spec.Refs.Repo}}{{end}}{{end}}{{if eq .Spec.Type "presubmit"}}/{{with index .Spec.Refs.Pulls 0}}{{.Number}}{{end}}{{else if eq .Spec.Type "batch"}}/batch{{end}}/{{.Spec.Job}}/{{.Status.BuildID}}/'
  job_url_prefix_config: 
    '*': "https://prow.kerbeross.dev/view/gcs/"
  pod_pending_timeout: 60m
  default_decoration_configs:
    '*':
      timeout: 2h
      grace_period: 15s
      utility_images:
        clonerefs: "gcr.io/k8s-prow/clonerefs:v20200117-903ce628f"
        initupload: "gcr.io/k8s-prow/initupload:v20200117-903ce628f"
        entrypoint: "gcr.io/k8s-prow/entrypoint:v20200117-903ce628f"
        sidecar: "gcr.io/k8s-prow/sidecar:v20200117-903ce628f"
      gcs_configuration:
        bucket: "kerbeross-prow-storage"
        path_strategy: "explicit"
      gcs_credentials_secret: "gcs"
28

Configuring Prow

Note: Careful with the file name, must be service-account.json, the secret name is customizable.

29

Configuring Prow

tide:
  sync_period: 2m
  merge_method:
    the-shadowmen/prow-devconf: squash
    the-shadowmen/kubevirt-tutorial: squash
    the-shadowmen/kubevirtci: squash
  queries:
    - repos:
        - the-shadowmen/prow-devconf
        - the-shadowmen/kubevirt-tutorial
        - the-shadowmen/kubevirtci
      labels:
        - lgtm
        - approved
      missingLabels:
        - do-not-merge
        - do-not-merge/hold
  pr_status_base_urls:
    '*': https://prow.kerbeross.dev/pr
  context_options:
    from-branch-protection: false
    skip-unknown-contexts: true
30

Configuring Prow

In Tide section you set the correct context to manages the automerge:

31

Configuring Prow

Inside of Deck section and concretelly on spyglass one, we just are telling it that we will have 3 artifacts and are located on those paths

deck:
  spyglass:
    size_limit: 500000000 # 500MB
    viewers:
      "started.json|finished.json":
      - "metadata"
      "build-log.txt":
      - "buildlog"
      "artifacts/junit.*\\.xml":

Also on the config file we used to have the Notifiers and the Jobs, we will talk about those in their own section.

32

Configuring Prow

Now we need to verify that the ConfigFile and PluginFile is well formed with a Bazel task and then load it as ConfigMap on the default namespace.

kubectl create configmap config --from-file=config.yaml=config.yaml --dry-run -o yaml \
  | kubectl create configmap config -f -    # If the CM doesn't exists

kubectl create configmap label-config --from-file=$HOME/prow_conf/labels.yaml -o yaml
33

Configuring Prow

Ok, now we have all set to start working with a basic Prow platform, this allows you to manage and automate your Github repository with auto-labelling, approve merges (without auto-merging), etc...

The capabilities of this depend on what plugins did you activate on the PluginsConfig file
there are plenty of them, but some of them needs to add additional ConfigMaps/Sections in ConfigFile/etc...

Let's take a look to plugins...

34

Questions?

35

Prow Plugins

36

Prow Plugins

Well, Prow plugins a a bunch of resources that give you capabilities on Prow platform. As an example, assign plugin gives the functionality to assign a reviewer to a PR that is already on going.

37

Prow Plugins

This is how looks like part of PluginsConfig file, this one shows the enabled plugins for our organization:

plugins:
  the-shadowmen:        # Organization
  - size                # Manages the 'size/*' labels per PR
  - label               # Base plugin for labeling
  - hold                # Allows to add or remove the 'do-not-merge/hold'
  - assign              # Assigns or requests reviews from users.
  - blunderbuss         # Auto-Assign new PRs created to the reviewers.
  - lifecycle           # Close, reopen, flag and/or unflag an issue or PR as frozen/stale/rotten
  - verify-owners       # Validates OWNERS files if they are modified in a PR.
  - wip                 # Applies the 'do-not-merge/wip' Label to pull requests.

  the-shadowmen/prow-devconf:
  - trigger

As you see those plugins are enabled for all the organization and you doesn't need to add them for every repo you have. Instead some other plugins need to be enabled by repository to make them work

38

Prow Plugins

Inside of plugins: section we should add every repo and plugins that want to be managed by Prow:

  the-shadowmen/kubevirt.github.io:
  - trigger
  - owners-label
lgtm:
- repos:
  - the-shadowmen/kubevirt-tutorial
  - the-shadowmen/kubevirtci
  - the-shadowmen/prow-devconf
  review_acts_as_lgtm: true
39

Prow Plugins

Some plugins needs additional Config sections on Prow ConfigFile or maybe needs Additional services to be working properly, like lgtm, approve, or trigger. All of them has a thing in common, are managed by the same service Tide, which needs to be properly configured.

As we said before:

Also interacts with Plank in order to trigger Jobs

40

Prow plugins: config-updater

As you see, the config and the Jobs are mixed in the same ConfigMap/File, this is weird isn't it?
Well this is what you need:

41

Prow plugins: config-updater

Config updater redeploys configuration and plugin configuration files when they change and allows you to keep separated your Jobs from your config.

config_updater:                 # Config Updater section
  maps:
    prow-config/config.yaml:    # It will take the Config from this path
      name: config
    prow-config/jobs/**/*.yaml: # It will take the Jobs from this path
      name: job-config
    prow-config/plugins.yaml:   # It will take the Plugins from this path
      name: plugins
    prow-config/labels.yaml:    # It will take the Labels from this path
      name: label-config

Note: Ensure you've been validated that the config, plugins and jobs are correctly set on their files with checkconfig.

42

Prow plugins: config-updater

After that you will need to add the config-updater to the repo that contains the data:

  the-shadowmen/prow-devconf:
  - trigger
  - owners-label
  - lgtm
  - approve
  - config-updater

This is the link between the repo and the config. Then the plugin will create the ConfigMaps:

NAME                     DATA   AGE
config                   1      2d2h
job-config               1      17h
label-config             1      20h
plugins                  1      2d2h
43

Prow plugins: config-updater

In order to let prow know that you are using a separated ConfigMap to the deployments, you need to patch the deck, hook, horologium, plank, sinker, tide and statusreconciler, with this changes:

- mountPath: /etc/job-config
  name: job-config
  readOnly: true
44

Prow plugins: config-updater

45

Prow plugins: config-updater

46

Prow plugins: Approvers/Owner-labels

Owners will allow you to set reviewers and approvers by folder or setting up somefilters in your managed repositories.

To make it work you only need to enable the plugin in the repo config and after that, create a OWNERS file in the desired folder, it will have this format:

    reviewers:
      - codificat
      - jparrill
      - iranzo
    approvers:
      - iranzo
      - ptrnull
    emeritus_approvers:
      - karmab # 10 july 2019
      - tripledes # 10 july 2019
47

Prow plugins: Approvers/Owner-labels

filters:
  ".*":
    reviewers:
      - codificat
      - jparrill
      - iranzo
    approvers:
      - iranzo
      - ptrnull
    emeritus_approvers:
      - karmab # 10 july 2019
      - tripledes # 10 july 2019
## This part is for owner-labels
  "^_posts/.*":
    labels:
      - kind/blog
  "^_(data|layouts|sass|css|js)/.*":
    labels:
      - kind/website

This is a real sample of filters

48

Prow plugins: Approvers/Owner-labels

This is a very good example about how to configure Prow Jobs among multiple work groups:

The folders have their own OWNERS file and every job file have the kind of job followed by the repo name: kubevirt-tutorial-presubmits.yaml
and the OWNERS file is like:

reviewers:
  - codificat
  - iranzo
  - ptrnull
  - jparrill
approvers:
  - jparrill
  - codificat
  - iranzo
  - ptrnull
49

Prow plugins: Others

50

Questions?

51

Auto-management of your GitHub repo

52

Auto-management of your GitHub repo

In order to manage out repo automatically, we need to go through our Config file. You need to ensure that you've filled these sections properly

You also need to have the Github Webhook pointing properly to your Hook service on K8s on your Github Org

53

Auto-management of your GitHub repo

There is not a great way to bake the config, because the documentation is not good and you need to go through the code to know all the config statements, but you at least you have a clear workflow to follow.

54

Auto-management of your GitHub repo

kubectl create configmap plugins --from-file=plugins.yaml=$HOME/prow_conf/plugins.yaml \
  --dry-run -o yaml | kubectl replace configmap plugins -f -

kubectl create configmap config --from-file=config.yaml=$HOME/prow_conf/config.yaml \
  --dry-run -o yaml | kubectl replace configmap config -f -

kubectl create configmap label-config --from-file=labels.yaml=$HOME/prow_conf/labels.yaml \
  --dry-run -o yaml | kubectl replace configmap label-config -f -

This will allow you to start with Prow Jobs easily.

55

Questions?

56

Testing with Prow

57

Testing with Prow

If you'd been set the config as we followed, I've good news for you!

You should be able to execute testing right now! \o/

58

Testing with Prow

The Prow jobs works in the same way as you spin up an application in K8s, just select a Base Image to work with, the EntryPoint, Volumes, Env variables, NodeSelector (in order to use concrete nodes in a kind of test).

Let's see what kind of Jobs we have and how to configure them.

Periodic:

59

Testing with Prow

This is how looks like the Periodic Job spec:

periodics:
  - interval: 24h
    name: kubevirt-io-periodic-link-checker
    decorate: true      # The pod will be decorated with our special config
    always_run: true    # Tests always run
    extra_refs:
    - org: the-shadowmen
      repo: kubevirt.github.io
      base_ref: master
      path_alias: kubevirt.github.io skip_report: false  # Avoid to report the Job status
    spec:
      nodeSelector:
        region: primary
      containers:
        - image: docker.io/library/ruby
          env:
            - name: NOKOGIRI_USE_SYSTEM_LIBRARIES
              value: "true"
          command: ["/bin/sh", "-c"]
          args: ["/usr/local/bin/bundle install && bundle exec rake"]
60

Testing with Prow

Presubmit:

61

Testing with Prow

This is how looks like the Presubmit Job spec:

presubmits:
  the-shadowmen/kubevirt.github.io:
    - name: kubevirt-io-presubmit-link-checker
      decorate: true      # The pod will be decorated with our special config
      always_run: true    # Tests always run
      skip_report: false  # Avoid to report the Job status
      spec:
        nodeSelector:
          region: primary
        containers:
          - image: docker.io/library/ruby
            env:
              - name: NOKOGIRI_USE_SYSTEM_LIBRARIES
                value: "true"
            command: ["/bin/sh", "-c"]
            args: ["/usr/local/bin/bundle install && bundle exec rake"]
62

Testing with Prow

Postsubmit:

63

Testing with Prow

This is how looks like the Postsubmit Job spec:

postsubmits:
  the-shadowmen/kubevirt.github.io:
    - name: kubevirt-io-postsubmit-link-checker
      decorate: true      # The pod will be decorated with our special config
      always_run: true    # Tests always run
      skip_report: false  # Avoid to report the Job status
      spec:
        nodeSelector:
          region: primary
        containers:
          - image: docker.io/library/ruby
            env:
              - name: NOKOGIRI_USE_SYSTEM_LIBRARIES
                value: "true"
            command: ["/bin/sh", "-c"]
            args: ["/usr/local/bin/bundle install && bundle exec rake"]
64

Questions?

65

Prow Notifications

66

Prow Notifications

For Presubmits and Postsubmits jobs are not necessary to have these because GitHub manage the notifications, but what happens when a Periodic job fails? who will let me know about?, well Crier is here to save the day :).

This is not a mandatory service to work, but recommendable, as we said before:

Those are the supported providers:

67

Prow Notifications

To Configure Crier you could follow this guide or this one, but let's summarize:

68

Prow Notifications

slack_reporter:
  job_types_to_report:
  - presubmit
  - postsubmit
  - periodic
  - batch
  job_states_to_report:
  - triggered
  - pending
  - success
  - failure
  - aborted
  - error
  channel: team-kni-community
  # The template shown below is the default
  report_template: 'Job {{.Spec.Job}} of type {{.Spec.Type}} ended with state {{.Status.State}}. <{{.Status.URL}}|View logs>'
69

Questions?

70

References

71

References

Introduction:

72

References

Prow Plugins:

Prow Jobs:

73

References

Prow SSL:

Others:

74

The end

75

Thank you

Juan Manuel Parrilla

Senior Software Engineer, Red Hat