Kubernetes Cluster on Azure and Expose Couchbase Service
This blog is part of a multi-partĀ blog series that shows how to run your applicationsĀ on Kubernetes. It will use theĀ Couchbase, an open source NoSQL distributed document database, as theĀ Ā Docker container.
- Part 1 explained how to start Kubernetes cluster using Vagrant āĀ Kubernetes on Vagrant
- Part 2Ā did the same for Amazon Web Services āĀ KubernetesĀ on AmazonĀ Web Services
- Part 3 did the same for Google Cloud āĀ Kubernetes on Google Cloud
This fourthĀ part will show:
- How to setup and start theĀ Kubernetes cluster onĀ Azure
- Run Docker container in the Kubernetes cluster
- Expose Pod on Kubernetes as Service
- Shutdown the cluster
Many thanks to @colemickensĀ for helpingĀ meĀ through this recipe. This blog content is heavily based upon the instructions atĀ colemickens.github.io/docs/getting-started-guides/azure/.
Install and Configure Azure CLI
Azure CLIĀ is a command-line interface to develop, deploy and manage Azure applications. This is needed in order to install Kubernetes cluster on Azure.
- Install Node:
brew install node ==> Downloading https://homebrew.bintray.com/bottles/node-6.2.0.yosemite.bottle.tar.gz ######################################################################## 100.0% ==> Pouring node-6.2.0.yosemite.bottle.tar.gz ==> Caveats Please note by default only English locale support is provided. If you need full locale support you should either rebuild with full icu: `brew reinstall node --with-full-icu` or add full icu data at runtime following: https://github.com/nodejs/node/wiki/Intl#using-and-customizing-the-small-icu-build Bash completion has been installed to: /usr/local/etc/bash_completion.d ==> Summary šŗ /usr/local/Cellar/node/6.2.0: 3,979 files, 40.4M
- Install Azure CLI:
npm install -g azure-cli /usr/local/bin/azure -> /usr/local/lib/node_modules/azure-cli/bin/azure > fibers@1.0.13 install /usr/local/lib/node_modules/azure-cli/node_modules/fibers > node build.js || nodejs build.js `darwin-x64-v8-5.0` exists; testing Binary is fine; exiting /usr/local/lib āā⬠azure-cli@0.10.0 āā⬠adal-node@0.1.17 ā āāā date-utils@1.2.21 ā āā⬠jws@3.1.3 ā ā āā⬠base64url@1.0.6 ā ā ā āā⬠meow@2.0.0 ā ā ā āā⬠camelcase-keys@1.0.0 ā ā ā ā āāā camelcase@1.2.1 ā ā ā ā āāā map-obj@1.0.1 ā ā ā āā⬠indent-string@1.2.2 ā ā ā ā āāā get-stdin@4.0.1 ā ā ā ā āā⬠repeating@1.1.3 ā ā ā ā āāā is-finite@1.0.1 ā ā ā āāā minimist@1.2.0 ā ā ā āāā object-assign@1.0.0 ā ā āā⬠jwa@1.1.3 ā ā āāā buffer-equal-constant-time@1.0.1 ā ā āā⬠ecdsa-sig-formatter@1.0.5 ā ā āāā base64-url@1.2.2 ā āāā node-uuid@1.4.1 ā āāā xmldom@0.1.22 ā āāā xpath.js@1.0.6 āāā applicationinsights@0.15.12 āāā async@1.4.2 āāā azure-arm-authorization@2.0.0 āāā azure-arm-batch@0.1.0 āāā azure-arm-cdn@0.1.0-preview āāā azure-arm-commerce@0.1.1 āāā azure-arm-compute@0.18.0 āāā azure-arm-datalake-analytics@0.3.2 āāā azure-arm-datalake-store@0.3.0 āāā azure-arm-dns@0.10.1 āāā azure-arm-hdinsight@0.2.0 āāā azure-arm-hdinsight-jobs@0.1.0 āāā azure-arm-insights@0.11.1 āāā azure-arm-network@0.13.1 āāā azure-arm-rediscache@0.2.1 āāā azure-arm-resource@1.4.4-preview āāā azure-arm-storage@0.13.1-preview āāā azure-arm-trafficmanager@0.10.5 āā⬠azure-arm-website@0.10.0 ā āā⬠azure-common@0.9.12 ā ā āā⬠request@2.45.0 ā ā ā āāā aws-sign2@0.5.0 ā ā ā āāā bl@0.9.5 ā ā ā āāā caseless@0.6.0 ā ā ā āāā forever-agent@0.5.2 ā ā ā āā⬠form-data@0.1.4 ā ā ā ā āāā async@0.9.2 ā ā ā ā āā⬠combined-stream@0.0.7 ā ā ā ā āāā delayed-stream@0.0.5 ā ā ā āā⬠hawk@1.1.1 ā ā ā ā āāā boom@0.4.2 ā ā ā ā āāā cryptiles@0.2.2 ā ā ā ā āāā hoek@0.9.1 ā ā ā ā āāā sntp@0.2.4 ā ā ā āā⬠http-signature@0.10.1 ā ā ā ā āāā asn1@0.1.11 ā ā ā ā āāā assert-plus@0.1.5 ā ā ā āāā mime-types@1.0.2 ā ā ā āāā node-uuid@1.4.7 ā ā ā āāā oauth-sign@0.4.0 ā ā ā āāā qs@1.2.2 ā ā āāā xml2js@0.2.7 ā āāā moment@2.6.0 āāā azure-asm-compute@0.15.0 āāā azure-asm-hdinsight@0.10.2 āāā azure-asm-mgmt@0.10.1 āāā azure-asm-network@0.11.0 āāā azure-asm-sb@0.10.1 āāā azure-asm-sql@0.10.1 āāā azure-asm-storage@0.10.1 āāā azure-asm-subscription@0.10.1 āāā azure-asm-trafficmanager@0.10.3 āā⬠azure-asm-website@0.10.1 ā āāā moment@2.6.0 āāā azure-batch@0.3.0 āā⬠azure-common@0.9.16 ā āāā dateformat@1.0.2-1.2.3 ā āāā duplexer@0.1.1 ā āāā envconf@0.0.4 ā āā⬠request@2.45.0 ā ā āāā aws-sign2@0.5.0 ā ā āāā bl@0.9.5 ā ā āāā caseless@0.6.0 ā ā āāā forever-agent@0.5.2 ā ā āā⬠form-data@0.1.4 ā ā ā āāā async@0.9.2 ā ā ā āā⬠combined-stream@0.0.7 ā ā ā ā āāā delayed-stream@0.0.5 ā ā ā āāā mime@1.2.11 ā ā āā⬠hawk@1.1.1 ā ā ā āāā boom@0.4.2 ā ā ā āāā cryptiles@0.2.2 ā ā ā āāā hoek@0.9.1 ā ā ā āāā sntp@0.2.4 ā ā āā⬠http-signature@0.10.1 ā ā ā āāā asn1@0.1.11 ā ā ā āāā assert-plus@0.1.5 ā ā ā āāā ctype@0.5.3 ā ā āāā mime-types@1.0.2 ā ā āāā node-uuid@1.4.7 ā ā āāā oauth-sign@0.4.0 ā ā āāā qs@1.2.2 ā āāā validator@3.22.2 ā āāā xml2js@0.2.7 āāā azure-gallery@2.0.0-pre.18 āāā azure-graph@0.1.1 āā⬠azure-keyvault@0.10.1 ā āāā node-uuid@1.4.7 āā⬠azure-monitoring@0.10.2 ā āāā moment@2.6.0 āā⬠azure-storage@0.7.0 ā āāā browserify-mime@1.2.9 ā āāā extend@1.2.1 ā āāā node-uuid@1.4.7 ā āā⬠readable-stream@2.0.6 ā ā āāā isarray@1.0.0 ā ā āāā process-nextick-args@1.0.7 ā ā āāā util-deprecate@1.0.2 ā āā⬠request@2.57.0 ā ā āāā aws-sign2@0.5.0 ā ā āā⬠bl@0.9.5 ā ā ā āā⬠readable-stream@1.0.34 ā ā ā āāā isarray@0.0.1 ā ā āāā caseless@0.10.0 ā ā āā⬠form-data@0.2.0 ā ā ā āāā async@0.9.2 ā ā ā āā⬠combined-stream@0.0.7 ā ā ā āāā delayed-stream@0.0.5 ā ā āā⬠har-validator@1.8.0 ā ā ā āāā bluebird@2.10.2 ā ā ā āāā commander@2.9.0 ā ā āāā hawk@2.3.1 ā ā āā⬠http-signature@0.11.0 ā ā ā āāā asn1@0.1.11 ā ā ā āāā assert-plus@0.1.5 ā ā āā⬠mime-types@2.0.14 ā ā ā āāā mime-db@1.12.0 ā ā āāā qs@3.1.0 ā āāā validator@3.22.2 ā āāā xml2js@0.2.7 āā⬠caller-id@0.1.0 ā āāā stack-trace@0.0.9 āāā colors@0.6.2 āā⬠commander@1.0.4 ā āāā keypress@0.1.0 āāā easy-table@0.0.1 āā⬠event-stream@3.1.5 ā āāā from@0.1.3 ā āāā map-stream@0.1.0 ā āāā pause-stream@0.0.11 ā āāā split@0.2.10 ā āāā stream-combiner@0.0.4 āāā eyes@0.1.8 āāā fast-json-patch@0.5.6 āāā github@0.1.6 āāā js2xmlparser@1.0.0 āāā jsrsasign@4.8.2 āā⬠kuduscript@1.0.6 ā āāā commander@1.1.1 ā āāā streamline@0.4.11 āāā moment@2.13.0 āāā ms-rest@1.14.2 āā⬠ms-rest-azure@1.14.2 ā āāā async@0.2.7 ā āāā uuid@2.0.1 āāā node-forge@0.6.23 āāā node-uuid@1.2.0 āāā number-is-nan@1.0.0 āāā omelette@0.1.0 āā⬠openssl-wrapper@0.2.1 ā āāā debug@0.7.4 ā āāā q@0.9.7 āā⬠read@1.0.7 ā āāā mute-stream@0.0.6 āā⬠readable-stream@1.0.34 ā āāā core-util-is@1.0.2 ā āāā inherits@2.0.1 ā āāā isarray@0.0.1 ā āāā string_decoder@0.10.31 āā⬠request@2.69.0 ā āāā aws-sign2@0.6.0 ā āāā aws4@1.4.1 ā āā⬠bl@1.0.3 ā ā āā⬠readable-stream@2.0.6 ā ā āāā isarray@1.0.0 ā āāā caseless@0.11.0 ā āā⬠combined-stream@1.0.5 ā ā āāā delayed-stream@1.0.0 ā āāā extend@3.0.0 ā āāā forever-agent@0.6.1 ā āā⬠form-data@1.0.0-rc4 ā ā āāā async@1.5.2 ā āā⬠har-validator@2.0.6 ā ā āā⬠chalk@1.1.3 ā ā ā āāā ansi-styles@2.2.1 ā ā ā āāā escape-string-regexp@1.0.5 ā ā ā āā⬠has-ansi@2.0.0 ā ā ā ā āāā ansi-regex@2.0.0 ā ā ā āāā strip-ansi@3.0.1 ā ā ā āāā supports-color@2.0.0 ā ā āā⬠commander@2.9.0 ā ā ā āāā graceful-readlink@1.0.1 ā ā āā⬠is-my-json-valid@2.13.1 ā ā ā āāā generate-function@2.0.0 ā ā ā āā⬠generate-object-property@1.2.0 ā ā ā ā āāā is-property@1.0.2 ā ā ā āāā jsonpointer@2.0.0 ā ā ā āāā xtend@4.0.1 ā ā āā⬠pinkie-promise@2.0.1 ā ā āāā pinkie@2.0.4 ā āā⬠hawk@3.1.3 ā ā āāā boom@2.10.1 ā ā āāā cryptiles@2.0.5 ā ā āāā hoek@2.16.3 ā ā āāā sntp@1.0.9 ā āā⬠http-signature@1.1.1 ā ā āāā assert-plus@0.2.0 ā ā āā⬠jsprim@1.2.2 ā ā ā āāā extsprintf@1.0.2 ā ā ā āāā json-schema@0.2.2 ā ā ā āāā verror@1.3.6 ā ā āā⬠sshpk@1.8.3 ā ā āāā asn1@0.2.3 ā ā āāā assert-plus@1.0.0 ā ā āā⬠dashdash@1.13.1 ā ā ā āāā assert-plus@1.0.0 ā ā āāā ecc-jsbn@0.1.1 ā ā āā⬠getpass@0.1.6 ā ā ā āāā assert-plus@1.0.0 ā ā āāā jodid25519@1.0.2 ā ā āāā jsbn@0.1.0 ā ā āāā tweetnacl@0.13.3 ā āāā is-typedarray@1.0.0 ā āāā isstream@0.1.2 ā āāā json-stringify-safe@5.0.1 ā āā⬠mime-types@2.1.11 ā ā āāā mime-db@1.23.0 ā āāā node-uuid@1.4.7 ā āāā oauth-sign@0.8.2 ā āāā qs@6.0.2 ā āāā stringstream@0.0.5 ā āāā tough-cookie@2.2.2 ā āāā tunnel-agent@0.4.3 āā⬠ssh-key-to-pem@0.11.0 ā āāā asn1@0.1.11 ā āāā ctype@0.5.2 āā⬠streamline@0.10.17 ā āāā fibers@1.0.13 ā āāā galaxy@0.1.12 ā āā⬠source-map@0.1.43 ā āāā amdefine@1.0.0 āāā streamline-streams@0.1.5 āā⬠sync-request@3.0.0 ā āā⬠concat-stream@1.4.10 ā ā āāā readable-stream@1.1.14 ā ā āāā typedarray@0.0.6 ā āāā http-response-object@1.1.0 ā āā⬠then-request@2.2.0 ā āāā http-basic@2.5.1 ā āā⬠promise@7.1.1 ā ā āāā asap@2.0.4 ā āāā qs@6.2.0 āāā through@2.3.4 āāā tunnel@0.0.2 āāā underscore@1.4.4 āāā validator@3.1.0 āā⬠winston@0.6.2 ā āāā async@0.1.22 ā āāā cycle@1.0.3 ā āāā pkginfo@0.2.3 ā āāā request@2.9.203 āāā wordwrap@0.0.2 āā⬠xml2js@0.1.14 ā āāā sax@0.5.2 āāā xmlbuilder@0.4.3
- Sign up for free trial at https://azure.microsoft.com/en-us/free/.
- Login to Azure using the command
azure login:
azure login info: Executing command login \info: To sign in, use a web browser to open the page https://aka.ms/devicelogin. Enter the code BS5P64ANU to authenticate. |info: Added subscription Free Trial info: Setting subscription "Free Trial" as default + info: login command OK
- Get account information using azure account show command:
azure account show info: Executing command account show data: Name : Free Trial data: ID : XXX data: State : Enabled data: Tenant ID : YYY data: Is Default : true data: Environment : AzureCloud data: Has Certificate : No data: Has Access Token : Yes data: User name : arun.gupta@gmail.com data: info: account show command OK
Note the value shown instead of XXX and YYY. These will be usedĀ to configure the Kubernetes cluster.
Start Kubernetes Cluster
- Download Kubernetes 1.2.4Ā andĀ extractĀ it.
- Kubernetes cluster on Azure can be started as:
export KUBERNETES_PROVIDER=azure export AZURE_SUBSCRIPTION_ID=XXX export AZURE_TENANT_ID=YYY ./cluster/kube-up.sh
Make sure to specify the appropriate values for XXX and YYY from the previous command.Ā AZURE_SUBSCRIPTION_ID andAZURE_TENANT_ID are specific to Azure.
These values can also be edited in cluster/azure/config-default.sh.
- Start Kubernetes cluster:
./kubernetes/cluster/kube-up.sh
... Starting cluster using provider: azure
... calling verify-prereqs
... calling kube-up
++> AZURE KUBE-UP STARTED: Tue May 31 16:15:26 PDT 2016
This will be interactive. (export AZURE_AUTH_METHOD=client_secret to avoid the prompt)
hyperkube-amd64:v1.2.4 was found in the gcr.io/google_containers repository
Flag --tenant-id has been deprecated, tenant-id is deprecated. it is now determined automatically from the subscription id
WARN[0000] --resource-group is unset. Derived one from --deployment-name: "kube-20160531-161525"
WARN[0000] --master-fqdn is unset. Derived one from input: "kube-20160531-161525.westus.cloudapp.azure.com".
To sign in, use a web browser to open the page https://aka.ms/devicelogin. Enter the code BPRLH2ARJ to authenticate.
INFO[0034] Starting ARM Deployment. This will take some time. deployment="kube-20160531-161525-1464736561"
INFO[0279] Finished ARM Deployment. deployment="kube-20160531-161525-1464736561"
INFO[0279] Validating Kubernetes cluster.
WARN[0279] Failed to validate components: Get https://kube-20160531-161525.westus.cloudapp.azure.com:6443/api/v1/componentstatuses: dial tcp 23.99.60.138:6443: getsockopt: connection refused
INFO[0294] Validating Kubernetes cluster.
WARN[0294] Failed to validate components: Get https://kube-20160531-161525.westus.cloudapp.azure.com:6443/api/v1/componentstatuses: dial tcp 23.99.60.138:6443: getsockopt: connection refused
INFO[0309] Validating Kubernetes cluster.
WARN[0309] Failed to validate components: Get https://kube-20160531-161525.westus.cloudapp.azure.com:6443/api/v1/componentstatuses: dial tcp 23.99.60.138:6443: getsockopt: connection refused
INFO[0324] Validating Kubernetes cluster.
WARN[0347] validate: incorrect healthy count. expected=3 actual=4
INFO[0347] Deployment Complete!
INFO[0347] master: "https://kube-20160531-161525.westus.cloudapp.azure.com:6443"
INFO[0347] output: "/opt/azkube/_deployments/kube-20160531-161525"
cluster "kube-20160531-161525" set.
user "kube-20160531-161525_user" set.
context "kube-20160531-161525" set.
switched to context "kube-20160531-161525".
++> AZURE KUBE-UP FINISHED: Tue May 31 16:21:15 PDT 2016 (duration: -349 seconds)
... calling validate-cluster
Detected 4 ready nodes, found 4 nodes out of expected 3. Found more nodes than expected, your cluster may not behave correctly.
Found 4 node(s).
NAME STATUS AGE
kube-20160531-161525-vm-master Ready,SchedulingDisabled 21s
kube-20160531-161525-vm-node-0 Ready 18s
kube-20160531-161525-vm-node-1 Ready 19s
kube-20160531-161525-vm-node-2 Ready 19s
Flag --api-version has been deprecated, flag is no longer respected and will be deleted in the next release
Validate output:
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-1 Healthy {"health": "true"}
etcd-0 Healthy {"health": "true"}
Cluster validation succeeded
Done, listing cluster services:
Kubernetes master is running at https://kube-20160531-161525.westus.cloudapp.azure.com:6443It starts fourĀ nodes of Standard_A1 size. Each nodeĀ gives you 1 core, 1.75 GB RAM, and 40GB HDD.
Run Docker Container in Kubernetes Cluster onĀ Azure
Now that the cluster is up and running,Ā get a list of all the nodes:
./kubernetes/cluster/kubectl.sh get no NAME STATUS AGE kube-20160531-161525-vm-master Ready,SchedulingDisabled 3m kube-20160531-161525-vm-node-0 Ready 3m kube-20160531-161525-vm-node-1 Ready 3m kube-20160531-161525-vm-node-2 Ready 3m
Four instances are created as shown ā one for master node and three for worker nodes.
Azure Portal shows all the created artifacts in the Resource Group:
FourĀ instances are created as shown ā one for master node and threeĀ for worker nodes.
Azure PortalĀ showsĀ all the created artifacts in the Resource Group:
More details about the created nodes isĀ available:
Create a Couchbase pod:
./kubernetes/cluster/kubectl.sh run couchbase --image=arungupta/couchbase deployment "couchbase" created
Notice, how the image name can be specified on the CLI. Kubernetes pre-1.2 versions created a Replication Controller with this command. This is explained in Ā Kubernetes onĀ Amazon Web Services or Kubernetes onĀ Google Cloud.Ā Kubernetes 1.2 introduced DeploymentsĀ and so this creates a Deployment instead. This enablesĀ simplified application deployment and management including versioning, multiple simultaneous rollouts, aggregating status across all pods, maintaining application availability and rollback.
The pod uses arungupta/couchbase Docker image that provides a pre-configured Couchbase server. Any Docker image can be specified here.
Status of the pod can be watched:
./kubernetes/cluster/kubectl.sh get -w po NAME READY STATUS RESTARTS AGE couchbase-2830197765-f0s9c 0/1 ContainerCreating 0 5s NAME READY STATUS RESTARTS AGE couchbase-2830197765-f0s9c 1/1 Running 0 1m
Get more details about the pod:
./kubernetes/cluster/kubectl.sh describe po couchbase-2830197765-f0s9c
Name: couchbase-2830197765-f0s9c
Namespace: default
Node: kube-20160531-161525-vm-node-2/10.0.0.6
Start Time: Tue, 31 May 2016 16:28:02 -0700
Labels: pod-template-hash=2830197765,run=couchbase
Status: Running
IP: 10.2.74.2
Controllers: ReplicaSet/couchbase-2830197765
Containers:
couchbase:
Container ID: docker://eba043085c95645cf650206469be5c7e2d6c7395883a053d197446a14e757440
Image: arungupta/couchbase
Image ID: docker://sha256:f6b013d9694354148ace6804127dadee01c733151b5ff5e169f7c3b0e4faf321
Port:
QoS Tier:
cpu: BestEffort
memory: BestEffort
State: Running
Started: Tue, 31 May 2016 16:29:04 -0700
Ready: True
Restart Count: 0
Environment Variables:
Conditions:
Type Status
Ready True
Volumes:
default-token-ylszs:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-ylszs
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
7m 7m 1 {default-scheduler } Normal Scheduled Successfully assigned couchbase-2830197765-f0s9c to kube-20160531-161525-vm-node-2
7m 7m 1 {kubelet kube-20160531-161525-vm-node-2} spec.containers{couchbase} Normal Pulling pulling image "arungupta/couchbase"
6m 6m 1 {kubelet kube-20160531-161525-vm-node-2} spec.containers{couchbase} Normal Pulled Successfully pulled image "arungupta/couchbase"
6m 6m 1 {kubelet kube-20160531-161525-vm-node-2} spec.containers{couchbase} Normal Created Created container with docker id eba043085c95
6m 6m 1 {kubelet kube-20160531-161525-vm-node-2} spec.containers{couchbase} Normal Started Started container with docker id eba043085c95
Expose Pod on Kubernetes as Service
Now that our pod is running, how do I access the Couchbase server? You need to expose the Deployment as a ServiceĀ outside the Kubernetes cluster.
Typically, this will be exposed using the command:
./kubernetes/cluster/kubectl.sh expose deployment couchbase --target-port=8091 --port=8091 --type=LoadBalancer
But Azure does not support --type=LoadBalancer at this time. This feature is being worked upon and will hopefully be availableĀ in the near future. So in the meanwhile, weāll expose the Service as:
./kubernetes/cluster/kubectl.sh expose deployment couchbase --target-port=8091 --port=8091 service "couchbase" exposed
Now proxy to this Service using kubectl proxy command:
./kubernetes/cluster/kubectl.sh proxy --address='0.0.0.0' --port=9999 --accept-hosts='.*' Starting to serve on [::]:9999
And now this exposed Service is accessible atĀ http://127.0.0.1:9999/api/v1/proxy/namespaces/default/services/couchbase/index.html. This shows the login screen of Couchbase Web Console:
Shutdown Kubernetes Cluster
Finally, shutdown the cluster using cluster/kube-down.sh script.
./kubernetes/cluster/kube-down.sh Bringing down cluster using provider: azure Bringing down cluster You must do this manually (for now)! This can be done with: ./kubernetes/cluster/../cluster/../cluster/azure/util.sh: line 246: AZ_RESOURCE_GROUP: unbound variable
This script shuts down the cluster but the AzureĀ resource group need to be explicitly removed. This can be done by selecting the Resource Group from portal.azure.com:
This is filed asĀ #26601.
Enjoy!
| Reference: | Kubernetes Cluster on Azure and Expose Couchbase Service from our JCG partner Arun Gupta at the Miles to go 3.0 ⦠blog. |












