Overview:
In this step, we will create Kubernetes manifests to deploy our FastAPI application locally using Minikube.
We'll configure various components, including namespaces, deployments, services, secrets, config maps, and ingress routes, to ensure our application runs smoothly within a Kubernetes environment.
Documentation provides basic but not comprehensive instruction. Kubernetes has a wide range of possibilities, resources and functionality.
For deeper information and possible configuration options, please refer to official documentation → https://kubernetes.io/docs/home/
Requirements:
- Minikube: Ensure Minikube is installed and running on your machine.
- kubectl: Kubernetes command-line tool to manage and interact with your clusters.
- Helm: Kubernetes package manager for managing charts.
- Minikube was launched with Traefik service. Follow instructions → Step 0: Pre-requisites - make sure you have Minikube and Traefik installed
- Docker image was uploaded to the remote registry and it is accessible → Step 3: Prepare and push docker images
Artifacts:
For the purpose of this tutorial we will be using this artifacts repository: https://gitlab.portaone.com:8949/read-only/tutorial-for-simple-application
Documentation Variables:
The documentation contains custom variables:
- <application_name>
- <application_version>
- <personal dockerhub repository>
For details related to variables meaning, please refer => Guide to deploy application in Add-On Mart for third-party developers
1. Create Kubernetes Namespace
Purpose:
Namespaces in Kubernetes provide a way to logically partition a cluster, allowing for the isolation and management of resources.
Explanation:
apiVersion: v1
: Specifies the Kubernetes API version for the resource.kind: Namespace
: Indicates that we are creating a namespace.metadata: name: <application_name>-ns
: Names the namespace<application_name>-ns
.
1.1 Create Namespace Manifest:
Create a file named namespace.yaml
in the Manifests_local
directory with the following content:
apiVersion: v1 kind: Namespace metadata: name: <application_name>-ns
1.2 Apply Namespace Manifest:
> kubectl apply -f ./Manifests_local/namespace.yaml
1.3 Verify Namespace Creation:
Check if the namespace was created:
> kubectl get namespaces | grep "<application_name>" <application_name>-ns Active 44s
2. Deploy Application
Purpose:
Deploying the application creates a running instance of your containerized application in the Kubernetes cluster.
This step defines how the application should run, including the number of replicas, container images, and ports.
Explanation:
apiVersion: apps/v1
: Specifies the API version for deployment resources.kind: Deployment
: Indicates that we are creating a deployment resource.metadata: name: <application_name>
: Names the deployment<application_name>
.namespace: <application_name>-ns
: Specifies the namespace for the deployment.spec: replicas: 1
: Defines the number of pod replicas.template: spec: containers
: Specifies the container image and ports.
2.1 Create Deployment Manifest:
Create a file named deployment.yaml
in the Manifests_local
directory with the following content:
Change <personal dockerhub repository> with appropriate repository name
apiVersion: apps/v1 kind: Deployment metadata: name: <application_name> namespace: <application_name>-ns spec: replicas: 1 selector: matchLabels: app: <application_name> template: metadata: labels: app: <application_name> spec: containers: - name: <application_name> image: <personal dockerhub repository>/<application_name>:<application_version> ports: - name: http containerPort: 8000 protocol: TCP
2.2 Apply Deployment Manifest:
Apply the manifest to deploy the application:
> kubectl apply -f ./Manifests_local/deployment.yaml deployment.apps/<application_name> created
2.3 Verify Deployment:
Check if the deployment was created:
> kubectl get -n <application_name>-ns deployment NAME READY UP-TO-DATE AVAILABLE AGE <application_name> 1/1 1 1 17s
2.4 Verify Pod Status:
Check if the pod is running:
> kubectl get -n <application_name>-ns pod NAME READY STATUS RESTARTS AGE <application_name>-7f6cf9c5cb-kpn52 1/1 Running 0 29s
3. Create Kubernetes Service
Purpose:
A Kubernetes Service enables network access to a set of pods. In this step, we create a service to expose the application and allow traffic to reach it
Explanation:
apiVersion: v1
: Specifies the API version for the service.kind: Service
: Indicates that we are creating a service.metadata: name: <application_name>
: Names the service<application_name>
.spec: type: ClusterIP
: Defines the service type as ClusterIP, making it accessible only within the cluster.ports: port: 8888, targetPort: 8000
: Maps port 8888 on the service to port 8000 on the pod.
3.1 Create Service Manifest:
Create a file named service.yaml
in the Manifests_local
directory with the following content:
apiVersion: v1 kind: Service metadata: namespace: <application_name>-ns name: <application_name> spec: type: ClusterIP selector: app: <application_name> ports: - name: http protocol: TCP port: 8888 targetPort: 8000
3.2 Apply Service Manifest:
Apply the manifest to create the service:
> kubectl apply -f ./Manifests_local/service.yaml service/<application_name> created
3.3 Verify Service Creation:
Check if the service was created:
> kubectl get -n <application_name>-ns svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE <application_name> ClusterIP 10.99.87.35 <none> 8888/TCP 6s
4. Configure Environment Variables
Purpose:
Environment variables allow us to configure the application without changing the code. We can set variables like configuration paths, custom settings, and more.
Explanation:
env
: Specifies environment variables to be used in the container.name: CONFIG_PATH, value: /app/config.yaml
: Sets the path to the configuration file.name: BASE_PATH, value: /
: Sets the base path for the application.name: CUSTOM_ENV_VARIABLE, value: "deployed_env_value"
: Defines a custom environment variable.
4.1 Extend Deployment Manifest with Environment Variables:
Update the deployment.yaml
file to include environment variables:
Change <personal dockerhub repository> with appropriate repository name
apiVersion: apps/v1 kind: Deployment metadata: name: <application_name> namespace: <application_name>-ns spec: replicas: 1 selector: matchLabels: app: <application_name> template: metadata: labels: app: <application_name> spec: containers: - name: <application_name> image: <personal dockerhub repository>/<application_name>:<application_version> ports: - name: http containerPort: 8000 protocol: TCP env: # new code line - name: CONFIG_PATH # new code line value: /app/config.yaml # new code line - name: BASE_PATH # new code line value: / # new code line - name: CUSTOM_ENV_VARIABLE # new code line value: "deployed_env_value" # new code line
4.2 Redeploy Application:
Apply the updated deployment manifest:
> kubectl apply -f ./Manifests_local/deployment.yaml
4.3 Enable port forwarding:
Open new terminal window (you will need to keep it open to keep forwarding in place) and forward port with following command:
The service we created in step 3 facilitates networking features for our application but is not exposed to traffic outside of the cluster yet. Later we will use Traefik to deliver outside connectivity, but for now we will use port forwarding.
> kubectl -n <application_name>-ns port-forward svc/<application_name> 8888:8888 Forwarding from 127.0.0.1:8888 -> 8000 Forwarding from [::1]:8888 -> 8000
4.4 Test environment variables:
curl -X 'GET' 'http://127.0.0.1:8888/environment_variables' | jq . | grep -E "CONFIG_PATH|BASE_PATH|CUSTOM_ENV_VARIABLE"
"BASE_PATH": "/", "CUSTOM_ENV_VARIABLE": "deployed_env_value", "CONFIG_PATH": "/app/config.yaml",
5. Create ConfigMap
Purpose:
A ConfigMap stores configuration data in key-value pairs. It allows us to decouple specific configurations from application code.
For our deployment, we will overwrite the config.yaml
file in the image with a new version containing slightly different content.
To verify that the configuration file stored in the image has been successfully overwritten, we will introduce a new value for configuration parameters in the ConfigMap manifest.
5.1 Create ConfigMap Manifest:
Create a file named config-cm.yaml
in the Manifests_local
directory with the following content:
Explanation:
apiVersion: v1
: Specifies the API version for the ConfigMap.kind: ConfigMap
: Indicates that we are creating a ConfigMap.metadata: name: <application_name>-config
: Names the ConfigMap<application_name>-config
.data: config-cm.yaml
: Stores the configuration file as data within the ConfigMap.
apiVersion: v1 kind: ConfigMap metadata: name: <application_name>-config namespace: <application_name>-ns labels: data: config.yaml: | SERVER_URL: "https://jsonplaceholder.typicode.com/users" CONFIG_OPTION: "deployed config value"
5.2 Apply ConfigMap Manifest:
Apply the manifest to create the ConfigMap:
> kubectl apply -f ./Manifests_local/config-cm.yaml configmap/<application_name>-config created
5.3 Verify ConfigMap Creation:
Check if the ConfigMap was created:
> kubectl get -n <application_name>-ns cm NAME DATA AGE <application_name>-config 1 18s
5.4 Mount ConfigMap to Deployment:
Update the deployment.yaml
file to mount the ConfigMap:
Explanation:
volumeMounts
: Mounts the ConfigMap as a volume in the container.mountPath: /app/config.yaml
: Specifies the path where the config file will be mounted.subPath: config.yaml
: Indicates the file name within the volume to mount a specific file (config.yaml
) from the ConfigMap instead of the entire volume.volumes: configMap
: Defines the volume available to the containers in the pod. Volume is sourced from configMap.
apiVersion: apps/v1 kind: Deployment metadata: name: <application_name> namespace: <application_name>-ns spec: replicas: 1 selector: matchLabels: app: <application_name> template: metadata: labels: app: <application_name> spec: containers: - name: <application_name> image: <personal dockerhub repository>/<application_name>:<application_version> ports: - name: http containerPort: 8000 protocol: TCP env: - name: CONFIG_PATH value: /app/config.yaml - name: BASE_PATH value: / - name: CUSTOM_ENV_VARIABLE value: "deployed_env_value" volumeMounts: # new code line - name: config-vol # new code line mountPath: /app/config.yaml # new code line subPath: config.yaml # new code line volumes: # new code line - name: config-vol # new code line configMap: # new code line name: <application_name>-config # new code line
5.5 Redeploy Application:
Apply the updated deployment manifest:
> kubectl apply -f ./Manifests_local/deployment.yaml
5.6 Test
Make sure Port Forwarding command is still running
Trigger /config_values endpoint
curl -X 'GET' 'http://127.0.0.1:8888/config_values' | jq .
{ "SERVER_URL": "https://jsonplaceholder.typicode.com/users", "CONFIG_OPTION": "deployed config value" }
6. Create Secret
Purpose:
Secrets in Kubernetes are used to store sensitive information such as passwords, tokens, or keys. By using secrets, we ensure that sensitive data is handled securely within the cluster.
6.1 Create Secret Manifest:
Create a file named secret.yaml
in the Manifests_local
directory with the following content:
Explanation:
apiVersion: v1
: Specifies the API version for the secret.kind: Secret
: Indicates that we are creating a secret.metadata: name: <application_name>-secret
: Names the secret<application_name>-secret
.type: Opaque
: Defines the secret type as opaque, which is a generic type for arbitrary user-defined data.stringData
: Allows you to provide secret data as plain strings (Kubernetes will handle the encoding).data
: Contains the base64-encoded data. Use this when data needs to be pre-encoded.
apiVersion: v1 kind: Secret metadata: name: <application_name>-secret namespace: <application_name>-ns type: Opaque stringData: SECRET_USERNAME: "username" SECRET_PASSWORD: "s_password" data: SECRET_BASE_64_ENCODED: VGhpcyBzdHJpbmcgd2FzIGVuY29kZWQgdXNpbmcgYmFzZTY0
6.2 Apply Secret Manifest:
Apply the manifest to create the secret:
> kubectl apply -f ./Manifests_local/secret.yaml secret/<application_name>-secret created
6.3 Verify Secret Creation:
Check if the secret was created:
> kubectl get -n <application_name>-ns secret NAME TYPE DATA AGE <application_name>-secret Opaque 3 20s
6.4 Update Deployment to Use Secret:
Update the deployment.yaml
file to include the secret:
Explanation:
envFrom: secretRef
: Pulls environment variables from the specified secret.
Change <personal dockerhub repository> with appropriate repository name
apiVersion: apps/v1 kind: Deployment metadata: name: <application_name> namespace: <application_name>-ns spec: replicas: 1 selector: matchLabels: app: <application_name> template: metadata: labels: app: <application_name> spec: containers: - name: <application_name> image: <personal dockerhub repository>/<application_name>:<application_version> ports: - name: http containerPort: 8000 protocol: TCP env: - name: CONFIG_PATH value: /app/config.yaml - name: BASE_PATH value: / - name: CUSTOM_ENV_VARIABLE value: "deployed_env_value" envFrom: # new code line - secretRef: # new code line name: <application_name>-secret # new code line volumeMounts: - name: config-vol mountPath: /app/config.yaml subPath: config.yaml volumes: - name: config-vol configMap: name: <application_name>-config
6.5 Redeploy Application:
Apply the updated deployment manifest:
> kubectl apply -f ./Manifests_local/deployment.yaml deployment.apps/<application_name> configured
6.7 Test:
Make sure Port Forwarding command is still running
Trigger the secret endpoint:
curl -X 'GET' 'http://127.0.0.1:8888/environment_variables' | jq . | grep -E 'SECRET_BASE_64_ENCODED|SECRET_PASSWORD|SECRET_USERNAME'
"SECRET_BASE_64_ENCODED": "This string was encoded using base64", "SECRET_PASSWORD": "s_password", "SECRET_USERNAME": "username"
7. Configure Ingress with Traefik
Purpose:
Traefik is an ingress controller that manages external access to services within a Kubernetes cluster. In this step, we'll configure Traefik to route traffic to our application.
Add-On Mart infrastructure uses Traefik Ingress Controller. If you plan to deploy applications on Add-On Mart infrastructure, do not choose other providers.
7.1 Configure Traefik:
Follow instructions → Step 0: Pre-requisites - make sure you have Minikube and Traefik installed
7.2 Create IngressRoute Manifest for HTTP:
Create a file named ingressroute.yaml
in the Manifests_local
directory with the following content:
Explanation:
apiVersion: traefik.containo.us/v1alpha1
: Specifies the API version for Traefik's custom resources.kind: IngressRoute
: Indicates that we are creating an IngressRoute resource.metadata: name: <application_name>-http
: Names the IngressRoute<application_name>-http
.entryPoints: web
: Specifies the entry point for HTTP traffic.routes: match
: Defines the routing rule based on the host and path prefix.services: name: <application_name>
: Specifies the service to route traffic to.
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: <application_name>-http namespace: <application_name>-ns spec: entryPoints: - web routes: - match: Host(`local_application.com`) && PathPrefix(`/`) kind: Rule services: - name: <application_name> namespace: <application_name>-ns port: 8888
7.3 Apply IngressRoute Manifest:
Now, as we have Traefik handling forwarding from the local computer to the cluster's service, we don't need Port Forwarding anymore that has been running in another terminal window. You can stop it now if it is still active.
Apply the manifest to create the IngressRoute:
> kubectl apply -f ./Manifests_local/ingressroute.yaml ingressroute.traefik.containo.us/<application_name>-http created
7.4 Verify IngressRoute:
Test the routing to ensure that the service is accessible via the domain name:
curl -X 'GET' 'http://local_application.com/environment_variables' | jq . | grep -E 'SECRET_BASE_64_ENCODED|SECRET_PASSWORD|SECRET_USERNAME'
"SECRET_BASE_64_ENCODED": "This string was encoded using base64", "SECRET_PASSWORD": "s_password", "SECRET_USERNAME": "username"
8. Enable HTTPS with TLS
Purpose:
Enabling HTTPS provides secure communication by encrypting traffic between the client and server. We'll use a TLS certificate to achieve this.
8.1 Generate TLS Certificate:
If you don't have a signed certificate, create a self-signed certificate for your domain name:
Generate a Private Key:
cd ./Certificate
openssl genrsa -out sec.demo.key 2048
Create a Simple Config for Certificate Generation:
Create a file named cert.conf
with the following content:
[ req ] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn req_extensions = req_ext [ dn ] C = US ST = California L = San Francisco O = My Organization OU = My Unit CN = local_application.com [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = local_application.com DNS.2 = www.local_application.com
Create a CSR (Certificate Signing Request):
openssl req -new -key sec.demo.key -out sec.demo.csr -config ./cert.conf
Generate a Self-Signed Certificate:
openssl x509 -req -days 365 -in sec.demo.csr -signkey sec.demo.key -out sec.demo.crt -extfile cert.conf
8.2 Create TLS Secret Manifest:
Convert the key and certificate into base64 format:
Convert Key:
Prepare base64 encoded value of the key for "data.tls.key" attribute in the tls-secret.yaml
file below
cat sec.demo.key | base64 | tr -d '\n'
Convert Certificate:
Prepare base64 encoded value of the certificate for "data.tls.crt" attribute in the tls-secret.yaml
file below
cat sec.demo.crt | base64 | tr -d '\n'
Using the base64-encoded data you obtained earlier, create the TLS secret manifest file. Below is the complete content of the file:
apiVersion: v1 kind: Secret metadata: name: <application_name>-secrets-tls namespace: <application_name>-ns type: kubernetes.io/tls data: tls.crt: <base64_certificate> tls.key: <base64_key>
8.3 Apply TLS Secret Manifest:
Move to the parant directory
> cd ../
Apply the TLS secret manifest to store the TLS certificate and key securely within Kubernetes:
> kubectl apply -f ./Manifests_local/tls-secret.yaml secret/<application_name>-secrets-tls created
8.4 Verify Secret Creation:
Ensure that the TLS secret has been created successfully:
> kubectl -n <application_name>-ns get secret NAME TYPE DATA AGE <application_name>-secret Opaque 3 57m <application_name>-secrets-tls kubernetes.io/tls 2 41s
8.5 Create HTTPS IngressRoute:
Extend the ingressroute.yaml
file to include an HTTPS route using the TLS secret:
Explanation:
tls
: Specifies the TLS configuration for the IngressRoute, using the secret created earlier.secretName: <application_name>-secrets-tls
: References the TLS secret for the HTTPS connection.domains: main: local_application.com
: Specifies the domain names covered by the certificate.
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: <application_name>-http namespace: <application_name>-ns spec: entryPoints: - web routes: - match: Host(`local_application.com`) && PathPrefix(`/`) kind: Rule services: - name: <application_name> namespace: <application_name>-ns port: 8888 --- # new code line apiVersion: traefik.containo.us/v1alpha1 # new code line kind: IngressRoute # new code line metadata: # new code line name: <application_name>-https # new code line namespace: <application_name>-ns # new code line spec: # new code line entryPoints: # new code line - websecure # new code line routes: # new code line - match: Host(`local_application.com`) && PathPrefix(`/`) # new code line kind: Rule # new code line services: # new code line - name: <application_name> # new code line namespace: <application_name>-ns # new code line port: 8888 # new code line tls: # new code line secretName: <application_name>-secrets-tls # new code line domains: # new code line - main: local_application.com # new code line
8.6 Reapply IngressRoute Manifest:
Apply the updated ingress route manifest to enable access via HTTPS:
kubectl apply -f ./Manifests_local/ingressroute.yaml ingressroute.traefik.containo.us/<application_name>-http unchanged ingressroute.traefik.containo.us/<application_name>-https created
8.7 Test HTTPS Endpoint:
Verify that the HTTPS endpoint is working correctly:
curl -k -X 'GET' 'https://local_application.com/health' | jq .
{ "status": "OK" }
9. Adding Middleware to Ingress Controller
Purpose:
Middleware in Traefik enhances routing and security for your application. In this step, we will configure middleware for:
- Redirecting HTTP traffic to HTTPS to ensure secure communication.
- Stripping prefixes from URLs to provide clean and manageable paths.
Explanation
- HTTP to HTTPS Redirection: Ensures all traffic is encrypted by redirecting HTTP requests to HTTPS.
- Strip Prefix: Removes specified prefixes from the URL path, making it easier to manage and route traffic within your application in kubernetes cluster.
9.1 Create Middleware for HTTP to HTTPS Redirection:
We will add following code to create a Middleware manifest to redirect HTTP traffic to HTTPS.
apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: <application_name>-redirect-scheme namespace: <application_name>-ns spec: redirectScheme: scheme: https permanent: true port: "443"
9.2 Create Middleware for Stripping Prefix:
We will add following code to create a Middleware manifest to strip the specified prefix from the URL path.
apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: <application_name>-strip-prefix namespace: <application_name>-ns spec: stripPrefix: prefixes: - /
9.3 Update IngressRoute to Use Middleware:
Update existing ingressroute.yaml
to include the newly created middleware for both HTTP and HTTPS routes.
apiVersion: traefik.containo.us/v1alpha1 # new code line kind: Middleware # new code line metadata: # new code line name: <application_name>-redirect-scheme # new code line namespace: <application_name>-ns # new code line spec: # new code line redirectScheme: # new code line scheme: https # new code line permanent: true # new code line port: "443" # new code line --- # new code line apiVersion: traefik.containo.us/v1alpha1 # new code line kind: Middleware # new code line metadata: # new code line name: <application_name>-strip-prefix # new code line namespace: <application_name>-ns # new code line spec: # new code line stripPrefix: # new code line prefixes: # new code line - / # new code line --- # new code line apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: <application_name>-http namespace: <application_name>-ns spec: entryPoints: - web routes: - match: Host(`local_application.com`) && PathPrefix(`/`) kind: Rule services: - name: <application_name> namespace: <application_name>-ns port: 8888 middlewares: # new code line - name: <application_name>-redirect-scheme # new code line - name: <application_name>-strip-prefix # new code line --- apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: <application_name>-https namespace: <application_name>-ns spec: entryPoints: - websecure routes: - match: Host(`local_application.com`) && PathPrefix(`/`) kind: Rule services: - name: <application_name> namespace: <application_name>-ns port: 8888 middlewares: # new code line - name: <application_name>-strip-prefix # new code line tls: secretName: <application_name>-secrets-tls domains: - main: local_application.com
9.4 Apply Middleware and IngressRoute Manifests:
Apply the middleware and updated IngressRoute manifests to the cluster:
> kubectl apply -f ./Manifests_local/ingressroute.yaml
9.5 Test middleware:
Verify HTTP to HTTPS redirection.
The flag "-v" can be used in the curl
command to display more information and ensure that the request was redirected from port 80 to port 443.
> curl -k -L -X 'GET' 'http://local_application.com/health' | jq . { "status": "OK" }
Verify "/" stripping.
> curl -k -X 'GET' 'https://local_application.com//health' | jq . { "status": "OK" }
10. Configure Startup and Liveness Probes
Purpose:
Kubernetes health probes help ensure that your application is running correctly and can automatically restart the application if it becomes unhealthy.
Explanation:
startupProbe
: This probe checks whether the application is started and ready. It prevents the application from being killed before it's ready to accept traffic.httpGet: path: "/health"
: Specifies the endpoint used for the health check.port: http
: Specifies the port for the health check.periodSeconds: 5
: Indicates how often to perform the probe.initialDelaySeconds: 5
: Specifies the initial delay before starting the probes.
livenessProbe
: This probe checks whether the application is running and healthy. If it fails, Kubernetes will restart the container.httpGet: path: "/health"
: Specifies the endpoint used for the health check.port: http
: Specifies the port for the health check.initialDelaySeconds: 5
: Specifies the initial delay before starting the probes.periodSeconds: 60
: Indicates how often to perform the probe.
10.1 Update Deployment Manifest with Probes:
Modify the deployment.yaml
file to include startup and liveness probes:
Change <personal dockerhub repository> with appropriate repository name
apiVersion: apps/v1 kind: Deployment metadata: name: <application_name> namespace: <application_name>-ns spec: replicas: 1 selector: matchLabels: app: <application_name> template: metadata: labels: app: <application_name> spec: containers: - name: <application_name> image: <personal dockerhub repository>/<application_name>:<application_version> ports: - name: http containerPort: 8000 protocol: TCP env: - name: CONFIG_PATH value: /app/config.yaml - name: BASE_PATH value: / - name: CUSTOM_ENV_VARIABLE value: "deployed_env_value" envFrom: - secretRef: name: <application_name>-secret startupProbe: # new code line httpGet: # new code line path: "/health" # new code line port: http # new code line periodSeconds: 5 # new code line initialDelaySeconds: 5 # new code line livenessProbe: # new code line httpGet: # new code line path: "/health" # new code line port: http # new code line initialDelaySeconds: 5 # new code line periodSeconds: 60 # new code line volumeMounts: - name: config-vol mountPath: /app/config.yaml subPath: config.yaml volumes: - name: config-vol configMap: name: <application_name>-config
10.2 Redeploy Application:
Apply the updated deployment manifest:
> kubectl apply -f ./Manifests_local/deployment.yaml deployment.apps/<application_name> configured
11. Test deployed application
11.1 Test /health endpoint
> curl -k -X 'GET' 'https://local_application.com/health' | jq .
{ "status": "OK" }
11.2 Test /config_values endpoint
> curl -k -X 'GET' 'https://local_application.com/config_values' | jq .
{ "SERVER_URL": "https://jsonplaceholder.typicode.com/users", "CONFIG_OPTION": "deployed config value" }
11.3 Test /environment_variables endpoint with secrets
> curl -k -X 'GET' 'https://local_application.com/environment_variables' | jq . | grep -E 'SECRET_BASE_64_ENCODED|SECRET_PASSWORD|SECRET_USERNAME'
"SECRET_BASE_64_ENCODED": "This string was encoded using base64", "SECRET_PASSWORD": "s_password", "SECRET_USERNAME": "username"
12. Clean-up procedures
If you no longer need the application deployed in the local cluster, you can initiate the clean-up procedure.
To clean up all the applied manifests with a single command, use the kubectl delete
command with the -f
option, specifying the directory where all the manifests are located. This will delete all the resources defined in the files within that directory.
> kubectl delete -f ./Manifests_local/
Summary:
In this step, we've successfully prepared Kubernetes manifests to deploy our FastAPI application locally using Minikube.
We've covered the setup of namespaces, deployments, services, environment variables, ConfigMaps, secrets, ingress routes, and health probes.
These components provide a robust foundation for deploying, managing, and testing your application in a local Kubernetes environment.