Download the helloserver
source code:
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
Change to the sample code directory:
cd anthos-service-mesh-samples/docs/helloserver
The sample application is written in Python. It has the following components that communicate using REST:
server
: A basic server with one GET
endpoint, /
, that prints "hello world" to the terminal window.loadgen
: A script that sends traffic to the server
, with a configurable number of requests per second (RPS).To get familiar with the sample application, run it in Cloud Shell:
From the sample-apps/helloserver
directory, run the server
:
python3 server/server.py
On startup, the server
displays the following:
INFO:root:Starting server...
Open another terminal window so that you can send requests to the server
. To do this in Cloud Shell, click add Open a new tab to open another session.
In the new terminal window, send a request to the server
:
curl http://localhost:8080
The output from server
is the following:
Hello World!
In the same tab, change to the directory that contains the loadgen
script:
cd anthos-service-mesh-samples/docs/helloserver/loadgen
Create the following environment variables:
export SERVER_ADDR=http://localhost:8080
export REQUESTS_PER_SECOND=5
Start virtualenv
:
virtualenv --python python3 env
Activate the virtual environment:
source env/bin/activate
Install the requirements for loadgen
:
pip3 install -r requirements.txt
Run the loadgen
application to generate traffic for the server
:
python3 loadgen.py
On startup, the output from loadgen
is similar to the following:
Starting loadgen: 2024-10-11 09:49:51.798028 5 request(s) complete to http://localhost:8080
Now open the terminal window that's running the server
. You should see messages similar to the following:
127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.32.3 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive
From a networking perspective, the entire application is now running on the same host, which lets you use localhost
to send requests to the server
.
To stop the loadgen
and the server
, press Ctrl-c
in each terminal window.
In the loadgen
terminal window, deactivate the virtual environment:
deactivate
To run the application on GKE, you need to package both the components of the sample application into containers. A container is a package that contains all of the necessary elements for your application to run in any environment. This tutorial uses Docker to containerize the application.
To containerize the application with Docker, you need a Dockerfile
. A Dockerfile
is a text file that defines the commands needed to assemble the application source code and its dependencies into a container image. After you build the image, you upload it to a container registry, such as Artifact Registry.
The source code for this tutorial includes a Dockerfile
for both the server
and the loadgen
with all the commands required to build the images. The following is the Dockerfile
for the server
:
In this file, you can see the following:
FROM python:3-slim as base
instruction tells Docker to use the latest Python 3 image as the base image.COPY . .
instruction copies the source files from the current working directory (in this case, server.py
) to the container's file system.ENTRYPOINT
defines the instruction that is used to run the container. In this example, the instruction is similar to the one you used to run server.py
from the source code.EXPOSE
instruction specifies that the server
listens on port 8080
. This instruction doesn't expose any ports, but serves as documentation that you need to open port 8080
when you run the container.Before you containerize the application, you need to do some setup for the tools and services that you're going to use:
Set the default Google Cloud project for the Google Cloud CLI.
gcloud config set project PROJECT_ID
Set the default region for the Google Cloud CLI.
gcloud config set compute/region us-central1
To create a new repository for Docker container images in Artifact Registry, do the following:
Make sure that the Artifact Registry service is enabled in your Google Cloud project.
gcloud services enable artifactregistry.googleapis.com
Create the Artifact Registry repository:
gcloud artifacts repositories create container-intro --repository-format=docker \
--location=us-central1 \
--description="My new Docker repository"
Set up authentication from Docker to Artifact Registry using the Google Cloud CLI:
gcloud auth configure-docker us-central1-docker.pkg.dev
server
Now it's time to containerize your application. First containerize the "hello world" server
and push the image to Artifact Registry:
Change to the directory where the sample server
is located:
cd ~/anthos-service-mesh-samples/docs/helloserver/server/
Build the image using the Dockerfile
:
docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
PROJECT_ID
with the ID of your Google Cloud project.The -t
flag represents the Docker tag. This is the name of the image that you use when you deploy the container.
Push the image to Artifact Registry:
docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
loadgen
Next, containerize the load generator service in the same way:
Change to the directory where the sample loadgen
is located:
cd ../loadgen
Build the image:
docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
Push the image to Artifact Registry:
docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
Get a list of the images in the repository to confirm that the images were pushed:
gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro
The output should list the image names that you pushed, similar to the following:
NAME us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgenCreate a GKE cluster
At this point you could just run the containers on the Cloud Shell VM by using the docker run
command. However, to run reliable production workloads you need to manage containers in a more unified way. For example, you need to make sure that the containers restart if they fail, and you need a way to scale up and start additional instances of a container to handle traffic increases.
GKE can help you meet these needs. GKE is a container orchestration platform that works by connecting VMs into a cluster. Each VM is referred to as a node. GKE clusters are powered by the Kubernetes open source cluster management system. Kubernetes provides the mechanisms through which you interact with your cluster.
To run the containers on GKE, you first need to create and then connect to a cluster:
Create the cluster:
gcloud container clusters create-auto container-intro
The gcloud
command creates a cluster in the default Google Cloud project and region that you set previously.
The command to create the cluster takes a few minutes to complete. When the cluster is ready, the output is similar to the following:
NAME: container-intro LOCATION: us-central1 MASTER_VERSION: 1.30.4-gke.1348000 MASTER_IP: 34.44.14.166 MACHINE_TYPE: e2-small NODE_VERSION: 1.30.4-gke.1348000 NUM_NODES: 3 STATUS: RUNNING
Provide credentials to the kubectl
command- line tool so that you can use it to manage the cluster:
gcloud container clusters get-credentials container-intro
When you ran the application from the source code, you used an imperative command: python3 server.py
Imperative means verb-driven: "do this."
By contrast, Kubernetes operates on a declarative model. This means that rather than telling Kubernetes exactly what to do, you provide Kubernetes with a desired state. For example, Kubernetes starts and terminates Pods as needed so that the actual system state matches the desired state.
You specify the desired state in a file called a manifest. Manifests are written in languages like YAML or JSON and contain the specification for one or more Kubernetes objects.
The sample contains a manifest each for the server
and loadgen
. Each manifest specifies the desired state for the Kubernetes Deployment object (which manages running your container, packaged for management as a Kubernetes Pod) and Service (which provides an IP address for the Pod). A Pod is the smallest deployable unit of computing that you can create and manage in Kubernetes, and holds one or more containers.
The following diagram depicts the application running on GKE:
You can learn more about Pods, Deployments, and Services in Start learning about Kubernetes, or in the resources at the end of this page.
ServerFirst, look at the manifest for the "hello world" server
:
This manifest contains the following fields:
kind
indicates the type of object.metadata.name
specifies the name of the Deployment.spec
field contains a description of the desired state.spec.replicas
specifies the number of desired Pods.spec.template
section defines a Pod template. Included in the specification for the Pods is the image
field, which is the name of the image to pull from Artifact Registry. In the next step, you'll update this to the new image that you just created.The hellosvc
Service is defined as follows:
LoadBalancer
: Clients send requests to the IP address of a network load balancer, which has a stable IP address and is reachable outside of the cluster.targetPort
: Recall that the EXPOSE 8080
command in the Dockerfile
doesn't actually expose any ports. You expose port 8080
so that you can reach the server
container outside of the cluster. In this case, hellosvc.default.cluster.local:80
(shortname: hellosvc
) maps to the helloserver
Pod IP's port 8080
.port
: This is the port number that other services in the cluster use when sending requests.The Deployment object in loadgen.yaml
is similar to server.yaml
. One notable difference is that the Pod specification for the loadgen
Deployment has a field called env
. This section defines the environment variables that are required by loadgen
, which you set previously when you ran the application from source.
Because the loadgen
doesn't accept incoming requests, the type
field is set to ClusterIP
. This type of Service provides a stable IP address that entities in the cluster can use, but the IP address isn't exposed to external clients.
To deploy the containers, you apply the manifests that specify your desired state by using kubectl
.
server
Change to the directory where the sample server
is located:
cd ~/anthos-service-mesh-samples/docs/helloserver/server/
Open server.yaml
in the Cloud Shell Editor (or your preferred text editor).
Replace the name in the image
field with the name of your Docker image.
image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
Replace PROJECT_ID with your Google Cloud project ID.
server.yaml
.Deploy the manifest to Kubernetes:
kubectl apply -f server.yaml
The output is similar to the following:
deployment.apps/helloserver created service/hellosvc created
loadgen
Change to the directory where loadgen
is located.
cd ../loadgen
Open loadgen.yaml
in a text editor, as before.
Again, replace the name in the image
field with the name of your Docker image.
image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
Replace PROJECT_ID with your Google Cloud project ID.
loadgen.yaml
.Deploy the manifest to your cluster:
kubectl apply -f loadgen.yaml
On success, the command responds with the following:
deployment.apps/loadgenerator created service/loadgensvc created
After deploying your manifests to the cluster, verify that your containers have been deployed successfully:
Check the status of the Pods in your cluster:
kubectl get pods
The command responds with the status similar to the following:
NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s
Get the application logs from the loadgen
Pod. Replace POD_ID with the load generator Pod identifier from the previous output.
kubectl logs POD_ID
Get the external IP addresses of hellosvc
:
kubectl get service hellosvc
The output is similar to the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m
Send a request to the hellosvc
. Replace EXTERNAL_IP with the external IP address of your hellosvc
.
curl http://EXTERNAL_IP
You should see a "Hello World!" message from the server.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4