Accessing and exposing Pods with Services
Pods are supposed to be temporary or short-lived. Once they crash, they are gone, and the ReplicaSet ensures to bring up a new Pod to maintain the desired number of replicas.
Let's say we are running a web frontend in a container within Pods. Each Pod gets a unique IP address. However, due to their temporary nature, we cannot rely on that IP address.
Let's create a deployment that runs a web frontend:
apiVersion: apps/v1 kind: Deployment metadata: name: web-frontend labels: app.kubernetes.io/name: web-frontend spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: web-frontend template: metadata: labels: app.kubernetes.io/name: web-frontend spec: containers: - name: web-frontend-container image: learncloudnative/helloworld:0.1.0 ports: - containerPort: 3000
Comparing this deployment to the previous one, you will notice we changed the resource names and the image we are using.
One new thing we added to the deployment is the
ports section. Using the
containerPort field, we set the port number website server listens on. The
learncloudnative/helloworld:0.1.0 is a simple Node.js Express application.
Save the above YAML in
web-frontend.yaml and create the deployment:
$ kubectl apply -f web-frontend.yaml deployment.apps/web-frontend created
kubectl get pods to ensure Pod is up and running and then get the logs from the container:
$ kubectl get po NAME READY STATUS RESTARTS AGE web-frontend-68f784d855-rdt97 1/1 Running 0 65s $ kubectl logs web-frontend-68f784d855-rdt97 > firstname.lastname@example.org start /app > node server.js Listening on port 3000
From the logs, you will notice that the container is listening on port
3000. If we set the output flag to gives up the wide output (
-o wide), you'll notice the Pods' IP address -
$ kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-frontend-68f784d855-rdt97 1/1 Running 0 15s 172.17.0.4 minikube <none> <none>
If we delete this Pod, a new one will take its' place, and it will get a brand new IP address as well:
$ kubectl delete po web-frontend-68f784d855-rdt97 pod "web-frontend-68f784d855-rdt97" deleted $ kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-frontend-68f784d855-8c76m 1/1 Running 0 15s 172.17.0.5 minikube <none> <none>
Similarly, if we scale up the deployment to four Pods, we will four different IP addresses:
$ kubectl scale deploy web-frontend --replicas=4 deployment.apps/web-frontend scaled $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-frontend-68f784d855-8c76m 1/1 Running 0 5m23s 172.17.0.5 minikube <none> <none> web-frontend-68f784d855-jrqq4 1/1 Running 0 18s 172.17.0.6 minikube <none> <none> web-frontend-68f784d855-mftl6 1/1 Running 0 18s 172.17.0.7 minikube <none> <none> web-frontend-68f784d855-stfqj 1/1 Running 0 18s 172.17.0.8 minikube <none> <none>
How to access the Pods without a service?
If you try to send a request to one of those IP addresses, it's not going to work:
$ curl -v 172.17.0.5:3000 * Trying 172.17.0.5... * TCP_NODELAY set * Connection failed * connect to 172.17.0.5 port 3000 failed: Network is unreachable * Failed to connect to 172.17.0.5 port 3000: Network is unreachable * Closing connection 0 curl: (7) Failed to connect to 172.17.0.5 port 3000: Network is unreachable
The Pods are running within the cluster, and that IP address is only accessible from within the cluster.
For the testing purposes, you can run a pod inside the cluster and then get shell access to that Pod. Yes, that is possible!
radialbusyboxplus:curl is the image I frequently run inside the cluster if I need to check something or debug things. Using the
--tty flags, we are want to allocate a terminal (
tty), and that we want an interactive session so that we can run commands directly inside the container.
I usually name this Pod
curl, but you can name it whatever you like:
$ kubectl run curl --image=radial/busyboxplus:curl -i --tty If you dont see a command prompt, try pressing enter. [ root@curl:/ ]$
Now that we have access to the the terminal running inside the container that' inside the cluster, we can run the same cURL command as before:
[ root@curl:/ ]$ curl -v 172.17.0.5:3000 > GET / HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 172.17.0.5:3000 > Accept: */* > < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/html; charset=utf-8 < Content-Length: 111 < ETag: W/"6f-U4ut6Q03D1uC/sbzBDyZfMqFSh0" < Date: Wed, 20 May 2020 22:10:49 GMT < Connection: keep-alive < <link rel="stylesheet" type="text/css" href="css/style.css" /> <div class="container"> Hello World! </div>[ root@curl:/ ]$
This time, we get a response from the Pod! Make sure you run
exit to return to your terminal. The
curl Pod will continue to run and to reaccess it, you can use the
kubectl attach curl -c curl -i -t
You can get a terminal session to any container running inside the cluster using the attach command.