Build and Deploy a Docker Image to a Kubernetes Cluster
Challenge scenario
Your development team is interested in adopting a containerized microservices approach to application architecture. You need to test a sample application they have provided for you to make sure that it can be deployed to a Google Kubernetes container. The development group provided a simple Go application called echo-web
with a Dockerfile and the associated context that allows you to build a Docker image immediately.
Your challenge
To test the deployment, you need to download the sample application, then build the Docker container image using a tag that allows it to be stored on the Container Registry. Once the image has been built, you’ll push it out to the Container Registry before you can deploy it.
With the image prepared you can then create a Kubernetes cluster, then deploy the sample application to the cluster.
Create a Kubernetes cluster
- Your test environment is limited in capacity, so you should limit the test Kubernetes cluster you are creating to just two
e2-standard-2
instances. You must call your clusterecho-cluster
.
Build a tagged Docker image
The sample application, including the Dockerfile and the application context files, are contained in an archive called echo-web.tar.gz
. The archive has been copied to a Cloud Storage bucket belonging to your lab project called gs://[PROJECT_ID].
- You must deploy this with a tag called
v1.
Push the image to the Google Container Registry
- Your organization has decided that it will always use the
gcr.io
Container Registry hostname for all projects. The sample application is a simple web application that reports some data describing the configuration of the system where the application is running. It is configured to use TCP port 8000 by default.
Deploy the application to the Kubernetes cluster
- Even though the application is configured to respond to HTTP requests on port 8000, you must configure the service to respond to normal web requests on port 80. When configuring the cluster for your sample application, call your deployment
echo-web
.
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to qwiklabs-gcp-02-b72e20704fdb.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ gcloud container clusters create echo-cluster --zone=us-east4-b --num-nodes 2 --machine-type=e2-standard-2
Default change: VPC-native is the default mode during cluster creation for versions greater than 1.21.0-gke.1500. To create advanced routes based clusters, please pass the `--no-enable-ip-alias` flag
Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
Creating cluster echo-cluster in us-east4-b... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/qwiklabs-gcp-02-b72e20704fdb/zones/us-east4-b/clusters/echo-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-east4-b/echo-cluster?project=qwiklabs-gcp-02-b72e20704fdb
kubeconfig entry generated for echo-cluster.
NAME: echo-cluster
LOCATION: us-east4-b
MASTER_VERSION: 1.28.8-gke.1095000
MASTER_IP: 34.85.218.181
MACHINE_TYPE: e2-standard-2
NODE_VERSION: 1.28.8-gke.1095000
NUM_NODES: 2
STATUS: RUNNING
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ gsutil cp gs://qwiklabs-gcp-02-b72e20704fdb/echo-web.tar.gz .
Copying gs://qwiklabs-gcp-02-b72e20704fdb/echo-web.tar.gz...
/ [1 files][ 2.0 KiB/ 2.0 KiB]
Operation completed over 1 objects/2.0 KiB.
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ ls
echo-web.tar.gz README-cloudshell.txt
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ tar -xvf echo-web.tar.gz
./
./README.md
./main.go
./manifests/
./manifests/echoweb-deployment.yaml
./manifests/echoweb-service-static-ip.yaml
./manifests/echoweb-ingress-static-ip.yaml
./Dockerfile
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ ls
Dockerfile echo-web.tar.gz main.go manifests README-cloudshell.txt README.md
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ cat Dockerfile
FROM golang:1.8-alpine
ADD . /go/src/echo-app
RUN go install echo-app
FROM alpine:latest
COPY --from=0 /go/bin/echo-app .
ENV PORT 8000
CMD ["./echo-app"]
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ gcloud auth configure-docker
WARNING: Your config file at [/home/student_02_0bc8a0c336eb/.docker/config.json] contains these credential helper entries:
{
"credHelpers": {
"africa-south1-docker.pkg.dev": "gcloud",
"asia-docker.pkg.dev": "gcloud",
"asia-east1-docker.pkg.dev": "gcloud",
"asia-east2-docker.pkg.dev": "gcloud",
"asia-northeast1-docker.pkg.dev": "gcloud",
"asia-northeast2-docker.pkg.dev": "gcloud",
"asia-northeast3-docker.pkg.dev": "gcloud",
"asia-south1-docker.pkg.dev": "gcloud",
"asia-south2-docker.pkg.dev": "gcloud",
"asia-southeast1-docker.pkg.dev": "gcloud",
"asia-southeast2-docker.pkg.dev": "gcloud",
"australia-southeast1-docker.pkg.dev": "gcloud",
"australia-southeast2-docker.pkg.dev": "gcloud",
"europe-docker.pkg.dev": "gcloud",
"europe-central2-docker.pkg.dev": "gcloud",
"europe-north1-docker.pkg.dev": "gcloud",
"europe-southwest1-docker.pkg.dev": "gcloud",
"europe-west1-docker.pkg.dev": "gcloud",
"europe-west10-docker.pkg.dev": "gcloud",
"europe-west12-docker.pkg.dev": "gcloud",
"europe-west2-docker.pkg.dev": "gcloud",
"europe-west3-docker.pkg.dev": "gcloud",
"europe-west4-docker.pkg.dev": "gcloud",
"europe-west6-docker.pkg.dev": "gcloud",
"europe-west8-docker.pkg.dev": "gcloud",
"europe-west9-docker.pkg.dev": "gcloud",
"me-central1-docker.pkg.dev": "gcloud",
"me-central2-docker.pkg.dev": "gcloud",
"me-west1-docker.pkg.dev": "gcloud",
"northamerica-northeast1-docker.pkg.dev": "gcloud",
"northamerica-northeast2-docker.pkg.dev": "gcloud",
"southamerica-east1-docker.pkg.dev": "gcloud",
"us-docker.pkg.dev": "gcloud",
"us-central1-docker.pkg.dev": "gcloud",
"us-central2-docker.pkg.dev": "gcloud",
"us-east1-docker.pkg.dev": "gcloud",
"us-east4-docker.pkg.dev": "gcloud",
"us-east5-docker.pkg.dev": "gcloud",
"us-east7-docker.pkg.dev": "gcloud",
"us-south1-docker.pkg.dev": "gcloud",
"us-west1-docker.pkg.dev": "gcloud",
"us-west2-docker.pkg.dev": "gcloud",
"us-west3-docker.pkg.dev": "gcloud",
"us-west4-docker.pkg.dev": "gcloud"
}
}
Adding credentials for all GCR repositories.
WARNING: A long list of credential helpers may cause delays running 'docker build'. We recommend passing the registry name to configure only the registry you are using.
After update, the following will be written to your Docker config file located at [/home/student_02_0bc8a0c336eb/.docker/config.json]:
{
"credHelpers": {
"africa-south1-docker.pkg.dev": "gcloud",
"asia-docker.pkg.dev": "gcloud",
"asia-east1-docker.pkg.dev": "gcloud",
"asia-east2-docker.pkg.dev": "gcloud",
"asia-northeast1-docker.pkg.dev": "gcloud",
"asia-northeast2-docker.pkg.dev": "gcloud",
"asia-northeast3-docker.pkg.dev": "gcloud",
"asia-south1-docker.pkg.dev": "gcloud",
"asia-south2-docker.pkg.dev": "gcloud",
"asia-southeast1-docker.pkg.dev": "gcloud",
"asia-southeast2-docker.pkg.dev": "gcloud",
"australia-southeast1-docker.pkg.dev": "gcloud",
"australia-southeast2-docker.pkg.dev": "gcloud",
"europe-docker.pkg.dev": "gcloud",
"europe-central2-docker.pkg.dev": "gcloud",
"europe-north1-docker.pkg.dev": "gcloud",
"europe-southwest1-docker.pkg.dev": "gcloud",
"europe-west1-docker.pkg.dev": "gcloud",
"europe-west10-docker.pkg.dev": "gcloud",
"europe-west12-docker.pkg.dev": "gcloud",
"europe-west2-docker.pkg.dev": "gcloud",
"europe-west3-docker.pkg.dev": "gcloud",
"europe-west4-docker.pkg.dev": "gcloud",
"europe-west6-docker.pkg.dev": "gcloud",
"europe-west8-docker.pkg.dev": "gcloud",
"europe-west9-docker.pkg.dev": "gcloud",
"me-central1-docker.pkg.dev": "gcloud",
"me-central2-docker.pkg.dev": "gcloud",
"me-west1-docker.pkg.dev": "gcloud",
"northamerica-northeast1-docker.pkg.dev": "gcloud",
"northamerica-northeast2-docker.pkg.dev": "gcloud",
"southamerica-east1-docker.pkg.dev": "gcloud",
"us-docker.pkg.dev": "gcloud",
"us-central1-docker.pkg.dev": "gcloud",
"us-central2-docker.pkg.dev": "gcloud",
"us-east1-docker.pkg.dev": "gcloud",
"us-east4-docker.pkg.dev": "gcloud",
"us-east5-docker.pkg.dev": "gcloud",
"us-east7-docker.pkg.dev": "gcloud",
"us-south1-docker.pkg.dev": "gcloud",
"us-west1-docker.pkg.dev": "gcloud",
"us-west2-docker.pkg.dev": "gcloud",
"us-west3-docker.pkg.dev": "gcloud",
"us-west4-docker.pkg.dev": "gcloud",
"gcr.io": "gcloud",
"us.gcr.io": "gcloud",
"eu.gcr.io": "gcloud",
"asia.gcr.io": "gcloud",
"staging-k8s.gcr.io": "gcloud",
"marketplace.gcr.io": "gcloud"
}
}
Do you want to continue (Y/n)? y
Docker configuration file updated.
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ docker build -t gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1 .
[+] Building 1.8s (11/11) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 195B 0.0s
=> [internal] load metadata for docker.io/library/golang:1.8-alpine 0.7s
=> [internal] load metadata for docker.io/library/alpine:latest 0.7s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2.94kB 0.0s
=> [stage-1 1/2] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b 0.0s
=> CACHED [stage-0 1/3] FROM docker.io/library/golang:1.8-alpine@sha256:693568f2ab0dae1e19f44b41628d2aea148fac65974cfd18f83cb9863ab1a177 0.0s
=> [stage-0 2/3] ADD . /go/src/echo-app 0.0s
=> [stage-0 3/3] RUN go install echo-app 0.8s
=> CACHED [stage-1 2/2] COPY --from=0 /go/bin/echo-app . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:d106b3841d829ea2adb605a84a243a7f68cbc4c4e737f2d52a11ed65d6627935 0.0s
=> => naming to gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1 0.0s
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ docker push gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
The push refers to repository [gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app]
41e88e995997: Layer already exists
d4fc045c9e3a: Layer already exists
v1: digest: sha256:c8a231ae40d1fd98ef21353cd1e637c8ef2805bff87a272357d95e810ce93f75 size: 739
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-echo-cluster-default-pool-15cbea64-l757 Ready <none> 24m v1.28.8-gke.1095000
gke-echo-cluster-default-pool-15cbea64-ldmp Ready <none> 24m v1.28.8-gke.1095000
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get deploy
No resources found in default namespace.
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl create deploy -h
Create a deployment with the specified name.
Aliases:
deployment, deploy
Examples:
# Create a deployment named my-dep that runs the busybox image
kubectl create deployment my-dep --image=busybox
# Create a deployment with a command
kubectl create deployment my-dep --image=busybox -- date
# Create a deployment named my-dep that runs the nginx image with 3 replicas
kubectl create deployment my-dep --image=nginx --replicas=3
# Create a deployment named my-dep that runs the busybox image and expose port 5701
kubectl create deployment my-dep --image=busybox --port=5701
Options:
--allow-missing-template-keys=true:
If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to
golang and jsonpath output formats.
--dry-run='none':
Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without
sending it. If server strategy, submit server-side request without persisting the resource.
--field-manager='kubectl-create':
Name of the manager used to track field ownership.
--image=[]:
Image names to run.
-o, --output='':
Output format. One of: (json, yaml, name, go-template, go-template-file, template, templatefile, jsonpath,
jsonpath-as-json, jsonpath-file).
--port=-1:
The port that this container exposes.
-r, --replicas=1:
Number of replicas to create. Default is 1.
--save-config=false:
If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will
be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--show-managed-fields=false:
If true, keep the managedFields when printing objects in JSON or YAML format.
--template='':
Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format
is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate='strict':
Must be one of: strict (or true), warn, ignore (or false). "true" or "strict" will use a schema to validate
the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation
is enabled on the api-server, but will fall back to less reliable client-side validation if not. "warn" will
warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled
on the API server, and behave as "ignore" otherwise. "false" or "ignore" will not perform any schema
validation, silently dropping any unknown or duplicate fields.
Usage:
kubectl create deployment NAME --image=image -- [COMMAND] [args...] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl create deployment echo-web --image=gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
deployment.apps/echo-web created
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
echo-web-5cd58676b4-jsjcd 1/1 Running 0 5s
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
echo-web-5cd58676b4-jsjcd 1/1 Running 0 11s 10.88.1.11 gke-echo-cluster-default-pool-15cbea64-l757 <none> <none>
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ docker run -p 8000:8000 --name echo-app -d gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
dd4ea2901da065fe381c72c35e0e10125e6f828dc7059887822f3da797ace872
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl exec -it echo-web-5cd58676b4-jsjcd -- ash
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1460 qdisc noqueue state UP
link/ether 86:ac:c0:3a:74:b8 brd ff:ff:ff:ff:ff:ff
inet 10.88.1.11/24 brd 10.88.1.255 scope global eth0
valid_lft forever preferred_lft forever
/ # curl localhost:8000
ash: curl: not found
/ # ps
PID USER TIME COMMAND
1 root 0:00 ./echo-app
17 root 0:00 ash
24 root 0:00 ps
/ # apt-get install curl
ash: apt-get: not found
/ # yum install curl
ash: yum: not found
/ # apt install curl
ash: apt: not found
/ # dnf curl
ash: dnf: not found
/ # exit
command terminated with exit code 127
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
echo-web 1/1 1 1 3m57s
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl expose deploy echo-web -h
Expose a resource as a new Kubernetes service.
Looks up a deployment, service, replica set, replication controller or pod by name and uses the selector for that
resource as the selector for a new service on the specified port. A deployment or replica set will be exposed as a
service only if its selector is convertible to a selector that service supports, i.e. when the selector contains only
the matchLabels component. Note that if no port is specified via --port and the exposed resource has multiple ports, all
will be re-used by the new service. Also if no labels are specified, the new service will re-use the labels from the
resource it exposes.
Possible resources include (case insensitive):
pod (po), service (svc), replicationcontroller (rc), deployment (deploy), replicaset (rs)
Examples:
# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000
kubectl expose rc nginx --port=80 --target-port=8000
# Create a service for a replication controller identified by type and name specified in "nginx-controller.yaml",
which serves on port 80 and connects to the containers on port 8000
kubectl expose -f nginx-controller.yaml --port=80 --target-port=8000
# Create a service for a pod valid-pod, which serves on port 444 with the name "frontend"
kubectl expose pod valid-pod --port=444 --name=frontend
# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name
"nginx-https"
kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https
# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.
kubectl expose rc streamer --port=4100 --protocol=UDP --name=video-stream
# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on
port 8000
kubectl expose rs nginx --port=80 --target-port=8000
# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000
kubectl expose deployment nginx --port=80 --target-port=8000
Options:
--allow-missing-template-keys=true:
If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to
golang and jsonpath output formats.
--cluster-ip='':
ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless
service.
--dry-run='none':
Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without
sending it. If server strategy, submit server-side request without persisting the resource.
--external-ip='':
Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to
a node, the service can be accessed by this IP in addition to its generated service IP.
--field-manager='kubectl-expose':
Name of the manager used to track field ownership.
-f, --filename=[]:
Filename, directory, or URL to files identifying the resource to expose a service
-k, --kustomize='':
Process the kustomization directory. This flag can't be used together with -f or -R.
-l, --labels='':
Labels to apply to the service created by this call.
--load-balancer-ip='':
IP to assign to the LoadBalancer. If empty, an ephemeral IP will be created and used (cloud-provider
specific).
--name='':
The name for the newly created object.
-o, --output='':
Output format. One of: (json, yaml, name, go-template, go-template-file, template, templatefile, jsonpath,
jsonpath-as-json, jsonpath-file).
--override-type='merge':
The method used to override the generated object: json, merge, or strategic.
--overrides='':
An inline JSON override for the generated object. If this is non-empty, it is used to override the generated
object. Requires that the object supply a valid apiVersion field.
--port='':
The port that the service should serve on. Copied from the resource being exposed, if unspecified
--protocol='':
The network protocol for the service to be created. Default is 'TCP'.
-R, --recursive=false:
Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests
organized within the same directory.
--save-config=false:
If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will
be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--selector='':
A label selector to use for this service. Only equality-based selector requirements are supported. If empty
(the default) infer the selector from the replication controller or replica set.)
--session-affinity='':
If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'
--show-managed-fields=false:
If true, keep the managedFields when printing objects in JSON or YAML format.
--target-port='':
Name or number for the port on the container that the service should direct traffic to. Optional.
--template='':
Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format
is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--type='':
Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.
Usage:
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name]
[--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
gke-echo-cluster-default-pool-15cbea64-l757 Ready <none> 31m v1.28.8-gke.1095000 10.150.0.5 34.145.144.92 Container-Optimized OS from Google 6.1.75+ containerd://1.7.13
gke-echo-cluster-default-pool-15cbea64-ldmp Ready <none> 31m v1.28.8-gke.1095000 10.150.0.4 34.85.137.235 Container-Optimized OS from Google 6.1.75+ containerd://1.7.13
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
echo-web-5cd58676b4-jsjcd 1/1 Running 0 6m40s
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl describe pods echo-web-5cd58676b4-jsjcd
Name: echo-web-5cd58676b4-jsjcd
Namespace: default
Priority: 0
Service Account: default
Node: gke-echo-cluster-default-pool-15cbea64-l757/10.150.0.5
Start Time: Tue, 21 May 2024 08:48:10 +0000
Labels: app=echo-web
pod-template-hash=5cd58676b4
Annotations: <none>
Status: Running
IP: 10.88.1.11
IPs:
IP: 10.88.1.11
Controlled By: ReplicaSet/echo-web-5cd58676b4
Containers:
echo-app:
Container ID: containerd://0da1200b4edb7e68a5e167fe662147006789d110b507dc9bcb9cf120901eadf3
Image: gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
Image ID: gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app@sha256:c8a231ae40d1fd98ef21353cd1e637c8ef2805bff87a272357d95e810ce93f75
Port: <none>
Host Port: <none>
State: Running
Started: Tue, 21 May 2024 08:48:12 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rmrgp (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-rmrgp:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m51s default-scheduler Successfully assigned default/echo-web-5cd58676b4-jsjcd to gke-echo-cluster-default-pool-15cbea64-l757
Normal Pulling 6m50s kubelet Pulling image "gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1"
Normal Pulled 6m49s kubelet Successfully pulled image "gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1" in 1.575s (1.575s including waiting)
Normal Created 6m49s kubelet Created container echo-app
Normal Started 6m49s kubelet Started container echo-app
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl logs echo-web-5cd58676b4-jsjcd
2024/05/21 08:48:12 Server listening on port 8000
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ curl 0.88.1.11:8000
^C
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl logs echo-web-5cd58676b4-jsjcd
2024/05/21 08:48:12 Server listening on port 8000
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl logs echo-web-5cd58676b4-jsjcd
2024/05/21 08:48:12 Server listening on port 8000
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl expose deploy echo-web --port=80 --target-port=8000 --type=LoadBalancer
service/echo-web exposed
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 9s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 21s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 23s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 26s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 30s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 33s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 36s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 <pending> 80:32152/TCP 39s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 34.48.102.246 80:32152/TCP 42s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 37m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ kubectl get svc
cuNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-web LoadBalancer 10.84.138.89 34.48.102.246 80:32152/TCP 71s
kubernetes ClusterIP 10.84.128.1 <none> 443/TCP 38m
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ curl 34.48.102.246
Echo Test
Version: 1.0.0
Hostname: echo-web-5cd58676b4-jsjcd
Host ip-address(es): 10.88.1.11
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$ history
1 gcloud container clusters create echo-cluster --zone=us-east4-b --num-nodes 2 --machine-type=e2-standard-2
2 gsutil cp gs://qwiklabs-gcp-02-b72e20704fdb/echo-web.tar.gz .
3 ls
4 tar -xvf echo-web.tar.gz
5 ls
6 cat Dockerfile
7 gcloud auth configure-docker us-east4-docker.pkg.dev
8 gcloud auth configure-docker
{snip}
27 docker images
28 docker build -t gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1 .
29 docker push gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
30 kubectl get nodes
31 kubectl get deploy
32 kubectl create deploy -h
33 kubectl create deployment echo-web --image=gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
34 kubectl get pods
35 kubectl get pods -o wide
36 curl 10.88.1.11:8080
37 curl 10.88.1.11:8000
38 docker run -p 8000:8000 --name echo-app -d gcr.io/qwiklabs-gcp-02-b72e20704fdb/echo-app:v1
{snip}
43 kubectl get deploy
44 kubectl expose deploy echo-web -h
{snip}
58 kubectl expose deploy echo-web --port=80 --target-port=8000 --type=LoadBalancer
59 kubectl get svc
60 curl 34.48.102.246
61 history
student_02_0bc8a0c336eb@cloudshell:~ (qwiklabs-gcp-02-b72e20704fdb)$