James E. Blair | f09c238 | 2018-02-08 16:50:31 -0800 | [diff] [blame] | 1 | Zuul From Scratch |
| 2 | ================= |
| 3 | |
| 4 | .. note:: This is a work in progress that attempts to walk through all |
| 5 | of the steps needed to run Zuul on a cloud server against |
| 6 | GitHub projects. |
| 7 | |
| 8 | Environment Setup |
| 9 | ----------------- |
| 10 | |
| 11 | We're going to be using Fedora 27 on a cloud server for this |
| 12 | installation. |
| 13 | |
| 14 | Login to your environment |
| 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 16 | |
| 17 | Since we'll be using a cloud image for Fedora 27, our login user will |
| 18 | be ``fedora`` which will also be the staging user for installation of |
| 19 | Zuul and Nodepool. |
| 20 | |
| 21 | To get started, ssh to your machine as the ``fedora`` user:: |
| 22 | |
| 23 | ssh fedora@<ip_address> |
| 24 | |
| 25 | Environment Setup |
| 26 | ~~~~~~~~~~~~~~~~~ |
| 27 | |
| 28 | :: |
| 29 | |
| 30 | sudo dnf update -y |
| 31 | sudo systemctl reboot |
| 32 | sudo dnf install git redhat-lsb-core python3 python3-pip python3-devel make gcc openssl-devel python-openstackclient -y |
| 33 | pip3 install --user bindep |
| 34 | |
| 35 | Zuul and Nodepool Installation |
| 36 | ------------------------------ |
| 37 | |
| 38 | Install Zookeeper |
| 39 | ~~~~~~~~~~~~~~~~~ |
| 40 | |
| 41 | :: |
| 42 | |
| 43 | sudo dnf install zookeeper -y |
| 44 | |
| 45 | Install Nodepool |
| 46 | ~~~~~~~~~~~~~~~~ |
| 47 | |
| 48 | :: |
| 49 | |
| 50 | sudo adduser --system nodepool --home-dir /var/lib/nodepool --create-home |
| 51 | git clone https://git.openstack.org/openstack-infra/nodepool |
| 52 | cd nodepool/ |
| 53 | sudo dnf -y install $(bindep -b) |
| 54 | sudo pip3 install . |
| 55 | |
| 56 | Install Zuul |
| 57 | ~~~~~~~~~~~~ |
| 58 | |
| 59 | :: |
| 60 | |
| 61 | sudo adduser --system zuul --home-dir /var/lib/zuul --create-home |
| 62 | git clone https://git.openstack.org/openstack-infra/zuul |
| 63 | cd zuul/ |
| 64 | sudo dnf install $(bindep -b) -y |
| 65 | sudo pip3 install git+https://github.com/sigmavirus24/github3.py.git@develop#egg=Github3.py |
| 66 | sudo pip3 install . |
| 67 | |
| 68 | Setup |
| 69 | ----- |
| 70 | |
| 71 | Zookeeper Setup |
| 72 | ~~~~~~~~~~~~~~~ |
| 73 | |
| 74 | .. TODO recommended reading for zk clustering setup |
| 75 | |
| 76 | :: |
| 77 | |
| 78 | sudo bash -c 'echo "1" > /etc/zookeeper/myid' |
| 79 | sudo bash -c 'echo "tickTime=2000 |
| 80 | dataDir=/var/lib/zookeeper |
| 81 | clientPort=2181" > /etc/zookeeper/zoo.cfg' |
| 82 | |
| 83 | Nodepool Setup |
| 84 | ~~~~~~~~~~~~~~ |
| 85 | |
| 86 | Before starting on this, you need to download your `openrc` |
| 87 | configuration from your OpenStack cloud. Put it on your server in the |
| 88 | fedora user's home directory. It should be called |
| 89 | ``<username>-openrc.sh``. Once that is done, create a new keypair |
| 90 | that will be installed when instantiating the servers:: |
| 91 | |
| 92 | cd ~ |
| 93 | source <username>-openrc.sh # this will prompt for password - enter it |
| 94 | umask 0066 |
| 95 | |
| 96 | ssh-keygen -t rsa -b 2048 -f nodepool_rsa # don't enter a passphrase |
| 97 | openstack keypair create --public-key nodepool_rsa.pub nodepool |
| 98 | |
| 99 | We'll use the private key later wheen configuring Zuul. In the same |
| 100 | session, configure nodepool to talk to your cloud:: |
| 101 | |
| 102 | sudo mkdir -p ~nodepool/.config/openstack |
| 103 | cat > clouds.yaml <<EOF |
| 104 | clouds: |
| 105 | mycloud: |
| 106 | auth: |
| 107 | username: $OS_USERNAME |
| 108 | password: $OS_PASSWORD |
| 109 | project_name: ${OS_PROJECT_NAME:-$OS_TENANT_NAME} |
| 110 | auth_url: $OS_AUTH_URL |
| 111 | region_name: $OS_REGION_NAME |
| 112 | EOF |
| 113 | sudo mv clouds.yaml ~nodepool/.config/openstack/ |
| 114 | sudo chown -R nodepool.nodepool ~nodepool/.config |
| 115 | umask 0002 |
| 116 | |
| 117 | Once you've written out the file, double check all the required fields have been filled out. |
| 118 | |
| 119 | :: |
| 120 | |
| 121 | sudo mkdir /etc/nodepool/ |
| 122 | sudo mkdir /var/log/nodepool |
| 123 | sudo chgrp -R nodepool /var/log/nodepool/ |
| 124 | sudo chmod 775 /var/log/nodepool/ |
| 125 | |
| 126 | Nodepool Configuration |
| 127 | ~~~~~~~~~~~~~~~~~~~~~~ |
| 128 | |
| 129 | Inputs needed for this file: |
| 130 | |
| 131 | * cloud name / region name - from clouds.yaml |
| 132 | * flavor-name |
| 133 | * image-name - from your cloud |
| 134 | |
| 135 | :: |
| 136 | |
| 137 | sudo bash -c "cat >/etc/nodepool/nodepool.yaml <<EOF |
| 138 | zookeeper-servers: |
| 139 | - host: localhost |
| 140 | port: 2181 |
| 141 | |
| 142 | providers: |
| 143 | - name: myprovider # this is a nodepool identifier for this cloud provider (cloud+region combo) |
| 144 | region-name: regionOne # this needs to match the region name in clouds.yaml but is only needed if there is more than one region |
| 145 | cloud: mycloud # This needs to match the name in clouds.yaml |
| 146 | cloud-images: |
| 147 | - name: centos-7 # Defines a cloud-image for nodepool |
| 148 | image-name: CentOS-7-x86_64-GenericCloud-1706 # name of image from cloud |
| 149 | username: centos # The user Zuul should log in as |
| 150 | pools: |
| 151 | - name: main |
| 152 | max-servers: 4 # nodepool will never create more than this many servers |
| 153 | labels: |
| 154 | - name: centos-7-small # defines label that will be used to get one of these in a job |
| 155 | flavor-name: 'm1.small' # name of flavor from cloud |
| 156 | cloud-image: centos-7 # matches name from cloud-images |
| 157 | key-name: nodepool # name of the keypair to use for authentication |
| 158 | |
| 159 | labels: |
| 160 | - name: centos-7-small # defines label that will be used in jobs |
| 161 | min-ready: 2 # nodepool will always keep this many booted and ready to go |
| 162 | EOF" |
| 163 | |
| 164 | .. warning:: |
| 165 | |
| 166 | `min-ready:2` may incur costs in your cloud provider |
| 167 | |
| 168 | |
| 169 | Zuul Setup |
| 170 | ~~~~~~~~~~ |
| 171 | |
| 172 | :: |
| 173 | |
| 174 | sudo mkdir /etc/zuul/ |
| 175 | sudo mkdir /var/log/zuul/ |
| 176 | sudo chown zuul.zuul /var/log/zuul/ |
| 177 | sudo mkdir /var/lib/zuul/.ssh |
| 178 | sudo chmod 0700 /var/lib/zuul/.ssh |
| 179 | sudo mv nodepool_rsa /var/lib/zuul/.ssh |
| 180 | sudo chown -R zuul.zuul /var/lib/zuul/.ssh |
| 181 | |
| 182 | Zuul Configuration |
| 183 | ~~~~~~~~~~~~~~~~~~ |
| 184 | |
| 185 | Write the Zuul config file. Note that this configures Zuul's web |
| 186 | server to listen on all public addresses. This is so that Zuul may |
| 187 | receive webhook events from GitHub. You may wish to proxy this or |
| 188 | further restrict public access. |
| 189 | |
| 190 | :: |
| 191 | |
| 192 | sudo bash -c "cat > /etc/zuul/zuul.conf <<EOF |
| 193 | [gearman] |
| 194 | server=127.0.0.1 |
| 195 | |
| 196 | [gearman_server] |
| 197 | start=true |
| 198 | |
| 199 | [executor] |
| 200 | private_key_file=/home/zuul/.ssh/nodepool_rsa |
| 201 | |
| 202 | [web] |
| 203 | listen_address=0.0.0.0 |
| 204 | |
| 205 | [scheduler] |
| 206 | tenant_config=/etc/zuul/main.yaml |
| 207 | EOF" |
| 208 | |
| 209 | sudo bash -c "cat > /etc/zuul/main.yaml <<EOF |
| 210 | - tenant: |
| 211 | name: quickstart |
| 212 | EOF" |
| 213 | |
| 214 | Service Management |
| 215 | ------------------ |
| 216 | |
| 217 | Zookeeper Service Management |
| 218 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 219 | |
| 220 | :: |
| 221 | |
| 222 | sudo systemctl start zookeeper.service |
| 223 | |
| 224 | :: |
| 225 | |
| 226 | sudo systemctl status zookeeper.service |
| 227 | ● zookeeper.service - Apache ZooKeeper |
| 228 | Loaded: loaded (/usr/lib/systemd/system/zookeeper.service; disabled; vendor preset: disabled) |
| 229 | Active: active (running) since Wed 2018-01-03 14:53:47 UTC; 5s ago |
| 230 | Process: 4153 ExecStart=/usr/bin/zkServer.sh start zoo.cfg (code=exited, status=0/SUCCESS) |
| 231 | Main PID: 4160 (java) |
| 232 | Tasks: 17 (limit: 4915) |
| 233 | CGroup: /system.slice/zookeeper.service |
| 234 | └─4160 java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -cp /usr/share/java/ |
| 235 | |
| 236 | :: |
| 237 | |
| 238 | sudo systemctl enable zookeeper.service |
| 239 | |
| 240 | |
| 241 | Nodepool Service Management |
| 242 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 243 | |
| 244 | :: |
| 245 | |
| 246 | sudo bash -c "cat > /etc/systemd/system/nodepool-launcher.service <<EOF |
| 247 | [Unit] |
| 248 | Description=Nodepool Launcher Service |
| 249 | After=syslog.target network.target |
| 250 | |
| 251 | [Service] |
| 252 | Type=simple |
| 253 | # Options to pass to nodepool-launcher. |
| 254 | Group=nodepool |
| 255 | User=nodepool |
| 256 | RuntimeDirectory=nodepool |
| 257 | ExecStart=/usr/local/bin/nodepool-launcher |
| 258 | |
| 259 | [Install] |
| 260 | WantedBy=multi-user.target |
| 261 | EOF" |
| 262 | |
| 263 | sudo chmod 0644 /etc/systemd/system/nodepool-launcher.service |
| 264 | sudo systemctl daemon-reload |
| 265 | sudo systemctl start nodepool-launcher.service |
| 266 | sudo systemctl status nodepool-launcher.service |
| 267 | sudo systemctl enable nodepool-launcher.service |
| 268 | |
| 269 | Zuul Service Management |
| 270 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 271 | :: |
| 272 | |
| 273 | sudo bash -c "cat > /etc/systemd/system/zuul-scheduler.service <<EOF |
| 274 | [Unit] |
| 275 | Description=Zuul Scheduler Service |
| 276 | After=syslog.target network.target |
| 277 | |
| 278 | [Service] |
| 279 | Type=simple |
| 280 | Group=zuul |
| 281 | User=zuul |
| 282 | RuntimeDirectory=zuul |
| 283 | ExecStart=/usr/local/bin/zuul-scheduler |
| 284 | ExecStop=/usr/local/bin/zuul-scheduler stop |
| 285 | |
| 286 | [Install] |
| 287 | WantedBy=multi-user.target |
| 288 | EOF" |
| 289 | |
| 290 | sudo bash -c "cat > /etc/systemd/system/zuul-executor.service <<EOF |
| 291 | [Unit] |
| 292 | Description=Zuul Executor Service |
| 293 | After=syslog.target network.target |
| 294 | |
| 295 | [Service] |
| 296 | Type=simple |
| 297 | Group=zuul |
| 298 | User=zuul |
| 299 | RuntimeDirectory=zuul |
| 300 | ExecStart=/usr/local/bin/zuul-executor |
| 301 | ExecStop=/usr/local/bin/zuul-executor stop |
| 302 | |
| 303 | [Install] |
| 304 | WantedBy=multi-user.target |
| 305 | EOF" |
| 306 | |
| 307 | sudo bash -c "cat > /etc/systemd/system/zuul-web.service <<EOF |
| 308 | [Unit] |
| 309 | Description=Zuul Web Service |
| 310 | After=syslog.target network.target |
| 311 | |
| 312 | [Service] |
| 313 | Type=simple |
| 314 | Group=zuul |
| 315 | User=zuul |
| 316 | RuntimeDirectory=zuul |
| 317 | ExecStart=/usr/local/bin/zuul-web |
| 318 | ExecStop=/usr/local/bin/zuul-web stop |
| 319 | |
| 320 | [Install] |
| 321 | WantedBy=multi-user.target |
| 322 | EOF" |
| 323 | |
| 324 | sudo systemctl daemon-reload |
| 325 | sudo systemctl start zuul-scheduler.service |
| 326 | sudo systemctl status zuul-scheduler.service |
| 327 | sudo systemctl enable zuul-scheduler.service |
| 328 | sudo systemctl start zuul-executor.service |
| 329 | sudo systemctl status zuul-executor.service |
| 330 | sudo systemctl enable zuul-executor.service |
| 331 | sudo systemctl start zuul-web.service |
| 332 | sudo systemctl status zuul-web.service |
| 333 | sudo systemctl enable zuul-web.service |
| 334 | |
| 335 | Use Zuul Jobs |
| 336 | ------------- |
| 337 | |
| 338 | Add to ``/etc/zuul/zuul.conf``:: |
| 339 | |
| 340 | sudo bash -c "cat >> /etc/zuul/zuul.conf <<EOF |
| 341 | |
| 342 | [connection zuul-git] |
| 343 | driver=git |
| 344 | baseurl=https://git.openstack.org/ |
| 345 | EOF" |
| 346 | |
| 347 | Restart executor and scheduler:: |
| 348 | |
| 349 | sudo systemctl restart zuul-executor.service |
| 350 | sudo systemctl restart zuul-scheduler.service |
| 351 | |
| 352 | Configure GitHub |
| 353 | ---------------- |
| 354 | |
| 355 | You'll need an organization in Github for this, so create one if you |
| 356 | haven't already. In this example we will use `my-org`. |
| 357 | |
| 358 | .. NOTE Duplicate content here and in drivers/github.rst. Keep them |
| 359 | in sync. |
| 360 | |
| 361 | Create a `GitHub application |
| 362 | <https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/registering-github-apps/>`_: |
| 363 | |
| 364 | * Go to your organization settings page to create the application, e.g.: |
| 365 | https://github.com/organizations/my-org/settings/apps/new |
| 366 | * Set GitHub App name to "my-org-zuul" |
| 367 | * Set Setup URL to your setup documentation, when users install the application |
| 368 | they are redirected to this url |
| 369 | * Set Webhook URL to |
| 370 | ``http://<IP ADDRESS>/connection/github/payload``. |
| 371 | * Create a Webhook secret, and record it for later use |
| 372 | * Set permissions: |
| 373 | |
| 374 | * Commit statuses: Read & Write |
| 375 | * Issues: Read & Write |
| 376 | * Pull requests: Read & Write |
| 377 | * Repository contents: Read & Write (write to let zuul merge change) |
| 378 | * Repository administration: Read |
| 379 | |
| 380 | * Set events subscription: |
| 381 | |
| 382 | * Label |
| 383 | * Status |
| 384 | * Issue comment |
| 385 | * Issues |
| 386 | * Pull request |
| 387 | * Pull request review |
| 388 | * Pull request review comment |
| 389 | * Commit comment |
| 390 | * Create |
| 391 | * Push |
| 392 | * Release |
| 393 | |
| 394 | * Set Where can this GitHub App be installed to "Any account" |
| 395 | * Create the App |
| 396 | * Generate a Private key in the app settings page and save the file for later |
| 397 | |
| 398 | .. TODO See if we can script this using GitHub API |
| 399 | |
| 400 | Go back to the `General` settings page for the app, |
| 401 | https://github.com/organizations/my-org/settings/apps/my-org-zuul |
| 402 | and look for the app `ID` number, under the `About` section. |
| 403 | |
| 404 | Edit ``/etc/zuul/zuul.conf`` to add the following:: |
| 405 | |
| 406 | [connection github] |
| 407 | driver=github |
| 408 | app_id=<APP ID NUMBER> |
| 409 | app_key=/etc/zuul/github.pem |
| 410 | webhook_token=<WEBHOOK TOKEN> |
| 411 | |
| 412 | Upload the private key which was generated earlier, and save it in |
| 413 | ``/etc/zuul/github.pem``. |
| 414 | |
| 415 | Restart all of Zuul:: |
| 416 | |
| 417 | sudo systemctl restart zuul-executor.service |
| 418 | sudo systemctl restart zuul-web.service |
| 419 | sudo systemctl restart zuul-scheduler.service |
| 420 | |
| 421 | Go to the `Advanced` tab for the app in GitHub, |
| 422 | https://github.com/organizations/my-org/settings/apps/my-org-zuul/advanced, |
| 423 | and look for the initial ping from the app. It probably wasn't |
| 424 | delivered since Zuul wasn't configured at the time, so click |
| 425 | ``Resend`` and verify that it is delivered now that Zuul is |
| 426 | configured. |
| 427 | |
| 428 | Visit the public app page on GitHub, |
| 429 | https://github.com/apps/my-org-zuul, and install the app into your org. |
| 430 | |
| 431 | Create two new repositories in your org. One will hold the |
| 432 | configuration for this tenant in Zuul, the other should be a normal |
| 433 | project repo to use for testing. We'll call them `zuul-test-config` |
| 434 | and `zuul-test`, respectively. |
| 435 | |
| 436 | Edit ``/etc/zuul/main.yaml`` so that it looks like this:: |
| 437 | |
| 438 | - tenant: |
| 439 | name: quickstart |
| 440 | source: |
| 441 | zuul-git: |
| 442 | config-projects: |
| 443 | - openstack-infra/zuul-base-jobs |
| 444 | untrusted-projects: |
| 445 | - openstack-infra/zuul-jobs |
| 446 | github: |
| 447 | config-projects: |
| 448 | - my-org/zuul-test-config |
| 449 | untrusted-projects: |
| 450 | - my-org/zuul-test |
| 451 | |
| 452 | The first section, under 'zuul-git' imports the "standard library" of |
| 453 | Zuul jobs, a collection of jobs that can be used by any Zuul |
| 454 | installation. |
| 455 | |
| 456 | The second section is your GitHub configuration. |
| 457 | |
| 458 | After updating the file, restart the Zuul scheduler:: |
| 459 | |
| 460 | sudo systemctl restart zuul-scheduler.service |
| 461 | |
| 462 | Add an initial pipeline configuration to the `zuul-test-config` |
| 463 | repository. Inside that project, create a ``zuul.yaml`` file with the |
| 464 | following contents:: |
| 465 | |
| 466 | - pipeline: |
| 467 | name: check |
| 468 | description: | |
| 469 | Newly opened pull requests enter this pipeline to receive an |
| 470 | initial verification |
| 471 | manager: independent |
| 472 | trigger: |
| 473 | github: |
| 474 | - event: pull_request |
| 475 | action: |
| 476 | - opened |
| 477 | - changed |
| 478 | - reopened |
| 479 | - event: pull_request |
| 480 | action: comment |
| 481 | comment: (?i)^\s*recheck\s*$ |
| 482 | start: |
| 483 | github: |
| 484 | status: pending |
| 485 | comment: false |
| 486 | success: |
| 487 | github: |
| 488 | status: 'success' |
| 489 | failure: |
| 490 | github: |
| 491 | status: 'failure' |
| 492 | |
| 493 | Merge that commit into the repository. |
| 494 | |
| 495 | In the `zuul-test` project, create a `.zuul.yaml` file with the |
| 496 | following contents:: |
| 497 | |
| 498 | - project: |
| 499 | check: |
| 500 | jobs: |
| 501 | - noop |
| 502 | |
| 503 | Open a new pull request with that commit against the `zuul-test` |
| 504 | project and verify that Zuul reports a successful run of the `noop` |
| 505 | job. |