copyright | lastupdated | ||
---|---|---|---|
|
2019-03-07 |
{:java: #java .ph data-hd-programlang='java'} {:swift: #swift .ph data-hd-programlang='swift'} {:ios: #ios data-hd-operatingsystem="ios"} {:android: #android data-hd-operatingsystem="android"} {:shortdesc: .shortdesc} {:new_window: target="_blank"} {:codeblock: .codeblock} {:screen: .screen} {:tip: .tip} {:pre: .pre}
{: #isolated-cloud-foundry-enterprise-apps}
With {{site.data.keyword.cfee_full_notm}} (CFEE) you can create multiple, isolated, enterprise-grade Cloud Foundry platforms on demand. With this, you get a private Cloud Foundry instance deployed on an isolated Kubernetes cluster. Unlike the public Cloud, you'll have full control over the environment: access control, capacity, version, resource usage, and monitoring. {{site.data.keyword.cfee_full_notm}} provides the speed and innovation of a platform-as-a-service with the infrastructure ownership found in enterprise IT.
A use case for {{site.data.keyword.cfee_full_notm}} is an enterprise-owned innovation platform. You as a developer within an enterprise can either create new microservices or migrate legacy applications to CFEE. Microservices can then be published to additional developers using the Cloud Foundry marketplace. Once there, other developers in your CFEE instance can consume services within the application just as is done today on public Cloud.
The tutorial will walk you through the process of creating and configuring an {{site.data.keyword.cfee_full_notm}}, setting up access control, and deploying apps and services. You'll also review the relationship between CFEE and {{site.data.keyword.containershort_notm}} by deploying a custom service broker that integrates custom services with CFEE.
{: #objectives}
- Compare and contrast CFEE with public Cloud Foundry
- Deploy apps and services within CFEE
- Understand the relationship between Cloud Foundry and {{site.data.keyword.containershort_notm}}
- Investigate basic Cloud Foundry and {{site.data.keyword.containershort_notm}} networking
{: #services}
This tutorial uses the following runtimes and services:
This tutorial may incur costs. Use the Pricing Calculator to generate a cost estimate based on your projected usage.
{: #architecture}
- Admin creates a CFEE instance, and adds users with developer access.
- Developer pushes a Node.js starter app to CFEE.
- Node.js starter app uses {{site.data.keyword.cloudant_short_notm}} to store data.
- Developer adds a new "welcome message" service.
- Node.js starter app binds the new service from a custom service broker.
- Node.js starter app displays "welcome" in different languages from the service.
{: #prereq}
{:provision_cfee}
In this section, you'll create an instance of {{site.data.keyword.cfee_full_notm}} deployed to Kubernetes worker nodes from {{site.data.keyword.containershort_notm}}.
- Prepare your {{site.data.keyword.cloud_notm}} account to ensure the creation of required infrastructure resources.
- From the {{site.data.keyword.cloud_notm}} catalog, create a service instance of {{site.data.keyword.cfee_full_notm}} .
- Configure CFEE by providing the following:
- Select the Standard plan.
- Enter a Name for the service instance.
- Select a Resource group in which the environment is created. You'll need permission to access at least one resource group in the account to be able to create a CFEE instance.
- Select a Geography and Location where the instance is deployed. See the list of available provisioning locations and data centers.
- Select a public Cloud Foundry Organization and Space where {{site.data.keyword.composeForPostgreSQL}} will be deployed.
- Select the Number of cells for the Cloud Foundry environment. A cell runs Diego and Cloud Foundry applications. At least 2 cells are required for highly available applications.
- Select the Machine type, which determines the size of the Cloud Foundry cells (CPU and memory).
- Review the Infrastructure section to view the properties of the Kubernetes cluster supporting CFEE. The Number of worker nodes equals the number of cells plus 2. Two of the provisioned Kubernetes worker nodes act as the CFEE control plane. The Kubernetes cluster on which the environment is deployed will appear in the {{site.data.keyword.cloud_notm}} Clusters dashboard.
- Click the Create button to begin automated deployment.
The automated deployment takes approximately 90 to 120 minutes. Once successfully created, you'll receive an email confirming the provisioning of CFEE and supporting services.
After you've created {{site.data.keyword.cfee_full_notm}}, see creating organizations and spaces for information on how to structure the environment through organizations and spaces. Apps in an {{site.data.keyword.cfee_full_notm}} are scoped within specific spaces. Similarly, a space exists within an organization. Members of an organization share a quota plan, apps, services instances, and custom domains.
Note: The Manage > Account > Cloud Foundry orgs menu located in the top {{site.data.keyword.cloud_notm}} header is intended exclusively for public {{site.data.keyword.cloud_notm}} organizations. CFEE organizations are managed within the organizations page of a CFEE instance.
Follow the steps below to create a CFEE org and space.
- From the Cloud Foundry dashboard select Environments under Enterprise.
- Select your CFEE instance and then select Organizations.
- Click on the Create Organizations button, provide a
tutorial
as the Organization Name, and select a Quota Plan. Finish by clicking Add. - Click on the newly created organization
tutorial
, and then select the Spaces tab, and click the Create Space button. - Provide
dev
as a Space Name and click Add.
In CFEE, you can assign roles controlling user access, but to do so, the user must be invited to your {{site.data.keyword.cloud_notm}} account in the Identity & Access page under the Manage > Users in the {{site.data.keyword.cloud_notm}} header.
Once the user has been invited, follow the steps below to add the user to the tutorial
organization created,
- Select your CFEE instance and then select Organizations again.
- Select the
tutorial
org created from the list. - Click on the Members tab to view and add a new user.
- Click on the Add members button, search for the username, select the appropriate Organization Roles, and click Add.
More on adding users to CFEE orgs and spaces can be found here.
{:deploycfeeapps}
In this section, you'll deploy a Node.js application to CFEE. Once deployed, you'll then bind an {{site.data.keyword.cloudant_short_notm}} to it and enable auditing and logging persistence. The Stratos console will also be added to manage the application.
- From your terminal, clone the get-started-node sample application.
{: codeblock}
git clone https://github.com/IBM-Cloud/get-started-node
- Run the app locally to ensure it builds and starts correctly. Confirm by accessing
http://localhost:3000/
in your browser.{: codeblock}cd get-started-node npm install npm start
- Log in to {{site.data.keyword.cloud_notm}} and target your CFEE instance. An interactive prompt will help you select your new CFEE instance. Since only one CFEE organization and space exist, these will be the defaulted target. You can run
ibmcloud target -o tutorial -s dev
if you've added more than one org or space.{: codeblock}ibmcloud login ibmcloud target --cf
- Push the get-started-node app to CFEE.
{: codeblock}
ibmcloud cf push
- The endpoint of your app will display in the final output next to the
routes
property. Open the URL in your browser to confirm the application is running.
To bind {{site.data.keyword.cloud_notm}} services to the get-started-node application, you'll first need to create a service in your {{site.data.keyword.cloud_notm}} account.
- Create an {{site.data.keyword.cloudant_short_notm}} service. Provide the service name
cfee-cloudant
and choose the same location where the CFEE instance has been created. - Add the newly created {{site.data.keyword.cloudant_short_notm}} service instance to CFEE.
- Navigate back to the
tutorial
Organization. Click the Spaces tab and select thedev
space. - Select the Services tab and click the Add Service button.
- Type
cfee-cloudant
in the search textbox and select the result. Finish by clicking Add. The service is now available to CFEE applications; however, it still resides in public {{site.data.keyword.cloud_notm}}.
- Navigate back to the
- On the overflow menu of the service instance shown, select Bind to application.
- Select the GetStartedNode application you pushed earlier and click Restage application after binding. Finally, click the Bind button. Wait for the application to restage. You can check progress with the command
ibmcloud app show GetStartedNode
. - In your browser, access the application, add your name and hit
enter
. Your name will be added to a {{site.data.keyword.cloudant_short_notm}} database. - Confirm by selecting the
tutorial
instance from the list on the Services tab. This will open the service instance's details page in public {{site.data.keyword.cloud_notm}}. - Click Launch Cloudant Dashboard and select the
mydb
database. A JSON document with your name should exist.
Auditing allows CFEE administrators to track Cloud Foundry activities such as login, creation of organizations and spaces, user membership and role assignments, application deployments, service bindings, and domain configuration. Auditing is supported through integration with the {{site.data.keyword.cloudaccesstrailshort}} service.
Cloud Foundry application logs can be stored by integrating {{site.data.keyword.loganalysisshort_notm}}. The {{site.data.keyword.loganalysisshort_notm}} service instance selected by a CFEE administrator is configured automatically to receive and persist Cloud Foundry logging events generated from the CFEE instance.
To enable CFEE auditing and logging persistence follow the steps here.
Stratos Console is an open source web-based tool for working with Cloud Foundry. The Stratos Console application can be optionally installed and used in a specific CFEE environment to manage organizations, spaces, and applications.
To install the Stratos Console application:
- Open the CFEE instance where you want to install the Stratos console.
- On the Overview page, click Install Stratos Console. The button is visible only to users with administrator or editor permissions.
- In the Install Stratos Console dialog, select an installation option. You can install the Stratos console application either on the CFEE control plane or in one of the cells. Select a version of the Stratos console and the number of instances of the application to install. If you install the Stratos console app in a cell, you're prompted for the organization and space where to deploy the application.
- Click Install.
The application takes about 5 minutes to install. Once the installation is complete, a Stratos Console button appears in place of the Install Stratos Console button on the overview page. More on Stratos console can be found here.
As an application platform, CFEE runs on some form of dedicated or shared virtual infrastructure. For many years, developers thought little about the underlying Cloud Foundry platform because IBM managed it for them. With CFEE, you are not only a developer writing Cloud Foundry applications but also an operator of the Cloud Foundry platform. This is because CFEE is deployed on a Kubernetes cluster that you control.
While Cloud Foundry developers may be new to Kubernetes, there are many concepts they both share. Like Cloud Foundry, Kubernetes isolates applications into containers, which run inside a Kubernetes construct called a pod. Similar to application instances, pods can have multiple copies (called replica sets) with application load balancing provided by Kubernetes. The Cloud Foundry GetStartedNode
application you deployed earlier runs inside the diego-cell-0
pod. To support high availability, another pod diego-cell-1
would run on a separate Kubernetes worker node. Because these Cloud Foundry apps run "inside" Kubernetes, you can also communicate with other Kubernetes microservices using Kubernetes-based networking. The following sections will help illustrate the relationships between CFEE and Kubernetes in more detail.
In this section, you'll deploy a microservice to Kubernetes that acts as a service broker for CFEE. Service brokers provide details on available services as well as binding and provisioning support to your Cloud Foundry application. You used a built-in {{site.data.keyword.cloud_notm}} service broker to add the {{site.data.keyword.cloudant_short_notm}} service. Now you'll deploy and use a custom one. You will then modify the GetStartedNode
app to use the service broker, which will return a "Welcome" message in several languages.
-
Back in your terminal, clone the projects that provide Kubernetes deployment files and the service broker implementation.
git clone https://github.com/IBM-Cloud/cfee-service-broker-kubernetes.git
{: codeblock}
cd cfee-service-broker-kubernetes
{: codeblock}
git clone https://github.com/IBM/sample-resource-service-brokers.git
{: codeblock}
-
Build and store the Docker image that contains the service broker on {{site.data.keyword.registryshort_notm}}. Use the
ibmcloud cr info
command to manually retrieve the registry URL or automatically with theexport REGISTRY
command below. Thecr namespace-add
command will create a namespace to store the docker image.export REGISTRY=$(ibmcloud cr info | head -2 | awk '{ print $3 }')
{: codeblock}
Create a namespace called
cfee-tutorial
.ibmcloud cr namespace-add cfee-tutorial
{: codeblock}
ibmcloud cr build . -t $REGISTRY/cfee-tutorial/service-broker-impl
{: codeblock}
Edit
./cfee-service-broker-kubernetes/deployment.yml
file. Update theimage
attribute to reflect your container registry URL. -
Deploy the container image to CFEE's Kubernetes cluster. Your CFEE's cluster exists in the
default
resource group, which should be targeted if not already. Using your cluster's name, export the KUBECONFIG variable using thecluster-config
command. Then create the deployment.ibmcloud target -g default
{: codeblock}
ibmcloud ks clusters
{: codeblock}
$(ibmcloud ks cluster-config <your-cfee-cluster-name> --export)
{: codeblock}
kubectl apply -f deployment.yml
{: codeblock}
-
Verify the pods have STATUS as
Running
. It may take a few moments for Kubernetes to pull the image and start the containers. Notice that you have two pods because thedeployment.yml
has requested 2replicas
.kubectl get pods
{: codeblock}
Now that you've deployed the service broker, confirm it functions properly. You'll do this in several ways: first by using the Kubernetes dashboard, then by accessing the broker from a Cloud Foundry app and finally by actually binding a service from the broker.
This section will confirm that Kubernetes artifacts are configured using {{site.data.keyword.containershort_notm}} dashboard.
- From the Kubernetes Clusters page, access your CFEE cluster by clicking the row item beginning with your CFEE service's name and ending with -cluster.
- Open the Kubernetes Dashboard by clicking the corresponding button.
- Click the Services link from the left menu and select tutorial-broker-service. This service was deployed when you ran
kubectl apply
in earlier steps. - In the resulting dashboard, notice the following:
- The service has been provided an overlay IP address (172.x.x.x) that is resolvable only within the Kubernetes cluster.
- The service has two endpoints, which correspond to the two pods that have the service broker containers running.
Having confirmed that the service is available and is proxying the service broker pods, you can verify the broker responds with information about available services.
You can view Cloud Foundry related artifacts from the Kubernetes dashboard. To see them, click on Namespaces to view all namespaces with artifacts including the cf
Cloud Foundry namespace.
{: tip}
To demonstrate Cloud Foundry to Kubernetes communication, you'll connect to the service broker directly from a Cloud Foundry application.
-
Back in your terminal, confirm you are still connected to your CFEE
tutorial
organization anddev
space usingibmcloud target
. If needed, re-target CFEE.ibmcloud target --cf
{: codeblock}
-
By default, SSH is disabled in spaces. This is different than the public cloud, so enable SSH in your CFEE
dev
space.ibmcloud cf allow-space-ssh dev
{: codeblock}
-
Use the
kubectl
command to show the same ClusterIP you saw in the Kubenetes dashboard. Then SSH into theGetStartedNode
application and retrieve data from the service broker using the IP address. Be aware the last command may result in an error, which the next step will resolve.kubectl get service tutorial-broker-service
{: codeblock}
ibmcloud cf ssh GetStartedNode
{: codeblock}
export CLUSTER_IP=<CLUSTER-IP address>
{: codeblock}
wget --user TestServiceBrokerUser --password TestServiceBrokerPassword -O- http://$CLUSTER_IP/v2/catalog
{: codeblock}
-
It's likely that you received a Connection refused error. This is due to CFEE's default application security groups. An application security group (ASG) defines the allowable IP range for egress traffic from a Cloud Foundry container. Since the
GetStartedNode
exists outside the default range, the error occurs. Exit the SSH session and download thepublic_networks
ASG.exit
{: codeblock}
ibmcloud cf security-group public_networks > public_networks.json
{: codeblock}
-
Edit the
public_networks.json
file, and verify that the ClusterIP address being used falls outside of the existing rules. For example, the range172.32.0.0-192.167.255.255
likely does not include the ClusterIP and needs to be updated. If for example, your ClusterIP address is something like this172.21.107.63
then you would need to edit to the file to have something like this172.0.0.0-255.255.255.255
. -
Adjust the ASG
destination
rule to include the IP address of the Kubernetes service. Trim the file to include only the JSON data, which begins and ends with the brackets. Then upload the new ASG.ibmcloud cf update-security-group public_networks public_networks.json
{: codeblock}
ibmcloud cf restart GetStartedNode
{: codeblock}
-
Repeat step 3, which should now succeed with mock catalog data. Finsh by exiting the SSH session.
exit
{: codeblock}
To allow developers to provision and bind services from the service broker, you'll register it with CFEE. Previously you've worked with the broker using an IP address. This is problematic though. If the service broker restarts, it receives a new IP address, which requires updating CFEE. To address this problem, you'll use another Kubernetes feature called KubeDNS that provides a Fully Qualified Domain Name (FQDN) to the service broker.
- Register the service broker with CFEE using the FQDN of the
tutorial-service-broker
service. Again, this route is internal to your CFEE Kubernetes cluster.{: codeblock}ibmcloud cf create-service-broker my-company-broker TestServiceBrokerUser TestServiceBrokerPassword http://tutorial-broker-service.default.svc.cluster.local
- Then add the services offered by the broker. Since the sample broker only has one mock service, a single command is needed.
{: codeblock}
ibmcloud cf enable-service-access testnoderesourceservicebrokername
- In your browser, access your CFEE instance from the Environments page and navigate to the
organizations -> spaces
and select yourdev
space. - Select the Services tab and the Create Service button.
- In the search texbox, search for Test. The Test Node Resource Service Broker Display Name mock service from the broker will display.
- Select the service, click the Create button, and provide the name
welcome-service
to create a service instance. It will become clear in the next section why it's named welcome-service. Then bind the service to theGetStartedNode
app using the Bind to appliction item in the overflow menu. - To view the bound service, run the
cf env
command. TheGetStartedNode
application can now leverage the data in thecredentials
object similar to how it uses data fromcloudantNoSQLDB
currently.{: codeblock}ibmcloud cf env GetStartedNode
Up to this point, you've deployed a service broker but not an actual service. While the service broker provides binding data to GetStartedNode
, no actual functionality from the service itself has been added. To correct this, a mock service has been created that provides a "Welcome" message to GetStartedNode
in various languages. You'll deploy this service to CFEE and update the broker and application to use it.
-
Push the
welcome-service
implementation to CFEE to allow additional development teams to leverage it as an API.cd sample-resource-service
{: codeblock}
ibmcloud cf push
{: codeblock}
-
Access the service using your browser. The
route
to the service will be shown as part of thepush
command's output. The resulting URL will be similar tohttps://welcome.<your-cfee-cluster-domain>
. Refresh the page to see alternating languages. -
Return to the
sample-resource-service-brokers
folder and edit the Node.js sample implementationsample-resource-service-brokers/node-resource-service-broker/testresourceservicebroker.js
with adding url after line 854 with adding the cluster URL.// TODO - Do your actual work here var generatedUserid = uuid(); var generatedPassword = uuid(); result = { credentials: { userid : generatedUserid, password : generatedPassword, url: 'https://welcome.<your-cfee-cluster-domain>' } };
{: codeblock}
-
Build and deploy the updated service broker. This will ensure the URL property will be provided to apps that bind the service.
cd ..
{: codeblock}
ibmcloud cr build . -t $REGISTRY/cfee-tutorial/service-broker-impl
{: codeblock}
kubectl patch deployment tutorial-servicebroker-deployment -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"version\":\"2\"}}}}}"
{: codeblock}
-
In terminal, navigate back to the
get-started-node
application folder.cd ..
{: codeblock}
cd get-started-node
{: codeblock}
-
Edit the
get-started-node/server.js
file inget-stared-node
to include the following middleware. Insert it just prior to theapp.listen()
call.// Use the welcome service const request = require('request'); const testService = appEnv.services['testnoderesourceservicebrokername']; if (testService) { const { credentials: { url} } = testService[0]; app.get("/api/welcome", (req, res) => request(url, (e, r, b) => res.send(b))); } else { app.get("/api/welcome", (req, res) => res.send('Welcome')); }
{: codeblock}
-
Refactor the
get-started-node/views/index.html
page. Changedata-i18n="welcome"
toid="welcome"
in theh1
tag. And then add a call to the service at the end of the$(document).ready()
function.<h1 id="welcome"></h1> <!-- Welcome -->
{: codeblock}
$.get('./api/welcome').done(data => document.getElementById('welcome').innerHTML= data);
{: codeblock}
-
Update the
GetStartedNode
app. Include therequest
package dependency that was added toserver.js
, rebind thewelcome-service
to pick up the newurl
property and finally push the app's new code.npm i request -S
{: codeblock}
ibmcloud cf unbind-service GetStartedNode welcome-service
{: codeblock}
ibmcloud cf bind-service GetStartedNode welcome-service
{: codeblock}
ibmcloud cf push
{: codeblock}
You're done! Now visit the application and refresh the page several times to see the welcome message in different languages.
If you continue to see only Welcome and not other languages, run the ibmcloud cf env GetStartedNode
command, and confirm the url
to the service is present. If not, retrace your steps, update, and re-deploy the broker. If the url
value is present, confirm it returns a message in your browser. Then run the unbind-service
and bind-service
commands again followed by ibmcloud cf restart GetStartedNode
.
{: tip}
While the welcome service uses Cloud Foundry as its implementation, you could just as easily use Kubernetes. The main difference is that the URL to the service would be likely be welcome-service.default.svc.cluster.local
. Using the KubeDNS URL has the added benefit of keeping network traffic to services internal to the Kubernetes cluster.
With {{site.data.keyword.cfee_full_notm}} these alternate approaches are now possible.
Optionally, you can deploy the complete solution tutorial using a toolchain. Follow the toolchain instruction to deploy all of above using a toolchain.
Note: Some prerequisites when using a toolchain, you must have created a CFEE instance and created a CFEE org and CFEE space. Detailed instructions outlined in the toolchain instruction readme.
{:related}