Ansible-Driven Container Deployment: Building, Pushing, and Deploying with Docker, Kubernetes, and Helm
Embark on an Epic DevOps Voyage with Ansible-Driven Container Deployment
Are you ready to set sail on a DevOps adventure like no other? In this journey, you’ll harness the power of Ansible to orchestrate the deployment of your containerized applications with Docker, Kubernetes (K8s), and Helm. So, fasten your seatbelts and let’s get started!
Prerequisites:
Before we hoist the anchor, make sure you’ve got these tools ready to roll:
Ansible: Our trusty captain, Ansible, will be steering the ship. Make sure you have it installed and ready for action.
Docker: Ahoy there, containerization! We’ll be using Docker to package our applications. If you don’t have it, you can easily set sail by installing it from the official website.
Git: You’ll need Git to navigate the high seas of version control. Install it on your system if you haven’t already.
**Installation and Usage:
**We’ll explore how to create an Ansible script to automate the installation of Minikube, Docker, and Helm. With this Ansible playbook, we’ll streamline the process of building Docker images for your React and Node.js applications, pushing them to Docker Hub. Plus, we’ll create Helm charts in the helm-v1 directory, making it easy to deploy and manage your applications with Helm
So this is Directory Structure
Create playbook.yml
- name: Install and start Minikube
hosts: localhost
become: true
gather_facts: false
tasks:
- name: Install dependencies
apt:
name:
- curl
- virtualbox
- conntrack
- libvirt-clients
- libvirt-daemon-system
- name: Download and install Minikube
block:
- name: Download Minikube
get_url:
url: "https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64"
dest: "/usr/local/bin/minikube"
mode: 0755
validate_certs: no
- name: Add Minikube to the PATH
lineinfile:
dest: "$HOME/.bashrc"
line: 'export PATH=/usr/local/bin:$PATH'
insertafter: EOF
become: false
- name: Start Minikube
shell: minikube start
args:
executable: /bin/bash
creates: "$HOME/.kube/config"
handlers:
- name: Restart shell
shell: exec $SHELL
- name: Install and configure Kubernetes with Minikube
hosts: localhost
connection: local
become: true
tasks:
- name: Install Docker
snap:
name: docker
- name: Install Docker.io package
apt:
name: docker.io
state: present
- name: Start Docker service
service:
name: docker
state: started
- name: Download kubectl
shell: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
- name: Verify kubectl integrity
shell: |
curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
- name: Install kubectl
shell: |
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
- name: Login to Docker Hub & Build Docker Images
hosts: localhost
gather_facts: false
vars:
inventory_file: "inventory.yml"
tasks:
- name: Load inventory file
include_vars:
file: "{{ inventory_file }}"
- name: Change Directory to Simple-crud-react-nodejs
shell: cd /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/
- name: Log in to Docker Hub
docker_login:
username: nacromancer858 #you should use your docker hub username
password: your-docker_hub_password
registry_url: https://index.docker.io/v2/
- name: Print Docker Hub login status
debug:
msg: "Docker Hub login successful!"
- name: Change Directory to Simple-crud-react-nodejs/frontend
shell: cd /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/frontend/
- name: Build Frontend Docker Image
shell: docker build -t frontend-image-777 .
args:
chdir: /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/frontend/
- name: Tag Frontend Docker Image
shell: docker tag frontend-image-777 nacromancer858/frontend-image-777:"{{ image_tags.frontend_tag }}"
args:
chdir: /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/frontend/
- name: Push Frontend Docker Image
shell: docker push nacromancer858/frontend-image-777:"{{ image_tags.frontend_tag }}"
args:
chdir: /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/frontend/
- name: Change Directory to Simple-crud-react-nodejs/backend
shell: cd /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/backend/
- name: Build Backend Docker Image
shell: |
docker build -t nacromancer858/backend-image -f Dockerfile .
docker tag nacromancer858/backend-image nacromancer858/backend-image:"{{ image_tags.backend_tag }}"
docker push nacromancer858/backend-image:"{{ image_tags.backend_tag }}"
args:
chdir: /home/saurabhadhau/Desktop/P-2/simple-crud-react-nodejs/backend/
- name: Install and configure Kubernetes with Minikube
hosts: localhost
connection: local
tasks:
- name: Start Minikube
command: minikube start
- name: Check Minikube status
command: minikube status
- name: Install helm
shell: |
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
- name: Pulling the Images and Install Helm
hosts: localhost
connection: local
tasks:
- name: Pull frontend Docker image
docker_image:
name: nacromancer858/frontend-image-777
tag: "{{ image_tags.frontend_tag }}"
source: pull
- name: Pull backend Docker image
docker_image:
name: nacromancer858/backend-image
tag: "{{ image_tags.backend_tag }}"
source: pull
- name: Change Directory to Helm-charts
shell: cd /home/saurabhadhau/Desktop/P-2/helm-v1/
- name: Update frontend values file
hosts: localhost
gather_facts: false
tasks:
- name: Read inventory file
include_vars:
file: inventory.yml
name: inventory_data
- name: Update frontend tag value
lineinfile:
path: helm-v1/values.frontend.yml
regexp: '^frontend:\n[[:space:]]*tag:'
line: 'frontend:\n tag: "{{ inventory_data.image_tags.frontend_tag }}"'
- name: Update Backend tag value
lineinfile:
path: helm-v1/values.backend.yml
regexp: '^backend:\n[[:space:]]*tag:'
line: 'backend:\n tag: "{{ inventory_data.image_tags.backend_tag }}"'
- name: Build Helm-Chart for Frontend
shell: helm install frontend ./frontend-chart -f values.frontend.yml
args:
chdir: /home/saurabhadhau/Desktop/P-2/helm-v1/
- name: Build Helm-Chart for Backend
shell: helm install backend ./backend-chart -f values.backend.yml
args:
chdir: /home/saurabhadhau/Desktop/P-2/helm-v1/
Create helm-v1 directory and as per the directory structure create the other files as well!
frontend-chart/templates/frontend-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "frontend-chart.fullname" . }}
spec:
replicas: {{ .Values.frontend.replicaCount }}
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: {{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}
ports:
- containerPort: {{ .Values.frontend.service.port }}
resources:
limits:
cpu: {{ .Values.frontend.resources.limits.cpu }}
memory: {{ .Values.frontend.resources.limits.memory }}
requests:
cpu: {{ .Values.frontend.resources.requests.cpu }}
memory: {{ .Values.frontend.resources.requests.memory }}
frontend-chart/templates/frontend-service.yaml:
{{- if eq .Values.frontend.service.type "NodePort" }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "frontend-chart.fullname" . }}
spec:
selector:
app: frontend
type: {{ .Values.frontend.service.type }}
ports:
- port: {{ .Values.frontend.service.port }}
targetPort: {{ .Values.frontend.service.targetPort }}
nodePort: {{ .Values.frontend.service.nodePort }}
{{- else }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "frontend-chart.fullname" . }}
spec:
selector:
app: frontend
type: ClusterIP
ports:
- port: {{ .Values.frontend.service.port }}
targetPort: {{ .Values.frontend.service.targetPort }}
{{- end }}
backend-chart/templates/backend-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "backend.fullname" . }}
spec:
replicas: {{ .Values.backend.replicas }}
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: {{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}
ports:
- containerPort: {{ .Values.backend.port }}
volumeMounts:
- name: backend-storage
mountPath: /data
resources:
limits:
cpu: {{ .Values.backend.resources.limits.cpu }}
memory: {{ .Values.backend.resources.limits.memory }}
requests:
cpu: {{ .Values.backend.resources.requests.cpu }}
memory: {{ .Values.backend.resources.requests.memory }}
volumes:
- name: backend-storage
persistentVolumeClaim:
claimName: backend-pvc
backend-chart/templates/backend-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ include "backend.fullname" . }}
spec:
selector:
app: backend
{{- if eq .Values.backend.serviceType "NodePort" }}
type: NodePort
{{- else }}
type: ClusterIP
{{- end }}
ports:
- port: {{ .Values.backend.port }}
targetPort: {{ .Values.backend.port }}
{{- if eq .Values.backend.serviceType "NodePort" }}
nodePort: {{ .Values.backend.nodePort }}
{{- end }}
backend-chart/templates/backend-pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: backend-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "1Gi"
You can dive into the complete code in all its glory right here at our repository : https://github.com/Saurabh-DevOpsVoyager77/ansible-driven-deployment-Docker_K8s_Helm
Now, let’s add some magic to your inventory.yaml file by setting those crucial tags:
image_tags:
frontend_tag: 1.0
backend_tag: 1.0
With the tags in place, you’re all set for the grand finale! Just execute this command:
sudo ansible-playbook playbook.yml -i inventory.yml
Celebrate Your Success 🎉
Congratulations! You’ve just embarked on a journey towards efficient container deployment with Ansible, Docker, Kubernetes, and Helm. This powerful combination allows you to take control of your applications and streamline your deployment process.
Now that you’ve completed the setup and executed your Ansible playbook, your React Node.js application is ready to shine ✨. Keep experimenting, exploring, and pushing your DevOps skills to new heights 🚀. There’s no limit to what you can achieve with this versatile toolkit.