acammies
2018-04-11 dba30b92cfb560c7e6c51ae42ffe4c4e92ea0e99
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.
dba30b 20 * [OpenShift Applier](https://github.com/redhat-cop/openshift-applier) - used to apply OpenShift objects to an OpenShift Cluster.
A 21
22
c951f7 23
5d0992 24 ## Big Picture
D 25 This exercise begins with an empty Cluster
26 > TODO - add big picture here...
27
28 _____
c951f7 29
D 30 ## 10,000 Ft View
5d0992 31 > 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 32
33 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:
34
3b1c96 35 2. Clone the repo `https://github.com/rht-labs/enablement-ci-cd` which contains the scaffold of the project.
3558ae 36
5d0992 37 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 38
D 39 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 40     * Nexus
D 41     * GitLab
3558ae 42     * Jenkins (using an s2i to pre-configure jenkins)
D 43
5d0992 44 2. Commit your `enablement-ci-cd` repository to the GitLab Instance you've created
3558ae 45
D 46 2. Burn it all down and re-apply your inventory proving config-as-code works. 
c951f7 47
D 48 ## Step by Step Instructions
bc2e43 49 > This is a structured guide with references to exact filenames and explanations.
c951f7 50
bc2e43 51 ### Part 1 - Create OpenShift Projects
de8ebb 52 > _Using the OpenShift Applier, we will add new project namespaces to the cluster which will be used throughout the exercise._
D 53
e7c877 54 3. Clone the scaffold project to your local machine and pull all remote branches for use in later labs. Open the repo in your favourite editor.
bc2e43 55 ```bash
e7c877 56 $ git clone https://github.com/rht-labs/enablement-ci-cd && cd enablement-ci-cd
RH 57 ```
58 Followed by;
59 ```
60 $ for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
61    git branch --track ${branch#remotes/origin/} $branch
62 done
c951f7 63 ```
D 64
bc2e43 65 3. The project is laid out as follows
D 66 ```
67 .
68 ├── README.md
69 ├── docker
70 │   └── jenkins-slave-node
71 ├── inventory
72 │   ├── group_vars
73 │   │   └── all.yml
74 │   └── hosts
75 ├── jenkins-s2i
76 │   ├── configuration
77 ├── params
78 │   └── project-requests-ci-cd
79 ├── requirements.yml
80 └── templates
81         └── project-requests.yml
82 ```
83  * `docker` folder contains our jenkins-slave images that will be used by the builds.
84  * `jenkins-s2i` contains the configuration and plugins we want to bring jenkins to life with
85  * `params` houses the variables we will load the templates with
86  * `templates` is a collection of OpenShift templates
87  * `inventory/group_vars/all.yml` is the collection of objects we want to insert into the cluster.
88  * `requirements.yml` is a manifest which contains the ansible modules needed to run the playbook
f79b6f 89 Open the `inventory/group_vars/all.yml` file; you should see 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
bc2e43 90
3558ae 91 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 92 ![new-item](../images/exercise1/ci-cd-project-namespace.png)
bc2e43 93
e7c877 94 3. Create another two params files for `params/project-requests-dev` & `params/project-requests-test`. Add `NAMESPACE=<YOUR_NAME>-dev` & `NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Dev` to `params/project-requests-dev`. Add `NAMESPACE=<YOUR_NAME>-test` & `NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Test` to `params/project-requests-test`.
bc2e43 95
f79b6f 96 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 e.g.
bc2e43 97 ```yaml
ff1bd7 98     - name: <YOUR_NAME>-dev
D 99       template: "{{ inventory_dir }}/../templates/project-requests.yml"
100       template_action: create
101       params: "{{ inventory_dir }}/../params/project-requests-dev"
102       tags:
103       - projects
104     - name: <YOUR_NAME>-test
105       template: "{{ inventory_dir }}/../templates/project-requests.yml"
106       template_action: create
107       params: "{{ inventory_dir }}/../params/project-requests-test"
108       tags:
109       - projects
bc2e43 110 ```
ff1bd7 111 ![project-request-yaml](../images/exercise1/project-request-yml.png)
bc2e43 112
D 113 3. With the configuration in place; install the OpenShift Applier dependency
114 ```bash
115 $ ansible-galaxy install -r requirements.yml --roles-path=roles
116 ```
117
f79b6f 118 3. Apply the inventory by logging into OpenShift and running the following: 
bc2e43 119 ```bash
D 120 $ oc login -p <password> -u <user> <cluster_url>
3558ae 121 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml -i inventory/
bc2e43 122 ``` 
D 123
f79b6f 124 3. Once successful you should see an output similar to this: ![playbook-success](../images/exercise1/play-book-success.png)
bc2e43 125
D 126 ### Part 2 - Nexus and GitLab
3f16e0 127 > _Now that we have our Projects setup; we can start to populate them with Apps to be used in our dev lifecycle_
bc2e43 128
3558ae 129 4. In the `enablement-ci-cd` repo, checkout the templates for Nexus by running
3f16e0 130 ```bash
3558ae 131 $ git checkout exercise1/git-nexus templates/nexus.yml
D 132 ```
f79b6f 133 The template 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.
3558ae 134
D 135 4. Add some parameters for running the template by creating a new file in the `params` directory. 
136 ```bash
137 $ touch params/nexus
3f16e0 138 ```
D 139
3558ae 140 4. The essential params to inclue in this file are: `params` directory. 
D 141 ```bash
142 VOLUME_CAPACITY=5Gi
143 MEMORY_LIMIT=2Gi
144 ```
145
de8ebb 146 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 147 ```yaml
ff1bd7 148   - object: ci-cd-deployments
D 149     content:
150     - name: "nexus"
151       namespace: "<YOUR_NAME>-ci-cd"
152       template: "{{ inventory_dir }}/../templates/nexus.yml"
153       params: "{{ inventory_dir }}/../params/nexus"
154       tags:
155       - nexus
3558ae 156 ```
ff1bd7 157 ![ci-cd-deployments-yml](../images/exercise1/ci-cd-deployments-yml.png)
3558ae 158
D 159 4. Run the OpenShift applier, specifying the tag `nexus` to speed up it's execution.
160 ```bash
161 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
162      -i inventory/ \
ff1bd7 163      -e "filter_tags=nexus"
3558ae 164 ```
D 165
b47510 166 4. Once successful; login to the cluster through the browser (using cluster URL) 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 167
f79b6f 168 4. Now let's do the same thing for GitLab to get it up and running. Checkout the template and params provided by running
3558ae 169 ```bash
aa106a 170 $ git checkout exercise1/git-nexus templates/gitlab.yml params/gitlab
3558ae 171 ``` 
D 172 Explore the template; it contains the PVC, buildConfig and services. The DeploymentConfig is made up of these apps
173  - Redis (3.2.3)
174  - PostgreSQL (9.4)
175  - GitLab CE (v10.2.3)
176
b47510 177 4. Open the `params/gitlab` file and complete the following params
RH 178 <p class="tip">
179 Note - The values here for the LDAP and BIND credentials will be provided by your tutor.
180 </p>
3558ae 181 ```
D 182 LDAP_BIND_DN=uid=<BIND_USER>,ou=People,dc=<YOUR_DOMAIN>,dc=com
183 LDAP_USER_FILTER=(memberof=CN=YourGroup,OU=Users,DC=<YOUR_DOMAIN>,DC=com)
184 LDAP_PASSWORD=<BIND_USER_PASSWORD>
185 LDAP_HOST=<LDAP_HOST>
186 LDAP_BASE=ou=People,dc=<YOUR_DOMAIN>,dc=com
187 LDAP_LABEL="<LDAP_DESCRIPTION>"
188 GITLAB_ROOT_PASSWORD=<GITLAB_ROOT_USER_PASSWORD>
189 GITLAB_DATA_VOL_SIZE=2Gi
190 POSTGRESQL_VOL_SIZE=1Gi
191 APPLICATION_HOSTNAME=<GITLAB_URL>
c41b51 192 NAMESPACE=<YOUR_NAME>-ci-cd
3558ae 193 ```
D 194 where the following need to be replaced by actual values:
195     * `<BIND_USER>` is the user used to query the LDAP
196     * `<BIND_USER_PASSWORD>` is the password used when querying the LDAP
197     * `<YOUR_DOMAIN>` is the domain the LDAP is hosted on
198     * `<LDAP_HOST>` is fqdn of the LDAP server
199     * `<LDAP_DESCRIPTION>` is the description to be used on the sign-in header for GitLab eg "Name LDAP Login"
200     * `<GITLAB_ROOT_USER_PASSWORD>` is the root user for GOD access on the GitLab instance eg password123
201     * `<GITLAB_URL>` is the endpoint for gitlab. It will take the form `gitlab-<YOUR_NAME>-ci-cd.apps.<ENV_ID>.<YOUR_DOMAIN>.com`
202
203 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
204 ```yaml
ff1bd7 205     - name: "gitlab"
D 206       namespace: "<YOUR_NAME>-ci-cd"
207       template: "{{ inventory_dir }}/../templates/gitlab.yml"
208       params: "{{ inventory_dir }}/../params/gitlab"
209       tags:
210       - gitlab
3558ae 211 ```
D 212
213 4. Run the OpenShift applier, specifying the tag `gitlab` to speed up it's execution.
214 ```bash
215 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
216      -i inventory/ \
ff1bd7 217      -e "filter_tags=gitlab"
3558ae 218 ```
D 219
ff1bd7 220 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 221
aa106a 222 4. Navigate to gitlab. You can login using your cluster credentials using the LDAP tab displaying your `<LDAP_DESCRIPTION>` from previous steps
ff1bd7 223 ![gitlab-ui](../images/exercise1/gitlab-ui.png)
c41b51 224
de8ebb 225 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 226 ![gitlab-new-project](../images/exercise1/gitlab-new-project.png)
D 227 <p class="tip">
de8ebb 228 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 229 </p>
D 230
231 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
232 ```bash
06e3b4 233 $ git remote set-url origin <YOUR_NEW_GIT_PROJECT>
ff1bd7 234 $ git add . 
D 235 $ git commit -m "Adding git and nexus config"
236 $ git push -u origin --all
237 ```
06e3b4 238 **Note - When making changes to enablement-ci-cd you should frequently commit the changes to git.**
bc2e43 239
D 240 ### Part 3 - Jenkins & s2i
de8ebb 241 > _Create a build and deployment config for Jenkins. Add new configuration and plugins to the OCP Stock Jenkins using s2i_
bc2e43 242
ff1bd7 243 5. Add the Jenkins Build & Deployment configs to the `enablement-ci-cd` repo by merging the contents `exercise1/jenkins` in
D 244 ```bash
245 $ git checkout exercise1/jenkins templates/jenkins.yml
246 ```
247 The Jenkins template is essentially the standard persistent jenkins one with OpenShift.
248
249 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.
250 ```bash
251 MEMORY_LIMIT=8Gi
252 VOLUME_CAPACITY=5Gi
253 JVM_ARCH=x86_64
254 NAMESPACE=<YOUR_NAME>-ci-cd
255 JENKINS_OPTS=--sessionTimeout=720
256 ```
257 5. Add a `jenkins` variable to the ansible inventory underneath the git and nexus ones. Remember to replace `<YOUR_NAME>` with the appropriate value.
258 ```yaml
259     - name: "jenkins"
260       namespace: "<YOUR_NAME>-ci-cd"
261       template: "{{ inventory_dir }}/../templates/jenkins.yml"
262       params: "{{ inventory_dir }}/../params/jenkins"
263       tags:
264       - jenkins
265 ```
f79b6f 266 This configuration, if applied now, will create the deployment configuration needed for Jenkins but the `${NAMESPACE}:${JENKINS_IMAGE_STREAM_TAG}` in the template won't exist yet.
ff1bd7 267
D 268 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
269 ```bash
270 $ git checkout exercise1/jenkins-s2i jenkins-s2i
271 ```
272 The structure of the jenkins s2i config is 
273 ```
274 jenkins-s2i
275 ├── README.md
276 ├── configuration
277 │   ├── build-failure-analyzer.xml
278 │   ├── init.groovy
279 │   ├── jenkins.plugins.slack.SlackNotifier.xml
280 │   └── jobs
281 │       └── seed-multibranch-job
282 │           └── config.xml
283 └── plugins.txt
284 ```
285  * `plugins.txt` is a list of `pluginId:version` for Jenkins to pre-install when starting
286  * `./configuration` contains content that is placed in `${JENKINS_HOME}`. A `config.xml` could be placed in here to control the bulk of Jenkins configuration.
287  * `./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 288  * `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 289  * `init.groovy` contains a collection of settings jenkins configures itself with when launching
D 290
291 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 
292 ```txt
293 greenballs:1.15
294 ``` 
295 ![green-balls.png](../images/exercise1/green-balls.png)
296 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/)
297
06e3b4 298 5. Before building and deploying the Jenkins s2i; add git credentials to it. These will be used by Jenkins to access the Git Repositories where our apps will be stored. We want Jenkins to be able to push tags to it so write access is required. There are a few ways we can do this; either adding them to the `template/jenkins.yml` as environment Variables and then including them in the `params/jenkins` file.  We could also create a token in GitLab and use it as the source secret in the jenkins template. 
RH 299 But for simplicity just replace the `<USERNAME>` && `<PASSWORD>` in the `jenkins-s2i/configuration/init.groovy` with your ldap credentials as seen below. This init file gets run when Jenkins launches and will setup the credentials for use in our Jobs in the next exercises
ff1bd7 300 <p class="tip">
de8ebb 301 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 302 </p>
D 303 ```groovy
304 gitUsername = System.getenv("GIT_USERNAME") ?: "<USERNAME>"
305 gitPassword = System.getenv("GIT_PASSWORD") ?: "<PASSWORD>"
306 ```
307
de8ebb 308 5. Open the `params/jenkins-s2i` file and add the following content; replacing variables as appropriate. 
ff1bd7 309 ```
D 310 SOURCE_REPOSITORY_URL=<YOUR_ENABLEMENT_REPO>
311 NAME=jenkins
312 SOURCE_REPOSITORY_CONTEXT_DIR=jenkins-s2i
313 IMAGE_STREAM_NAMESPACE=<YOUR_NAME>-ci-cd
06e3b4 314 SOURCE_REPOSITORY_USERNAME=<BASE64_YOUR_LDAP_USERNAME>
RH 315 SOURCE_REPOSITORY_PASSWORD=<BASE64_YOUR_LDAP_PASSWORD>
ff1bd7 316 ```
D 317 where 
de8ebb 318     * `<YOUR_ENABLEMENT_REPO>` is the full path clone path of the repo where this project is stored (including the https && .git)
D 319     * `<YOUR_NAME>` is the prefix for your `-ci-cd` project.
320     * Explore some of the other parameters in `templates/jenkins-s2i.yml`
06e3b4 321     * `<BASE64_YOUR_LDAP_USERNAME>` is the base64encoded username builder pod will use to login and clone the repo with
RH 322     * `<BASE64_YOUR_LDAP_PASSWORD>` is the base64encoded password the builder pod will use to authenticate and clone the repo using
f79b6f 323 You can use `echo -n '<YOUR_LDAP_PASSWORD>' | openssl base64` to encode your username and password accordingly. For example 'password' base64 encoded will look like `cGFzc3dvcmQ=`.
de8ebb 324 <p class="tip">
D 325 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, A service user would be created for this.
326 </p>
ff1bd7 327
D 328 5. Create a new object `ci-cd-builds` in the ansible `all.yml` to drive the s2i build configuration.
329 ```yaml
330   - object: ci-cd-builds
331     content:
332     - name: "jenkins-s2i"
333       namespace: "<YOUR_NAME>-ci-cd"
334       template: "{{ inventory_dir }}/../templates/jenkins-s2i.yml"
335       params: "{{ inventory_dir }}/../params/jenkins-s2i"
336       tags:
337       - jenkins
338 ```
339
340 5. Commit your code to your GitLab instance
341 ```bash
de8ebb 342 $ git add .
ff1bd7 343 $ git commit -m "Adding Jenkins and Jenkins s2i"
D 344 $ git push
345 ```
346
347 5. When your code is commited; run the OpenShift Applier to add the config to the cluster
348 ```bash
349 $ ansible-playbook roles/openshift-applier/playbooks/openshift-cluster-seed.yml \
350      -i inventory/ \
351      -e "filter_tags=jenkins"
352 ```
353
de8ebb 354 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 355 ![jenkins-s2i-log](../images/exercise1/jenkins-s2i-log.png)
bc2e43 356
de8ebb 357 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 358
de8ebb 359 ### Part 4 - Jenkins Hello World 
D 360 > _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._
361
362 6. Log in to Jenkins and hit `New Item` ![new-item](../images/exercise1/new-item.png).
363
e90e9c 364 6. Create a freestyle job called `hello-world` ![jenkins-new-hello-world](../images/exercise1/jenkins-new-hello-world.png).
de8ebb 365
f79b6f 366 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)
de8ebb 367
D 368 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).
369
370 6. Run the build and we should see if pass succesfully and with Green Balls! ![jenkins-green-balls](../images/exercise1/jenkins-green-balls.png)
371
372 ### Part 5 - Live, Die, Repeat
373 > _TOOD - improve & flesh out this section ...._
374
375 7. Commit your code to the new repo in GitLab
376
377 7. Burn your OCP content to the ground
378
379 7. Re-apply the inventory!
c951f7 380
5d0992 381 _____
D 382
c951f7 383 ## Extension Tasks
de8ebb 384 > _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 385
3558ae 386  - Add more secure access for Nexus (ie not admin / admin123) using the automation to drive secret creation
ff1bd7 387  - Add a SonarQube persistent deployment to the `ci-cd-deployments` section.
D 388  - Add `jenkins.plugins.slack.SlackNotifier.xml` to `jenkins-s2i/configuration` to include URL of Slack for team build notifications and rebuild Jenkins S2I
c951f7 389
5d0992 390 _____
D 391
c951f7 392 ## Additional Reading
D 393  > List of links or other reading that might be of use / reference for the exercise