Setup & Running First App

Setup on Azure

Please refer to this guide.

Running First App

  • Let's run an application on the new Kubernetes cluster
  • Before we can launch a container based on the image, we need to create a pod definition
    • A pod describes an application running on Kubernetes
    • A pod can contain one or more tightly coupled containers, that make up the app
      • Those apps can easily communicate with each other using their local
  • Our app has only one container

Create a Pod

Create a file pod-helloworld.yml with the pod definition:

apiVersion: v1
kind: Pod
    app: helloworld
    - name: k8s-demo
      image: wardviaene/k8s-demo
        - containerPort: 3000

Use kubectl to create the pod on the kubernetes cluster:

$ kubectl create -f pod-helloworld.yml
pod "" created

See pod status

$ kubectl get pod
NAME                         READY     STATUS    RESTARTS   AGE   1/1       Running   0          2m

See pod config

$ kubectl describe pod
Namespace:	default
Node:		k8s-agent-7d111633-0/
Start Time:	Sun, 29 Apr 2018 04:36:37 +0000
Labels:		app=helloworld
Annotations:	<none>
Status:		Running
    Container ID:	docker://dddf1e925faf9c3fee56b373244bb7227d7f4c139c76816dbafb8237d6d00515
    Image:		wardviaene/k8s-demo
    Image ID:		docker-pullable://wardviaene/k8s-demo@sha256:2c050f462f5d0b3a6430e7869bcdfe6ac48a447a89da79a56d0ef61460c7ab9e
    Port:		3000/TCP
    State:		Running
      Started:		Sun, 29 Apr 2018 04:37:46 +0000
    Ready:		True
    Restart Count:	0
    Environment:	<none>
      /var/run/secrets/ from default-token-lr576 (ro)
  Type		Status
  Initialized 	True
  Ready 	True
  PodScheduled 	True
    Type:	Secret (a volume populated by a Secret)
    SecretName:	default-token-lr576
    Optional:	false
QoS Class:	BestEffort
Node-Selectors:	<none>
Tolerations:	<none>
  FirstSeen	LastSeen	Count	From				SubObjectPath			Type		Reason		      	Message
  ---------	--------	-----	----				-------------			--------	------		      	-------
  4m		4m		1	default-scheduler						Normal		Scheduled	      	Successfully assigned to k8s-agent-7d111633-0
  4m		4m		1	kubelet, k8s-agent-7d111633-0					Normal		SuccessfulMountVolume  	MountVolume.SetUp succeeded for volume "default-token-lr576"
  4m		4m		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Pulling		      	pulling image "wardviaene/k8s-demo"
  2m		2m		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Pulled		      	Successfully pulled image "wardviaene/k8s-demo"
  2m		2m		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Created		      	Created container
  2m		2m		1	kubelet, k8s-agent-7d111633-0	spec.containers{k8s-demo}	Normal		Started		      	Started container

Forward port

$ kubectl port-forward 8081:3000
Forwarding from -> 3000
Forwarding from [::1]:8081 -> 3000

Create Service

Expose service

$ kubectl expose pod --type=NodePort --name nodehelloworld-service
service "nodehelloworld-service" exposed

See list of service

$ kubectl get service
NAME                     CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
kubernetes           <none>        443/TCP          7d
nodehelloworld-service   <nodes>       3000:30706/TCP   25s

Get service url

$ kubectl describe service nodehelloworld-service
Name:				nodehelloworld-service
Namespace:			default
Labels:				app=helloworld
Annotations:		<none>
Selector:			app=helloworld
Type:				NodePort
Port:				<unset>	3000/TCP
NodePort:			<unset>	30706/TCP
Session Affinity:	None
Events:				<none>

Try accessing app locally

$ curl
Hello World!

Access From the Internet

Edit service with VI

$ kubectl edit service/nodehelloworld-service
service "nodehelloworld-service" edited

Change externalTrafficPolicy to Local and change type to LoadBalancer.

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
apiVersion: v1
kind: Service
  creationTimestamp: 2018-04-29T04:44:16Z
    app: helloworld
  name: nodehelloworld-service
  namespace: default
  resourceVersion: "109236"
  selfLink: /api/v1/namespaces/default/services/nodehelloworld-service
  uid: f8e985ab-4b67-11e8-9b4e-000d3aa08982
  externalTrafficPolicy: Local
  healthCheckNodePort: 31970
  - nodePort: 30706
    port: 3000
    protocol: TCP
    targetPort: 3000
    app: helloworld
  sessionAffinity: None
  type: LoadBalancer
    - ip:

VI Usage: Press i to enter edit mode. Once done, press ESC and type :wq to save and quite.

Check service using kubectl get service

$ kubectl get service
NAME                     CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
kubernetes           <none>        443/TCP          7d
nodehelloworld-service   <pending>     3000:30706/TCP   56m

Wait for a few minutes until <pending> changing to an IP address

$ kubectl get service
NAME                     CLUSTER-IP    EXTERNAL-IP      PORT(S)          AGE
kubernetes           <none>           443/TCP          7d
nodehelloworld-service   3000:30706/TCP   59m

Try to access the app at the displayed IP:port e.g.


Useful Commands



kubectl get pod

Get information about all running pods

kubectl describe pod <pod>

Describe one pod

kubectl expose pod <pod> --port=444 --name=frontend

Expose the pod of a pod (creates a new service)

kubectl port-forward <pod> 8080

Pod forward the exposed pod port to your local machine

kubectl attach <pod> -i

Attach to the pod

kubectl exec <pod> -- <command>

Execute a command on the pod

kubectl label pod <pod> mylabel=awesome

Add a new label to a pod

kubectl run -i --tty busybox --image=busybox --restart=never -- sh

Run a shell in a pod, very useful for debugging

Revision #3
Created Tue, May 1, 2018 6:29 AM by Chairat (Par)
Updated Fri, Feb 5, 2021 1:24 PM by Chairat (Par)