Add self-deployment playbook
This adds a playbook and some Zuul secrets which will eventually
allow Zuul to deploy itself.
This also switches to using plain k8s objects instead of the
helm charts. The current system has too much local customization
for the helm charts, so just use plain k8s yaml.
Change-Id: I4e67be7976d421d211cfbfab014826d0cda299cf
diff --git a/.zuul.yaml b/.zuul.yaml
index 2a5dca9..9a5a9a3 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -2,3 +2,82 @@
check:
jobs:
- noop
+
+- secret:
+ name: zuul_deploy
+ data:
+ server: "https://10.0.0.1:443"
+ cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURDekNDQWZPZ0F3SUJBZ0lRWW9OSEJiWlBvUXpEZ2JCMVNhOGFLekFOQmdrcWhraUc5dzBCQVFzRkFEQXYKTVMwd0t3WURWUVFERXlSbE5ETXhZVFU1WWkwNFptRTFMVFJsT1dRdFlqRTFZeTA1WmpNeE16UmpNR1psTUdFdwpIaGNOTVRreE1qSXdNVFl5TnpNMldoY05NalF4TWpFNE1UY3lOek0yV2pBdk1TMHdLd1lEVlFRREV5UmxORE14CllUVTVZaTA0Wm1FMUxUUmxPV1F0WWpFMVl5MDVaak14TXpSak1HWmxNR0V3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNoS2k4cTJ5d2N4WWR4OHlQQmZzMXlGUmJuZ1ZXK29GUzFYV1FlKy9pTgo4a2M4K05IU3I2RGNFQUtGVExnMTU3VTNiOE5TdG9MdEdUNUtoV010MHh2NEcrQVc5Qy9GNzFzWWhscThGdXkxCkphQWZOeCtydlZEeW80YnJ2bU1ubXAwWmpMZzNIUjVBMThXT2xBZW52OGtyRVZ2VnNYL1hZbnMzb2FWeUhGYVEKNzdDcUNlYWpqeS9uLzdSUlBKNDhReVVvVTNRZDRmV0xXQ0c5emxhNzZ4eHlFSVh0MWlMVGZ5NElGYk9pbFlYcwpUVzMvZ1ZObTRjZHZaQmtjeDlPWkNNZXN5aHBEK1ZTUkpuVkdUdHA5UmZVNWlHc3JiejdTVzh6S3ovVjI4amV4CjEzY2V0cWw4Mk5PUGs4cTRleDJsZmJibGdqUTJBSWIrZWNtYUJHaWQxWmtMQWdNQkFBR2pJekFoTUE0R0ExVWQKRHdFQi93UUVBd0lDQkRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBawpuMEdRRGFYYW1Da2twY0ZneUI1bWlHd0s2NktLNnRqNG1Jc1ZDMG9DdWJ2bFQ0UDBFS2pJeDlad0hHeDJTK3ZiCnM1M2s4bmx5cHBtb1VYRXVxcUVLREpONlNMS3JhTFhWVGo4c1EwaExxbWltYTc4UmhTSVJMU3EraWJTMVlMSVcKakRvR3lzYXgzVE1mamEyRlU1ZC9IZXJHNHI5cWQxaXFMTnRiWU4xYWovUmJ3SUFvOFdqWE42WldkRDJic0hNaQpFVDFwbEQrSzhEb3E2R3MzbEt6c1k1Q1MyS1ZlSmVnWFhVc0dFMExIYjYwY3FvVldVMUhHc1NYTXJuTldrZVM0Cldrc0hSa0dpQVZBU21DMDZaZUM1d0lvSGNIYzJRTjhZTjdKTE9CV0FRUHhBRHlLc053OC9Eci8xS1VLdkZvZHkKSlhCNlhBS2pnUnFCdW9ROUJlMzkKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
+ token: !encrypted/pkcs1-oaep
+ - YWeClYtmP1RICp9ZoPQRBv80N/q70r3KEcqN64aDA9mq9O0kL7xGpUcCOLtsFoEG9bTtL
+ W/A9mv2Y1E2zEOVTKB2whdqkEA7kUbXht4pCc9FSqbg7/dJ4SyNy0b2tdCHfGc+9mLdRj
+ m2CLTYurUYQIDfQGlzjseFuv1RKX+8DDKVLas/Gsb6JGo6hBeq2CvryJHQnX8YPgz678g
+ UCQbFrUTpKmL0w+MJY8uP5I4WVBZtCzV1yGQHj+oxWLiZdVv7gJClm/y0gyndyZpWuGn1
+ Bx2dy0Y2ziKYBdV5Q9SXSHjA2PrZHU04B9Nkl2Hnez6Wqy/b1jQHMNbgmdzmmbQsbkjYS
+ e0wrjLxqXdZNNQJc9Fse7juPPVuaHtVdtZBSYPNyqjSPiWTUQDN09hULkq6XIT41TJF7g
+ Vh3Ti5+mDsD2VlqosXzOVsAilDyukIHTEVbJXpqsKY8EfPljRH6IPwUpvyWZsjrlktszY
+ qZedlLbBn/ke5Rkq9ULMakFQguniVaZ4VImU+VJOzbJlqXXzMO6OmEgwsgzEdOI4WMTKT
+ nu+YZdKtGQczh5j95+zpPC5PGyaZGEP6CQPPl1giOYoUHzoaYS1vagFhSoiY1pK3IarmF
+ 85kcLqvUtMcK/q591Ju02Hd7wiSJs0mE91BFeBTPZZBmMU9ePM0HV1oxj/Fy/8=
+ - UaJIBAJSdtakgx8AUecMKUx2ov5yX+E7lVn/xAz4Jqw5F6kgFBUJD3ht4zTPcwHxoVtR2
+ 32wzGon5X3Kqw9+mvSB5az9kKD5rbMB3Mgn01y4UGrMuGyFjPCaSUJDESSDqC0bXWqswY
+ 0+PhvzpJa5yE0ovmsR8wNJ8Ca8SfvcbRpRDe+h+r5LcBCG3cr3JkkbkaRkriH/ooWGrko
+ ESLQ42pGF7Z77v73zkFaQquKmV99logLwPnXnUYEkuxjaEAWLKc8aPAkEp//WVCuR+xKn
+ 2WClkdojrSu6GgPmIWd5/kS0lKXd+N5nEz3KaNXOYNvx9cIEVTWiLaWshbZX3KyTIahv8
+ qvqJrWD6Mw8Ug78QM4E0bwqxuk4l8SbQKoZjdOFQLqUu+ZEYOOSC45p0IcEHCxblP46E8
+ qEpzVBtliMjZ6MLi5M22IwRYJN5hr0L56MGCMg9b3vlDqPrX6Gz6p0FNKRZHekMSD5KtE
+ dwOFiwvzk9+GI2ZzxyjB+BSDLCr52OhgsK8lt+fUsc7/nDxnnop/tI76FcZ/5cm8DQGbS
+ wjzSbnwF0Qq5gdreQqcpGzF/NvKU2LDbHCO7sPxjI9+WOJQS4cy6J6EHmy5/jPAqaKG9K
+ 4yqqUj+70mc/0xd+sQP4UQWbO4kqWVjTg4b3o/Dof+3ghSTKEyD13q5KvbUzWo=
+ db_password: !encrypted/pkcs1-oaep
+ - kxXAI0xRUVstc8q/lloTpo5bs4HwecTJyip/Te2uYgSTDsFKJLipWEAkbb3ziA2/rdgbP
+ nJIiD1IYzjfqIE574LsJpqe5TssR5GMnsENRxxzjOJagSJJWUZJHBIU3EiLs1rrnr5TtY
+ 3wlFJvsdC1F5XNtuM17tFvgsH1ClsfrwjtcibQbYYm0dzBO1ZY7bqvl17AZPPE9G18G1O
+ FlfALHpkS1Cu84MY7Q8+jp33jftjaxxkPsOKLKoxtYkT4nn5MsDsvkstg+d7KiVl/bPKj
+ YKe5T2UzTBWak/P5Z7CQkfsuHe++sX4fHrdNgpKTp1EUfYYbMZ46vi9MM0sVN39RMlWHP
+ 72HqhHeuVbZH1uyi+P7xJKfmpZkbtiTCNQSmenuNypE2Dlwxu37VQlftCtYD4zP4xUSp5
+ 33z8+KRQmqJ3ases/VvbEdlxeuRG05CekYdenkGhqwcojefU8jcNQoqDBEfUAPH7Go+cB
+ aivnk+i+qvYcprAJ2YqXmLFLmI5//W1JD7k3te2M1KQuW/Wee7bb9RYeUGzeeG71g/reb
+ 0MP9FIAGK6HxBFWLiRS+Q0gktOEOlfPYdWGFQt+3r1kArARPj6M8vskMhrw+ncp9+zi7V
+ rNR1vRhoQieBzZtIYrgg7fqV/y7y28lLlRrxOMR7Vdk1WjJPDR57B8XV38oMHE=
+ nodepool_private_key: !encrypted/pkcs1-oaep
+ - qGQJDEhQizjE7WiZVEZlwuBwCkA6PbixWJxj6ijQmo7ARmo2yT+FHekwCPbuilUQoI4rV
+ Bzqn9uwbOJCveS1MeRag31gSsvwGwNsfuHNmjcpHacvJk22H3YZxSapjNAWK/csx17Avm
+ tvSVGZOO9U/di7z7uhnlHMHG1oDl6aaSwluQ+At6upsZNzdRNYNbngeBxsE9NwNFnNsqA
+ /V7jCtX1dCK9pSt1ptXUr/jrLnT7mI4ix/fS/bjYNlxc6T8Ouz6P3ZyE3Gwe38t8Oi87n
+ 6DE01YxH119Zv2T6xxZrRugkmr23fwkgKlZ8tp212EEiUo18MZv+FpjAQnbUNNEQkt7CO
+ SawL2cjg/TetPRtIhsmknkQVABc6ZP5edxZi87620kV4BoLbmmavFgKVMMtcAzntinGTp
+ zgo+Eidrtlt6JsyUATI/2MlZ+TIc7+0llV5QOspM4HzJgeyYj5ywjNKycUZfWiA8PN+8x
+ eIVQANsAQRT6GbOcbhw96mO6FeuaOaAsAwmSt2++xoaymx+TScYwDNFfr3ZBRG++34o2r
+ EFpIWEKgdDoLeDD/G8FrRZzlpzcy/QslvWbcQn9Qs/AdnhvMiEgSOk4ZZvkQi0Txu5/xr
+ jpHXFS3zzGiiwUVDiUvC115ZUR9TTQa0WQAmjiFcXWo1npLJvVjYlX6BNUEr7A=
+ - aL0DcCaiOlQ1nI1PtdsK6x/kxx6dCNWgAmLzIzqUFOmKNUckMBJvtzWg/qFa8smfyEMKE
+ yPLyXiA92f7geVK9kRasnuRqDPHWeeURLpkrV1PN65RBLobsW2dBcf3PTRb3/hBUsgplo
+ i4TCRHKF89xvHVcSKpLcqq0Y3A6R7jlJDou//SxjYJhw7qnSD+hI9v+5Fl+8jq9hUfwDN
+ 5/Y4ElgfskeuVrS6Kt88xJTqR4Epn5fjXej+VEu9k7e12m7Tt0Q7dTEWGh+uYnWVxbDUu
+ l2Bmc01BoUh0hFLvNSzDuORHWl4genRExaBfp+dNjRLHB1e7YYLuE1fDY+zU3lH7ik5jo
+ HcUEdueCj/X9oPAVj3F653gG9Z4hcc5a1itucfh+FcFnil4WA9TmjhIA7n3cCE7/bRLJG
+ xab63NFAqSBYCBTIWtQX+9DLGBn48LVHs7j6mhmpsco9Dt/JW0uL4eG4VhmwnawdVCehP
+ pAtcNBn2KrBoD7hM+18zdGJC57CorJ71McqN6rGT4ula+0ACGYZHRPuPdqhDQhjtrD2FV
+ fkRaqOVo7CS7hB9gQbbxFjB9tFQwMHAQiVYEmow1pRMrH84agxMMSUS377DK+BJvu88Ku
+ SBuDaxxq4NAG+eQORT2myh7wkDYoefAyxLJVAzy4EgH/tC7uOKE4+V3Mb5RXjc=
+ - E0/f19t+at0iV1duvEDi37kkQYmZjf1EmOQ7+42+J3laR9n8QY1Zzd9GqsXTyq2jVoA+F
+ Crvw8C1t6XZTudbxp7QQlYzOuSWCncZB2Tspe/W4r8STD8LEjncZcawbxPGIalIeoQ/BP
+ E4vEzgZXbaIPUwCHTQm6TzRhGViVlYhPrBWmSnWikcFUhMn1lUpwp1/5F+1aZV3H7HBds
+ dxp0oKad7M+uCtmzRvNufvr8667ZVaWzfOx8nisuZVwLM8Jau3kLdX4OyVbVFB18MK8j8
+ 0R2wDjG1ihsjwsekIuKkK1mkBUoR9zHQqwN1PTv6Ih43Wc1LXNSyin/TqYcwr+x/c374q
+ aiabasVcGgiOCqbtKBM8KJGC7CbSBrYnszDuiwBzmVbd1IcIj6vzxyO0Pypmy9Wu9o6UN
+ Stmwyv28brV90KC5+rJdiN63/u6uXvJN8lHjUUQ87PbQsSGGFlINprdNeU4bELhYImvjh
+ IT43YBl4JMF4fOQrlqSZwQzsAZ+xRT4pXf3V490LpIIDzUeYDvPZ/11vLoAr/77d2u2uN
+ M0VWknjEDoJa+CkeQ6df/OAwRMzdMIk45XmjFXsNC/eCRSv74GgD7Mpd2K1t8kBMOdmZ5
+ dljO1xVpo+z0J9z+dGVdIBXBFkO0+lamzNSBUXq64H3CPtShPJvIRlS8b9+wSc=
+ - USLP72RgSDDYXX748OPn0o1h/LyM5PLEigZQllhno/vx2gxhKwkaUlzrHHbxmvuvhAlIJ
+ 08IOfcySTzf1Gr1t+3iTBrpUPq/9qm5cuMMso+eI/9IMQ0W7vqQmiB8vWji57kuXsLIX5
+ SEQtBSC6IlJKLm8aJhjlWH0A2F3OqqpbH8vOpWnPMOnrPHGFB+KmqJUllkdCxDFtvcVVD
+ ChCcNORR+N6X3r7i/m6Niu3Ehro7ynOwUM7btYOXWMqOp1nUXbXdWim1/5sqcKvl76A++
+ lDDr/12mx+LCfLEEpMhpq6P4jFjhXCs9fs57DaE5CROmJO0iKKXHgyRShNC5o6h6Lb+rd
+ dGWUeiNXwEYQbCKPjJBJ+kzFtO3+zctzVwkI0TwYrF3pPa2fS/chB69JbPovYTf+Jx921
+ p4WYO9wvOPqrRD6VQetGDBaF3yZgqqAA6wPt2MM56+jrSq0O+eRRO6Xg99cY5wTFq9Tgs
+ pgkAfAdVnuvWAtXDnnmQacixdGCunSg+gNCyVW+UDMiNsB75I+QcEzAbnTIFzLMCZzOIK
+ UWg4OXFafQPI/+JvdVVgqDggURHi9arahXXEKb69xIi9BIYucNhKQ1NeAMjQpUAfm8krw
+ suzdXr2VOIJIcgVz3S9Kg1oiTgkY6PNdI/nuc3Aq1LzDeKykB0wGaulcpQ6H/o=
diff --git a/README b/README
index d1a7327..f18df48 100644
--- a/README
+++ b/README
@@ -39,19 +39,60 @@
kubectl create namespace cert-manager
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml
-kubectl apply -n cert-manager -f letsencrypt.yaml
+kubectl apply -n cert-manager -f letsencrypt.yaml
+
+# Install mariadb
+
+kubectl create namespace mariadb
+
+Use Google cloud click to deploy
+TODO: find a better HA sql database operator
+
+kubectl port-forward svc/mariadb-mariadb --namespace mariadb 3306
+mysql -h 127.0.0.1 -P 3306 -u root -p
+create database zuul;
+GRANT ALL PRIVILEGES ON zuul.* TO 'zuul'@'%' identified by '<password>' WITH GRANT OPTION;
# Install Zuul
gcloud compute addresses create zuul-static-ip --global
-
kubectl create namespace zuul
-kubectl create -n zuul secret generic nodepool-config --from-file=./nodepool/nodepool.yaml --from-file=./nodepool/clouds.yaml
+# Bind k8s service accounts to gcp service accounts
+kubectl create serviceaccount --namespace zuul logs
+kubectl create serviceaccount --namespace zuul nodepool
+kubectl create serviceaccount --namespace zuul zuul
-kubectl create -n zuul secret generic zuul-tenant-config --from-file=./zuul/main.yaml
+gcloud iam service-accounts add-iam-policy-binding \
+ --role roles/iam.workloadIdentityUser \
+ --member "serviceAccount:gerritcodereview-ci.svc.id.goog[zuul/logs]" \
+ zuul-logs@gerritcodereview-ci.iam.gserviceaccount.com
-kubectl apply -n argocd -f nodepool-app.yaml
-kubectl apply -n argocd -f zuul-app.yaml
+gcloud iam service-accounts add-iam-policy-binding \
+ --role roles/iam.workloadIdentityUser \
+ --member "serviceAccount:gerritcodereview-ci.svc.id.goog[zuul/nodepool]" \
+ nodepool@gerritcodereview-ci.iam.gserviceaccount.com
-kubectl apply -n zuul -f ingress.yaml
+gcloud iam service-accounts add-iam-policy-binding \
+ --role roles/iam.workloadIdentityUser \
+ --member "serviceAccount:gerritcodereview-ci.svc.id.goog[zuul/zuul]" \
+ zuul-63@gerritcodereview-ci.iam.gserviceaccount.com
+
+kubectl annotate serviceaccount \
+ --namespace zuul logs \
+ iam.gke.io/gcp-service-account=zuul-logs@gerritcodereview-ci.iam.gserviceaccount.com
+
+kubectl annotate serviceaccount \
+ --namespace zuul nodepool \
+ iam.gke.io/gcp-service-account=nodepool@gerritcodereview-ci.iam.gserviceaccount.com
+
+kubectl annotate serviceaccount \
+ --namespace zuul zuul \
+ iam.gke.io/gcp-service-account=zuul-63@gerritcodereview-ci.iam.gserviceaccount.com
+
+# create a service account for self-deployment
+
+kubectl -n zuul create serviceaccount zuul-deployment
+kubectl create clusterrolebinding zuul-deployment-cluster-admin-binding \
+ --clusterrole cluster-admin \
+ --user system:serviceaccount:zuul:zuul-deployment
diff --git a/ingress.yaml b/ingress.yaml
deleted file mode 100644
index f678b17..0000000
--- a/ingress.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-apiVersion: extensions/v1beta1
-kind: Ingress
-metadata:
- name: zuul-web
- namespace: zuul
- annotations:
- kubernetes.io/ingress.global-static-ip-name: "zuul-static-ip"
- cert-manager.io/cluster-issuer: letsencrypt-prod
- acme.cert-manager.io/http01-edit-in-place: "true"
-spec:
- rules:
- - host: gerrit-zuul.inaugust.com
- http:
- paths:
- - backend:
- serviceName: zuul-web
- servicePort: 9000
- path: /*
- tls:
- - secretName: zuul-web-certs
- hosts:
- - gerrit-zuul.inaugust.com
diff --git a/k8s/authdaemon.yaml b/k8s/authdaemon.yaml
new file mode 100644
index 0000000..256002a
--- /dev/null
+++ b/k8s/authdaemon.yaml
@@ -0,0 +1,39 @@
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: gcloud-authdaemon
+ namespace: zuul
+ labels:
+ app.kubernetes.io/name: gcloud-authdaemon
+spec:
+ selector:
+ matchLabels:
+ name: gcloud-authdaemon
+ template:
+ metadata:
+ labels:
+ name: gcloud-authdaemon
+ spec:
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ containers:
+ - name: gcloud-authdaemon
+ image: docker.io/jeblair/authdaemon:latest
+ resources:
+ limits:
+ memory: 200Mi
+ requests:
+ cpu: 100m
+ memory: 200Mi
+ volumeMounts:
+ - name: authdaemon
+ mountPath: /authdaemon
+ terminationGracePeriodSeconds: 2
+ volumes:
+ - name: authdaemon
+ hostPath:
+ path: /var/authdaemon/executor
+ type: DirectoryOrCreate
+ serviceAccountName: logs
diff --git a/letsencrypt.yaml b/k8s/letsencrypt.yaml
similarity index 100%
rename from letsencrypt.yaml
rename to k8s/letsencrypt.yaml
diff --git a/k8s/nodepool.yaml b/k8s/nodepool.yaml
new file mode 100644
index 0000000..f3b2eab
--- /dev/null
+++ b/k8s/nodepool.yaml
@@ -0,0 +1,41 @@
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ namespace: zuul
+ name: nodepool-launcher-gcs
+ labels:
+ app.kubernetes.io/name: nodepool
+ app.kubernetes.io/instance: nodepool
+ app.kubernetes.io/part-of: nodepool
+ app.kubernetes.io/component: nodepool-launcher
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: nodepool
+ app.kubernetes.io/instance: nodepool
+ app.kubernetes.io/part-of: nodepool
+ app.kubernetes.io/component: nodepool-launcher
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: nodepool
+ app.kubernetes.io/instance: nodepool
+ app.kubernetes.io/part-of: nodepool
+ app.kubernetes.io/component: nodepool-launcher
+ spec:
+ containers:
+ - name: launcher
+ image: zuul/nodepool-launcher:latest
+ env:
+ - name: OS_CLIENT_CONFIG_FILE
+ value: /etc/nodepool/clouds.yaml
+ volumeMounts:
+ - name: nodepool-config
+ mountPath: /etc/nodepool
+ volumes:
+ - name: nodepool-config
+ secret:
+ secretName: nodepool-gcs
+ serviceAccountName: nodepool
diff --git a/k8s/zuul.yaml b/k8s/zuul.yaml
new file mode 100644
index 0000000..ed4eda8
--- /dev/null
+++ b/k8s/zuul.yaml
@@ -0,0 +1,301 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+ namespace: zuul
+ name: zuul-executor
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-executor
+spec:
+ type: ClusterIP
+ clusterIP: None
+ ports:
+ - name: logs
+ port: 7900
+ protocol: TCP
+ targetPort: logs
+ selector:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-executor
+---
+apiVersion: v1
+kind: Service
+metadata:
+ namespace: zuul
+ name: zuul-gearman
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-scheduler
+spec:
+ type: ClusterIP
+ ports:
+ - name: gearman
+ port: 4730
+ protocol: TCP
+ targetPort: gearman
+ selector:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-scheduler
+---
+apiVersion: v1
+kind: Service
+metadata:
+ namespace: zuul
+ name: zuul-web
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-web
+spec:
+ type: NodePort
+ ports:
+ - name: zuul-web
+ port: 9000
+ protocol: TCP
+ targetPort: zuul-web
+ selector:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-web
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ namespace: zuul
+ name: zuul-merger
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-merger
+spec:
+ replicas: 0
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-merger
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-merger
+ spec:
+ containers:
+ - name: merger
+ image: zuul/zuul-merger:latest
+ args:
+ - /usr/local/bin/zuul-merger
+ - -d
+ volumeMounts:
+ - name: zuul-config
+ mountPath: /etc/zuul
+ volumes:
+ - name: zuul-config
+ secret:
+ secretName: zuul-config
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ namespace: zuul
+ name: zuul-web
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-web
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-web
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-web
+ spec:
+ containers:
+ - name: web
+ image: jeblair/zuul-web:latest
+ args:
+ - /usr/local/bin/zuul-web
+ - -d
+ ports:
+ - name: zuul-web
+ containerPort: 9000
+ volumeMounts:
+ - name: zuul-config
+ mountPath: /etc/zuul
+ volumes:
+ - name: zuul-config
+ secret:
+ secretName: zuul-config
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ namespace: zuul
+ name: zuul-executor
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-executor
+spec:
+ serviceName: zuul-executor
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-executor
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-executor
+ spec:
+ securityContext:
+ runAsUser: 1000
+ runAsGroup: 1000
+ containers:
+ - name: executor
+ image: jeblair/zuul-executor:latest
+ args:
+ - /usr/local/bin/zuul-executor
+ - -d
+ ports:
+ - name: logs
+ containerPort: 7900
+ volumeMounts:
+ - name: zuul-config
+ mountPath: /etc/zuul
+ - name: authdaemon
+ mountPath: /authdaemon
+ - name: zuul-var
+ mountPath: /var/lib/zuul
+ - name: nodepool-private-key
+ mountPath: /var/lib/zuul/ssh
+ securityContext:
+ privileged: true
+ volumes:
+ - name: zuul-var
+ emptyDir: {}
+ - name: zuul-config
+ secret:
+ secretName: zuul-config
+ - name: authdaemon
+ hostPath:
+ path: /var/authdaemon/executor
+ type: DirectoryOrCreate
+ - name: nodepool-private-key
+ secret:
+ secretName: nodepool-private-key
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ namespace: zuul
+ name: zuul-scheduler
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-scheduler
+spec:
+ replicas: 1
+ serviceName: zuul-scheduler
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-scheduler
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ app.kubernetes.io/component: zuul-scheduler
+ spec:
+ containers:
+ - name: scheduler
+ image: jeblair/zuul-scheduler:latest
+ args:
+ - /usr/local/bin/zuul-scheduler
+ - -d
+ ports:
+ - name: gearman
+ containerPort: 4730
+ volumeMounts:
+ - name: zuul-config
+ mountPath: /etc/zuul
+ - name: zuul-tenant-config
+ mountPath: /etc/zuul/tenant
+ - name: zuul-scheduler
+ mountPath: /var/lib/zuul
+ volumes:
+ - name: zuul-config
+ secret:
+ secretName: zuul-config
+ - name: zuul-tenant-config
+ secret:
+ secretName: zuul-tenant-config
+ serviceAccountName: zuul
+ volumeClaimTemplates:
+ - metadata:
+ name: zuul-scheduler
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 80Gi
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: zuul-web
+ namespace: zuul
+ annotations:
+ kubernetes.io/ingress.global-static-ip-name: "zuul-static-ip"
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ acme.cert-manager.io/http01-edit-in-place: "true"
+spec:
+ rules:
+ - host: gerrit-zuul.inaugust.com
+ http:
+ paths:
+ - backend:
+ serviceName: zuul-web
+ servicePort: 9000
+ path: /*
+ tls:
+ - secretName: zuul-web-certs
+ hosts:
+ - gerrit-zuul.inaugust.com
diff --git a/nodepool-app.yaml b/nodepool-app.yaml
deleted file mode 100644
index dfe4413..0000000
--- a/nodepool-app.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: argoproj.io/v1alpha1
-kind: Application
-metadata:
- name: nodepool
- finalizers:
- - resources-finalizer.argocd.argoproj.io
-spec:
- project: default
- source:
- repoURL: https://github.com/jeblair/zuul-helm
- path: charts/nodepool
- helm:
- values: |
- clouds: ''
- builder:
- enabled: false
- config:
- secret: nodepool-config
- destination:
- namespace: zuul
- server: https://kubernetes.default.svc
diff --git a/nodepool/clouds.yaml b/nodepool/clouds.yaml
deleted file mode 100644
index e69de29..0000000
--- a/nodepool/clouds.yaml
+++ /dev/null
diff --git a/nodepool/nodepool.yaml b/nodepool/nodepool.yaml
index 17cbe7d..819d500 100644
--- a/nodepool/nodepool.yaml
+++ b/nodepool/nodepool.yaml
@@ -17,7 +17,6 @@
pools:
- name: main
max-servers: 8
- #host-key-checking: False
use-internal-ip: True
labels:
- name: testlabel
diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml
new file mode 100644
index 0000000..669d644
--- /dev/null
+++ b/playbooks/deploy.yaml
@@ -0,0 +1,133 @@
+- name: Deploy Zuul
+ hosts: localhost
+ tasks:
+ - name: Make kube directory
+ file:
+ path: "{{ ansible_user_dir }}/.kube"
+ state: directory
+ - name: Write kube config
+ template:
+ src: kubecfg.yaml.j2
+ dest: "{{ ansible_user_dir }}/.kube/config"
+
+ - name: Update Letsencrypt configuration
+ k8s:
+ state: present
+ src: ../k8s/letsencrypt.yaml
+
+ - name: Update authdaemon configuration
+ k8s:
+ state: present
+ src: ../k8s/authdaemon.yaml
+
+ - name: Update Nodepool config
+ k8s:
+ state: present
+ definition:
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ namespace: zuul
+ name: nodepool-gcs
+ labels:
+ app.kubernetes.io/name: nodepool
+ app.kubernetes.io/instance: nodepool
+ app.kubernetes.io/part-of: nodepool
+ stringData:
+ clouds.yaml: ""
+ nodepool.yaml: "{{ lookup('file', '../nodepool/nodepool.yaml') }}"
+
+ - name: Update Zuul/Nodepool private key
+ k8s:
+ state: present
+ definition:
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ namespace: zuul
+ name: nodepool-private-key
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ stringData:
+ nodepool_id_rsa: "{{ zuul_deploy.nodepool_private_key }}"
+ register: zuul_config
+ # Set no_log because we are templating in the private key
+ no_log: true
+
+ - name: Update Zuul service config
+ k8s:
+ state: present
+ definition:
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ namespace: zuul
+ name: zuul-config
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ stringData:
+ main.yaml: "{{ lookup('template', '../zuul/zuul.conf') }}"
+ register: zuul_config
+ # Set no_log because we are templating passwords into the config
+ no_log: true
+
+ - name: Update Zuul tenant config
+ k8s:
+ state: present
+ definition:
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ namespace: zuul
+ name: zuul-tenant-config
+ labels:
+ app.kubernetes.io/name: zuul
+ app.kubernetes.io/instance: zuul
+ app.kubernetes.io/part-of: zuul
+ stringData:
+ main.yaml: "{{ lookup('file', '../zuul/main.yaml') }}"
+ register: tenant_config
+
+ - name: Update Nodepool deployment
+ k8s:
+ state: present
+ src: ../k8s/nodepool.yaml
+
+ - name: Update Zuul deployment
+ k8s:
+ state: present
+ src: ../k8s/zuul.yaml
+
+ - name: Reconfigure Zuul
+ when: tenant_config.changed or zuul_config.changed
+ block:
+ - name: Add scheduler to inventory
+ add_host:
+ name: 'zuul-scheduler-0'
+ ansible_kubectl_namespace: zuul
+ ansible_connection: kubectl
+ - name: Wait until remote Zuul config is updated
+ delegate_to: 'zuul-scheduler-0'
+ stat:
+ path: /etc/zuul/zuul.conf
+ follow: true
+ register: remote_zuul_st
+ until: "remote_zuul_st.stat.checksum == (zuul_config.result.data['zuul.conf'] | b64decode | hash('sha1'))"
+ delay: 10
+ retries: 30
+ - name: Wait until remote tenant config is updated
+ delegate_to: 'zuul-scheduler-0'
+ stat:
+ path: /etc/zuul/tenant/main.yaml
+ follow: true
+ register: remote_tenant_st
+ until: "remote_tenant_st.stat.checksum == (tenant_config.result.data['main.yaml'] | b64decode | hash('sha1'))"
+ delay: 10
+ retries: 30
+ - name: Send reconfiguration notice to scheduler
+ delegate_to: 'zuul-scheduler-0'
+ command: zuul-scheduler full-reconfigure
diff --git a/playbooks/templates/kubecfg.yaml.j2 b/playbooks/templates/kubecfg.yaml.j2
new file mode 100644
index 0000000..8ee3d82
--- /dev/null
+++ b/playbooks/templates/kubecfg.yaml.j2
@@ -0,0 +1,20 @@
+# -*- mode: yaml -*-
+
+apiVersion: 'v1'
+kind: 'Config'
+preferences: {}
+users:
+ - name: "zuul-deploy"
+ user:
+ token: "{{ zuul_deploy.token }}"
+clusters:
+ - name: 'control-plane'
+ cluster:
+ server: "{{ zuul_deploy.server }}"
+ certificate-authority-data: "{{ zuul_deploy.cert }}"
+contexts:
+ - name: "zuul-deploy/control-plane"
+ context:
+ user: "zuul-deploy"
+ cluster: "control-plane"
+current-context: "zuul-deploy/control-plane"
diff --git a/zuul-app.yaml b/zuul-app.yaml
deleted file mode 100644
index 561e1e5..0000000
--- a/zuul-app.yaml
+++ /dev/null
@@ -1,34 +0,0 @@
-apiVersion: argoproj.io/v1alpha1
-kind: Application
-metadata:
- name: zuul
- finalizers:
- - resources-finalizer.argocd.argoproj.io
-spec:
- project: default
- source:
- repoURL: https://github.com/jeblair/zuul-helm
- path: charts/zuul
- helm:
- values: |
- zookeeper:
- hosts: zookeeper.zookeeper
- executor:
- replicas: 1
- merger:
- replicas: 1
- web:
- replicas: 1
- host: gerrit-zuul.inaugust.com
- serviceType: NodePort
- scheduler:
- tenantConfigPath: /etc/zuul/tenant/main.yaml
- tenantConfigSecret: zuul-tenant-config
- connections:
- opendev:
- name: opendev
- driver: git
- baseurl: https://opendev.org
- destination:
- namespace: zuul
- server: https://kubernetes.default.svc
diff --git a/zuul/main.yaml b/zuul/main.yaml
index 4d6631a..f5ee681 100644
--- a/zuul/main.yaml
+++ b/zuul/main.yaml
@@ -1,11 +1,12 @@
- tenant:
name: gerrit
report-build-page: true
- web-root: http://localhost:3000/
source:
opendev:
untrusted-projects:
- zuul/zuul-jobs
-# googlesource:
-# untrusted-projects:
-# - zuul/ops
+ gerrit:
+ config-projects:
+ - zuul/config
+ untrusted-projects:
+ - zuul/ops
diff --git a/zuul/zuul.conf b/zuul/zuul.conf
new file mode 100644
index 0000000..e81ad4b
--- /dev/null
+++ b/zuul/zuul.conf
@@ -0,0 +1,42 @@
+[gearman]
+server=zuul-gearman
+port=4730
+
+[zookeeper]
+hosts=zookeeper.zookeeper
+
+[gearman_server]
+start=true
+port=4730
+
+[web]
+listen_address=0.0.0.0
+root=https://gerrit-zuul.inaugust.com
+port=9000
+
+[scheduler]
+tenant_config=/etc/zuul/tenant/main.yaml
+
+[executor]
+private_key_file=/var/lib/zuul/ssh/nodepool_id_rsa
+trusted_ro_paths=/authdaemon/token
+disk_limit_per_job=500
+
+[connection "sql"]
+name=sql
+driver=sql
+dburi=mysql+pymysql://zuul:{{ zuul_deploy.db_password }}@mariadb-mariadb.mariadb/zuul
+
+[connection "opendev"]
+name=opendev
+driver=git
+baseurl=https://opendev.org
+
+[connection "gerrit"]
+name=gerrit
+driver=gerrit
+server=gerrit-review.googlesource.com
+canonical_hostname=gerrit.googlesource.com
+user=zuul
+stream_events=false
+auth_type=gcloud_service