├── LICENSE ├── NOTICE ├── README.adoc ├── Spring-Cloud.adoc └── images ├── blue-green-process.png ├── blue-green.png ├── cities-ui.png ├── devops-cf.png └── welcome.png /LICENSE: -------------------------------------------------------------------------------- 1 | Redistribution and use in source and binary forms, with or without 2 | modification, are permitted provided that the following conditions are 3 | met: 4 | 5 | 1. Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 VMware, Inc. 2 | 3 | This product is licensed to you under the BSD 2 clause (the "License"). You may not use this product except in compliance with the License. 4 | 5 | This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = DevOps on Cloud Foundry Platform 2 | 3 | == Goals 4 | 5 | To deploy and configure a microservice and UI, leverage the platform for monitoring & management of the microservice, and do a blue green deployment with zero downtime. 6 | 7 | == Prerequisites 8 | 9 | . Java SDK 1.7+ 10 | . Git from link:https://mac.github.com/[github.com] 11 | . Cloud Foundry CLI from link:https://github.com/cloudfoundry/cli/releases[`CF CLI Releases`] 12 | . Curl from link:http://curl.haxx.se/[curl] 13 | . Pivotal Web Services Account. + 14 | Create a free trial account here link:http://run.pivotal.io/[`Pivotal Web Services`] 15 | . Optional: Install link:http://www.mysql.com/products/workbench/[MySQL Workbench] or other MySQL tool 16 | . Optional: Install link:https://golang.org/doc/install[Go Programming Language ] 17 | . Familiarity with link:http://www.spring.io[Spring IO] 18 | 19 | == Pre-work 20 | . FE has given a PCF deep dive to the workshop attendees link:https://drive.google.com/a/pivotal.io/file/d/0B_s5GpI2bqC9NjNDLUdUOFJKSjQ[Technical Deep Dive on Cloud Foundry] 21 | . Fork and Clone link:https://github.com/Pivotal-Field-Engineering/pcf-workspace-devops/[`PCF Workspace for DevOps`] 22 | . Review the link:https://github.com/Pivotal-Field-Engineering/pcf-workspace-devops/tree/master[ `cities`] application. 23 | 24 | == Steps 25 | In this workshop we are going to follow these steps to deploy apps on Cloud foundry and manage the lifecycle of the application. 26 | 27 | image:./images/devops-cf.png[DevOps on CF] 28 | 29 | 30 | [NOTE] 31 | The instructions in this document are for Mac/Linux based CLI/Shell. If you are using Windows, you can use link:http://docs.cloudfoundry.org/devguide/installcf/install-go-cli.html#windows[Windows CLI] 32 | or a Virtual Box / Vagrant with a link:./vagrant.adoc[Linux VM]. 33 | 34 | === Building apps 35 | To build the app go to the workspace folder 36 | 37 | [source,bash] 38 | ---- 39 | cd pcf-workspace-devops/cities 40 | ./gradlew clean 41 | ./gradlew build 42 | ---- 43 | 44 | 45 | == PART 1: Introduction to CF, Push an App. 46 | 47 | === Login to the Cloud Platform 48 | 49 | Use `cf help` and/or `cf --help` for details on each of the commands below. 50 | 51 | . Review the docs: http://docs.pivotal.io/pivotalcf/devguide/deploy-apps/deploy-app.html 52 | . Login to the Pivotal Cloud Foundry. 53 | + 54 | [source,bash] 55 | ---- 56 | // Assuming you are using PWS, your system domain is run.pivotal.io and Use the interactive prompts to login in. 57 | $ cf login -a https://api.run.pivotal.io 58 | ---- 59 | + 60 | . Alternatively, you can set the env varibles in the `env` file in `cities` folder and source the `env` file 61 | + 62 | [source,bash] 63 | ---- 64 | $nano env.sh 65 | 66 | export CF_SYSTEM_DOMAIN= //CF_SYSTEM_DOMAIN will look similar to run.pivotal.io 67 | export CF_APPS_DOMAIN= //CF_APPS_DOMAIN will look similar to cfapps.io 68 | export CF_USER= //CF_USER is the user account to sign into Pivotal Cloud Foundry, which is usually your email address. 69 | export CF_ORG= //CF_ORG is the name of the Organization within Pivotal Cloud Foundry where you want to deploy your applications. 70 | export CF_SPACE= //CF_SPACE is the name of the Space within the above Organization where you want your application deployed. 71 | ---- 72 | + 73 | [source,bash] 74 | ---- 75 | $ source ./env 76 | $ cf login -a https://api.$CF_SYSTEM_DOMAIN -u $CF_USER -o $CF_ORG -s $CF_SPACE 77 | ---- 78 | + 79 | [NOTE] 80 | add `--skip-ssl-validation` if you are pointing to CF installation which is using self signed certificates. 81 | 82 | + 83 | . Verify you are logged in with your own userid (*not admin*) and targeted to your PCF instance: 84 | + 85 | [source,bash] 86 | ---- 87 | $ cf target 88 | ---- 89 | 90 | === Push the app 91 | 92 | . Push the cities-hello + 93 | 94 | + 95 | [source,bash] 96 | ---- 97 | $ cd cities-hello 98 | $ cf push -cities-hello 99 | 100 | // This will give an output which is similar to this 101 | 102 | requested state: started 103 | instances: 1/1 104 | usage: 512M x 1 instances 105 | urls: cities-hello-lactiferous-unanswerableness.cfapps.io 106 | last uploaded: Mon Jun 15 14:53:10 UTC 2015 107 | stack: cflinuxfs2 108 | 109 | ---- 110 | + 111 | . Open the app url + 112 | When you push the apps, it will give the url route to the app. + 113 | image:./images/welcome.png[Welcome to PCF Workshop] + 114 | 115 | . Walk through the App Console and the Ops Manager 116 | 117 | 118 | === Recap: Part 1 119 | 120 | .Cloud Foundry Haiku 121 | [quote, Cloud Foundry] 122 | ____ 123 | Here is my source code + 124 | Run it on the cloud for me + 125 | I do not care how 126 | ____ 127 | 128 | === Discussion: Part 1 129 | 130 | [NOTE] 131 | ==== 132 | * How do you push an app to the cloud today? 133 | * How does the cloud platform understand which runtime to use to run the app? 134 | ==== 135 | 136 | 137 | == PART 2: Build, Push, Bind, Monitor and Scale an App. 138 | 139 | The cities-service app requires a database service to store and fetch cities info. 140 | 141 | 142 | === Create a Database Service from Marketplace 143 | 144 | . Review the docs on Services: 145 | + 146 | * link:http://docs.pivotal.io/pivotalcf/devguide/services/adding-a-service.html[Adding a Service] 147 | * link:http://docs.pivotal.io/pivotalcf/devguide/services/managing-services.html[Managing Services] 148 | + 149 | . Create a mysql service instance, name it as `-cities-db` 150 | You can create the service from the `cli` or launch the App Manager http://console.run.pivotal.io and login. 151 | Navigate to the marketplace and see the available services. Here you will create the service using the CLI. 152 | + 153 | [source,bash] 154 | ---- 155 | $ cf marketplace // check if cleardb mysql service is available 156 | $ cf create-service cleardb spark -cities-db 157 | ---- 158 | + 159 | 160 | . Launch the DB console via the `Manage` link in the App Manager. Note the database is empty. 161 | 162 | 163 | === Push the App 164 | 165 | . Do a cf push on cities-service. Notice that the push will fail. In the next step you can learn why. 166 | + 167 | [source,bash] 168 | ---- 169 | $ cf push -cities-service -i 1 -m 512M -p build/libs/cities-service-0.0.1-SNAPSHOT.jar 170 | ---- 171 | + 172 | . Check the logs to learn more about why the application is not starting 173 | + 174 | [source,bash] 175 | ---- 176 | $ cf logs -cities-service --recent 177 | ---- 178 | 179 | 180 | === Manually Binding the Service Instance 181 | 182 | . Review the docs on link:http://docs.pivotal.io/pivotalcf/devguide/services/bind-service.html[Binding a Service Instance] 183 | 184 | . Bind the mysql instance `-cities-db` to your app cities-service 185 | You can bind from the App Manager or from the `cli` 186 | + 187 | [source,bash] 188 | ---- 189 | $ cf bind-service -cities-service -cities-db 190 | ---- 191 | + 192 | 193 | . Restage your cities-service application to inject the new database. 194 | 195 | + 196 | [source,bash] 197 | ---- 198 | $ cf restage -cities-service 199 | ---- 200 | 201 | Notice that the application is now running. 202 | 203 | . Check the Env variables to see if the service is bound. 204 | You can do it from App Manager or from the `cli` 205 | + 206 | [source,bash] 207 | ---- 208 | $ cf env -cities-service 209 | ---- 210 | + 211 | . Check the MySQL database to see that it now contains data using MySQL Workbench or a similar tool. 212 | 213 | [NOTE] 214 | This app is an Spring Cloud app which uses Spring Cloud Configuration to bind to a database service provided by the cloud platform. 215 | For more information refer to link:Spring-Cloud.adoc[this document] on Spring Cloud configuration. 216 | 217 | 218 | 219 | === Binding Services via the Manifest 220 | 221 | Next, let's push the cities-service app with a manifest to help automate deployment. 222 | 223 | . Review the documentation: http://docs.pivotal.io/pivotalcf/devguide/deploy-apps/manifest.html 224 | . Edit the application manifest `manifest.service` in your `cities-service` 225 | + 226 | [source,bash] 227 | ---- 228 | $ nano manifest.service 229 | ---- 230 | + 231 | . Set the name of the app, the amount of memory, the number of instances, and the path to the .jar file. 232 | *Be sure to name your application '-cities-service' and use this as the host value.* 233 | . Add the services binding `-cities-db` to your deployment manifest for cities-service . 234 | . Now, manually unbind the service and re-push your app using the manifest. 235 | + 236 | [source,bash] 237 | ---- 238 | $ cf unbind-service -cities-service -cities-db 239 | ---- 240 | + 241 | . Test your manifest by re-pushing your app with no parameters: 242 | + 243 | [source,bash] 244 | ---- 245 | $ cf push -f manifest.service 246 | ---- 247 | Notice that using a manifest, you have moved the command line parameters (number of instances, memory, etc) into the manifest. 248 | . Verify you can access your application via a curl request: 249 | [source,bash] 250 | ---- 251 | $ curl -i http://-cities-service.cfapps.io 252 | ---- 253 | We must be able to access your application at https://-cities-service.cfapps.io for the next steps to work properly. 254 | 255 | [NOTE] 256 | The default manifest file for an app is `manifest.yml` and it if is present, it is automatically picked without specifying the manifest file option. 257 | In this exercise we have used a different naming convention. 258 | 259 | 260 | === Health, logging & events via the CLI 261 | 262 | Learning about how your application is performing is critical to help you diagnose and troubleshoot potential issues. Cloud Foundry gives you options for viewing the logs. 263 | 264 | To tail the logs of your application perform this command: 265 | [source,bash] 266 | ---- 267 | $ cf logs -cities-service 268 | ---- 269 | 270 | Notice that nothing is showing because there isn't any activity. Use the following curl command to see the application working: 271 | [source,bash] 272 | ---- 273 | $ curl -i http://-cities-service.cfapps.io/cities/ 274 | ---- 275 | 276 | For other ways of viewing logs check out the documentation here: link:http://docs.pivotal.io/pivotalcf/devguide/deploy-apps/streaming-logs.html#view[Streaming Logs] 277 | 278 | To view recent events, including application crashes, and error codes, you can see them from the App Manager or from the cli. 279 | [source,bash] 280 | ---- 281 | $ cf events -cities-service 282 | ---- 283 | 284 | To view the health of the application you can see from the App Manager or from the cli: 285 | [source,bash] 286 | ---- 287 | $ cf app -cities-service 288 | ---- 289 | You will get detailed output of the health 290 | [source,bash] 291 | ---- 292 | Showing health and status for app cities-service in org / space development as... 293 | OK 294 | 295 | requested state: started 296 | instances: 1/1 297 | usage: 512M x 1 instances 298 | urls: cities-service.cfapps.io 299 | last uploaded: Wed May 27 15:53:32 UTC 2015 300 | stack: cflinuxfs2 301 | 302 | state since cpu memory disk details 303 | #0 running 2015-05-27 12:17:55 PM 0.1% 434.5M of 512M 145.4M of 1G 304 | ---- 305 | 306 | === Environment variables 307 | 308 | View the environment variable and explanation of link:http://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#view-env[VCAP Env] 309 | 310 | [source,bash] 311 | ---- 312 | $ cf env -cities-service 313 | ---- 314 | 315 | You will get the output similar to this on your terminal 316 | [source,bash] 317 | ---- 318 | Getting env variables for app rj-cities-service in org Central / space development as rajesh.jain@pivotal.io... 319 | OK 320 | 321 | System-Provided: 322 | { 323 | "VCAP_SERVICES": { 324 | "cleardb": [ 325 | { 326 | "credentials": { 327 | "hostname": "xxxx", 328 | "jdbcUrl": "xxxx", 329 | "name": "xxxx", 330 | "password": "xxxx", 331 | "port": "3306", 332 | "uri": "mysql://xxxx?reconnect=true", 333 | "username": "xxxx" 334 | }, 335 | "label": "cleardb", 336 | "name": "rj-cities-db", 337 | "plan": "spark", 338 | "tags": [ 339 | "Data Stores", 340 | "Cloud Databases", 341 | "Developer Tools", 342 | "Data Store", 343 | "mysql", 344 | "relational" 345 | ] 346 | } 347 | ] 348 | } 349 | } 350 | 351 | { 352 | "VCAP_APPLICATION": { 353 | "application_name": "rj-cities-service", 354 | "application_uris": [ 355 | "rj-cities-service.cfapps.io" 356 | ], 357 | "application_version": "c3c35527-424f-4dbc-a4ea-115e1250cc5d", 358 | "limits": { 359 | "disk": 1024, 360 | "fds": 16384, 361 | "mem": 512 362 | }, 363 | "name": "rj-cities-service", 364 | "space_id": "56e1d8ef-e87f-4b1c-930b-e7f46c00e483", 365 | "space_name": "development", 366 | "uris": [ 367 | "rj-cities-service.cfapps.io" 368 | ], 369 | "users": null, 370 | "version": "c3c35527-424f-4dbc-a4ea-115e1250cc5d" 371 | } 372 | } 373 | 374 | User-Provided: 375 | SPRING_PROFILES_ACTIVE: cloud 376 | 377 | No running env variables have been set 378 | 379 | No staging env variables have been set 380 | ---- 381 | 382 | 383 | === Scaling apps 384 | 385 | Applications can be scaled via the command line or the console. When we talk about scale, there are two different types of scale: Vertical and Horizontal. Read link:http://docs.cloudfoundry.org/devguide/deploy-apps/cf-scale.html[this] doc on more details on scaling applications. 386 | 387 | When you vertically scale your application, you are increasing the amount of memory made available to your application. You would vertically scale your application while profiling your app, do performance tuning and to find the best memory settings before you deploy it in production. 388 | Scaling your application horizontally means that you are adding application instances to increase your application throughput and performance under load. 389 | 390 | Let's vertically scale the application to 1 GB of RAM. 391 | [source,bash] 392 | ---- 393 | $ cf scale -cities-service -m 1G 394 | ---- 395 | 396 | Now scale your application down to 512 MB. 397 | 398 | Next, let's scale up your application to 2 instances 399 | [source,bash] 400 | ---- 401 | $ cf scale -cities-service -i 2 402 | ---- 403 | 404 | To check the status of your applications you can check from the command line to see how many instances your app is running and their current state 405 | [source,bash] 406 | ---- 407 | $ cf app -cities-service 408 | ---- 409 | 410 | Once the second instance as started, scale the app back down to one instance. 411 | 412 | === Verify the app from the Console 413 | 414 | To verify that the application is running, use the following curl commands to retrieve data from the service or use a browser to access the URL: 415 | 416 | [source,bash] 417 | ---- 418 | $ curl -i http://-cities-service.cfapps.io/cities 419 | ---- 420 | 421 | [source,bash] 422 | ---- 423 | $ curl -i http://-cities-service.cfapps.io/cities/162 424 | ---- 425 | 426 | [source,bash] 427 | ---- 428 | $ curl -i http://-cities-service.cfapps.io/cities?size=5 429 | ---- 430 | 431 | === Discussion: Part 2 432 | In this part of the workshop we created a database service from the marketplace, pushed an app, bound it to the database service, monitored the health of the app and scaled the app. 433 | 434 | [NOTE] 435 | ==== 436 | * How does the app get the database info today vs. VCAP_SERVICES? 437 | * How do you horizontally scale your applications? 438 | ==== 439 | 440 | 441 | 442 | 443 | == PART 3: Deploying Upstream App and Bind to backend services 444 | 445 | The `cities` directory also includes a `cities-ui` application which uses the `cities-client` to consume from the `cities-service`. 446 | 447 | The `cities-client` demonstrates using the link:http://cloud.spring.io/spring-cloud-connectors[Spring Cloud Connector] project to consume from a microservice. This is a common pattern for 3rd platform apps. For more details on building 12 Factor Apps for the 3rd platform (Cloud Foundry) refer to link:http://12factor.net/[this] website. 448 | 449 | The goal of this exercise is to use what you have learned to deploy the `cities-ui` application. 450 | 451 | === Build the Cities UI and Cities Client App 452 | 453 | The cities-ui and cities-client can be both built at once by running `./gradlew assemble` in the parent +cities+ directory. Run this commmand now. 454 | 455 | 456 | === Create a User Provided Service Instance. 457 | In this section we will create a backend microservice end point for cities-service. 458 | 459 | * Review the documentation on link:http://docs.pivotal.io/pivotalcf/devguide/services/user-provided.html[User Provided Service Instances] 460 | * Look for the details by running `cf cups --help`. 461 | 462 | * You will need to specify two parameters when you create the service instance: `uri` and `tag` (see: CitiesWebServiceInfoCreator.java in the cities-client project). 463 | ** The `uri` should point to your deployed microservice 464 | ** The `tag` is a property specified in the CitiesWebServiceInfoCreator. Tags have a special meaning in CF: 465 | + 466 | _Tags provide a flexible mechanism to expose a classification, attribute, or base technology of a service, enabling equivalent services to be swapped out without changes to dependent logic in applications, buildpacks, or other services. Eg. mysql, relational, redis, key-value, caching, messaging, amqp. Tags also allow application configurations to be independent of a service instance name._ 467 | 468 | + 469 | * Refer to the CitiesWebServiceInfoCreator class for the necessary tag value. 470 | 471 | [source,bash] 472 | ---- 473 | // Use the interactive prompt to create user defined service 474 | // It will prompt you for the parameters 475 | 476 | $ cf create-user-provided-service -cities-ws -p "uri,tag" 477 | 478 | uri> http://-cities-service.cfapps.io/ 479 | tag> cities 480 | 481 | Creating user provided service.... 482 | ---- 483 | 484 | === Deploy cities-ui project 485 | 486 | A `manifest.yml` is included in the cities-ui app. Edit this manifest with your initials and add the service binding to your cities-service 487 | 488 | 489 | [source,bash] 490 | ---- 491 | --- 492 | applications: 493 | - name: -cities-ui 494 | memory: 512M 495 | instances: 1 496 | path: build/libs/cities-ui.jar 497 | services: [ -cities-ws ] 498 | env: 499 | SPRING_PROFILES_ACTIVE: cloud 500 | ---- 501 | 502 | Push the `cities-ui` without specifying the manifest.yml. It will by default pick the manifest.yml file and deploy the app. 503 | [source,bash] 504 | ---- 505 | $ cf push 506 | ---- 507 | 508 | Note the URL once the application has been successfully pushed. 509 | 510 | === Verify the backend service is bound to cities-ui 511 | 512 | [source,bash] 513 | ---- 514 | $ cf env -cities-ui 515 | 516 | System-Provided: 517 | { 518 | "VCAP_SERVICES": { 519 | "user-provided": [ 520 | { 521 | "credentials": { 522 | "tag": "cities", 523 | "uri": "http://rj-cities-service.cfapps.io/" 524 | }, 525 | "label": "user-provided", 526 | "name": "cities-ws", 527 | "syslog_drain_url": "", 528 | "tags": [] 529 | } 530 | ] 531 | } 532 | } 533 | 534 | { 535 | "VCAP_APPLICATION": { 536 | "application_name": "rj-cities-ui", 537 | "application_uris": [ 538 | "rj-cities-ui.cfapps.io" 539 | ], 540 | "application_version": "dceb111b-3a68-45ad-83fd-3b8b836ebbe7", 541 | "limits": { 542 | "disk": 1024, 543 | "fds": 16384, 544 | "mem": 512 545 | }, 546 | "name": "rj-cities-ui", 547 | "space_id": "56e1d8ef-e87f-4b1c-930b-e7f46c00e483", 548 | "space_name": "development", 549 | "uris": [ 550 | "rj-cities-ui.cfapps.io" 551 | ], 552 | "users": null, 553 | "version": "dceb111b-3a68-45ad-83fd-3b8b836ebbe7" 554 | } 555 | } 556 | 557 | User-Provided: 558 | SPRING_PROFILES_ACTIVE: cloud 559 | ---- 560 | 561 | === Access the cities-ui to verify it is connected to your microservice. 562 | Open the App Manager (Console) and navigate to your apps. You will see the cities-ui app, with a link to launch the cities-ui application. Alternatively you can open up your browser and navigate to the URL listed from a successful cf push command. 563 | 564 | image:./images/cities-ui.png[Cities UI] 565 | 566 | 567 | 568 | === Discussion: Part 3 569 | In this part of the workshop we created a cities-ui app which is loosely bound and independently developed from the backend service. We bound that app to the cities-service microservice. 570 | 571 | [NOTE] 572 | ==== 573 | * Discussion on loose coupling of your services from your app and 12 Factor App design principles. 574 | ==== 575 | 576 | 577 | == PART 4: Deploy Version 2 of the App 578 | 579 | In this section we are going to do a green-blue deployment using a shell script. The same can be done by executing the commands one at a time. 580 | 581 | === Delete the unversioned app and the route 582 | [source,bash] 583 | ---- 584 | cf delete -cities-ui 585 | cf delete-route cfapps.io -n -cities-ui 586 | ---- 587 | 588 | === Push Version 2 and Delete the Old Route using the script 589 | We are going to deploy the next version of the `cities-ui` app. The deployment typically is automated using a CD pipeline built with Jenkins or any CD automation tool, but in this workshop we will walk through a simple version number change in the deployment manifest. 590 | 591 | . Edit the `manifest.blue-green` with the following variables 592 | [source,bash] 593 | --- 594 | VERSION: CITIES_APP_1_0 595 | --- 596 | + 597 | . Edit and source the `env` file from the cities-ui folder with the following variables 598 | + 599 | [source,bash] 600 | --- 601 | export CF_SYSTEM_DOMAIN= //CF_SYSTEM_DOMAIN will look similar to run.pivotal.io 602 | export CF_APPS_DOMAIN= //CF_APPS_DOMAIN will look similar to cfapps.io 603 | export CF_USER= //CF_USER is the user account to sign into Pivotal Cloud Foundry, which is usually your email address. 604 | export CF_ORG= //CF_ORG is the name of the Organization within Pivotal Cloud Foundry where you want to deploy your applications. 605 | export CF_SPACE= //CF_SPACE is the name of the Space within the above Organization where you want your application deployed. 606 | export CF_APP=-cities-ui 607 | export CF_JAR=build/libs/cities-ui.jar 608 | export CF_MANIFEST=manifest.blue-green 609 | export BUILD_NUMBER=1001 610 | --- 611 | + 612 | Note: Be sure to change the CF_APP name to match your application and add the BUILD_NUMBER to the env file. Add the Version number in the manifest.blue-green 613 | + 614 | . First deploy the blue v1 of the app. 615 | + 616 | [source,bash] 617 | ---- 618 | // Push the new version of the app, with the version number and route 619 | $cf push "$CF_APP-$BUILD_NUMBER" -n "$CF_APP-$BUILD_NUMBER" -d $CF_APPS_DOMAIN -p $CF_JAR -f $CF_MANIFEST 620 | ---- 621 | 622 | . Next, increment the BUILD_NUMBER in the env file and source it. Change the VERSION number in the manifest.blue-green 623 | + 624 | [source,bash] 625 | ---- 626 | .... 627 | export BUILD_NUMBER=2001 628 | 629 | $nano manifest.yml 630 | .... 631 | VERSION: CITIES_APP_2_0 632 | ---- 633 | 634 | . Deploy the green v2 and delete the blue v1 of the app. 635 | + 636 | [source,bash] 637 | ---- 638 | // Push the new version of the app, with the version number and route 639 | $cf push "$CF_APP-$BUILD_NUMBER" -n "$CF_APP-$BUILD_NUMBER" -d $CF_APPS_DOMAIN -p $CF_JAR -f $CF_MANIFEST 640 | 641 | // Map the route to point to the new app 642 | $cf map-route "$CF_APP-${BUILD_NUMBER}" $CF_APPS_DOMAIN -n $CF_APP 643 | 644 | // Get the deployed version of the app 645 | $export DEPLOYED_VERSION=`cf apps | grep $CF_APP- | cut -d" " -f1` 646 | 647 | // Un-map an existing routes and delete the app / routes 648 | 649 | $cf unmap-route "$DEPLOYED_VERSION" $CF_APPS_DOMAIN -n $CF_APP 650 | $cf delete "$DEPLOYED_VERSION" -f 651 | $cf delete-route $CF_APPS_DOMAIN -n "$DEPLOYED_VERSION" -f 652 | 653 | ---- 654 | 655 | . Alternatively, use the bash script `blue-green.sh` in the cities-ui directory, deploy the green v2 and delete the blue v1 of the app. + 656 | If you are using the script make sure you increment the BUILD_NUMBER in the env file and change the VERSION number in the manifest.blue-green. 657 | 658 | + 659 | 660 | [source,bash] 661 | ---- 662 | $ cat blue-green.sh 663 | 664 | source env 665 | cf login -a https://api.$CF_SYSTEM_DOMAIN -u $CF_USER -o $CF_ORG -s $CF_SPACE --skip-ssl-validation 666 | 667 | DEPLOYED_VERSION_CMD=$(CF_COLOR=false cf apps | grep $CF_APP- | cut -d" " -f1) 668 | DEPLOYED_VERSION="$DEPLOYED_VERSION_CMD" 669 | ROUTE_VERSION=$(echo "${BUILD_NUMBER}" | cut -d"." -f1-3 | tr '.' '-') 670 | echo "Deployed Version: $DEPLOYED_VERSION" 671 | echo "Route Version: $ROUTE_VERSION" 672 | 673 | # push a new version and map the route 674 | cf push "$CF_APP-$BUILD_NUMBER" -n "$CF_APP-$ROUTE_VERSION" -d $CF_APPS_DOMAIN -p $CF_JAR -f $CF_MANIFEST 675 | cf map-route "$CF_APP-${BUILD_NUMBER}" $CF_APPS_DOMAIN -n $CF_APP 676 | 677 | if [ ! -z "$DEPLOYED_VERSION" -a "$DEPLOYED_VERSION" != " " -a "$DEPLOYED_VERSION" != "$CF_APP-${BUILD_NUMBER}" ]; then 678 | echo "Performing zero-downtime cutover to $BUILD_NUMBER" 679 | echo "$DEPLOYED_VERSION" | while read line 680 | do 681 | if [ ! -z "$line" -a "$line" != " " -a "$line" != "$CF_APP-${BUILD_NUMBER}" ]; then 682 | echo "Scaling down, unmapping and removing $line" 683 | # Unmap the route and delete 684 | cf unmap-route "$line" $CF_APPS_DOMAIN -n $CF_APP 685 | cf delete "$line" -f 686 | cf delete-route $CF_APPS_DOMAIN -n "$line" -f 687 | else 688 | echo "Skipping $line" 689 | fi 690 | done 691 | fi 692 | ---- 693 | 694 | === Verify the app, zero downtime 695 | [source,bash] 696 | ---- 697 | $cf apps | grep -i cities-ui 698 | rj-cities-ui-1001 started 1/1 512M 1G rj-cities-ui.cfapps.io, rj-cities-ui-5001.cfapps.io 699 | 700 | ---- 701 | 702 | [source,bash] 703 | ---- 704 | $cf routes | grep -i cities-ui 705 | 706 | development rj-cities-ui cfapps.io rj-cities-ui-2001 707 | development rj-cities-ui-1001 cfapps.io rj-cities-ui-2001 708 | 709 | ---- 710 | 711 | [source,bash] 712 | ---- 713 | 714 | $ curl -i http://-cities-ui.cfapps.io/cities/version 715 | 716 | HTTP/1.1 200 OK 717 | Content-Type: text/plain;charset=ISO-8859-1 718 | Date: Thu, 21 May 2015 02:22:29 GMT 719 | Server: Apache-Coyote/1.1 720 | X-Application-Context: rj-cities-ui-1001:cloud:0 721 | X-Cf-Requestid: d9fa0481-5cb4-47cd-6335-35adf575a0b6 722 | Content-Length: 4 723 | Connection: keep-alive 724 | 725 | CITIES_APP_2_0 726 | 727 | ---- 728 | === Repeat the Process 729 | Change the version (in the manifest) and build numbers (in the env file) and run the script to do blue-green deployment. Check the output using curl. 730 | 731 | 732 | === Process of Blue Green Deployment 733 | 734 | Review the CF Document for blue green deployment link:http://docs.cloudfoundry.org/devguide/deploy-apps/blue-green.html[Using Blue-Green Deployment to Reduce Downtime and Risk] 735 | 736 | In summary Blue-green deployment is a release technique that reduces downtime and risk by running two identical production environments called Blue and Green. 737 | image:./images/blue-green-process.png[Blue Green Deployment Process] 738 | 739 | 740 | === Newsworthy: Automated Blue Green with cf plugin 741 | Cloud Foundry plugin link:https://github.com/concourse/autopilot[Autopilot] does blue green deployment, albeit it takes a different approach to other zero-downtime plugins. It doesn't perform any complex route re-mappings instead it leans on the manifest feature of the Cloud Foundry CLI. The method also has the advantage of treating a manifest as the source of truth and will converge the state of the system towards that. This makes the plugin ideal for continuous delivery environments. 742 | 743 | [source,bash] 744 | ---- 745 | $ mkdir $HOME/go 746 | $ export GOPATH=$HOME/go 747 | $ export PATH=$PATH:$GOPATH/bin 748 | 749 | $ go get github.com/concourse/autopilot 750 | $ cf install-plugin $GOPATH/bin/autopilot 751 | $ cd cities-services 752 | // Increment the Build 753 | $ cf zero-downtime-push cities-services \ 754 | -f manifest.blue-green \ 755 | -p build/libs//cities-service-0.0.1-SNAPSHOT.jar 756 | 757 | ---- 758 | 759 | === Discussion: Part 4 760 | In this part of the workshop did deployment using a blue green script without any downtime. 761 | This script / methodology can be used in your CD pipeline to build and deploy Cloud Native Apps with zero downtime. 762 | 763 | [NOTE] 764 | ==== 765 | * Discussion on how do you do Continous Deployment and Delivery with zero downtime today. 766 | ==== 767 | 768 | 769 | == Recap 770 | 771 | In this workshop we saw how to build, deploy, bind, scale, monitor apps on Cloud foundry and manage the lifecycle of the application 772 | 773 | image:./images/devops-cf.png[DevOps on CF] 774 | 775 | 776 | == Q/A 777 | 778 | == Feedback 779 | Please provide your feedback using this form link:https://docs.google.com/a/pivotal.io/forms/d/1qWlLtTuoULomw9DAW0tuhn7YVWXwVILaMTNKfXkcq0s/viewform?usp=send_form[Feedback Form] 780 | -------------------------------------------------------------------------------- /Spring-Cloud.adoc: -------------------------------------------------------------------------------- 1 | The cities-service app using Spring Cloud Configuration to connect to the database. 2 | 3 | 4 | . Review link:http://docs.pivotal.io/pivotalcf/buildpacks/java/spring-service-bindings.html[Configuring Service Connections in Spring] 5 | 6 | . Notice the Spring Cloud and MySQL dependencies to our Gradle build file (build.gradle) 7 | 8 | + 9 | [source,groovy] 10 | ---- 11 | $cd cities-service 12 | $nano build.gradle 13 | 14 | ---- 15 | + 16 | 17 | + 18 | [source,groovy] 19 | ---- 20 | dependencies { 21 | // .... 22 | compile("org.springframework.cloud:spring-cloud-spring-service-connector:1.0.0.RELEASE") 23 | compile("org.springframework.cloud:spring-cloud-cloudfoundry-connector:1.0.0.RELEASE") 24 | runtime("mysql:mysql-connector-java:5.1.25") 25 | } 26 | ---- 27 | + 28 | . Review the Spring Cloud Config files (CloudDataSourceConfig.java and application.properties). 29 | + 30 | [source,bash] 31 | ---- 32 | $ nano src/main/java/org/example/cities/config/CloudDataSourceConfig.java 33 | ---- 34 | + 35 | 36 | .. The `@Profile` annotation will cause this class (which becomes Spring configuration when annotated as `@Configuration`) to be added to the configuration set because of the `SPRING_PROFILES_ACTIVE` environment variable (more on this later). You can still run the application locally (with the default profile) using the embedded database. 37 | .. With this code, Spring Cloud will detect a bound service that is compatible with +DataSource+, read the credentials, and then create a +DataSource+ as appropriate (it will throw an exception otherwise). 38 | + 39 | [source,java] 40 | ---- 41 | package org.example.cities.config; 42 | 43 | import javax.sql.DataSource; 44 | 45 | import org.springframework.cloud.config.java.AbstractCloudConfig; 46 | import org.springframework.context.annotation.Bean; 47 | import org.springframework.context.annotation.Configuration; 48 | import org.springframework.context.annotation.Profile; 49 | 50 | @Profile("cloud") 51 | @Configuration 52 | public class CloudDataSourceConfig extends AbstractCloudConfig { 53 | @Bean 54 | public DataSource dataSource() { 55 | return connectionFactory().dataSource(); 56 | } 57 | } 58 | ---- 59 | + 60 | .. The properties file at `src/main/resources/application.properties` will cause Hibernate to create the database schema and import data at startup. This is done automatically for embedded databases, not for custom ++DataSource++s. Other Hibernate native properties can be set in a similar fashion: 61 | + 62 | [source,java] 63 | ---- 64 | spring.jpa.hibernate.ddl-auto=create 65 | ---- 66 | + 67 | -------------------------------------------------------------------------------- /images/blue-green-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pcf-workshop-devops/fd82fc84f8d850b06f14cc44767c038ef64a8fa6/images/blue-green-process.png -------------------------------------------------------------------------------- /images/blue-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pcf-workshop-devops/fd82fc84f8d850b06f14cc44767c038ef64a8fa6/images/blue-green.png -------------------------------------------------------------------------------- /images/cities-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pcf-workshop-devops/fd82fc84f8d850b06f14cc44767c038ef64a8fa6/images/cities-ui.png -------------------------------------------------------------------------------- /images/devops-cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pcf-workshop-devops/fd82fc84f8d850b06f14cc44767c038ef64a8fa6/images/devops-cf.png -------------------------------------------------------------------------------- /images/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vmware-archive/pcf-workshop-devops/fd82fc84f8d850b06f14cc44767c038ef64a8fa6/images/welcome.png --------------------------------------------------------------------------------