This project creates a complete micro service demo system in Docker containers. The services are implemented in Java using Spring and Spring Cloud.
It uses four docker microservices:
Apache
homepage and proxyOrder
to process orders.Customer
to handle customer data.Catalog
to handle the items in the catalog.
Apache HTTP is used to provide the web page of the demo at port 8080. It also forwards HTTP requests to the microservices. This is not really necessary as each service has its own port on the Minikube host but it provides a single point of entry for the whole system. Apache HTTP is configured as a reverse proxy for this. Load balancing is left to Kubernetes.
To configure this Apache HTTP needs to get all registered services from Kubernetes. It just uses DNS for that.
Please refer to the subdirectory microservice-kubernetes-demo/apache to see how this works.
The microservices are:
- microservice-kubernetes-demo-catalog is the application to take care of items.
- microservice-kubernetes-demo-customer is responsible for customers.
- microservice-kubernetes-demo-order does order processing. It uses microservice-kubernetes-demo-catalog and microservice-kubernetes-demo-customer.
The microservices use REST to communicate to each other.
See e.g. CatalogClient .
The hostname is configurable to allow tests with stubs.
The default is catalog
which works with Kubernetes.
Other microservices are found using Kubernetes built-in DNS.
Kubernetes does the load balancing on the IP level.
- Use your AWS account
- Create an AWS IAM user - Note this user will need some IAM permissions including roles, policies, OpenID
% aws --version
aws-cli/2.11.5 Python/3.11.2 Darwin/22.3.0 exe/x86_64 prompt/off
% aws sts get-caller-identity
{
"UserId": "YYA4ZRSAMPLE6IDAGV2YP",
"Account": "378929636692",
"Arn": "arn:aws:iam::378929636692:user/dockerbisson"
}
- Setup (one time only) Make sure there are not credientials in the .aws/credientials file Configure the SSO session
aws sso configure
- Clear prior AWS credentials from env:
for var in AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_SECURITY_TOKEN AWS_PROFILE export AWS_CREDENTIAL_EXPIRATION; do eval unset $var ; done
- SSO Login with profile:
aws sso login --profile yourProfile
- Export new credentials to env:
eval $(aws-export-credentials --profile yourProfile --env-export)
NOTE: SSO credentials have timed expirations. To renew your credentials, first sign out then repeat steps above:
aws sso logout
- Install brew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Install helm:
brew install helm
- Install jq:
brew install jq
- Create account
- Create an org - use the org name in the terraform.tf file
- Terraform variables with AWS credentials
From the top level of the repo
brew install terraform
(first time install only )- Set the AWS region in the
variables.tf
file terraform init
terraform plan
time terraform apply -auto-approve
Set kubectl
config (more details):
Note: Make sure the region matches and is one you can use.
Individual Account:
aws eks --region us-east-1 update-kubeconfig --name demo-eks-tp
Profile Account:
aws --profile yourProfile eks update-kubeconfig --region us-east-1 --name demo-eks-tp
The region
and name
values match those in the variables.tf
and main.tf
files.
- Log in to your Docker Hub account by entering
docker login
on the command line. - Set the environment variable
DOCKER_ACCOUNT
to the name of the account and verify it with echo.
export DOCKER_ACCOUNT=your account
echo $DOCKER_ACCOUNT
- Building locally (and push for x86). Run
docker-build.sh
in the directorymicroservice-kubernetes-demo
. It compiles the Java source and builds the images locally by default.
./docker-build.sh
If you use the "push" command, it will also upload them to Docker Hub using your account.
./docker-build.sh push
3a. If you are running on arm64 (apple silicon) and want to push x86 images, you will need to compile locally then push images to hub using buildx. Change to the directory microservice-kubernetes-demo
and run the following command. NOTE: This does not build images locally, only remotely.
./docker-buildx.sh
The ./kubernetes-deploy.sh
script will deploy the images located in your account on docker hub. Run this in the directory
microservice-kubernetes-demo
:
[~/microservice-kubernetes/microservice-kubernetes-demo]./kubernetes-deploy.sh
deployment "apache" created
service "apache" exposed
deployment "catalog" created
service "catalog" exposed
deployment "customer" created
service "customer" exposed
deployment "order" created
service "order" exposed
Confirm the services are running using kubectl
kubectl get all
Confirm the app is running in EKS (may take a minute or two for the app to be running). Once it is running, use the command below to open a browser tab to the application
open "http://$(kubectl get service -o json | jq -r '.items[0].status.loadBalancer.ingress[].hostname')"
- Install the mod header extension for chrome
- Open Docker Desktop
- Install telepresence extension
- Update the kubernetes context in the yaml file that you plan to use (apache-intercept.yaml, catalog-order-intercept.yaml, or order-intercept.yaml) files in the microservice-kubernetes directory - get it from kubectl
kubectl config current-context
I have seen intermittent errors when loading the telepresence sidecar traffic agents onto the kubernetes pods. Once the sidecars are loaded, the intercepts seem to be stable.
I would HIGHLY recommend running the intercepts for each pod that you want to demo before the meeting to ensure the pods are working properly. You can check this by looking at the pods through kubectl to ensure they are running, and by checking the demo app functionality
Show the app running in EKS, show the homepage is missing the logo and has two links with the same name
Update the index.html page to add the telepresence logo and change the link text for the second catalog link and build the image
- cd to the microservice-kubernetes-demo/apache directory
- Open the index.html file
- Add the telepresence logo image (changes are bolded)
<body>
<img src="images/telepresence-for-docker.svg"/>
<h1>Order Processing</h1>
- change the second catalog link in index.html and save(changes have ** around them)
<a href="/catalog/searchForm.html">**Search** Catalog</a>
- Run
docker build --tag=microservice-kubernetes-demo-apache .
IMPORTANT - the Spec, GUI and CLI telepresence intercept options are separate. You can do each of them, but you need to make sure the intercept is down before switching between them. Please make sure you click the "disconnect/leave" icon when you are switching between these options
- Open Docker Desktop
- Go to the telepresence extension
- Select "Get Started" - the Select Cluster for Telepresence Connection Dialog will appear
- The kubeconfig context should show the aws cluster
- Select "Install telepresence on this cluster" only if this is the first connection since building the cluster
- Select the down arrow next to the connect button, upload intercept spec should display
- Select the apache-intercept.yaml file in the microservice-kubernetes-demo folder
- Telepresence will start the intercept with the image specified in the intercept file
- There may be a warning message show up in a pop up from the container, you can ignore this and close it
- Open Docker Desktop
- Go to the telepresence extension
- Select "Get Started" - the Select Cluster for Telepresence Connection Dialog will appear
- The kubeconfig context should show the aws cluster
- Select "Install telepresence on this cluster" only if this is the first connection since building the cluster
- Select connect
- The default namespace should pop
- The four services service should be listed
- Click Intercept next to the Apache service
- A dialog appears for the Intercept
- Make sure the target docker image is microservice-kubernetes-demo-apache:latest
- Both the Service Port Number and the Target Port Number are 80
- Leave the other settings
- Click Create Intercept
- There may be a warning message show up in a pop up from the container, you can ignore this and close it
- Type
telepresence intercept --docker apache --port 80:80 --docker-run -- -it --rm microservice-kubernetes-demo-apache:latest
- Go to the containers tab
- Show there is a
tp-apache
orintercept-apache
container running - Explain that the telepresence extension runs this container when the intercept starts based on the image you specify
- Also note there is another container running that is the telepresence daemon.
Option 1: HTTP headers
- Copy the request header string shown in the current running intercepts (or on the terminal page)
- Put the
x-telepresence-intercept-id
in the name field in mod header - Put the rest (minus the colon after id) into the value field and make sure the green check is there
- Refresh the order processing homepage page to see the new image and link text
- Turn off the header and show the unchanged page
Option 2: Preview URL
- Click the preview URL link (or copy from the terminal page), put it in a new tab, and show the updated page
- Refresh the original tab to show the unchanged page
- Click stop intercept
- (optional) show the local container has stopped as well
- You may need to click the "leave" icon in the upper right to get back to the connect/startpage in the telepresence extension - there may also be a warning message, you can ignore it.
- type 'telepresence leave' (note this may not be required if you control C the telepresence command)
- Show the app running in EKS, go to the orders page - there are no orders.
- Create an order, add a line with a quantity, and hit submit.
- Click list to see the order
- Click delete next to the order
- Get an error that the method is not allowed
- cd to the microservice-kubernetes-demo/microservice-kubernetes-demo-order/src/main/java/com/ewolff/microservice/order/logic directory
- Open the OrderController.java file
- Update the method that has "DELETE" in it to POST(change in **)
@RequestMapping(value = "/{id}", method = RequestMethod.**POST**)
public ModelAndView post(@PathVariable("id") long id) {
orderRepository.deleteById(id);
- save the file
- cd up to the microservices-kubernetes-demo directory
- Run
./docker-build.sh
to recompile and build the image (local only)
IMPORTANT - the Spec, GUI and CLI telepresence intercept options are separate. You can do each of them, but you need to make sure the intercept is down before switching between them.
- Open Docker Desktop
- Go to the telepresence extension
- Select "Get Started" - the Select Cluster for Telepresence Connection Dialog will appear
- The kubeconfig context should show the aws cluster
- Select "Install telepresence on this cluster" only if this is the first connection since building the cluster
- Select the down arrow next to the connect button, upload intercept spec should display
- Select the order-intercept.yaml file in the microservice-kubernetes folder
- Telepresence will start the intercept with the image specified in the intercept file
- Open Docker Desktop
- Go to the telepresence extension
- Select "Get Started" - the Select Cluster for Telepresence Connection Dialog will appear
- The kubeconfig context should show the aws cluster
- Select "Install telepresence on this cluster" only if this is the first connection since building the cluster
- Select connect
- The default namespace should pop
- The four services service should be listed
- Click Intercept next to the Order service
- A dialog appears for the Intercept
- Make sure the target docker image is microservice-kubernetes-demo-order:latest
- Target Port Number is 8080
- Leave the other settings
- Click Create Intercept
- Type
telepresence intercept --docker order --port 8080:8080 --docker-run -- -it --rm microservice-kubernetes-demo-order:latest
Note: you will get logging from the Java service, just scroll up to the telepresence output you need
- Go to the containers tab
- Show there is a
tp-order
container running - Explain that the telepresence extension runs this container when the intercept starts based on the image you specify
- Also note there is another container running that is the telepresence daemon.
HTTP headers
- Copy the request header string shown in the current running intercepts (or on the terminal page)
- Put the
x-telepresence-intercept-id
in the name field in mod header - Put the rest (minus the colon after id) into the value field and make sure the green check is there
- Go to the orders list - see there are no orders now because the order service has no permament storage
- Create an order, add a line with a quantity, and hit submit.
- Click list to see the order
- Click delete next to the order
- Delete successful
- Click list to see the order is gone
- Turn off header and click list to see original order is there, still can't delete it
- Click stop intercept
- (optional) show the local container has stopped as well
- type 'telepresence leave'
- Show the app running in EKS, go to the catalog page
- Show that the price field has no $ and only one decimal point
- Go to the orders page
- If there are no orders then create an order, add a line with a quantity, and hit submit
- Click list to see the order
- Show that the price field has no $ and only one decimal point
- Go to the microservice-kubernetes-demo/microservice-kubernetes-demo-catalog/src/main/resources/templates directory
- Open the itemlist.html file
- Update the line for item price to use the numbers currency format (shown below)
<td th:text="${#numbers.formatCurrency(item.price)}">42.0</td>
- save the file
- Go to the microservice-kubernetes-demo/microservice-kubernetes-demo-order/src/main/resources/templates directory
- Open the orderlist.html file
- Update the line for item price to use the numbers currency format (shown below)
<td th:text="${#numbers.formatCurrency(order.totalPrice(@catalogClient))}">42.0</td>
- save the file
- Open Docker Desktop
- Go to the telepresence extension
- Select "Get Started" - the Select Cluster for Telepresence Connection Dialog will appear
- The kubeconfig context should show the aws cluster
- Select "Install telepresence on this cluster" only if this is the first connection since building the cluster
- Select the down arrow next to the connect button, upload intercept spec should display
- Select the intercept-catalog-order.yaml file in the microservice-kubernetes folder
- Telepresence will start the intercept with the images specified in the intercept file
- Go to the containers tab
- Show there is both a
tp-catalog
and atp-order
container running - Explain that the telepresence extension runs both these containers when the intercept starts based on the image you specify
- Also note there is another container running that is the telepresence daemon.
HTTP headers
- Copy the request header string shown in the current running intercepts (or on the terminal page)
- Put the
x-intercept-id
in the name field in mod header - Put the rest (minus the colon after id) into the value field and make sure the green check is there
- Go to the catalog list - show the prices are now formatted properly
- Go to the order list - see there are no orders now because the order service has no permament storage
- Create an order, add a line with a quantity, and hit submit.
- Click list to see the order
- Show the prices are now formatted properly
- Turn off header and show both prices are back to being incorrectly formatted
- Click stop intercept
- (optional) show the local container has stopped as well
Either revert the changes manually, or use git (warning this will remove any config changes you have made in the app as well as the code changes)
git reset –hard
git clean -fxd
- cd to the microservices-kubernetes-demo directory
- To remove all services and deployments run
kubernetes-remove.sh
:
[~/microservice-kubernetes/microservice-kubernetes-demo]./kubernetes-remove.sh
service "apache" deleted
service "catalog" deleted
service "customer" deleted
service "order" deleted
deployment "apache" deleted
deployment "catalog" deleted
deployment "customer" deleted
deployment "order" deleted
kubectl get all
- type
kubectl config use-context docker-desktop
From the top-level of the repo
terraform destroy -auto-approve
- Manually delete any load balancers associated with the cluster in the web console
- Manually delete the VPC associated with the cluster in the web console
terraform destroy -auto-approve
again
If needed...
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder