Wednesday, February 28, 2018

CUPS & services


What is a service? Can you name some examples? 
  • A service is a PCF component (a resource reserved) to access on demand components. 
  • Examples
    • Database on a shared server. 
    • Access to a SaaS app. 

What is the “marketplace”? Does it show all services? 
  • Is a list of all service brokers
  • Cf marketplace will show all services. And 
  • Cf services will show all the services available inside a particular space. 

What is the difference between a managed and user-provided service? 
  • Managed services are services available in the marketplace. 
  • User provided service enable developers to create and use custom services. 

How would you create a managed service? 
  cf create-service SERVICE PLAN SERVICE_INSTANCE -c '{"name":"value","name":"value"}'
  cf create-service db-service silver mydb -c '{"ram_gb":4}'

How would you use a managed service? 
   cf bind-service APP_NAME SERVICE_INSTANCE -c '{"name":"value","name":"value"}'
      cf bind-service myapp mydb -c '{"permissions":"read-only"}'


How would you create a user-provided service? 
   cf create-user-provided-service SERVICE_INSTANCE [-p CREDENTIALS] [-l SYSLOG_DRAIN_URL] [-r ROUTE_SERVICE_URL]
  cf create-user-provided-service my-db-mine -p "username, password"

How would you use a user-provided service? 
  cf bind-service APP_NAME SERVICE_INSTANCE -c '{"name":"value","name":"value"}'

What is VCAPS_SERVICES? 
VCAP_SERVICES are environment variables that contain the details of bindable services that CF adde

Buildpack basics


What is a buildpack? 
Any application deployment will require softwares to be downloaded, container to be initialized and app to be deployed. A build pack is noting but the runtime and libraries on which the apps will be deployed. It defines how to run application - provide runtime support and framework for apps. 

A Java build pack for example takes care of the JRE and memory management, Container which the app should run on (tomcat, spring boot etc) and makes it easy for the developer to configure with the service. 

Why are they important?
provides runtime support and framework for applications. 
- examine your app artifacts, decides which build pack to use. 
  • Determines which dependencies to download.

Can you name some buildpacks? 
  • Go, Java, .net, Node.js, PHP, Python, Ruby, Staticfile. 

How does Cloud Foundry know which buildpack to run? 
  • Each build pack has a position in the priority list. If it is in 1 position and is compatible then it takes the 1st build pack, if not it goes on to second build pack and so on till the correct build pack. If no build pack found it says staging failed - no app detected error. 


How does a buildpack work? Are you aware of the scripts that run and how they might be written or modified? 
A build pack is in the form of a script, bash script. 
  • Detect script
    • Identifies which language this code and decides if it need to apply the build pack to an app. 
  • Supply script: 
    • Provides the dependencies for the app. 
    • Installing the runtime libraries 
      • Java: (JAR files, tomcat, sprint boot etc., 
      • Python (Puython2x, package manager, flask etc., )
  • Finalize script
    • prepares the app for launch. 
      • Handle and config params, 

  • Release script
    • Tell the cloud foundry platform how to start the application
    • Spits out a YML file which explains how to start. 
      • Tomcat - catalina.sh file. 

Config server - Basics


Cloud Config server: 
Its a way by which we can externalize the property values by moving out of the project. Primarily kept for properties that you normally override or keep secret values out of the project src. 

Motivation:
  • Externalize config data from the applications across all environments. 
  • Store crucial information such as password for DB in a centralized place. 
  • Share data between different services. 
  • See who changed which property and when and why. 

What should you do to use Spring cloud config
  1. Application configuration: 
    • Manage app configuration in a git hub or a local file system. 
  2. Config server
    • Point the location of GIT or local file system where the app config is located (i.e., GIT URI)
    • @EnableConfigServer
  3. Config client
    • Use it normally as how you would read from the properties file 
      • @Value or 

Features
  • Many storage options including Git, Subversion. 
  • Pull model
  • Traceability
  • @RefreshScope for allowing properties to refresh. Calls the constructor of the beans and reinitializes it. 
  • @ConfigurationProperties alternate for @RefreshScope which does reinitialize the Bean that is annotated with @ConfigurationProperties. 
  • Encrypt and decrypt property values. 

Usecases for Cloud config: 
  • Change log level in the properties. 
  • Environment config - containing passwords. 
  • Toggle a feature on or off. 
  • Using @RefreshScope
  • @ConfigurationProperties. 

Order in which the Cloud config looks into the properties files. 
  • Config server. 
  • Command line parameters
  • System properties.
  • Classpath: application.yml file
  • Classpath: bootstrap.yml

Things that you can try: 
  • Simple example to demonstrate properties in Git and reading from config server and client 
  • Using maven profiles specific properties in Config server in Github. 
  • Managing log levels in the Config server
  • Using @RefreshScope and @CofigurationProperties. 

Best practices: 
  • Config server communication with the Git hub, pull every time when client requests for properties file. Use a Jenkins job which will push the properties to a Config server properties (clone). 
  • Single repository for all teams, subdirectories for different environments. 
  • Source code maintenance, having branch per release vs always using the master. 
  • Managing encrypted values for secure data, using JWT with Config server.
  • Use Spring cloud bus to refresh all the services which listens to the rabbitmq.

Note: 
  • Store only things that need to be externalized, I.e., Resource bundles for internationalization should be at the project level. 

PCF Dev - Get started


PCF dev: lightweight version of PCF for local app development, It contains basic services such as mysql, reds etc., 

Requirements: Good memory, 8 GB, 16 GB preferred. 

Getting started with PCF dev: 
  • Installing the PCF dev environment: 
  • Starting PCF dev environment: 
cf dev start
  • Logging into pcfdev: 
cf login -a api.local.pcfdev.io --skip-ssl-validation
user/pass

Have fun with pcf dev in local :-)

Reference:

PCF Manifest file - reference


Manifest file is a way by which you can configure a pcf application without having to use much CLI commands every time you deploy an application. 

A sample manifest file for reference. The application name is mandatory. 

--applications: 
  • Name: myappname <name of the application>
Memory: 512M <Mmemory to allocate for this app M, MB, G, GB (upper or lower case)
Instances: 2 <no. Of instances> 
Buildpack: https://github.com/cloudfoundry/java-buildpack.git <buildpack url or local build pack name>
path: /dist/myapp.jar <location of your application artifact>
host: my-application
(or)
hosts: 
- my-application-1
- my application-2
(or)
no-hostname: true

Command: bundle exec rake VERBOSE=true <command to be executed during startup>
disk_quota: 1024M <disk quota to allocate> 
docker: 
image: dockerimage-repo/imagename <docker image name>
username: docker-user-name <user-name for the docker>
domain: abc.com <domain name>
(or)
domains:

random-route: true <do you want to use a random route to be generated dynamically>
(or)
routes:
- route: test1.abc.com
- route: test2.abc.com
(or)
route-path: test.abc.com
(or)
no-route: true <do you want the app to not have any route> 
stack: cflinuxfs2 <stack to be used>
timeout: 60 <timeout in seconds for starting the application> 
services: 
- mysql-db <name of the service to be bound>
- dvn-new-relic <name of the service to be bound>
env: <environment variables to be used >
APP_HEADER_NAME=Deivee APP
LOCATION=TEXAS
health-check-type: http <http | port | process>
health-check-http-endpoint: /performHealthcheck <custom url for CF to check health of app>

PCF Tasks basics


What is a task
A tasks is an app whose code is part of the deployed artifact, but runs independently in its own container.

Characteristics: 
  • Uses minimal resources. 
  • CF destroys the container once it has completed running. 
Sample tasks:
  • Migrating a database. 
  • Running a batch script. 
  • Process images
  • Upload or backup data. 
  • Send mail 

How can you run a task:

Cf run-task APPNAME “TASK”

Life cycle of a task
  • CF cli calls run-task
  • CC creates a container for the task
  • CF runs the task on the container
  • CF destroys the container. 

Listing all the tasks: 
Cf tasks <app-name>

Cancelling a task: 
Cf terminate-task <my-app> 2

Friday, February 23, 2018

Spring refresh: Custom Event listeners

You can also create your own listeners in Spring. For example whenever a new role is added to the system, you would want to publish a custom event and have a custom listener listent to this and say log them (or) send an email.

Steps to do this.
1. Create a custom event.
2. Create a custom  event listener handling that event.
3. Trigger (or) publish the event when something happens.


1. Create a custom event.
public class UserEvent extends ApplicationEvent {

    private AppRole appRole;

    public UserEvent(Object source, AppRole appRole) {
        super(source);
        this.appRole = appRole;
    }

    public AppRole getAppRole() {
        return appRole;
    }
}

2. Create a custom  event listener handling that event.
@Componentpublic class UserEventListener {
    Logger logger = Logger.getLogger(UserEventListener.class);

    @EventListener    public void handleAppRoleListener(UserEvent userEvent) {
        logger.info("User event listener: " + userEvent.getAppRole().getName());
    }
}

3. Trigger (or) publish the event when something happens.
@Autowiredprivate ApplicationEventPublisher applicationEventPublisher;

@Transactionalpublic AppRole save(@RequestBody AppRole appAppRole) {
    roleRepository.save(appAppRole);
    logger.info("App role info modified : " + appAppRole);    applicationEventPublisher.publishEvent(new UserEvent(this, appAppRole));    return appAppRole;
}


Thats it. Now whenever a new role is added, you will get a message in the console as below.
2018-02-24 01:11:54.375  INFO 51885 --- [nio-8080-exec-1] cs.trk.user.util.UserEventListener       : User event listener: User

2018-02-24 01:11:54.433  INFO 51885 --- [nio-8080-exec-1] cs.trk.user.util.AppListener             : -- Request Handled at : Sat Feb 24 01:11:54 CST 2018



Create a custom event :-)

Spring refresh: Standard Event Listeners


Spring has a easier way to handle context events. You just have to annotate a event handler method with @EventListener and accept the respect event class as the parameter. 

@Component
public class AppListener {

    Logger logger = Logger.getLogger(AppListener.class);

    @EventListener
    public void handleContextRefresh(ContextRefreshedEvent cfe) {
        logger.info("-- Context Refreshed at : " + new Date(cfe.getTimestamp()).toString());
    }

    @EventListener
    public void handleContextStarted(ContextStartedEvent cfe) {
        logger.info("-- Context Started at : " + new Date(cfe.getTimestamp()).toString());
    }
    @EventListener
    public void handleContextStop(ContextStoppedEvent cfe) {
        logger.info("-- Context Stopped at : " + new Date(cfe.getTimestamp()).toString());
    }
    @EventListener
    public void handleContextClose(ContextClosedEvent cfe) {
        logger.info("-- Context Closed at : " + new Date(cfe.getTimestamp()).toString());
    }
    @EventListener
    public void handleRequestHandle(RequestHandledEvent cfe) {
        logger.info("-- Request Handled at : " + new Date(cfe.getTimestamp()).toString());
    }

}


In the above code, context time events are logged in the console as and when it happens. 

For example. When the server is started or when you process the request, the following log appears. 
Context Close will be called while you shut down your application. 


-- Context Refreshed at : Sat Feb 24 00:57:14 CST 2018

Hibernate: insert into app_role (name, name_value) values (?, ?)
2018-02-24 01:01:05.465  INFO 50721 --- [nio-8080-exec-1] cs.trk.user.service.RoleService          : App role info modified : AppRole{id='20', name='User'}
2018-02-24 01:01:05.487  INFO 50721 --- [nio-8080-exec-1] cs.trk.user.config.AppListener           : -- Request Handled at : Sat Feb 24 01:01:05 CST 2018

2018-02-24 00:59:41.242  INFO 50425 --- [       Thread-4] cs.trk.user.config.AppListener           : -- Context Closed at : Sat Feb 24 00:59:41 CST 2018
2018-02-24 00:59:41.243  INFO 50425 --- [       Thread-4] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown


Saturday, February 17, 2018

PCF NFS file volume services


Volume services are available in the market place which can provide non-ephemeral storage as a service which apps can bind and store data into those external nfs mount. 

How to do this: 

Check your market place for Volume services. 
user-service $cf marketplace
Getting services from marketplace in org pcfdev-org / space pcfdev-space as admin...
OK

service        plans             description
local-volume   free-local-disk   Local service docs: https://github.com/cloudfoundry-incubator/local-volume-release/
p-mysql        512mb, 1gb        MySQL databases on demand
p-rabbitmq     standard          RabbitMQ is a robust and scalable high-performance multi-protocol messaging broker.
p-redis        shared-vm         Redis service to provide a key-value store

user-service $cf create-service local-volume free-local-disk usernfs -c '{"share": "10.10.10.10/export/myshare"}'
Creating service instance usernfs in org pcfdev-org / space pcfdev-space as admin...
OK

The share attribute forwards this information to the broker about the nfs server and share required for this service. 

user-service $cf bind-service userservice usernfs -c '{"uid":"1000", "gid":"1000", "mount":"var/volume1"}'
Binding service usernfs to app userservice in org pcfdev-org / space pcfdev-space as admin...
OK

Mount - mount volume to a particular path than the default path. 

Cf env will show you the following:
 "VCAP_SERVICES": {
  "local-volume": [
   {
    "credentials": {},
    "label": "local-volume",
    "name": "usernfs",
    "plan": "free-local-disk",
    "provider": null,
    "syslog_drain_url": null,
    "tags": [
     "local"
    ],
    "volume_mounts": [
     {
      "container_dir": "var/volume1",
      "device_type": "shared",
      "mode": "rw"
     }
    ]
   }
  ]

Mode is read or read and write. 
Device type supported is shared only, which can be used by multiple instances. 

You can ssh into the instance to check if the path has been mounted. 
user-service $cf ssh userservice
vcap@860ceeb4-08be-4611-4f73-7dd8bb405901:~$ l
vcap@860ceeb4-08be-4611-4f73-7dd8bb405901:/$ cd /var/volume1
vcap@860ceeb4-08be-4611-4f73-7dd8bb405901:/var/volume1$ 

Now you can write content to this mount path in your application. 


Log drain (log management service - Logit)


CF aggregates the logs from all the instances and make them available whenever you say cf logs <app name>
This displays logs from all the instances in the app. 

However this only shows the recent logs and if you want to view more logs, then you have to drain the logs to a log management services

Steps to stream logs to a log management service: 

1: Log service configuration. 
a. Go to the third party log service provider, signup. 
https://logit.io/
d. Get the syslog url provided by the third party service. 

2: Create a User provided service instance. 
a. create CUPS -l <syslog url>
$cf cups logit-ssl-drain -l syslog-tls://d0cde9b8-8275-41f8-bccf-af38173c62e7-ls.logit.io:21298

b. Bind the service instance to the app that needs logging. 
$cf bind-service userservice logit-ssl-drain

3: Verify the logs
Go to your service provider and view the logs. 



Managing service instances in PCF


We will look at how to we use the services available in the market place. 

Some basic commands: 
cf marketplace : list all services in the marketplace
cf services: list all service instances created. 

Creating and binding a service from marketplace. 
View list of all the services in the market place

/ $cf marketplace
Getting services from marketplace in org pcfdev-org / space pcfdev-space as user...
OK

service        plans             description
local-volume   free-local-disk   Local service docs: https://github.com/cloudfoundry-incubator/local-volume-release/
p-mysql        512mb, 1gb        MySQL databases on demand
p-rabbitmq     standard          RabbitMQ is a robust and scalable high-performance multi-protocol messaging broker.
p-redis        shared-vm         Redis service to provide a key-value store

Create a new service instance
/ $cf create-service p-mysql 512mb user-db
Creating service instance user-db in org pcfdev-org / space pcfdev-space as user...


/ $cf apps
Getting apps in org pcfdev-org / space pcfdev-space as user...
OK

name          requested state   instances   memory   disk   urls
userservice   started           2/2         512M     512M   userservice-dev.local.pcfdev.io
/ $cf services
Getting services in org pcfdev-org / space pcfdev-space as user...
OK

name      service   plan    bound apps   last operation
user-db   p-mysql   512mb                create succeeded


/ $cf bind-service userservice user-db
Binding service user-db to app userservice in org pcfdev-org / space pcfdev-space as user...
OK

Unbinding and deleting services
/ $cf services
Getting services in org pcfdev-org / space pcfdev-space as user...
OK

name      service   plan    bound apps    last operation
user-db   p-mysql   512mb   userservice   create succeeded

/ $cf unbind-service userservice user-db
Unbinding app userservice from service user-db in org pcfdev-org / space pcfdev-space as user...
OK
/ $cf delete-service user-db

Really delete the service user-db?> y
Deleting service user-db in org pcfdev-org / space pcfdev-space as user...
OK
/ $cf services
Getting services in org pcfdev-org / space pcfdev-space as user...
OK

No services found
/ $

list information about a specific service. 
Cf service user-db

You may not want to bind the service everytime you push an application. You can use the following entries to bind in the app manifest file. 

services:
  • user-db

Some services require to pass some json attributes while binding the services. 
 cf bind-service userservice user-db-c ‘{“ref-name”:”DeiveeService”, role=“Admin”}’

You can also send as a json file. 
Cf bind-service userservice user-db -c /tmp/configuration.json

Other commands 

cf rename-service user-db myuser-db
cf update-service user-db -p 1GB

Friday, February 16, 2018

SSH ing into PCF application and service instances


Developers normally dont have to SSH into the pcf application or services. they normally view logs using cf logs. However if you really have to ssh into instances to troubleshoot something, then here are the steps. 

First you should have access to SSH into the application. Typically this depends upon your role. you can use the following commands to enable or disable ssh. ssh access can be provided at the app level or space level. 

Please find the below basic commands for enabling or disabling ssh access. 


SSHing directly using CF command
cf enable-ssh <app name>
cf disable-ssh <app name>
cf allow-space-ssh <space name>
cf disallow-space-ssh <space name>
cf ssh-enabled userservice
cf space-ssh-allowed pcfdev-space


Now that you have access to SSH, we can see the following
1. SSH into applications
2. SSH into service instances (such as database services )

1. —— SSH ing into apps ——

There are 2 ways to SSH one using CF CLI and other not using CF CLI (basically other ways). 
Accessing SSH without CF CLI

cf ssh <app name> -I <instance number to login> (optional)

$ cf ssh userservice

vcap@6fe377f0-43cd-4631-641f-c87ac239069e:~$ ls
app  logs  staging_info.yml  tmp


Get the GUID of the application. 
$ cf app userservice --guid
355aa3f0-2d28-4c52-a537-980e9d02f97e

Get the environmental information. 
$ cf curl /v2/info
{
   "name": "pcfdev",
   "build": "037c3c92eaf4bcab911fb12f09b0cdd464c0a9b2",
   "support": "pcfdev@pivotal.io",
   "version": 0,
   "description": "",
   "authorization_endpoint": "https://login.local.pcfdev.io",
   "token_endpoint": "https://uaa.local.pcfdev.io",
   "min_cli_version": null,
   "min_recommended_cli_version": null,
   "api_version": "2.65.0",
   "app_ssh_endpoint": "ssh.local.pcfdev.io:2222",
   "app_ssh_host_key_fingerprint": "a6:d1:08:0b:b0:cb:9b:5f:c4:ba:44:2a:97:26:19:8a",
   "app_ssh_oauth_client": "ssh-proxy",
   "routing_endpoint": "https://api.local.pcfdev.io/routing",
   "logging_endpoint": "wss://loggregator.local.pcfdev.io:443",
   "doppler_logging_endpoint": "wss://doppler.local.pcfdev.io:443",
   "user": "89bbff6f-bda1-4efe-b38a-2cc6f020217b"
}

Get the ssh-code
$ cf ssh-code
DhqVXotyRA

SSH into the instance provide the guid, and serverinformation, also provide the ssh-code obtained as the password. 
$ ssh -p 2222 cf:355aa3f0-2d28-4c52-a537-980e9d02f97e/0@ssh.local.pcfdev.io
cf:355aa3f0-2d28-4c52-a537-980@ssh.local.pcfdev.io's password: 
vcap@6fe377f0-43cd-4631-641f-c87ac239069e:~$ 


Now that we know how to ssh into the application, we can have a look at ssh ing into the services. 
—— SSH ing into services ——

View the services
$ cf services
Getting services in org pcfdev-org / space pcfdev-space as user...
OK

name      service   plan    bound apps    last operation
user-db   p-mysql   512mb   userservice   create succeeded

Create a service key, mention the service instance id and a service key. 
$ cf create-service-key user-db EXTERNAL-ACCESS-KEY
Creating service key EXTERNAL-ACCESS-KEY for service instance user-db as user...
OK

Get the service details using the key. 
$ cf service-key user-db EXTERNAL-ACCESS-KEY
Getting key EXTERNAL-ACCESS-KEY for service instance user-db as user...

{
 "hostname": "mysql-broker.local.pcfdev.io",
 "jdbcUrl": "jdbc:mysql://mysql-broker.local.pcfdev.io:3306/cf_05a179d8_9b8f_470f_9b81_14e4b4877c8b?user=FfbDMZl571mskftA\u0026password=MyfJQwpcq82lyJfh",
 "name": "cf_05a179d8_9b8f_470f_9b81_14e4b4877c8b",
 "password": "MyfJQwpcq82lyJfh",
 "port": 3306,
 "uri": "mysql://FfbDMZl571mskftA:MyfJQwpcq82lyJfh@mysql-broker.local.pcfdev.io:3306/cf_05a179d8_9b8f_470f_9b81_14e4b4877c8b?reconnect=true",
 "username": "FfbDMZl571mskftA"
}

ssh into the service instance by providing the server details and the app name that it is bound to.
$ cf ssh -L 63306:mysql-broker.local.pcfdev.io:3306 userservice
vcap@6fe377f0-43cd-4631-641f-c87ac239069e:~$ ls
app  logs  staging_info.yml  tmp
vcap@6fe377f0-43cd-4631-641f-c87ac239069e:~$ 


Happy SSHing into your apps and services.

Friday, February 9, 2018

Using PCF Autoscaler


What is the PCF autoscaler? 
A PCF service which scales to multiple instances based on app usage in the environment. 

How would you use it? 
Attributes that determine autoscaling: 
  • CPU usage. 
  • Throughput
  • Latency

CPU Utilization
    • Average CPU percentage for all instances of the app. 

Throughput:
    • Total http requests per second (divided by total app instances). 
    • No. Of bytes of data that you can move in the network over a given amount of time. 
    • A fatter pipe or no. of lanes will help you move more people. 
      • Speed test: through put. 
        • Download: 50 MB
        • Upload: 20 MB

Latency:
    • Average latency of applications response to http requests. 
    • Does not include router processing or network latency. 
    • How long the smallest packet of data it takes to send from point A to point B. 

What can you configure? 
  • Set minimum and maximum instance limits.
  • Schedule these limits: reduce on weekends, scale up during peak holidays etc., 
  • Scaling rules:
    • CPU Utilization: 
      • Scale up or down depending upon CPU usage in percentage
    • HTTP throughput: 
      • Scale up or down when the http through put is less than or greater than __ requests per second. 
    • HTTP Latency: 
      • Scale up or down if latency is less than or greater than __ milliseconds. 


Autoscaling schedules
There is an option to specify min and max limits and schedule autoscale limits based on schedules. This allows you to select the date time and repeatable on specific weekdays.

Note:
  • If you manually scale an app, the autoscaler instance unbinds from that app and goes to manual setting.