Skip to main content

Docker + Kubernetes + Ansible

 Docker + Kubernetes + Ansible

-----------------------------------------------------------------------------------------------------------------------------

Web Application Deployment using Kubernetes and Ansible
A Flask application named "application.py" is given in the path
Run the given setup.sh file given in the path to install the required dependencies be the challenge.

1. Start Minikube and sync host Docker with Minikube Docker.
Note: If you get any errors while starting Minikube, please do try again by running the command to start Minikube.

2. Create a Dockerfile in the path and dockerize the given 'Flask' application as 'webapp-img'
using 'python:alpine3.7' as its base image.

3. Create a 'deployment.yml' file in the path to create a Kubernetes deployment object named "web-deployment" with 3 replicas which uses the 'webapp-img' and runs a container named "webapp-container". Add Label "app=webapp" and namespace 'web' to this deployment object.

4. Create a 'service.yml' file in the path to create a Kubernetes service named 'web-service' of type LoadBalancer to expose the Flask application: Add a namespace 'web' to this service.

5. Create a 'statefulset.yml' file in the path to create a Kubernetes statefulset named "db-statefulset" with 3 replicas and service name 'db'. This should use the 'mysql:5.6' image and run a container named 'db-container' on port 3386

Set environmental variables "MYSQL_ROOT_PASSWORD" and "MYSQL_USER" by referencing Kubernetes secrets and "MYSQL_DATABASE" as 'db application'. Mount it to a volume named 'db-persistent-storage' which claims the storage using a persistent volume claim named 'db-persistent-claim' and add label 'app-db-mysql' and namespace 'web' to this statefulset.

6. Create an Ansible playbook named 'playbook.yml' in the path  to automate the following tasks. Creates a Kubernetes namespace named 'web' using inline definition.

- Create a Kubernetes immutable secret named 'deploy-secret of type basic authentication with username as "admin" and password as "admin123" using inline definition.
- Create a Kubernetes Persistent volume claim named 'db-persistent-claim with a storage size of 2061, RWD access mode, add label 'app-db-mysql' and namespace 'web' using inline definition.
Create a Statefulset object by invoking the statefulset.yml file. Create a deployment object by invoking the 'deployment.yml' file.
Create a service by invoking the service.yml file.

7. Finally, run the Ansible playbook and check whether the kubernetes objects are created and the application has been deployed & exposed externally using LoadBalancer.
-----------------------------------------------------------------------------------------------------------------------------

SOLUTION:
-----------------------------------------------------------------------------------------------------------------------------
Dockerfile

FROM python:alpine3.7

WORKDIR /app

COPY ./app /app

RUN pip install -r requirements.txt

EXPOSE 8080
# ENV FLASK_APP=app.py
# ENV FLASK_RUN_HOST=0.0.0.0
# ENV FLASK_RUN_PORT=5005

# CMD ["flask", "run"]
CMD ["python3", "app.py"]



deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  namespace: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: web-container
        image: webapp-img:latest
        imagePullPolicy: Never
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 8080
        # command: ["flask", "run"]



service.yml

apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: web
spec:
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
  externalIPs:
  - 192.168.49.2



seceret.yml (optional)

apiVersion: v1
kind: Secret
metadata:
    name: mysecret
type: Opaque
data:
   mysql-user: bXlzcWx1c2Vy
   mysql-password: bXlzcWxwd2Q=


statefulset.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: db-persistent-storage
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /home/ubuntu1804/mysql
    server: localhost

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db-statefulset
  # namespace: web
spec:
  replicas: 1
  serviceName: db
  selector:
    matchLabels:
      app: db-mysql
  template:
    metadata:
      labels:
        app: db-mysql
    spec:
      containers:
      - name: db-container
        image: mysql:5.6
        ports:
        - containerPort: 3306
          name: web
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              key: mysql-password
              name: deploy-secret
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              key: mysql-user
              name: deploy-secret        
        - name: MYSQL_DATABASE
          value: db_application
        volumeMounts:
        - name: db-persistent-claim
          mountPath: /home/ubuntu1804/mysql
  volumeClaimTemplates:
  - metadata:
      name: db-persistent-claim
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Mi





playbook.yml

# code: language=ansible
---
- name: Automate Docker and K8 build and deploy
  hosts: localhost
  vars:
    dockerimg: webapp-img

  tasks:
    - name: Build Docker Image
      ansible.builtin.docker_image:
        path: .
        name: "{{ dockerimg }}"
        tag: latest
        state: present

    - name: Check if minikube running
      command: minikube status
      register: minikube_status
      ignore_errors: true

    - name: Start minikube if not running
      command: minikube start
      when: "'Running' not in minikube_status.stdout"
     
    - name: Load Docker image to minikube
      command: "minikube image load {{ dockerimg }}"
      ignore_errors: true
   
    - name: Create 'web' namespace in k8
      command: minikube kubectl -- create namespace web
      ignore_errors: true

    - name: Create Service in k8
      command: minikube kubectl -- apply -f service.yml
      ignore_errors: true

    - name: Create Deployment in k8
      command: minikube kubectl -- apply -f deployment.yml
      ignore_errors: true

    - name: Create Secrets in k8
      command: minikube kubectl -- create secret generic deploy-secret --from-literal=mysql-user=admin --from-literal=mysql-password=admin123
      ignore_errors: true

    - name: Create Statefulset in k8
      command: minikube kubectl -- apply -f statefulset.yml
      ignore_errors: true



Commands
# docker
docker build -t webapp-img .
docker ps -a

# minikube
minikube start
minikube image load webapp-img
alias kubectl="minikube kubectl --"
kubectl create namespace web
kubectl apply -f service.yml
kubectl apply -f deployment.yml

# check if external ip is present
kubectl get all -n web


kubectl create secret generic deploy-secret --from-literal=mysql-user=admin --from-literal=mysql-password=admin123

kubectl apply -f statefulset.yml
kubectl get statefulset db-statefulset


















Comments

Popular posts from this blog

Kubernetes2

  Challenge 2 ConfigMaps: Step-1: To create a ConfigMap named 'fresco-config' with the key-value pair SERVER_URL= https://www.fresco.me , use the following command: kubectl create configmap fresco-config --from-literal=SERVER_URL=https://www.fresco.me To verify if the ConfigMap is created, use the following command: kubectl get configmap fresco-config Step-2: To create an nginx pod with the environmental variable SERVER_URL_ENV using the ConfigMap created earlier, use the following YAML template: apiVersion: v1 kind: Pod metadata: name: fresco-nginx-pod spec: containers: - name: fresco-nginx-container image: nginx env: - name: SERVER_URL_ENV valueFrom: configMapKeyRef: name: fresco-config key: SERVER_URL Deploy the above file you can name it deployment.yaml and use the command: kubectl apply -f deployment.yaml To test your configuration by executing the following command:

Kubernetes1

  Challenge 1 Welcome to the Kubernetes challenge, your task is to follow the below steps and complete them successfully. Environment Setup Check whether docker & minikube are properly installed and configured. Start Minikube and execute this command to sync host docker with minikube docker minikube -p minikube docker-env and eval $(minikube docker-env) Step-1 Create a pod object using kubectl run command with google's sample image: gcr.io/google-samples/kubernetes-bootcamp:v1 and expose it on port 8080, name the pod as firstapp. Check if the pod creation is successful by running the command: kubectl get pod firstapp Step-2 Expose the application to the local VM by creating a Service object of type NodePort. Check if the service is created by running the command: kubectl get svc firstapp Step-3 Create another deployment using a 'YAML' file, create a deployment.yaml file that contains information of the number of replicas and the images to be

Docker + Docker Compose + Ansible

 Docker + Docker Compose + Ansible ----------------------------------------------------------------------------------------------------------------------------- Flask Application Deployment using Ansible roles and Docker-Compose 1. Run the "setup.sh" file given in the path to install the required dependencies before starting the challenge. 2. A Flask application named "app.py" is given in the path . 3. Create an Ansible role named "Installation" in the path "/etc/ansible/roles" to install docker-compose. 4. Write an Ansible playbook named "creation.yaml" in the path , to perform the following tasks: 1. Using "file" and "copy" modules, create a Multi-stage "Dockerfile" in the path to  - Dockerize the given Flask application with "python:alpine3.7" as its base image, using the given 'requirements.txt' file.  - Build an image using "postgres" as its base image. 2. Using &q