Change-Id: I2975607a51860df88863454785ae5d189f6f2831
This commit is contained in:
James E. Blair 2021-04-06 18:59:05 -07:00
parent 245f6d4713
commit a32c31bc3c
9 changed files with 753 additions and 1 deletions

View File

@ -92,16 +92,19 @@
- project: - project:
check: check:
jobs: jobs:
- zuul-tox-docs
- zuul-operator-build-image - zuul-operator-build-image
- zuul-operator-functional-k8s: - zuul-operator-functional-k8s:
dependencies: zuul-operator-build-image dependencies: zuul-operator-build-image
gate: gate:
jobs: jobs:
- zuul-tox-docs
- zuul-operator-upload-image - zuul-operator-upload-image
- zuul-operator-functional-k8s: - zuul-operator-functional-k8s:
dependencies: zuul-operator-upload-image dependencies: zuul-operator-upload-image
promote: promote:
jobs: jobs:
- zuul-promote-docs
- zuul-operator-promote-image - zuul-operator-promote-image
release: release:
jobs: jobs:

View File

@ -2,7 +2,7 @@ image:
podman build -f build/Dockerfile -t docker.io/zuul/zuul-operator . podman build -f build/Dockerfile -t docker.io/zuul/zuul-operator .
install: install:
kubectl apply -f deploy/crds/zuul-ci_v1alpha2_zuul_crd.yaml -f deploy/rbac.yaml -f deploy/operator.yaml kubectl apply -f deploy/crds/zuul-ci_v1alpha2_zuul_crd.yaml -f deploy/rbac-admin.yaml -f deploy/operator.yaml
deploy-cr: deploy-cr:
kubectl apply -f deploy/crds/zuul-ci_v1alpha2_zuul_cr.yaml kubectl apply -f deploy/crds/zuul-ci_v1alpha2_zuul_cr.yaml

124
deploy/rbac-admin.yaml Normal file
View File

@ -0,0 +1,124 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: zuul-operator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: zuul-operator
rules:
- apiGroups:
- ""
resources:
- pods
- pods/exec
- services
- services/finalizers
- endpoints
- persistentvolumeclaims
- events
- configmaps
- secrets
- ingresses
- namespaces
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- deployments
- daemonsets
- replicasets
- statefulsets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resourceNames:
- zuul-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- replicasets
- deployments
verbs:
- get
- apiGroups:
- operator.zuul-ci.org
- cert-manager.io
- pxc.percona.com
resources:
- '*'
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- monitoring.coreos.com
resources:
- servicemonitors
verbs:
- get
- create
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: zuul-operator
subjects:
- kind: ServiceAccount
name: zuul-operator
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin #zuul-operator
apiGroup: rbac.authorization.k8s.io

2
doc/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
sphinx>=1.6.1
zuul-sphinx

View File

@ -0,0 +1,6 @@
.logo img {
width: 75%;
}
div.sphinxsidebarwrapper p.logo {
text-align: left;
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 144 144" style="enable-background:new 0 0 144 144;" xml:space="preserve">
<style type="text/css">
.st0{fill:#071D49;}
</style>
<g>
<path class="st0" d="M12.8,102.6h118.5L106,58.8v-15l7-9.2H92L72,0L52,34.7H31.1l7,9.2v15L12.8,102.6z M38,96.6H23.1L38,70.8V96.6z
M48.4,96.6H44V61.3h4.3V96.6z M48.4,55.3H44V51h4.3V55.3z M69,96.6H54.3V61.3H69V96.6z M89.7,96.6H75V61.3h14.7V96.6z M89.7,55.3
H54.3V51h35.3V55.3z M100,96.6h-4.3V61.3h4.3V96.6z M100,55.3h-4.3V51h4.3V55.3z M106,70.8l14.9,25.8H106V70.8z M72,12l13.1,22.7
H58.9L72,12z M100.9,40.7l-0.9,1.2V45H44v-3.2l-0.9-1.2H100.9z"/>
<polygon class="st0" points="138.2,137.3 125.1,137.3 125.1,114.6 119.1,118.1 119.1,137.3 119.1,139.6 119.1,143.3 141.6,143.3
"/>
<path class="st0" d="M99.1,131.5L99.1,131.5L99.1,131.5c0,3.6-2.9,6.5-6.5,6.5c-3.6,0-6.5-2.9-6.5-6.5v0h0v-16.9l-6,3.5v13.5v0
c0,6.9,5.6,12.5,12.5,12.5c6.9,0,12.5-5.6,12.5-12.5v0v-16.9l-6,3.5V131.5z"/>
<path class="st0" d="M60.2,131.5L60.2,131.5L60.2,131.5c0,3.6-2.9,6.5-6.5,6.5c-3.6,0-6.5-2.9-6.5-6.5v0h0v-16.9l-6,3.5v13.5v0
c0,6.9,5.6,12.5,12.5,12.5c6.9,0,12.5-5.6,12.5-12.5v0v-16.9l-6,3.5V131.5z"/>
<polygon class="st0" points="25.8,114.6 25.4,114.6 18.9,114.6 5.8,114.6 2.4,120.6 15.5,120.6 2.4,143.3 23.8,143.3 27.3,137.3
12.7,137.3 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

93
doc/source/conf.py Executable file
View File

@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'zuul_sphinx',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
primary_domain = 'zuul'
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'zuul-operator'
copyright = u'2021, Zuul contributors'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'Zuul contributors', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '_static/logo.svg'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Sample additional role paths
zuul_role_paths = ['tests/roles']

460
doc/source/index.rst Normal file
View File

@ -0,0 +1,460 @@
Zuul Operator
=============
This is a Kubernetes Operator for the Zuul Project Gating System.
Zuul has a number of components and depencencies, and this operator is
designed to simplify creating and maintaining Zuul systems in
Kubernetes.
Somewhat unusually, this operator offers the ability to completely
manage Zuul's operational dependencies, to the point of even
installing other operators upon which it relies. Be sure to read
about deployment options if you want to perform some of these tasks
yourself.
Simple Example
--------------
The quickest way to get a running Zuul is to allow the operator to
manage all of the dependencies for you. In this case, the operator
will:
* Install cert-manager and set up a self-signed cluster issuer
* Install the Percona XtraDB operator and create a three-node PXC
database cluster
* Create a three-node ZooKeeper cluster
* And of course, create a Zuul system
.. note::
Installing other operators requires a high level of access, so when
used in this manner, zuul-operator runs with cluster admin
privileges. If you would like the operator to run with reduced
privileges, see Managing Operator Dependencies.
From the root of the zuul-operator repo, run:
.. code-block:: bash
kubectl apply -f deploy/crds/zuul-ci_v1alpha1_zuul_crd.yaml
kubectl apply -f deploy/rbac-admin.yaml
kubectl apply -f deploy/operator.yaml
You probably want a namespace, so go ahead and create one with:
.. code-block:: bash
kubectl create namespace zuul
You will need to prepare two config files for Zuul: the Nodepool
config file and the Zuul tenant config file. See the Zuul and
Nodepool manuals for how to prepare those. When they are ready, add
them to Kubernetes with commands like:
.. code-block:: bash
kubectl -n zuul create secret generic zuul-nodepool-config --from-file=nodepool.yaml
kubectl -n zuul create secret generic zuul-tenant-config --from-file=main.yaml
Then create a file called ``zuul.yaml`` which looks like:
.. code-block:: yaml
---
apiVersion: operator.zuul-ci.org/v1alpha2
kind: Zuul
metadata:
name: zuul
spec:
executor:
count: 1
sshkey:
secretName: gerrit-secrets
scheduler:
config:
secretName: zuul-tenant-config
launcher:
config:
secretName: zuul-nodepool-config
web:
count: 1
connections:
opendev:
driver: git
baseurl: https://opendev.org
This will create the most basic of Zuul installations, with one each
of the `zuul-executor`, `zuul-scheduler`, and `zuul-web` processes.
It will also create a Nodepool launcher for each of the providers
listed in your ``nodepool.yaml``. If your Zuul tenant config file
requires more connections, be sure to add them here.
Managing Operator Dependencies
------------------------------
You may not want zuul-operator to install other operators (for
example, if your cluster has other users and you don't want
cert-manager or pxc-operator to be tied to a Zuul installation, or if
you would prefer to avoid granting zuul-operator cluster admin
privileges). In that case, you may install the other operators
yourself and still allow zuul-operator to use those other operators.
It can still create a PXC cluster for you as long as the pxc-operator
is present.
To use this mode of operation, make sure the following dependencies
are installed before using zuul-operator:
* Cert-manager (at least version 1.2.0)
* Percona-xtradb-cluster-operator (at least version 1.7.0)
With these installed, you may install zuul-operator with reduced
privileges:
.. code-block:: bash
kubectl apply -f deploy/crds/zuul-ci_v1alpha1_zuul_crd.yaml
kubectl apply -f deploy/rbac.yaml
kubectl apply -f deploy/operator.yaml
After this point, usage is the same as other methods.
Externally Managed Zuul Dependencies
------------------------------------
If you want zuul-operator to do even less work, you can have it avoid
managing either ZooKeeper or the SQL database.
Externally Managed ZooKeeper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you already have a ZooKeeper instance you would like Zuul to use,
add the following to the `Zuul` spec:
.. code-block:: yaml
---
apiVersion: operator.zuul-ci.org/v1alpha2
kind: Zuul
spec:
zookeeper:
connectionString: ...
secretName: ...
The ``connectionString`` field should be a standard ZooKeeper
connection string, and the ``secretName`` field should be a Kubernetes
TLS secret with the client cert for Zuul to use when connecting to
ZooKeeper. TLS is required.
Externally Managed Database
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you would like to use an existing database, add the following to
the `Zuul` spec:
.. code-block:: yaml
---
apiVersion: operator.zuul-ci.org/v1alpha2
kind: Zuul
spec:
database:
dburi: ...
The ``dburi`` field should contain a Python db-api URI; it corresponds
to the ``dburi`` entry in ``zuul.conf``.
Secrets
-------
The operator uses Kubernetes secrets as input values for several
aspects of operation. There are some general rules about how secrets
are used:
* For configuration files, secret keys are expected to be the typical
filename (for example, ``nodepool.yaml`` for the Nodepool config
file).
* For Zuul connection entries, secret keys correspond to the
configuration file attributes for that section (e.g., ``app_key``
for the github driver).
See the reference documentation for the specific `secretName` entry
for details.
Specification Reference
-----------------------
This is a fully populated example (with the exception of connection
entries which can contain `zuul.conf` attributes passed through
verbatim):
.. code-block:: yaml
apiVersion: zuul-ci.org/v1alpha2
kind: Zuul
spec:
database:
secretName: mariadbSecret
zookeeper:
hosts: zk.example.com:2282
secretName: zookeeperTLS
merger:
count: 5
git_user_email: zuul@example.org
git_user_name: Example Zuul
executor:
count: 5
manage_ansible: false
web:
count: 1
status_url: https://zuul.example.org
fingergw:
count: 1
scheduler:
count: 1
connections:
gerrit:
driver: gerrit
server: gerrit.example.com
secretName: gerritSecrets
user: zuul
baseurl: http://gerrit.example.com:8080
github:
driver: github
secretName: githubSecrets
rate_limit_logging: false
app_id: 1234
jobVolumes:
- context: trusted
access: ro
path: /authdaemon/token
volume:
name: gcp-auth
hostPath:
path: /var/authdaemon/executor
type: DirectoryOrCreate
.. attr:: Zuul
The Zuul kind is currently the only resource directly handled by
the operator. It holds a complete description of a Zuul system
(though at least partly via secrets referenced by this resource).
.. attr:: spec
.. attr:: imagePrefix
:default: docker.io/zuul
The prefix to use for images. The image names are fixed
(``zuul-executor``, etc). However, changing the prefix will
allow you to use custom images or private registries.
.. attr:: zuulImageVersion
:default: latest
The image tag to append to the Zuul images.
.. attr:: nodepoolImageVersion
:default: latest
The image tag to append to the Nodepool images.
.. attr:: database
This is not required unless you want to manage the database
yourself. If you omit this section, zuul-operator will
create a Percona XtraDB cluster for you.
You may add any attribute corresponding to the `database`
section of zuul.conf here. The ``dburi`` attribute will come
from the secret below.
.. attr:: secretName
The name of a secret containing connection information for
the database.
The key name in the secret should be ``dburi``.
.. attr:: zookeeper
This is not required unless you want to manage the ZooKeeper
cluster yourself. If you omit this section, zuul-operator
will create a ZooKeeper cluster for you
You may add any attribute corresponding to the `zookeeper`
section of zuul.conf here. The ``hosts`` and TLS attributes
will come from the secret below.
.. attr:: hosts
A standard ZooKeeper connection string.
.. attr:: secretName
The name of a secret containing a TLS client certificate
and key for ZooKeeper. This should be (or the format
should match) a standard Kubernetes TLS secret.
The key names in the secret should be:
* ``ca.crt``
* ``tls.crt``
* ``tls.key``
.. attr:: scheduler
.. attr:: config
.. attr:: secretName
The name of a secret containing the Zuul tenant config
file.
The key name in the secret should be ``main.yaml``.
.. attr:: launcher
.. attr:: config
.. attr:: secretName
The name of a secret containing the Nodepool config
file.
The key name in the secret should be ``nodepool.yaml``.
.. attr:: executor
.. attr:: count
:default: 1
How many executors to manage. This is a required
component and should be at least 1.
.. attr:: sshkey
.. attr:: secretName
The name of a secret containing the SSH private key
that executors should use when logging into Nodepool
nodes. You will need to arrange for the public half of
this key to be installed on those nodes via whatever
mechanism provided by your cloud.
The key name in the secret should be ``sshkey``.
.. attr:: merger
.. attr:: count
:default: 0
How many mergers to manage. Executors also act as mergers
so this is not required. They may be useful on a busy
system.
.. attr:: web
.. attr:: count
:default: 1
How many Zuul webservers to manage. This is a required
component and should be at least 1.
.. attr:: fingergw
.. attr:: count
:default: 1
How many Zuul finger gateway servers to manage.
.. attr:: connections
This is a mapping designed to match the `connections` entries
in the main Zuul config file (`zuul.conf`). Each key in the
mapping is the name of a connection (this is the name you
will use in the tenant config file), and the values are
key/value pairs that are directly added to that connectien
entry in `zuul.conf`. In the case of keys which are
typically files (for example, SSH keys), the values will be
written to disk for you (so you should include the full
values here and not the path).
You may provide any of these values directly in this resource
or using the secret described below. You may use both, and
the values will be combined (for example, you may include all
the values here except a private key which you include in a
secret).
Example:
.. code-block:: yaml
connections:
opendev:
driver: git
baseurl: https://opendev.org
gerrit:
driver: git
baseurl: https://gerrit.examplec.mo
secretName: gerrit-secrets
.. attr:: <name>
The name of the connection. You will use this is the
tenant config file. All of the attributes describing this
connection should be included underneath this key.
.. attr:: secretName
The name of a secret describing this connection. All
of the keys and values in this secret will be merged
with the keys and values described in this connection
entry. If you need to provide a file (for example, the
``sshkey`` attribute of a Gerrit connection), include
the contents as the value of the ``sshkey`` attribute
in the secret.
.. attr:: jobVolumes
A list of Kubernetes volumes to be bind mounted into the
executor's execution context. These correspond to the
`trusted_ro_paths`, `untrusted_ro_paths`, `trusted_rw_paths`,
and `untrusted_ro_paths` entries in `zuul.conf`.
The first part of each entry describes how the volume should
appear in the executor, and the `volume` attribute describes
the Kubernetes volume.
.. attr:: context
One of the following values:
.. value:: trusted
To be mounted in the `trusted` execution context.
.. value:: untrusted
To be mounted in the `untrusted` execution context.
.. attr:: access
One of the following values:
.. value:: rw
To be mounted read/write.
.. value:: ro
To be mounted read-only.
.. attr:: path
The mount point within the execution context.
.. attr:: volume
A mapping corresponding to a Kubernetes volume.

42
tox.ini Normal file
View File

@ -0,0 +1,42 @@
[tox]
minversion = 1.6
skipsdist = True
envlist = pep8
[testenv]
basepython = python3
install_command = pip install {opts} {packages}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
python setup.py testr --slowest --testr-args='{posargs}'
[testenv:bindep]
# Do not install any requirements. We want this to be fast and work even if
# system dependencies are missing, since it's used to tell you what system
# dependencies are missing! This also means that bindep must be installed
# separately, outside of the requirements files.
deps = bindep
commands = bindep test
[testenv:docs]
install_command = pip install {opts} {packages}
deps =
-r{toxinidir}/doc/requirements.txt
commands =
sphinx-build -E -W -d doc/build/doctrees -b html doc/source/ doc/build/html
[testenv:pep8]
whitelist_externals = bash
commands =
flake8 {posargs}
[testenv:venv]
commands = {posargs}
[flake8]
# These are ignored intentionally in openstack-infra projects;
# please don't submit patches that solely correct them or enable them.
ignore = E124,E125,E129,E252,E402,E741,H,W503,W504
show-source = True
exclude = .venv,.tox,dist,doc,build,*.egg