summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2019-03-15 16:32:29 +0000
committerGerrit Code Review <review@openstack.org>2019-03-15 16:32:29 +0000
commit0892d7f98cbf834a5087772f7ccd7a4a6419cbd3 (patch)
tree4d2c5185ae0af511a749456d2a671bb62eb07179
parent825ab5fb9965488e68cc7d36e38703c65ddbf8d9 (diff)
parente620f0b74e633d1f2f062d30173fc392be06ff4d (diff)
Merge "Document how to build a buildset registry"
-rwxr-xr-xdoc/source/conf.py2
-rw-r--r--doc/source/docker-image.rst375
-rw-r--r--doc/source/index.rst1
-rw-r--r--test-requirements.txt2
4 files changed, 380 insertions, 0 deletions
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 71466d9..1cdba5f 100755
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -19,6 +19,8 @@
19extensions = [ 19extensions = [
20 'sphinx.ext.autodoc', 20 'sphinx.ext.autodoc',
21 # 'sphinx.ext.intersphinx', 21 # 'sphinx.ext.intersphinx',
22 'sphinxcontrib.blockdiag',
23 'sphinxcontrib.seqdiag',
22 'zuul_sphinx', 24 'zuul_sphinx',
23] 25]
24 26
diff --git a/doc/source/docker-image.rst b/doc/source/docker-image.rst
new file mode 100644
index 0000000..14cb245
--- /dev/null
+++ b/doc/source/docker-image.rst
@@ -0,0 +1,375 @@
1Container Images
2================
3
4This repo has several jobs which can form the basis of a system
5supporting a full gating process for continuously deployed container
6images. They can be used to build or test images which rely on other
7images using the full power of Zuul's speculative execution.
8
9In order to use these jobs to their full potential, the Zuul site
10administrator will need to run a simple but dedicated container image
11registry, and define local versions of the jobs to use it. The
12following sections describe how to define those jobs and how the
13system is intended to work once the jobs are defined.
14
15Run an Intermediate Container Registry
16--------------------------------------
17
18A dedicated container registry is required for the use of these jobs.
19It is merely used to temporarily hold images so that they can be
20transferred between jobs running in different projects at different
21times. It does not need to be publicly accessible or particularly
22robust. If its backing storage fails and needs to be replaced, the
23only result is that some jobs running in Zuul may fail and may need to
24be re-run. In this system, it is called the "intermediate registry"
25to distinguish it from other registry services.
26
27You may run the registry in whatever manner is appropriate for your
28site. The following docker-compose file may be used as an example
29of a working deployment suitable for production:
30
31.. code-block:: yaml
32
33 services:
34 registry:
35 restart: always
36 image: registry:2
37 network_mode: host
38 environment:
39 REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
40 REGISTRY_HTTP_TLS_KEY: /certs/domain.key
41 REGISTRY_AUTH: htpasswd
42 REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
43 REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
44 volumes:
45 - /var/registry/data:/var/lib/registry
46 - /var/registry/certs:/certs
47 - /var/registry/auth:/auth
48
49You will need to provide the SSL certificate and key values, as well
50as the htpassword file with a user and password already present.
51
52Once that service is running, create the following four jobs in a
53Zuul config-project:
54
55.. _yoursite-buildset-registry:
56
57yoursite-buildset-registry
58~~~~~~~~~~~~~~~~~~~~~~~~~~
59
60This job is used to provide a temporary "buildset registry" to jobs
61running in your system; it communicates with the "intermediate"
62registry described above.
63
64.. code-block:: yaml
65 :caption: zuul.yaml
66
67 - secret:
68 name: yoursite-intermediate-registry
69 data:
70 host: insecure-ci-registry.example.org
71 port: 5000
72 username: zuul
73 password: !encrypted/pkcs1-oaep
74 - ...
75
76 - job:
77 name: yoursite-buildset-registry
78 pre-run: playbooks/buildset-registry/pre.yaml
79 run: playbooks/buildset-registry/run.yaml
80 post-run: playbooks/buildset-registry/post.yaml
81 secrets:
82 - secret: yoursite-intermediate-registry
83 name: intermediate_registry
84 requires: docker-image
85
86The credentials in the secret should match those you supplied when
87creating the intermediate registry.
88
89The ``requires: docker-image`` attribute means that whenever this job
90(or any jobs which inherit from it) run, Zuul will search ahead of the
91change in the dependency graph to find any jobs which produce
92docker-images and tell this job about them. This allows the job to
93pull images from the intermediate registry into the buildset registry.
94
95.. code-block:: yaml
96 :caption: playbooks/buildset-registry/pre.yaml
97
98 - hosts: all
99 tasks:
100 - name: Install docker
101 include_role:
102 name: install-docker
103 - name: Run buildset registry (if not already running)
104 when: buildset_registry is not defined
105 include_role:
106 name: run-buildset-registry
107 - name: Use buildset registry
108 include_role:
109 name: use-buildset-registry
110
111 - hosts: localhost
112 roles:
113 - pull-from-intermediate-registry
114
115This playbook runs a buildset registry if one isn't already running.
116It returns the connection information back to Zuul in a variable
117called ``buildset_registry``. Other jobs will use that to learn how
118to connect to the registry, and we can use that here to find out if
119one was already started in a previous job. We will use that facility
120in the :ref:`yoursite-build-docker-image` job below.
121
122.. code-block:: yaml
123 :caption: playbooks/buildset-registry/run.yaml
124
125 - hosts: localhost
126 tasks:
127 - name: Pause the job
128 zuul_return:
129 data:
130 zuul:
131 pause: true
132
133The ``pause`` causes the job to wait until all jobs which depend on
134this one are completed.
135
136.. code-block:: yaml
137 :caption: playbooks/buildset-registry/post.yaml
138
139 - hosts: localhost
140 roles:
141 - push-to-intermediate-registry
142
143.. _yoursite-build-docker-image:
144
145yoursite-build-docker-image
146~~~~~~~~~~~~~~~~~~~~~~~~~~~
147
148This job builds one or more docker images and interacts with the
149buildset and intermediate registries.
150
151.. code-block:: yaml
152 :caption: zuul.yaml
153
154 - job:
155 name: yoursite-build-docker-image
156 parent: yoursite-buildset-registry
157 run: playbooks/docker-image/run.yaml
158 provides: docker-image
159
160Note that the parent of this job is :ref:`yoursite-buildset-registry`.
161This means that a simple repo that only needs to support one image
162building job and doesn't have any other jobs which require a buildset
163registry can just add this job alone and it will run a buildset
164registry on the build host. More complex scenarios would run the
165:ref:`yoursite-buildset-registry` job on its own and construct a job
166graph that depends on it. Because the pre-run playbook in the
167buildset-registry job only runs a buildset registry if one isn't
168already running, it can be used for both cases. And because the run
169playbook which pauses the job is overridden in this job, this job will
170not pause.
171
172.. code-block:: yaml
173 :caption: playbooks/docker-image/run.yaml
174
175 - hosts: all
176 roles:
177 - build-docker-image
178
179.. _yoursite-upload-docker-image:
180
181yoursite-upload-docker-image
182~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183
184This job further builds on the :ref:`yoursite-build-docker-image` job
185and additionally uploads the image to Docker Hub. Depending on the
186situation, you could encode the Docker Hub credentials into this job
187as a secret, or you could allow other users to provide them via the
188`pass-to-parent <https://zuul-ci.org/docs/zuul/user/config.html#attr-job.secrets.pass-to-parent>`_ feature of secrets.
189
190.. code-block:: yaml
191 :caption: zuul.yaml
192
193 - job:
194 name: yoursite-upload-docker-image
195 parent: yoursite-build-docker-image
196 post-run: playbooks/docker-image/upload.yaml
197
198.. code-block:: yaml
199 :caption: playbooks/docker-image/upload.yaml
200
201 - hosts: all
202 roles:
203 - upload-docker-image
204
205.. _yoursite-promote-docker-image:
206
207yoursite-promote-docker-image
208~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
209
210This job does nothing that the :zuul:job:`promote-docker-image` job in
211this repo doesn't already do, but since you created local versions of
212the other two jobs, you should make one of this as well for
213consistency. If you chose to add Docker Hub credentials to the
214:ref:`yoursite-upload-docker-image` job, you should do that here as
215well.
216
217.. code-block:: yaml
218 :caption: zuul.yaml
219
220 - job:
221 name: yoursite-promote-docker-image
222 parent: promote-docker-image
223
224System Architecture
225-------------------
226
227Now that those jobs are defined, this section describes how they work
228together.
229
230There are a few key concepts to keep in mind:
231
232A *buildset* is a group of jobs all running on the same change.
233
234A *buildset registry* is a container image registry which is used to
235store speculatively built images for the use of jobs in a single
236buildset. It holds the differences between the current state of the
237world and the future state if the change in question (and all of its
238dependent changes) were to merge. It must be started by one of the
239jobs in a buildset, and it ceases to exist once that job is complete.
240
241An *intermediate registry* is a long-running registry that is used to
242store images created for unmerged changes for use by other unmerged
243changes. It is not publicly accessible and is intended only to be
244used by Zuul in order to transfer artifacts from one buildset to
245another.
246
247With these concepts in mind, the jobs described above implement the
248following workflow for a single change:
249
250.. _buildset_image_transfer:
251
252.. seqdiag::
253 :caption: Buildset registry image transfer
254
255 seqdiag image_transfer {
256 Ireg [label="Intermediate\nRegistry"];
257 Breg [label="Buildset\nRegistry"];
258 Bjob [label="Image Build Job"];
259 Djob [label="Deployment Test Job"];
260
261 Ireg -> Breg [label='Images from previous changes'];
262 Breg -> Bjob [label='Images from previous changes'];
263 Breg <- Bjob [label='Current image'];
264 Ireg <- Breg [noactivate, label='Current image'];
265 Breg -> Djob [label='Current and previous images'];
266 Breg <- Djob [style=none];
267 Ireg <- Breg [style=none];
268 }
269
270The intermediate registry is always running and the buildset registry
271is started by a job running on a change. The "Image Build" and
272"Deployment Test" jobs are example jobs which might be running on a
273change. Essentially, these are image producer or consumer jobs
274respectively.
275
276There are two ways to use the jobs described above:
277
278A Repository with Producers and Consumers
279-----------------------------------------
280
281The first is in a repository where images are both produced and
282consumed. In this case, we can expect that there will be at least one
283image build job, and at least one job which uses that image (for
284example, by performing a test deployment of the image). In this case
285we need to construct a job graph with dependencies as follows:
286
287.. blockdiag::
288
289 blockdiag dependencies {
290 obr [label='yoursite-\nbuildset-registry'];
291 bi [label='build-image'];
292 ti [label='test-image'];
293
294 obr <- bi <- ti;
295 }
296
297The :ref:`yoursite-buildset-registry` job will run first and
298automatically start a buildset registry populated with images built
299from any changes which appear ahead of the current change. It will
300then return its connection information to Zuul and pause and continue
301running until the completion of the build and test jobs.
302
303The build-image job should inherit from
304:ref:`yoursite-build-docker-image`, which will ensure that it is
305automatically configured to use the buildset registry.
306
307The test-image job is something that you will create yourself. There
308is no standard way to test or deploy an image, that depends on your
309application. However, there is one thing you will need to do in your
310job to take advantage of the buildset registry. In a pre-run playbook,
311use the `use-buildset-registry
312<https://zuul-ci.org/docs/zuul-jobs/roles.html#role-use-buildset-registry>`_
313role:
314
315.. code-block:: yaml
316
317 - hosts: all
318 roles:
319 - use-buildset-registry
320
321That will configure the docker daemon on the host to use the buildset
322registry so that it will use the newly built version of any required
323images.
324
325A Repository with Only Producers
326--------------------------------
327
328The second way to use these jobs is in a repository where an image is
329merely built, but not deployed. In this case, there are no consumers
330of the buildset registry other than the image build job, and so the
331registry can be run on the job itself. In this case, you may omit the
332:ref:`yoursite-buildset-registry` job and run only the
333:ref:`yoursite-build-docker-image` job.
334
335Publishing an Image
336-------------------
337
338So far we've covered the image building process. This system also
339provides two more jobs that are used in publishing images to Docker
340Hub.
341
342The :ref:`yoursite-upload-docker-image` job does everything the
343:ref:`yoursite-build-docker-image` job does, but it also uploads
344the built image to Docker Hub using an automatically-generated and
345temporary tag. The "build" job is designed to be used in the
346*check* pipeline, while the "upload" job is designed to take its
347place in the *gate* pipeline. By front-loading the upload to Docker
348Hub, we reduce the chance that a credential or network error will
349prevent us from publishing an image after a change lands.
350
351The :ref:`yoursite-promote-docker-image` job is designed to be
352used in the *promote* pipeline and simply re-tags the image on Docker
353Hub after the change lands.
354
355Keeping in mind that everything described above in
356:ref:`buildset_image_transfer` applies to the
357:ref:`yoursite-upload-docker-image` job, the following illustrates
358the additional tasks performed by the "upload" and "promote" jobs:
359
360.. seqdiag::
361
362 seqdiag image_transfer {
363 DH [activated, label="Docker Hub"];
364 Ujob [label="upload-image"];
365 Pjob [label="promote-image"];
366
367 DH -> Ujob [style=none];
368 DH <- Ujob [label='Current image with temporary tag'];
369 DH -> Pjob [label='Current image manifest with temporary tag',
370 note='Only the manifest
371 is transferred,
372 not the actual
373 image layers.'];
374 DH <- Pjob [label='Current image manifest with final tag'];
375 }
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 72ca440..31017c3 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -7,6 +7,7 @@
7 policy 7 policy
8 jobs 8 jobs
9 roles 9 roles
10 docker-image
10 11
11Indices and tables 12Indices and tables
12================== 13==================
diff --git a/test-requirements.txt b/test-requirements.txt
index 5cce771..b7e0546 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -22,3 +22,5 @@ openstacksdk>=0.17.1
22requests 22requests
23requestsexceptions 23requestsexceptions
24bs4 24bs4
25sphinxcontrib-blockdiag>=1.1.0
26sphinxcontrib-seqdiag