Spring Application Deployed with Kubernetes
Step by step building an application using Spring Boot and deployed via Docker on Kubernetes with Helm
full course- Setup: IDE and New Project
- Create the Data Repository
- Building a Service Layer
- Create a REST Controller
- Logging, Tracing and Error Handling
- Documentation and Code Coverage
- Database as a Service
- Containerize the Service With Docker
- Docker Registry
- Automated Build Pipeline
- Helm for Deployment
- Setting up a Kubernetes Cluster
- Automating Deployment (for CICD)
- System Design
- Messaging and Event Driven Design
- Web UI with React
- Containerizing our UI
- UI Build Pipeline
- Put the UI in to Helm
- Creating an Ingress in Kubernetes
- Simplify Deployment
- Conclusion and Review
We’ve got multiple service available for deployment now. Lets allow them to communicate internally and externally with the cluster. We’ll do that by creating an ingress.
Current State of Our Application
We’re using our services as nodeports which allows us to expose an external port that will map to the internal port used by the the application. From our helm configuration our services start up on their default port (spring=8080, nginx=80) but that gets mapped to port 80 internally. So if we were inside our cluster we could talk to customer manager directly by calling its service on port 80. When we’re external we have to use port 30002.
This works okay when we’re running externally on our development machine, but is terrible for production. For one, keeping track of the cluster IP and making sure that each service is calling the correct port can be a maintenance nightmare.
Using an Ingress
We’re going to install another component called an ingress which acts like an api gateway. This allows us to only talk to a single IP and port combination to access all components within our application. We can still access services directly via their external port (for testing, etc…) but the most important part is that our front-end application won’t need to know anything about where our services live and how to access them. The ingress takes care of that.
Creating an Ingress
Create a new git repository called medium-ingress
. Clone that locally and in that repo create a directory called helm
. In here use helm create medium-ingress
to initialize the chart. We’re going to strip out all of the files since we really only need 3.
templates/ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: medium-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: medium-example.com
http:
paths:
- path: /
backend:
serviceName: medium-customer-manager-service
servicePort: 80
- path: /customer
backend:
serviceName: customer-medium-customer
servicePort: 80
Chart.yaml
apiVersion: v1
name: medium-ingress
description: The ingress into the medium application
type: application
version: 0.1.0
appVersion: 1.16.0
values.yaml
can be left empty
The important part is the ingress deployment descriptor. In here we’re creating the mapping of the request path to the internal kubernetes service name and port. I just realized that my names are not very clean and I should fix that but this will get us going.
Minikube Setup
We need to do some things first before we can deploy. Ingress is a definition, but it is actually implemented within the kubernetes cluster and there are lots of implementations to choose from. We’re going to use the basic ingress for minikube, but we need to install it first.
minikube addons enable ingress
verify the pod is running
kubectl get pods -n ingress-nginx
We also want to update our hosts file to add a mapping for medium-example.com
to our minikube ip (which can be retrieved via minikube ip
). This is partly for ease of use for us, but also important because the ingress controller uses the domain for mapping.
...
172.18.51.82 medium-example.com
# End of section
Update Frontend
We have one more minor change to make to our react frontend. Change helm/medium-customer-manager/values.yaml
to stop calling the customer service via external port
config:
## Currently only supports file
type: file
## Contents of config in YAML
content: |-
window.REACT_APP_CUSTOMER_HOST=''
Go ahead and commit this to kick off a build
git checkout -b ingress
git add .
git commit -m "updates for ingress"
git push
git checkout master
git merge ingress
git push
Deploy Ingress
use helm to install
helm install ingress helm/medium-ingress
and load up your page at http://medium-example.com/.
You can verify that its all working together in the logs as well if you review the application and ingress pod log instances.
Publish the Chart
We want to version this ingress and publish it as a chart because we’ll eventually pull all of these services under an umbrella chart in the future. First we need to create a pipeline.
In codefresh make a new build pipeline for this project called medium-ingress
under the medium
project. Make sure to add the helm repository under the environment variables setup. Then use this workflow for the pipeline:
version: "1.0"
stages:
- "clone"
- "helmpublish"
steps:
Clone:
title: "Cloning repository"
type: "git-clone"
repo: "https://github.com/brianrook/medium-ingress"
revision: "master"
stage: "clone"
HelmChartGetVersion:
title: Get Helm Chart Version
stage: helmpublish
image: codefresh/cfstep-helm
working_directory: '/codefresh/volume/medium-ingress'
environment:
- CHART_PATH=helm/medium-ingress
- CHART_NAME=medium-ingress
commands:
- export ACTION=auth
- source /opt/bin/release_chart
- helm repo add default ${{CF_CTX_CF_HELM_DEFAULT_URL}}
- yq .version ${CHART_PATH}/Chart.yaml
- export CURRENT_CHART_VERSION=`helm search default/${CHART_NAME} | awk 'FNR==2{print $2}' || yq .version ${CHART_PATH}/Chart.yaml`
- echo $CURRENT_CHART_VERSION
- cf_export NEW_CHART_VERSION=`echo "${CURRENT_CHART_VERSION}" | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g'`
- echo $NEW_CHART_VERSION
HelmChartUpdate:
title: Update Helm Chart Version
stage: helmpublish
image: gksoftware/yq
working_directory: '/codefresh/volume/medium-ingress'
environment:
- CHART_PATH=helm/medium-ingress
- YAML_PATH=image.tag
commands:
- echo $NEW_CHART_VERSION
- yq w -i ${CHART_PATH}/Chart.yaml version ${NEW_CHART_VERSION}
- echo $CF_SHORT_REVISION
- yq w -i ${CHART_PATH}/values.yaml ${YAML_PATH} ${{CF_SHORT_REVISION}}
HelmChartPush:
title: Push Helm Chart to Chart Repository
stage: helmpublish
image: codefresh/cfstep-helm
working_directory: '/codefresh/volume/medium-ingress'
environment:
- CHART_REF=helm/medium-ingress/
- ACTION=push
Finally, make sure that this pipeline is triggered off push to master. Lets commit our changes and start a build
git checkout -b helm
git add .
git commit -m "ingress helm chart"
git push
git checkout master
git merge helm
git push
once that builds lets deploy all of our components
helm repo update
helm install customer codefresh/medium-customer
helm install cust-mgr codefresh/medium-customer-manager
helm install ingress codefresh/medium-ingress
And verify that everything works together.
0 comments on “Creating an Ingress in Kubernetes”Add yours →