Adding services by using IBM Cloud service binding
Add IBM Cloud services to enhance your Kubernetes cluster with extra capabilities in areas such as Watson AI, data, security, and Internet of Things (IoT).
About service binding
Review the following frequently asked questions about service binding.
What types of services can I bind to my cluster?
You can bind services that are enabled for IBM Cloud Identity and Access Management (IAM). IAM-enabled services offer more granular access control and can be managed in an IBM Cloud resource group. For more information, see Managing access to resources.
To find a list of supported IBM Cloud services, see the IBM Cloud catalog.
What is IBM Cloud service binding?
Service binding is a quick way to create service credentials for an IBM Cloud service by using its public cloud service endpoint and storing these credentials in a Kubernetes secret in your cluster. To bind a service to your cluster, you must
provision an instance of the service first. Then, you use the ibmcloud ks cluster service bind
command to create the service credentials
and the Kubernetes secret. The Kubernetes secret is automatically encrypted in etcd to protect your data.
Want to make your secrets even more secured? Ask your cluster admin to enable a key management service provider in your cluster to encrypt new and existing secrets, such as the secret that stores the credentials of your IBM Cloud service instances.
I already have an IBM Cloud service. Can I still use IBM Cloud service binding?
Yes, you can use services that meet naming requirements and reuse the service credentials.
- Naming: Make sure that the service name is in the following regex format. Example permitted names are
myservice
orexample.com
. Characters that are not allowed include spaces and underscores.[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
- Service credentials: To use your existing service credentials, specify the
--key
option in theibmcloud ks cluster service bind
command and provide the name of your service credentials. IBM Cloud service binding automatically creates a Kubernetes secret with your existing service credentials.
What if I want to use service credentials that use the private cloud service endpoint?
By default, the ibmcloud ks cluster service bind
command creates service credentials with the public cloud service endpoint. To use the private cloud service endpoint, you must manually create service credentials for your service
that use the private cloud service endpoint, and then use the --key
option to specify the name of the existing service credentials.
Your service might not yet support private cloud service endpoints. If you have a private-only cluster, you must use service credentials that use the private cloud service endpoint, or open up the public IP address and port to connect to your service.
Can I use all IBM Cloud services in my cluster?
You can use service binding only for services that support service keys so that the service credentials can automatically be created and stored in a Kubernetes secret. To find a list of services that support service keys, see Enabling external apps to use IBM Cloud services.
Services that don't support service keys usually provide an API that you can use in your app. The service binding method does not automatically set up API access for your app. Make sure to review the API documentation of your service and implement the API interface in your app.
Can I bind multiple IBM Cloud services to multiple clusters at once?
IBM Cloud service binding is on a per-cluster, per-service basis, and works by creating a Kubernetes secret that your pods can mount.
For multiple clusters and services, you can use IAM trusted profiles instead. In IAM, you create a trusted profile with access policies for the IBM Cloud services that you want.
Then, you link the trusted profile with as many clusters as you want, based on conditions such as all the prod
Kubernetes namespaces in clusters in a resource group. Finally, your pods mount the Kubernetes service account projected
volume to get a token that can be exchanged for an IAM token that your apps use to authenticate with the IBM Cloud services.
Adding IBM Cloud services to clusters
Use IBM Cloud service binding to automatically create service credentials for your IBM Cloud services and store these credentials in a Kubernetes secret.
Before you begin:
- Ensure you have the following roles:
- Editor or Administrator IBM Cloud IAM platform access role for the cluster where you want to bind a service.
- Writer or Manager IBM Cloud IAM service access role for the Kubernetes namespace where you want to bind the service.
- Log in to your account. If applicable, target the appropriate resource group. Set the context for your cluster.
To add an IBM Cloud service to your cluster:
-
Create an instance of the IBM Cloud service.
- Some IBM Cloud services are available only in select regions. You can bind a service to your cluster only if the service is available in the same region as your cluster. In addition, if you want to create a service instance in the Washington DC zone, you must use the CLI.
- For IAM-enabled services: You must create the service instance in the same resource group as your cluster. A service can be created in only one resource group that you can't change afterward.
- Make sure that the service name is in the format
myservice
orexample.com
. Spaces and underscores are not allowed.
-
Check the type of service that you created and make note of the service instance Name.
ibmcloud resource service-instances
Example output
NAME Location State Type Tags <iam_service_instance_name> <region> active service_instance
-
Identify the cluster namespace that you want to use to add your service.
kubectl get namespaces
-
Bind the service to your cluster to create service credentials for your service that use the public cloud service endpoint and store the credentials in a Kubernetes secret. If you have existing service credentials, use the
--key
option to specify the name of the credentials. For IAM-enabled services, the credentials are automatically created with the Writer service access role, but you can use the--role
option to specify a different service access role. If you use the--key
option, don't include the--role
option.If your service supports private cloud service endpoints, you can manually create the service credentials with the private cloud service endpoint, and then use the
--key
option to specify the name of your credentials.ibmcloud ks cluster service bind --cluster <cluster_name_or_ID> --namespace <namespace> --service <service_instance_name> [--key <service_instance_key>] [--role <IAM_service_role>]
When the creation of the service credentials is successful, a Kubernetes secret with the name
binding-<service_instance_name>
is created.Example output
ibmcloud ks cluster service bind --cluster mycluster --namespace mynamespace --service cleardb Binding service instance to namespace... OK Namespace: mynamespace Secret name: binding-<service_instance_name>
-
Verify the service credentials in your Kubernetes secret.
- Get the details of the secret and note the binding value. The binding value is base64 encoded and holds the credentials for your service instance in JSON format.
Example outputkubectl get secrets binding-<service_instance_name> --namespace=<namespace> -o yaml
apiVersion: v1 data: binding: <binding> kind: Secret metadata: annotations: service-instance-id: 1111aaaa-a1aa-1aa1-1a11-111aa111aa11 service-key-id: 2b22bb2b-222b-2bb2-2b22-b22222bb2222 creationTimestamp: 2018-08-07T20:47:14Z name: binding-<service_instance_name> namespace: <namespace> resourceVersion: "6145900" selfLink: /api/v1/namespaces/default/secrets/binding-mycloudant uid: 33333c33-3c33-33c3-cc33-cc33333333c type: Opaque
- Decode the binding value.
Example outputecho "<binding>" | base64 -D
{"apikey":"<API_key>","host":"<ID_string>-bluemix.cloudant.com","iam_apikey_description":"Auto generated apikey during resource-key operation for Instance - crn:v1:bluemix:public:cloudantnosqldb:us-south:a/<ID_string>::","iam_apikey_name":"auto-generated-apikey-<ID_string>","iam_role_crn":"crn:v1:bluemix:public:iam::::serviceRole:Writer","iam_serviceid_crn":"crn:v1:bluemix:public:iam-identity::a/1234567890brasge5htn2ec098::serviceid:ServiceId-<ID_string>","password":"<ID_string>","port":443,"url":"https://<ID_string>-bluemix.cloudant.com","username":"123b45da-9ce1-4c24-ab12-rinwnwub1294-bluemix"}
- Optional: Compare the service credentials that you decoded in the previous step with the service credentials that you find for your service instance in the IBM Cloud dashboard.
- Get the details of the secret and note the binding value. The binding value is base64 encoded and holds the credentials for your service instance in JSON format.
-
Now that your service is bound to your cluster, you must configure your app to access the service credentials in the Kubernetes secret.
Accessing service credentials from your apps
To access an IBM Cloud service instance from your app, you must make the service credentials that are stored in the Kubernetes secret available to your app.
The credentials of a service instance are base64 encoded and stored inside your secret in JSON format. To access the data in your secret, choose among the following options:
Before you begin:
- Ensure you have the Writer or Manager IBM Cloud IAM service access role for the
kube-system
namespace. - Log in to your account. If applicable, target the appropriate resource group. Set the context for your cluster.
- Add an IBM Cloud service to your cluster.
Mounting the secret as a volume to your pod
When you mount the secret as a volume to your pod, a file that is named binding
is stored in the volume mount directory. The binding
file in JSON format includes all the information and credentials that you need to
access the IBM Cloud service.
-
List available secrets in your cluster and note the name of your secret. Look for a secret of type Opaque. If multiple secrets exist, contact your cluster administrator to identify the correct service secret.
kubectl get secrets
Example output
NAME TYPE DATA AGE binding-<service_instance_name> Opaque 1 3m
-
Create a YAML file for your Kubernetes deployment and mount the secret as a volume to your pod.
apiVersion: apps/v1 kind: Deployment metadata: labels: app: secret-test name: secret-test namespace: <my_namespace> spec: selector: matchLabels: app: secret-test replicas: 1 template: metadata: labels: app: secret-test spec: containers: - image: icr.io/ibm/liberty:latest name: secret-test volumeMounts: - mountPath: <mount_path> name: <volume_name> volumes: - name: <volume_name> secret: defaultMode: 420 secretName: binding-<service_instance_name>
volumeMounts.mountPath
- The absolute path of the directory to where the volume is mounted inside the container.
volumeMounts.name
andvolumes.name
- The name of the volume to mount to your pod.
secret.defaultMode
- The read and write permissions on the secret. Use
420
to set read-only permissions. secret.secretName
- The name of the secret that you noted in the previous step.
-
Create the pod and mount the secret as a volume.
kubectl apply -f secret-test.yaml
-
Verify that the pod is created.
kubectl get pods
Example CLI output:
NAME READY STATUS RESTARTS AGE secret-test-1111454598-gfx32 1/1 Running 0 1m
-
Access the service credentials.
-
Log in to your pod.
kubectl exec <pod_name> -it bash
-
Navigate to your volume mount path that you defined earlier and list the files in your volume mount path.
cd <volume_mountpath> && ls
Example output
binding
The
binding
file includes the service credentials that you stored in the Kubernetes secret. -
View the service credentials. The credentials are stored as key value pairs in JSON format.
cat binding
Example output
{"apikey":"<API_key>","host":"<ID_string>-bluemix.cloudant.com","iam_apikey_description":"Auto generated apikey during resource-key operation for Instance - crn:v1:bluemix:public:cloudantnosqldb:us-south:a/<ID_string>:<ID_string>::","iam_apikey_name":"auto-generated-apikey-<ID_string>","iam_role_crn":"crn:v1:bluemix:public:iam::::serviceRole:Writer","iam_serviceid_crn":"crn:v1:bluemix:public:iam-identity::a/<ID_string>::serviceid:ServiceId-<ID_string>","password":"<ID_string>","port":443,"url":"https://<ID_string>-bluemix.cloudant.com","username":"123b45da-9ce1-4c24-ab12-rinwnwub1294-bluemix"}
-
Configure your app to parse the JSON content and retrieve the information that you need to access your service.
-
Referencing the secret in environment variables
You can add the service credentials and other key value pairs from your Kubernetes secret as environment variables to your deployment.
-
List available secrets in your cluster and note the name of your secret. Look for a secret of type Opaque. If multiple secrets exist, contact your cluster administrator to identify the correct service secret.
kubectl get secrets
Example output
NAME TYPE DATA AGE binding-<service_instance_name> Opaque 1 3m
-
Get the details of your secret to find potential key value pairs that you can reference as environment variables in your pod. The service credentials are stored in the
binding
key of your secret.kubectl get secrets binding-<service_instance_name> --namespace=<namespace> -o yaml
Example output
apiVersion: v1 data: binding: <binding> kind: Secret metadata: annotations: service-instance-id: 7123acde-c3ef-4ba2-8c52-439ac007fa70 service-key-id: 9h30dh8a-023f-4cf4-9d96-d12345ec7890 creationTimestamp: 2018-08-07T20:47:14Z name: binding-<service_instance_name> namespace: <namespace> resourceVersion: "6145900" selfLink: /api/v1/namespaces/default/secrets/binding-mycloudant uid: 12345a31-9a83-11e8-ba83-cd49014748f type: Opaque
-
Create a YAML file for your Kubernetes deployment and specify an environment variable that references the
binding
key.apiVersion: apps/v1 kind: Deployment metadata: labels: app: secret-test name: secret-test namespace: <my_namespace> spec: selector: matchLabels: app: secret-test template: metadata: labels: app: secret-test spec: containers: - image: icr.io/ibm/liberty:latest name: secret-test env: - name: BINDING valueFrom: secretKeyRef: name: binding-<service_instance_name> key: binding
containers.env.name
- The name of your environment variable.
env.valueFrom.secretKeyRef.name
- The name of the secret that you noted in the previous step.
env.valueFrom.secretKeyRef.key
- The key that is part of your secret and that you want to reference in your environment variable. To reference the service credentials, you must use the binding key.
-
Create the pod that references the
binding
key of your secret as an environment variable.kubectl apply -f secret-test.yaml
-
Verify that the pod is created.
kubectl get pods
Example CLI output:
NAME READY STATUS RESTARTS AGE secret-test-1111454598-gfx32 1/1 Running 0 1m
-
Verify that the environment variable is set correctly.
- Log in to your pod.
kubectl exec <pod_name> -it bash
- List all environment variables in the pod.
Example outputenv
BINDING={"apikey":"<API_key>","host":"<ID_string>-bluemix.cloudant.com","iam_apikey_description":"Auto generated apikey during resource-key operation for Instance - crn:v1:bluemix:public:cloudantnosqldb:us-south:a/<ID_string>::","iam_apikey_name":"auto-generated-apikey-<ID_string>","iam_role_crn":"crn:v1:bluemix:public:iam::::serviceRole:Writer","iam_serviceid_crn":"crn:v1:bluemix:public:iam-identity::a/1234567890brasge5htn2ec098::serviceid:ServiceId-<ID_string>","password":"<password>","port":443,"url":"https://<ID_string>-bluemix.cloudant.com","username":"<ID_string>-bluemix"}
- Log in to your pod.
-
Configure your app to read the environment variable and to parse the JSON content to retrieve the information that you need to access your service.
Example code in Python:
if os.environ.get('BINDING'): credentials = json.loads(os.environ.get('BINDING'))
-
Optional: As a precaution, add error handling to your app in case that the
BINDING
environment variable is not set properly.Example code in Java:
if (System.getenv("BINDING") == null) { throw new RuntimeException("Environment variable 'SECRET' is not set!"); }
Example code in Node.js:
if (!process.env.BINDING) { console.error('ENVIRONMENT variable "BINDING" is not set!'); process.exit(1); }
Removing a service from a cluster
If you don't want to use an IBM Cloud service that you bound to your cluster, you can manually remove the Kubernetes secret and the pods that access the secret from your cluster.
-
List the services that are bound to your cluster and note the name of your service and the namespace that the service is bound to.
ibmcloud ks cluster service ls --cluster
Example output
OK Service Instance GUID Key Namespace myservice 12345ab1-1234-1abc-a12b-12abc12a12ab kube-a1a12abcd12a123abc1a12ab1a1234ab7.abcdefg0p1abcd123lgg.default default
-
List the Kubernetes secrets in the namespace that your service is bound to and look for the secret with a name that follows the
binding-<service_name>
format.kubectl get secrets -n <namespace> | grep Opaque
Example output
binding-myservice Opaque 1 3d23h
-
Retrieve all the pods that access the secret.
kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.volumes[*]}{.secret.secretName}{" "}{end}{end}' | grep "<secret_name>"
If your CLI output is empty, no pods exist in your cluster that mount the secret.
-
If you have pods that mount the secret, either remove the pod or the deployment that manages the pod, or update the pod and deployment YAML to use a different secret instead.
- To remove a pod or deployment:
kubectl delete pod <pod_name> -n <namespace>
kubectl delete deployment <deployment_name> -n <namespace>
- To update an existing pod or deployment:
- Get the pod or deployment YAML file.
kubectl get pod <pod_name> -o yaml
kubectl get deployment <deployment_name> -o yaml
- Copy the YAML file and in the
spec.volumes
section, change the name of the secret that you want to use. - Apply the change in your cluster.
kubectl apply -f pod.yaml
kubectl apply -f deployment.yaml
- Verify that a new pod is created with the updated volume specification.
kubectl get pods
kubectl describe pod <pod_name>
- Get the pod or deployment YAML file.
- To remove a pod or deployment:
-
Remove the secret.
kubectl delete secret <secret_name> -n <namespace>
-
Verify that your secret is removed.
kubectl get secrets -n <namespace>
-
Optional. Remove the IBM Cloud service instance.
ibmcloud resource service-instance-delete <service_name>