Adds Prow cluster deployment config and documentation

Change-Id: I3cf47da026bf8f40ee8ae4dd3fdbebc64116ce15
Google-Bug-Id: 119890379
Signed-off-by: Avi Kondareddy <avikr@google.com>
diff --git a/README.md b/README.md
index 22c3cf9..54b2c8a 100644
--- a/README.md
+++ b/README.md
@@ -169,4 +169,39 @@
 signals failure akin to regular shell scripts.
 
 ## Prow Cluster Deployment
-TODO(avikr@google.com): add cluster.yaml and explain
+
+To deploy in any Kubernetes environment, first read Prow deployment
+documentation [here](https://github.com/kubernetes/test-infra/blob/master/prow/\
+getting_started_deploy.md) and for further clarification, the Kubernetes
+documentation [here](https://kubernetes.io/docs/setup/). Prow comes with several
+[components](https://github.com/kubernetes/test-infra/blob/master/prow/cmd/README.md),
+several of which are only necessary for interacting with github webhooks. We
+have included here a [deployment.yaml](deployment.yaml) which includes just the
+components needed to poll gerrit repos. For every new gerrit repo to run
+presubmits on, you will need to update the
+[Gerrit](https://github.com/kubernetes/test-infra/tree/master/prow/cmd/gerrit)
+component in the deployment accordingly.
+
+Checkout [prow/cluster/starter.yaml](
+https://github.com/kubernetes/test-infra/blob/master/prow/cluster/starter.yaml)
+for github presubmit instructions which requires oauth token authentication.
+Job configuration in config.yaml does not need to change.
+
+Succinctly, a Kubernetes deployment file specifies all the API objects needed
+for deployment. Each prow component is a container pod that is described in
+an object of kind *Deployment*, specifying a Docker image that the deployment
+will launch. *Services* specify extra-pod communication and
+*ServiceAccount*s provide an identity to the processes that run in these pods.
+*Role*s and *RoleBinding*s provide RBAC authorization for components. Read this
+[article](https://www.cncf.io/blog/2018/08/01/demystifying-rbac-in-kubernetes/)
+on RBAC in Kubernetes if documentation is not sufficient.
+*PersistentVolumeClaim* are a type of Volume used for maintaining state and
+is used for gerrit to keep track of the latest synced commit. You may also need
+to configure the *Ingress* depending on your network / deployment environment
+for all external communication.
+
+You will also need a git https cookie file to interact with your gerrit
+instances as anonymous access is not currently supported. For a token
+periodically authenticated with gcloud, see/deploy [grandmatriarch](
+https://github.com/kubernetes/test-infra/blob/master/prow/cmd/grandmatriarch/bake.sh)
+(TODO(avikr) BUG #120081009: change documentation upon gcr image update)
diff --git a/deployment.yaml b/deployment.yaml
new file mode 100644
index 0000000..bb5bc5c
--- /dev/null
+++ b/deployment.yaml
@@ -0,0 +1,505 @@
+# This file contains Kubernetes YAML files for the most important prow
+# components. Don't edit resources in this file. Instead, pull them out into
+# their own files.
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: plugins
+data:
+  plugins.yaml: ""
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: prowjobs.prow.k8s.io
+spec:
+  group: prow.k8s.io
+  version: v1
+  names:
+    kind: ProwJob
+    singular: prowjob
+    plural: prowjobs
+  scope: Namespaced
+  validation:
+    openAPIV3Schema:
+      properties:
+        spec:
+          properties:
+            max_concurrency:
+              type: integer
+              minimum: 0
+            type:
+              type: string
+              enum:
+              - "presubmit"
+              - "postsubmit"
+              - "periodic"
+              - "batch"
+        status:
+          properties:
+            state:
+              type: string
+              enum:
+              - "triggered"
+              - "pending"
+              - "success"
+              - "failure"
+              - "aborted"
+              - "error"
+          anyOf:
+          - not:
+              properties:
+                state:
+                  type: string
+                  enum:
+                  - "success"
+                  - "failure"
+                  - "error"
+                  - "aborted"
+          - required:
+            - completionTime
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: plank
+  labels:
+    app: plank
+spec:
+  replicas: 1 # Do not scale up.
+  template:
+    metadata:
+      labels:
+        app: plank
+    spec:
+      serviceAccountName: plank
+      containers:
+      - name: plank
+        image: gcr.io/k8s-prow/plank:v20181101-84d67de
+        args:
+        - --dry-run=false
+        - --github-token-path=
+        volumeMounts:
+        - name: config
+          mountPath: /etc/config
+          readOnly: true
+      volumes:
+      - name: config
+        configMap:
+          name: config
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: sinker
+  labels:
+    app: sinker
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: sinker
+    spec:
+      serviceAccountName: sinker
+      containers:
+      - name: sinker
+        image: gcr.io/k8s-prow/sinker:v20181101-84d67de
+        volumeMounts:
+        - name: config
+          mountPath: /etc/config
+          readOnly: true
+      volumes:
+      - name: config
+        configMap:
+          name: config
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: deck
+  labels:
+    app: deck
+spec:
+  replicas: 2
+  strategy:
+    type: RollingUpdate
+    rollingUpdate:
+      maxSurge: 1
+      maxUnavailable: 1
+  template:
+    metadata:
+      labels:
+        app: deck
+    spec:
+      serviceAccountName: deck
+      terminationGracePeriodSeconds: 30
+      containers:
+      - name: deck
+        image: gcr.io/k8s-prow/deck:v20181101-84d67de
+        ports:
+          - name: http
+            containerPort: 8080
+        volumeMounts:
+        - name: config
+          mountPath: /etc/config
+          readOnly: true
+      volumes:
+      - name: config
+        configMap:
+          name: config
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: deck
+spec:
+  selector:
+    app: deck
+  ports:
+  - port: 80
+    targetPort: 8080
+  type: NodePort
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: horologium
+  labels:
+    app: horologium
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: horologium
+    spec:
+      serviceAccountName: horologium
+      terminationGracePeriodSeconds: 30
+      containers:
+      - name: horologium
+        image: gcr.io/k8s-prow/horologium:v20181101-84d67de
+        volumeMounts:
+        - name: config
+          mountPath: /etc/config
+          readOnly: true
+      volumes:
+      - name: config
+        configMap:
+          name: config
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: ing
+spec:
+  rules:
+  - http:
+      paths:
+      - path: /*
+        backend:
+          serviceName: deck
+          servicePort: 80
+---
+# start gerrit
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+  labels:
+    app: gerrit
+  name: gerrit-storage
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 1Gi
+  # volumeName: added automatically after volume creation
+  # See https://cloud.google.com/kubernetes-engine/docs/concepts/persistent-volumes
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: gerrit
+  labels:
+    app: gerrit
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: gerrit
+  template:
+    metadata:
+      labels:
+        app: gerrit
+    spec:
+      serviceAccountName: gerrit
+      terminationGracePeriodSeconds: 30
+      containers:
+      - name: gerrit
+        image: gcr.io/k8s-prow/gerrit:v20181101-84d67de
+        args:
+        - --config-path=/etc/config/config.yaml
+        - --cookiefile=/etc/cookies/cookies
+        - --gerrit-projects=https://kunit.googlesource.com=linux
+        - --last-sync-fallback=/store/gerrit
+        volumeMounts:
+        - name: config
+          mountPath: /etc/config
+          readOnly: true
+        - name: gerrit-volume
+          mountPath: /store
+        - name: cookies
+          mountPath: /etc/cookies
+          readOnly: true
+      volumes:
+      - name: config
+        configMap:
+          name: config
+      - name: cookies
+        secret:
+          defaultMode: 420
+          secretName: http-cookiefile
+      - name: gerrit-volume
+        persistentVolumeClaim:
+          claimName: gerrit-storage
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: crier
+  labels:
+    app: crier
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: crier
+    spec:
+      serviceAccountName: crier
+      terminationGracePeriodSeconds: 30
+      containers:
+      - name: crier
+        image: gcr.io/k8s-prow/crier:v20180923-f4dcfcecf
+        args:
+        - --gerrit-workers=1
+        - --cookiefile=/etc/cookies/cookies
+        - --gerrit-projects=https://kunit.googlesource.com=linux
+        volumeMounts:
+        - name: cookies
+          mountPath: /etc/cookies
+          readOnly: true
+      volumes:
+      - name: cookies
+        secret:
+          defaultMode: 420
+          secretName: http-cookiefile
+### Cluster rbac rules
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: "deck"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "deck"
+rules:
+  - apiGroups:
+      - ""
+    resources:
+      - pods/log
+    verbs:
+      - get
+  - apiGroups:
+      - "prow.k8s.io"
+    resources:
+      - prowjobs
+    verbs:
+      - get
+      - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "deck"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: "deck"
+subjects:
+- kind: ServiceAccount
+  name: "deck"
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: "horologium"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "horologium"
+rules:
+  - apiGroups:
+      - "prow.k8s.io"
+    resources:
+      - prowjobs
+    verbs:
+      - create
+      - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "horologium"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: "horologium"
+subjects:
+- kind: ServiceAccount
+  name: "horologium"
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: "plank"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "plank"
+rules:
+  - apiGroups:
+      - ""
+    resources:
+      - pods
+    verbs:
+      - create
+      - delete
+      - list
+  - apiGroups:
+      - "prow.k8s.io"
+    resources:
+      - prowjobs
+    verbs:
+      - create
+      - list
+      - update
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "plank"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: "plank"
+subjects:
+- kind: ServiceAccount
+  name: "plank"
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: "sinker"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "sinker"
+rules:
+  - apiGroups:
+      - ""
+    resources:
+      - pods
+    verbs:
+      - delete
+      - list
+  - apiGroups:
+      - "prow.k8s.io"
+    resources:
+      - prowjobs
+    verbs:
+      - delete
+      - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "sinker"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: "sinker"
+subjects:
+- kind: ServiceAccount
+  name: "sinker"
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: "gerrit"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "gerrit"
+rules:
+- apiGroups:
+    - "prow.k8s.io"
+  resources:
+    - prowjobs
+  verbs:
+    - create
+    - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "gerrit"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: "gerrit"
+subjects:
+- kind: ServiceAccount
+  name: "gerrit"
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: "crier"
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  # "namespace" omitted since ClusterRoles are not namespaced
+  name: crier
+rules:
+- apiGroups:
+    - "prow.k8s.io"
+  resources:
+    - "prowjobs"
+  verbs:
+    - "get"
+    - "watch"
+    - "list"
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: "crier"
+  namespace: "default"
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: "crier"
+subjects:
+- kind: ServiceAccount
+  name: "crier"
+  namespace: "default"