Objectives
--
-
- Learn about application Deployments. -
- Deploy your first app on Kubernetes with kubectl. -
-
+
- Learn about application Deployments. +
- Deploy your first app on Kubernetes with kubectl. +
Kubernetes Deployments
- Once you have a running Kubernetes cluster, you can deploy your containerized applications on top of it. - To do so, you create a Kubernetes Deployment configuration. The Deployment instructs Kubernetes + Once you have a running Kubernetes cluster, you can deploy your containerized applications on top of it. + To do so, you create a Kubernetes Deployment. The Deployment instructs Kubernetes how to create and update instances of your application. Once you've created a Deployment, the Kubernetes control plane schedules the application instances included in that Deployment to run on individual Nodes in the cluster.
-Once the application instances are created, a Kubernetes Deployment Controller continuously monitors those instances. If the Node hosting an instance goes down or is deleted, the Deployment controller replaces the instance with an instance on another Node in the cluster. This provides a self-healing mechanism to address machine failure or maintenance.
+Once the application instances are created, a Kubernetes Deployment controller continuously monitors those instances. If the Node hosting an instance goes down or is deleted, the Deployment controller replaces the instance with an instance on another Node in the cluster. This provides a self-healing mechanism to address machine failure or maintenance.
In a pre-orchestration world, installation scripts would often be used to start applications, but they did not allow recovery from machine failure. By both creating your application instances and keeping them running across Nodes, Kubernetes Deployments provide a fundamentally different approach to application management.
@@ -72,7 +74,7 @@Deploying your first app on Kubernetes
You can create and manage a Deployment by using the Kubernetes command line interface, Kubectl. Kubectl uses the Kubernetes API to interact with the cluster. In this module, you'll learn the most common Kubectl commands needed to create Deployments that run your applications on a Kubernetes cluster.
+You can create and manage a Deployment by using the Kubernetes command line interface, kubectl. Kubectl uses the Kubernetes API to interact with the cluster. In this module, you'll learn the most common Kubectl commands needed to create Deployments that run your applications on a Kubernetes cluster.
When you create a Deployment, you'll need to specify the container image for your application and the number of replicas that you want to run. You can change that information later by updating your Deployment; Modules 5 and 6 of the bootcamp discuss how you can scale and update your Deployments.
@@ -91,18 +93,69 @@Deploying your first app on Kubernetes
For your first Deployment, you'll use a hello-node application packaged in a Docker container that uses NGINX to echo back all the requests. (If you didn't already try creating a hello-node application and deploying it using a container, you can do that first by following the instructions from the Hello Minikube tutorial). -
- -
Now that you know what Deployments are, let's go to the online tutorial and deploy our first app!
+You will need to have installed kubectl as well. If you need to install it, visit install tools.
+Now that you know what Deployments are, let's deploy our first app!
+
kubectl basics
+The common format of a kubectl command is: kubectl action resource
This performs the specified action (like create, describe or delete) on the specified resource (like node or deployment). You can use --help
after the subcommand to get additional info about possible parameters (for example: kubectl get nodes --help
).
Check that kubectl is configured to talk to your cluster, by running the kubectl version
command.
Check that kubectl is installed and you can see both the client and the server versions.
+To view the nodes in the cluster, run the kubectl get nodes
command.
You see the available nodes. Later, Kubernetes will choose where to deploy our application based on Node available resources.
+Deploy an app
+Let’s deploy our first app on Kubernetes with the kubectl create deployment
command. We need to provide the deployment name and app image location (include the full repository url for images hosted outside Docker hub).
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
Great! You just deployed your first application by creating a deployment. This performed a few things for you:
+-
+
- searched for a suitable node where an instance of the application could be run (we have only 1 available node) +
- scheduled the application to run on that Node +
- configured the cluster to reschedule the instance on a new Node when needed +
To list your deployments use the kubectl get deployments
command:
kubectl get deployments
We see that there is 1 deployment running a single instance of your app. The instance is running inside a container on your node.
View the app
+Pods that are running inside Kubernetes are running on a private, isolated network.
+ By default they are visible from other pods and services within the same kubernetes cluster, but not outside that network.
+ When we use kubectl
, we're interacting through an API endpoint to communicate with our application.
We will cover other options on how to expose your application outside the kubernetes cluster in Module 4.
+The kubectl
command can create a proxy that will forward communications into the cluster-wide, private network. The proxy can be terminated by pressing control-C and won't show any output while its running.
You need to open a second terminal window to run the proxy.
+kubectl proxy
+
We now have a connection between our host (the online terminal) and the Kubernetes cluster. The proxy enables direct access to the API from these terminals.
+You can see all those APIs hosted through the proxy endpoint. For example, we can query the version directly through the API using the curl
command:
curl http://localhost:8001/version
kubectl proxy
that you started above is running in the second terminal.The API server will automatically create an endpoint for each pod, based on the pod name, that is also accessible through the proxy.
+First we need to get the Pod name, and we'll store in the environment variable POD_NAME:
+export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
+ echo Name of the Pod: $POD_NAME
You can access the Pod through the proxied API, by running:
+curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/
In order for the new Deployment to be accessible without using the proxy, a Service is required which will be explained in the next modules.
++ Once you're ready, move on to Viewing Pods and Nodes.
+ +Node overview
Troubleshooting with kubectl
-In Module 2, you used Kubectl command-line interface. You'll continue to use it in Module 3 to get information about deployed applications and their environments. The most common operations can be done with the following kubectl commands:
+In Module 2, you used the kubectl command-line interface. You'll continue to use it in Module 3 to get information about deployed applications and their environments. The most common operations can be done with the following kubectl subcommands:
-
-
- kubectl get - list resources -
- kubectl describe - show detailed information about a resource -
- kubectl logs - print the logs from a container in a pod -
- kubectl exec - execute a command on a container in a pod +
- kubectl get - list resources +
- kubectl describe - show detailed information about a resource +
- kubectl logs - print the logs from a container in a pod +
- kubectl exec - execute a command on a container in a pod
You can use these commands to see when applications were deployed, what their current statuses are, where they are running and what their configurations are.
@@ -124,14 +128,72 @@Troubleshooting with kubectl
Check application configuration
+Let's verify that the application we deployed in the previous scenario is running. We'll use the kubectl get
command and look for existing Pods:
kubectl get pods
If no pods are running, please wait a couple of seconds and list the Pods again. You can continue once you see one Pod running.
+Next, to view what containers are inside that Pod and what images are used to build those containers we run the kubectl describe pods
command:
kubectl describe pods
We see here details about the Pod’s container: IP address, the ports used and a list of events related to the lifecycle of the Pod.
+The output of the describe subcommand is extensive and covers some concepts that we didn’t explain yet, but don’t worry, they will become familiar by the end of this bootcamp.
+Note: the describe subcommand can be used to get detailed information about most of the Kubernetes primitives, including Nodes, Pods, and Deployments. The describe output is designed to be human readable, not to be scripted against.
Show the app in the terminal
+Recall that Pods are running in an isolated, private network - so we need to proxy access
+ to them so we can debug and interact with them. To do this, we'll use the kubectl proxy
command to run a proxy in a second terminal. Open a new terminal window, and in that new terminal, run:
kubectl proxy
Now again, we'll get the Pod name and query that pod directly through the proxy. + To get the Pod name and store it in the POD_NAME environment variable:
+export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
+ echo Name of the Pod: $POD_NAME
To see the output of our application, run a curl
request:
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
The URL is the route to the API of the Pod.
+View the container logs
+Anything that the application would normally send to standard output becomes logs for the container within the Pod. We can retrieve these logs using the kubectl logs
command:
kubectl logs "$POD_NAME"
Note: We don't need to specify the container name, because we only have one container inside the pod.
+Executing command on the container
+We can execute commands directly on the container once the Pod is up and running.
+ For this, we use the exec
subcommand and use the name of the Pod as a parameter. Let’s list the environment variables:
kubectl exec "$POD_NAME" -- env
Again, it's worth mentioning that the name of the container itself can be omitted since we only have a single container in the Pod.
+Next let’s start a bash session in the Pod’s container:
+kubectl exec -ti $POD_NAME -- bash
We have now an open console on the container where we run our NodeJS application. The source code of the app is in the server.js file:
+cat server.js
You can check that the application is up by running a curl command:
+curl http://localhost:8080
Note: here we used localhost because we executed the command inside the NodeJS Pod. If you cannot connect to localhost:8080, check to make sure you have run the kubectl exec
command and are launching the command from within the Pod
To close your container connection, type exit
.
+ Once you're ready, move on to Using A Service To Expose Your App.
+ +Objectives
- Learn about a Service in Kubernetes -
- Understand how labels and LabelSelector objects relate to a Service +
- Understand how labels and selectors relate to a Service
- Expose an application outside a Kubernetes cluster using a Service
Overview of Kubernetes Services
Kubernetes Pods are mortal. Pods have a lifecycle. When a worker node dies, the Pods running on the Node are also lost. A ReplicaSet might then dynamically drive the cluster back to the desired state via the creation of new Pods to keep your application running. As another example, consider an image-processing backend with 3 replicas. Those replicas are exchangeable; the front-end system should not care about backend replicas or even if a Pod is lost and recreated. That said, each Pod in a Kubernetes cluster has a unique IP address, even Pods on the same Node, so there needs to be a way of automatically reconciling changes among Pods so that your applications continue to function.
-A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services enable a loose coupling between dependent Pods. A Service is defined using YAML (preferred) or JSON, like all Kubernetes objects. The set of Pods targeted by a Service is usually determined by a LabelSelector (see below for why you might want a Service without including a selector
in the spec).
A Service in Kubernetes is an abstraction which defines a logical set of Pods and a policy by which to access them. Services enable a loose coupling between dependent Pods. A Service is defined using YAML or JSON, like all Kubernetes object manifests. The set of Pods targeted by a Service is usually determined by a label selector (see below for why you might want a Service without including a selector
in the spec).
Although each Pod has a unique IP address, those IPs are not exposed outside the cluster without a Service. Services allow your applications to receive traffic. Services can be exposed in different ways by specifying a type
in the ServiceSpec:
Although each Pod has a unique IP address, those IPs are not exposed outside the cluster without a Service. Services allow your applications to receive traffic. Services can be exposed in different ways by specifying a type
in the spec of the Service:
- ClusterIP (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.
- NodePort - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using
<NodeIP>:<NodePort>
. Superset of ClusterIP.
@@ -88,11 +92,75 @@
Services and Labels
Labels can be attached to objects at creation time or later on. They can be modified at any time. Let's expose our application now using a Service and apply some labels.
-Create a new Service
+Let’s verify that our application is running. We’ll use the kubectl get
command and look for existing Pods:
kubectl get pods
If no pods are running then it means the interactive environment is still reloading its previous state. Please wait a couple of seconds and list the Pods again. You can continue once you see the one Pod running.
+Next, let’s list the current Services from our cluster:
+kubectl get services
We have a Service called kubernetes that is created by default when minikube starts the cluster. + To create a new service and expose it to external traffic we'll use the expose command with NodePort as parameter.
+kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
Let's run again the get services
subcommand:
kubectl get services
We have now a running Service called kubernetes-bootcamp. Here we see that the Service received a unique cluster-IP, an internal port and an external-IP (the IP of the Node).
+To find out what port was opened externally (for the type: NodePort Service) we’ll run the describe service
subcommand:
kubectl describe services/kubernetes-bootcamp
Create an environment variable called NODE_PORT that has the value of the Node port assigned:
+export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
+ echo "NODE_PORT=$NODE_PORT"
Now we can test that the app is exposed outside of the cluster using curl
, the IP address of the Node and the externally exposed port:
curl http://"$(minikube ip):$NODE_PORT"
And we get a response from the server. The Service is exposed.
+Step 2: Using labels
+The Deployment created automatically a label for our Pod. With the describe deployment
subcommand you can see the name (the key) of that label:
kubectl describe deployment
Let’s use this label to query our list of Pods. We’ll use the kubectl get pods
command with -l as a parameter, followed by the label values:
kubectl get pods -l app=kubernetes-bootcamp
You can do the same to list the existing Services:
+kubectl get services -l app=kubernetes-bootcamp
Get the name of the Pod and store it in the POD_NAME environment variable:
+export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
+ echo "Name of the Pod: $POD_NAME"
To apply a new label we use the label
subcommand followed by the object type, object name and the new label:
kubectl label pods "$POD_NAME" version=v1
This will apply a new label to our Pod (we pinned the application version to the Pod), and we can check it with the describe pod command:
+kubectl describe pods "$POD_NAME"
We see here that the label is attached now to our Pod. And we can query now the list of pods using the new label:
+kubectl get pods -l version=v1
And we see the Pod.
+Deleting a service
+To delete Services you can use the delete service
subcommand. Labels can be used also here:
kubectl delete service -l app=kubernetes-bootcamp
Confirm that the Service is gone:
+kubectl get services
This confirms that our Service was removed. To confirm that route is not exposed anymore you can curl the previously exposed IP and port:
+curl http://"$(minikube ip):$NODE_PORT"
This proves that the application is not reachable anymore from outside of the cluster. + You can confirm that the app is still running with a curl from inside the pod:
+kubectl exec -ti $POD_NAME -- curl http://localhost:8080
We see here that the application is up. This is because the Deployment is managing the application. To shut down the application, you would need to delete the Deployment as well.
+ Once you're ready, move on to Running Multiple Instances of Your App.
+ +