Rob Harris
2018-04-09 3b1c962a223264635aea790339a7fbdb8d300471
commit | author | age
5d0992 1 # The Manual Menace
c951f7 2
5d0992 3 > In this lab learners will use Ansible to drive automated provisioning of Projects, Access Control, Git, Jenkins and Nexus
D 4
5 _____
c951f7 6
D 7 ## Learning Outcomes
8 As a learner you will be able to
5d0992 9
D 10 1. Run the OpenShift Applier to automate creating cluster content
11 1. Create and admin project namespaces in OpenShift
12 1. Deploy commonly used applications to support the development process
c951f7 13
D 14 ## Tools and Frameworks
15
5d0992 16 * [GitLab](https://about.gitlab.com/) - Community driven Git server now with integrated DevOps Toolchain.
D 17 * [Nexus](https://www.sonatype.com/nexus-repository-sonatype) - Repository manager for storing lots of application types. Can also host `npm` and `Docker` registries.
18 * [Jenkins](https://jenkins.io/) - OpenSource Build automation server. Highly customisable with plugins.
19 * [Ansible](https://www.ansible.com/) - IT Automation tool used to provision and manage state of cloud and physical infrastructure.
20 * [OpenShift Applier](https://github.com/redhat-cop/openshift-applier) - Community driven Git server
c951f7 21
5d0992 22 ## Big Picture
D 23 This exercise begins with an empty Cluster
24 > TODO - add big picture here...
25
26 _____
c951f7 27
D 28 ## 10,000 Ft View
5d0992 29 > This lab is aimed at the creation of the tooling that will be used to support the rest of the Exercises. The highlevel goal is to create a collection of project namespaces and populate them with Git, Jenkins & Nexus.
D 30
31 If you're feeling confident and don't want to follow the step-by-step guide these highlevel instructions should provide a challenge for you:
32
3b1c96 33 2. Clone the repo `https://github.com/rht-labs/enablement-ci-cd` which contains the scaffold of the project.
3558ae 34
5d0992 35 2. Create `<your-name>-ci-cd`, `<your-name>-dev` and `<your-name>-test` project namespaces using the inventory and run them with the OpenShift Applier to populate the cluster
3558ae 36
D 37 2. Use the templates provided to create build and deployment configs in `<your-name>-ci-cd` for. Templates are on a branch called `exercise1/git-nexus` && `exercise1/jenkins`:
5d0992 38     * Nexus
D 39     * GitLab
3558ae 40     * Jenkins (using an s2i to pre-configure jenkins)
D 41
5d0992 42 2. Commit your `enablement-ci-cd` repository to the GitLab Instance you've created
3558ae 43
D 44 2. Burn it all down and re-apply your inventory proving config-as-code works. 
c951f7 45
D 46 ## Step by Step Instructions
bc2e43 47 > This is a structured guide with references to exact filenames and explanations.
c951f7 48
bc2e43 49 ### Part 1 - Create OpenShift Projects
de8ebb 50 > _Using the OpenShift Applier, we will add new project namespaces to the cluster which will be used throughout the exercise._
D 51
bc2e43 52 3. Clone the scaffold project to your local machine and open it in your favourite editor.
D 53 ```bash
54 git clone git@github.com:rht-labs/enablement-ci-cd.git
c951f7 55 ```
D 56
bc2e43 57 3. The project is laid out as follows
D 58 ```
59 .
60 ├── README.md
61 ├── docker
62 │   └── jenkins-slave-node
63 ├── inventory
64 │   ├── group_vars
65 │   │   └── all.yml
66 │   └── hosts
67 ├── jenkins-s2i
68 │   ├── configuration
69 ├── params
70 │   └── project-requests-ci-cd
71 ├── requirements.yml
72 └── templates
73         └── project-requests.yml
74 ```
75  * `docker` folder contains our jenkins-slave images that will be used by the builds.
76  * `jenkins-s2i` contains the configuration and plugins we want to bring jenkins to life with
77  * `params` houses the variables we will load the templates with
78  * `templates` is a collection of OpenShift templates
79  * `inventory/group_vars/all.yml` is the collection of objects we want to insert into the cluster.
80  * `requirements.yml` is a manifest which contains the ansible modules needed to run the playbook
81 Open the `inventory/group_vars/all.yml` file; you should see a some variables setup to create the `ci-cd` namespace. This calls the `templates/project-requests.yml` template with the `params/project-requests-ci-cd` parameters. We will add some additional content here but first let's explore the parameters and the template
82
3558ae 83 3. Open the `params/project-requests-ci-cd` and replace the `<YOUR_NAME or initials>` with your name to create the correstponding projects in the cluster. 
ff1bd7 84 ![new-item](../images/exercise1/ci-cd-project-namespace.png)
bc2e43 85
3558ae 86 3. Create another two params files for `params/project-requests-dev` & `params/project-requests-test` and add the `NAMESPACE=<YOUR_NAME>-dev` && `NAMESPACE=<YOUR_NAME>-test` and update their Display names.
bc2e43 87
D 88 3. In the `inventory/group_vars/all.yml` file; add the new inventory items for the projects you want to create (dev & test) by adding another object to the content array. You can copy and paste them from the `ci-cd` example and update them accordingly eg
89 ```yaml
ff1bd7 90     - name: <YOUR_NAME>-dev
D 91       template: "{{ inventory_dir }}/../templates/project-requests.yml"
92       template_action: create
93       params: "{{ inventory_dir }}/../params/project-requests-dev"
94       tags:
95       - projects
96     - name: <YOUR_NAME>-test
97       template: "{{ inventory_dir }}/../templates/project-requests.yml"
98       template_action: create
99       params: "{{ inventory_dir }}/../params/project-requests-test"
100       tags:
101       - projects
bc2e43 102 ```
ff1bd7 103 ![project-request-yaml](../images/exercise1/project-request-yml.png)
bc2e43 104
D 105 3. With the configuration in place; install the OpenShift Applier dependency
106 ```bash
107 $ ansible-galaxy install -r requirements.yml --roles-path=roles
108 ```
109
110 3. Apply the inventory by logging into OpenShift and then running 
111 ```bash
112 $ oc login -p <password> -u <user> <cluster_url>
3558ae 113 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml -i inventory/
bc2e43 114 ``` 
D 115
ff1bd7 116 3. Once successful you should see an output similar to this ![playbook-success](../images/exercise1/play-book-success.png)
bc2e43 117
D 118 ### Part 2 - Nexus and GitLab
3f16e0 119 > _Now that we have our Projects setup; we can start to populate them with Apps to be used in our dev lifecycle_
bc2e43 120
3558ae 121 4. In the `enablement-ci-cd` repo, checkout the templates for Nexus by running
3f16e0 122 ```bash
3558ae 123 $ git checkout exercise1/git-nexus templates/nexus.yml
D 124 ```
125 The tempate contains all the things needed to setup a persistent nexus server, exposing a service and route while also creating the persistent volume needed. Have a read through the template; at the bottom you'll see a collection of parameters we will pass to the template.
126
127 4. Add some parameters for running the template by creating a new file in the `params` directory. 
128 ```bash
129 $ touch params/nexus
3f16e0 130 ```
D 131
3558ae 132 4. The essential params to inclue in this file are: `params` directory. 
D 133 ```bash
134 VOLUME_CAPACITY=5Gi
135 MEMORY_LIMIT=2Gi
136 ```
137
de8ebb 138 4. Create a new object in the inventory variables called `ci-cd-deployments` and populate it's `content` is as follows remembering to swap `<YOUR_NAME>-ci-cd` for the namespace you created previously
3558ae 139 ```yaml
ff1bd7 140   - object: ci-cd-deployments
D 141     content:
142     - name: "nexus"
143       namespace: "<YOUR_NAME>-ci-cd"
144       template: "{{ inventory_dir }}/../templates/nexus.yml"
145       params: "{{ inventory_dir }}/../params/nexus"
146       tags:
147       - nexus
3558ae 148 ```
ff1bd7 149 ![ci-cd-deployments-yml](../images/exercise1/ci-cd-deployments-yml.png)
3558ae 150
D 151 4. Run the OpenShift applier, specifying the tag `nexus` to speed up it's execution.
152 ```bash
153 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
154      -i inventory/ \
ff1bd7 155      -e "filter_tags=nexus"
3558ae 156 ```
D 157
ff1bd7 158 4. Once successful; login to the cluster and navigate to the `<YOUR_NAME>-ci-cd`. You should see Nexus up and running. You can login with default credentials (admin / admin123) ![nexus-up-and-running](../images/exercise1/nexus-up-and-running.png)
3558ae 159
D 160 4. Now lets do the same thing for GitLab to get it up and running. Checkout the template provided by running
161 ```bash
162 $ git checkout exercise1/gitlab-nexus templates/gitlab.yml
163 ``` 
164 Explore the template; it contains the PVC, buildConfig and services. The DeploymentConfig is made up of these apps
165  - Redis (3.2.3)
166  - PostgreSQL (9.4)
167  - GitLab CE (v10.2.3)
168
169 4. Add a new params file in the `params` folder called `gitlab`
170 ```bash
171 $ touch params/gitlab
172 ```
173
174 4. Open the `params/gitlab` file and add the following params
175 ```
176 LDAP_BIND_DN=uid=<BIND_USER>,ou=People,dc=<YOUR_DOMAIN>,dc=com
177 LDAP_USER_FILTER=(memberof=CN=YourGroup,OU=Users,DC=<YOUR_DOMAIN>,DC=com)
178 LDAP_PASSWORD=<BIND_USER_PASSWORD>
179 LDAP_HOST=<LDAP_HOST>
180 LDAP_BASE=ou=People,dc=<YOUR_DOMAIN>,dc=com
181 LDAP_LABEL="<LDAP_DESCRIPTION>"
182 GITLAB_ROOT_PASSWORD=<GITLAB_ROOT_USER_PASSWORD>
183 GITLAB_DATA_VOL_SIZE=2Gi
184 POSTGRESQL_VOL_SIZE=1Gi
185 APPLICATION_HOSTNAME=<GITLAB_URL>
c41b51 186 NAMESPACE=<YOUR_NAME>-ci-cd
3558ae 187 ```
D 188 where the following need to be replaced by actual values:
189     * `<BIND_USER>` is the user used to query the LDAP
190     * `<BIND_USER_PASSWORD>` is the password used when querying the LDAP
191     * `<YOUR_DOMAIN>` is the domain the LDAP is hosted on
192     * `<LDAP_HOST>` is fqdn of the LDAP server
193     * `<LDAP_DESCRIPTION>` is the description to be used on the sign-in header for GitLab eg "Name LDAP Login"
194     * `<GITLAB_ROOT_USER_PASSWORD>` is the root user for GOD access on the GitLab instance eg password123
195     * `<GITLAB_URL>` is the endpoint for gitlab. It will take the form `gitlab-<YOUR_NAME>-ci-cd.apps.<ENV_ID>.<YOUR_DOMAIN>.com`
de8ebb 196 <p class="tip">
D 197 Note - some of the values here for the LDAP will be provided by your tutor.
198 </p>
3558ae 199
D 200 4. Create another object in the inventory `all_vars.yml` file to run the build & deploy of this template. Add the following and update the `namespace:` accordingly
201 ```yaml
ff1bd7 202     - name: "gitlab"
D 203       namespace: "<YOUR_NAME>-ci-cd"
204       template: "{{ inventory_dir }}/../templates/gitlab.yml"
205       params: "{{ inventory_dir }}/../params/gitlab"
206       tags:
207       - gitlab
3558ae 208 ```
D 209
210 4. Run the OpenShift applier, specifying the tag `gitlab` to speed up it's execution.
211 ```bash
212 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
213      -i inventory/ \
ff1bd7 214      -e "filter_tags=gitlab"
3558ae 215 ```
D 216
ff1bd7 217 4. Once successful; login to the cluster and navigate to the `<YOUR_NAME>-ci-cd`. You should see GitLab up and running. ![gitlab-up-and-running](../images/exercise1/gitlab-up-and-running.png)
c41b51 218
D 219 4. Navigate to gitlab. You can login with using your cluster credentials using the LDAP tab displaying your `<LDAP_DESCRIPTION>` from previous steps
220
ff1bd7 221 ![gitlab-ui](../images/exercise1/gitlab-ui.png)
c41b51 222
de8ebb 223 4. Once logged in create a new project called `enablement-ci-cd` and mark it as internal. Once created; copy out the `git remote add origin ...` instructions for use on the next step.
ff1bd7 224 ![gitlab-new-project](../images/exercise1/gitlab-new-project.png)
D 225 <p class="tip">
de8ebb 226 Note - we would not normally make the project under your name but create an group and add the project there on residency but for simplicity of the exercise we'll do that here
ff1bd7 227 </p>
D 228
229 4. Commit your local project to this new origin by first removing the existing origin (github) where the the project was cloned from. Remember to substitute `<YOUR_NEW_GIT_PROJECT>` accordingly
230 ```bash
231 $ git remote remove origin
232 $ git remote add origin <YOUR_NEW_GIT_PROJECT>
233 $ git add . 
234 $ git commit -m "Adding git and nexus config"
235 $ git push -u origin --all
236 ```
bc2e43 237
D 238 ### Part 3 - Jenkins & s2i
de8ebb 239 > _Create a build and deployment config for Jenkins. Add new configuration and plugins to the OCP Stock Jenkins using s2i_
D 240
ff1bd7 241 5. Add the Jenkins Build & Deployment configs to the `enablement-ci-cd` repo by merging the contents `exercise1/jenkins` in
D 242 ```bash
243 $ git checkout exercise1/jenkins templates/jenkins.yml
244 ```
bc2e43 245
ff1bd7 246 5. Add the Jenkins Build & Deployment configs to the `enablement-ci-cd` repo by merging the contents `exercise1/jenkins` in
D 247 ```bash
248 $ git checkout exercise1/jenkins templates/jenkins.yml
249 ```
250 The Jenkins template is essentially the standard persistent jenkins one with OpenShift.
251
252 5. As before; create a new set of params by creating a `params/jenkins` file and adding some overrides to the template and updating the `NAMESPACE` value.
253 ```bash
254 MEMORY_LIMIT=8Gi
255 VOLUME_CAPACITY=5Gi
256 JVM_ARCH=x86_64
257 NAMESPACE=<YOUR_NAME>-ci-cd
258 JENKINS_OPTS=--sessionTimeout=720
259 ```
260 5. Add a `jenkins` variable to the ansible inventory underneath the git and nexus ones. Remember to replace `<YOUR_NAME>` with the appropriate value.
261 ```yaml
262     - name: "jenkins"
263       namespace: "<YOUR_NAME>-ci-cd"
264       template: "{{ inventory_dir }}/../templates/jenkins.yml"
265       params: "{{ inventory_dir }}/../params/jenkins"
266       tags:
267       - jenkins
268 ```
269 This configuration if applied now; it will create the deployment configuration needed for Jenkins but the `${NAMESPACE}:${JENKINS_IMAGE_STREAM_TAG}` in the template won't exist yet.
270
271 5. To create this image we will take the supported OpenShift Jenkins Image and bake into it some extra configuration using an [s2i](https://github.com/openshift/source-to-image) builder image. More information on Jenkins s2i is found on the [openshift/jenkins](https://github.com/openshift/jenkins#installing-using-s2i-build) github page. To create an s2i configuration for jenkins, check out the pre-canned configuration source in the `enablement-ci-cd` repo
272 ```bash
273 $ git checkout exercise1/jenkins-s2i jenkins-s2i
274 ```
275 The structure of the jenkins s2i config is 
276 ```
277 jenkins-s2i
278 ├── README.md
279 ├── configuration
280 │   ├── build-failure-analyzer.xml
281 │   ├── init.groovy
282 │   ├── jenkins.plugins.slack.SlackNotifier.xml
283 │   └── jobs
284 │       └── seed-multibranch-job
285 │           └── config.xml
286 └── plugins.txt
287 ```
288  * `plugins.txt` is a list of `pluginId:version` for Jenkins to pre-install when starting
289  * `./configuration` contains content that is placed in `${JENKINS_HOME}`. A `config.xml` could be placed in here to control the bulk of Jenkins configuration.
290  * `./configuration/jobs/*` contains job names and xml config that jenkins loads when starting. The seed job in there we will return to in later lessons.
de8ebb 291  * `build-failure-analyzer.xml` is config for the plugin to read the logs and look for key items based on a Regex. More on this in later lessons.
ff1bd7 292  * `init.groovy` contains a collection of settings jenkins configures itself with when launching
D 293
294 5. Let's add a plugin for Jenkins to be started with, [green-balls](https://plugins.jenkins.io/greenballs). This simply changes the default `SUCCESS` status of Jenkins from Blue to Green. Append the `plugins.txt` file with 
295 ```txt
296 greenballs:1.15
297 ``` 
298 ![green-balls.png](../images/exercise1/green-balls.png)
299 Why does Jenkins have Blue Balls? More can be found [on reddit](https://www.reddit.com/r/programming/comments/4lu6q8/why_does_jenkins_have_blue_balls/) or the [jenkins blog](https://jenkins.io/blog/2012/03/13/why-does-jenkins-have-blue-balls/)
300
301 5. Before building and deploying Jenkins; add git credentials to the s2i by either adding them to the `template/jenkins.yml` and `params/jenkins` or for simplicity just replace the `<USERNAME>` && `<PASSWORD>` with your ldap credentials.
302 <p class="tip">
de8ebb 303 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, A service user would be created for this.
ff1bd7 304 </p>
D 305 ```groovy
306 gitUsername = System.getenv("GIT_USERNAME") ?: "<USERNAME>"
307 gitPassword = System.getenv("GIT_PASSWORD") ?: "<PASSWORD>"
308 ```
309
310 5. Add a new params file in the `params` folder called `jenkins-s2i`
311 ```bash
312 $ touch params/jenkins-s2i
313 ```
314
de8ebb 315 5. Open the `params/jenkins-s2i` file and add the following content; replacing variables as appropriate. 
ff1bd7 316 ```
D 317 SOURCE_REPOSITORY_URL=<YOUR_ENABLEMENT_REPO>
318 NAME=jenkins
319 SOURCE_REPOSITORY_CONTEXT_DIR=jenkins-s2i
320 IMAGE_STREAM_NAMESPACE=<YOUR_NAME>-ci-cd
de8ebb 321 SOURCE_REPOSITORY_USERNAME=<YOUR_LDAP_USERNAME>
D 322 SOURCE_REPOSITORY_PASSWORD=<YOUR_LDAP_PASSWORD>
ff1bd7 323 ```
D 324 where 
de8ebb 325     * `<YOUR_ENABLEMENT_REPO>` is the full path clone path of the repo where this project is stored (including the https && .git)
D 326     * `<YOUR_NAME>` is the prefix for your `-ci-cd` project.
327     * Explore some of the other parameters in `templates/jenkins-s2i.yml`
328     * `<YOUR_LDAP_USERNAME>` is the base64encoded username builder pod will use to login and clone the repo with
329     * `<YOUR_LDAP_PASSWORD>` is the base64encoded password the builder pod will use to authenticate and clone the repo using
330 You can use `echo -n '<YOUR_LDAP_PASSWORD>' | openssl base64` to encode your username and password accordingly.
331 <p class="tip">
332 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, A service user would be created for this.
333 </p>
ff1bd7 334
D 335 5. Create a new object `ci-cd-builds` in the ansible `all.yml` to drive the s2i build configuration.
336 ```yaml
337   - object: ci-cd-builds
338     content:
339     - name: "jenkins-s2i"
340       namespace: "<YOUR_NAME>-ci-cd"
341       template: "{{ inventory_dir }}/../templates/jenkins-s2i.yml"
342       params: "{{ inventory_dir }}/../params/jenkins-s2i"
343       tags:
344       - jenkins
345 ```
346
347 5. Commit your code to your GitLab instance
348 ```bash
de8ebb 349 $ git add .
ff1bd7 350 $ git commit -m "Adding Jenkins and Jenkins s2i"
D 351 $ git push
352 ```
353
354 5. When your code is commited; run the OpenShift Applier to add the config to the cluster
355 ```bash
356 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
357      -i inventory/ \
358      -e "filter_tags=jenkins"
359 ```
360
de8ebb 361 5. This will trigger a build of the s2i and when it's complete it will add an imagestream of `<YOUR_NAME>-ci-cd/jenkins:latest` to the project. The Deployment config should kick in and deploy the image once it arrives. You can follow the build of the s2i by going to the OpenShift console's project
D 362 ![jenkins-s2i-log](../images/exercise1/jenkins-s2i-log.png)
bc2e43 363
de8ebb 364 5. When the Jenkins deployment has completed; login (using your openshift credentials) and accept the role permissions. You should now see a fairly empty Jenkins with just the seed job
3558ae 365
de8ebb 366 ### Part 4 - Jenkins Hello World 
D 367 > _To test things are working end-to-end; create a hello world job that doesn't do much but proves we can pull code from git and that our balls are green._
368
369 6. Log in to Jenkins and hit `New Item` ![new-item](../images/exercise1/new-item.png).
370
371 6. Create a freesyle job called `hello-world` ![jenkins-new-hello-world](../images/exercise1/jenkins-new-hello-world.png).
372
373 6. On the Source Code Management tab; add your `enablement-ci-cd` git repo and hit the dropdown to add your credentials we baked into the s2i on previous steps`` ![jenkins-scm-git](../images/exercise1/jenkins-scm-git.png).
374
375 6. On the build tab add an Execute Shell step and fill it with `echo "Hello World"` ![jenkins-hello-world](../images/exercise1/jenkins-hello-world.png).
376
377 6. Run the build and we should see if pass succesfully and with Green Balls! ![jenkins-green-balls](../images/exercise1/jenkins-green-balls.png)
378
379 ### Part 5 - Live, Die, Repeat
380 > _TOOD - improve & flesh out this section ...._
381
382 7. Commit your code to the new repo in GitLab
383
384 7. Burn your OCP content to the ground
385
386 7. Re-apply the inventory!
c951f7 387
5d0992 388 _____
D 389
c951f7 390 ## Extension Tasks
de8ebb 391 > _Ideas for go-getters. Advanced topic for doers to get on with if they finish early. These will usually not have a solution and are provided for additional scope._
c951f7 392
3558ae 393  - Add more secure access for Nexus (ie not admin / admin123) using the automation to drive secret creation
ff1bd7 394  - Add a SonarQube persistent deployment to the `ci-cd-deployments` section.
D 395  - Add `jenkins.plugins.slack.SlackNotifier.xml` to `jenkins-s2i/configuration` to include URL of Slack for team build notifications and rebuild Jenkins S2I
c951f7 396
5d0992 397 _____
D 398
c951f7 399 ## Additional Reading
D 400  > List of links or other reading that might be of use / reference for the exercise