Kode Kloud Kubernetes

Task: Rolling Updates And Rolling Back Deployments in Kubernetes

Date: 7/14/2024

There is a production deployment planned for next week. The Nautilus DevOps team wants to test the deployment update and rollback on Dev environment first so that they can identify the risks in advance. Below you can find more details about the plan they want to execute.

1. Create a namespace xfusion. Create a deployment called httpd-deploy under this new namespace, It should have one container called httpd, use httpd:2.4.25 image and 4 replicas. The deployment should use RollingUpdate strategy with maxSurge=1, and maxUnavailable=2. Also create a NodePort type service named httpd-service and expose the deployment on nodePort: 30008.
2. Now upgrade the deployment to version httpd:2.4.43 using a rolling update.
3. Finally, once all pods are updated undo the recent update and roll back to the previous/original version.

Solution: 

Step 1: Create Namespace

First, create the namespace `xfusion`.

# kubectl create namespace xfusion

Step 2: Create Deployment

Create a deployment named `httpd-deploy` in the `xfusion` namespace with the specified parameters.

# vi httpd-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deploy
  namespace: xfusion
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 2
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd:2.4.25
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpd-service
  namespace: xfusion
spec:
  type: NodePort
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30008

Apply the deployment and service:

# kubectl apply -f httpd-deploy.yaml

Step 3: Verify the Deployment and Service

Verify that the deployment and service have been created correctly:

# kubectl get deployments -n xfusion
# kubectl get pods -n xfusion
# kubectl get services -n xfusion

Step 4: Upgrade the Deployment

Update the deployment to use the `httpd:2.4.43` image:

# kubectl set image deployment/httpd-deploy httpd=httpd:2.4.43 -n xfusion

Step 5: Verify the Update

Check the status of the rolling update:

# kubectl rollout status deployment/httpd-deploy -n xfusion

### Step 6: Rollback the Deployment

Rollback the deployment to the previous version:

# kubectl rollout undo deployment/httpd-deploy -n xfusion

Step 7: Verify the Rollback

Check the status of the rollback:

# kubectl rollout status deployment/httpd-deploy -n xfusion

Summary
1. Created a namespace `xfusion`.
2. Created a deployment `httpd-deploy` with 4 replicas using the `httpd:2.4.25` image and RollingUpdate strategy.
3. Created a NodePort service `httpd-service` to expose the deployment on port `30008`.
4. Upgraded the deployment to version `httpd:2.4.43`.
5. Rolled back the deployment to the previous version `httpd:2.4.25`.

This process ensures that the deployment can be updated and rolled back as required, minimizing downtime and maintaining application availability.

Task: Kubernetes: Deploy Jenkins on Kubernetes
Date: 7/17/2024
The Nautilus DevOps team is planning to set up a Jenkins CI server to create/manage some deployment pipelines for some of the projects. They want to set up the Jenkins server on Kubernetes cluster. Below you can find more details about the task:
1) Create a namespace jenkins
2) Create a Service for jenkins deployment. Service name should be jenkins-service under jenkins namespace, type should be NodePort, nodePort should be 30008
3) Create a Jenkins Deployment under jenkins namespace, It should be name as jenkins-deployment , labels app should be jenkins , container name should be jenkins-container , use jenkins/jenkins image , containerPort should be 8080 and replicas count should be 1.
Make sure to wait for the pods to be in running state and make sure you are able to access the Jenkins login screen in the browser before hitting the Check button.

Solution: 
Here is a step-by-step guide to set up the Jenkins CI server on a Kubernetes cluster based on your requirements:

Step 1: Create Namespace
First, create a namespace named `jenkins`.

# kubectl create namespace jenkins

Step 2: Create Service for Jenkins Deployment
Create a service named `jenkins-service` with type `NodePort` and nodePort `30008`.

# vi jenkins-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: jenkins
spec:
  type: NodePort
  selector:
    app: jenkins
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30008

Apply the service configuration:

# kubectl apply -f jenkins-service.yaml

Step 3: Create Jenkins Deployment

Create a deployment named `jenkins-deployment` using the `jenkins/jenkins` image.

# vi jenkins-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins-deployment
  namespace: jenkins
  labels:
    app: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      containers:
      - name: jenkins-container
        image: jenkins/jenkins
        ports:
        - containerPort: 8080

Apply the deployment configuration:

# kubectl apply -f jenkins-deployment.yaml

Step 4: Verify the Deployment and Service
Check the status of the deployment and service to ensure they are running correctly:

# kubectl get pods -n jenkins
# kubectl get services -n jenkins

Wait until the Jenkins pod is in the `Running` state:

# kubectl wait --for=condition=ready pod -l app=jenkins -n jenkins

Step 5: Access Jenkins in Browser
To access the Jenkins login screen in the browser, you need to find the IP address of one of the nodes in your Kubernetes cluster. You can get this information using the following command:

# kubectl get nodes -o wide

Now, open a browser and navigate to `http://<NodeIP>:30008`.

Summary
1. Created a namespace `jenkins`.
2. Created a service `jenkins-service` of type `NodePort` on port `30008`.
3. Created a deployment `jenkins-deployment` with 1 replica using the `jenkins/jenkins` image.
4. Verified the deployment and service status.
5. Accessed the Jenkins login screen in the browser.

By following these steps, you should be able to set up a Jenkins CI server on your Kubernetes cluster and access the Jenkins login screen.

Below are my labs results: 

root@kub01:~# kubectl get pods -n jenkins
NAME                                  READY   STATUS    RESTARTS   AGE
jenkins-deployment-668856675c-hsr62   1/1     Running   0          13m
root@kub01:~#

root@kub01:~# kubectl get services -n jenkins
NAME              TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
jenkins-service   NodePort   10.110.39.226   <none>        8080:30008/TCP   14m
root@kub01:~#

root@kub01:~# kubectl wait --for=condition=ready pod -l app=jenkins -n jenkins
pod/jenkins-deployment-668856675c-hsr62 condition met
root@kub01:~#

root@kub01:~#  kubectl get nodes -o wide
NAME               STATUS   ROLES           AGE   VERSION    INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
kub01              Ready    control-plane   28d   v1.28.11   172.16.1.230   <none>        Ubuntu 20.04.5 LTS   5.4.0-189-generic   cri-o://1.28.4
kub02.darole.org   Ready    <none>          28d   v1.28.11   172.16.1.231   <none>        Ubuntu 20.04.5 LTS   5.4.0-189-generic   cri-o://1.28.4
root@kub01:~#

http://172.16.1.230:30008/ 



root@kub01:~# kubectl exec -it jenkins-deployment-668856675c-hsr62 -n jenkins -- bash
jenkins@jenkins-deployment-668856675c-hsr62:/$ cat /var/jenkins_home/secrets/initialAdminPassword
f9448ce2a8be4ed69ac292d206efa3ba
jenkins@jenkins-deployment-668856675c-hsr62:/$






root@kub01:~# kubectl delete deploy jenkins-deployment -n jenkins
deployment.apps "jenkins-deployment" deleted
root@kub01:~# kubectl delete service jenkins-service -n jenkins
service "jenkins-service" deleted
root@kub01:~#


Task: Deploy Grafana on Kubernetes Cluster
Date: 7/19/2024
The Nautilus DevOps teams is planning to set up a Grafana tool to collect and analyze analytics from some applications. They are planning to deploy it on Kubernetes cluster. Below you can find more details.
1.) Create a deployment named grafana-deployment-datacenter using any grafana image for Grafana app. Set other parameters as per your choice.
2.) Create NodePort type service with nodePort 32000 to expose the app.

Solution: 

To set up the Grafana tool on a Kubernetes cluster as specified, follow these steps:

Step 1: Create Deployment for Grafana
First, create a deployment named `grafana-deployment-nautilus` using a Grafana image.

# vi grafana-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana-deployment-datacenter
  labels:
    app: grafana
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
      - name: grafana-container
        image: grafana/grafana:latest
        ports:
        - containerPort: 3000

Apply the deployment configuration:

# kubectl apply -f grafana-deployment.yaml

Step 2: Create NodePort Service for Grafana

Next, create a NodePort type service to expose the Grafana app on port `32000`.

# vi grafana-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: grafana-service
  labels:
    app: grafana
spec:
  type: NodePort
  selector:
    app: grafana
  ports:
  - port: 3000
    targetPort: 3000
    nodePort: 32000

Apply the service configuration:

# kubectl apply -f grafana-service.yaml

Step 3: Verify Deployment and Service

Check the status of the deployment and service to ensure they are running correctly:

# kubectl get pods
# kubectl get services

Wait until the Grafana pod is in the `Running` state:

# kubectl wait --for=condition=ready pod -l app=grafana

Step 4: Access Grafana in Browser

To access the Grafana login page in the browser, you need to find the IP address of one of the nodes in your Kubernetes cluster. You can get this information using the following command:

# kubectl get nodes -o wide

Now, open a browser and navigate to `http://<NodeIP>:32000`.

### Summary

1. Created a deployment `grafana-deployment-nautilus` using the `grafana/grafana` image.
2. Created a NodePort service `grafana-service` to expose the Grafana app on port `32000`.
3. Verified the deployment and service status.
4. Accessed the Grafana login page in the browser.

By following these steps, you should be able to set up Grafana on your Kubernetes cluster and access the login page.

Task: Kubernetes: Deploy Node App on Kubernetes
Date: 7/21/2024

The Nautilus development team has completed development of one of the node applications, which they are planning to deploy on a Kubernetes cluster. They recently had a meeting with the DevOps team to share their requirements. Based on that, the DevOps team has listed out the exact requirements to deploy the app. Find below more details:
1. Create a deployment using gcr.io/kodekloud/centos-ssh-enabled:node image, replica count must be 2.
2. Create a service to expose this app, the service type must be NodePort, targetPort must be 8080 and nodePort should be 30012.
3. Make sure all the pods are in Running state after the deployment.
4. ou can check the application by clicking on NodeApp button on top bar.

Solution: 

To deploy the Node application on the Kubernetes cluster according to the provided specifications, follow these steps:

Step 1: Create the Deployment

Create a deployment using the `gcr.io/kodekloud/centos-ssh-enabled:node` image with 2 replicas.

# vi node-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-app-deployment
  labels:
    app: node-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: node-app
  template:
    metadata:
      labels:
        app: node-app
    spec:
      containers:
      - name: node-app-container
        image: gcr.io/kodekloud/centos-ssh-enabled:node
        ports:
        - containerPort: 8080

Apply the deployment configuration:

# kubectl apply -f node-app-deployment.yaml

Step 2: Create the Service

Create a NodePort type service to expose the Node app, with target port 8080 and node port 30012.

# vi node-app-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: node-app-service
  labels:
    app: node-app
spec:
  type: NodePort
  selector:
    app: node-app
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30012

Apply the service configuration:

# kubectl apply -f node-app-service.yaml

Step 3: Verify the Deployment and Service

Check the status of the deployment and service to ensure all pods are running correctly:

# kubectl get pods
# kubectl get services

Wait until both Node app pods are in the `Running` state:

# kubectl wait --for=condition=ready pod -l app=node-app --timeout=120s

Step 4: Access the Node Application

To access the Node application, you need the IP address of one of the nodes in your Kubernetes cluster. You can get this information using the following command:

# kubectl get nodes -o wide

Open a browser and navigate to `http://<NodeIP>:30012` to access the Node application.

Summary
1. Created a deployment `node-app-deployment` using the `gcr.io/kodekloud/centos-ssh-enabled:node` image with 2 replicas.
2. Created a NodePort service `node-app-service` to expose the Node app on port `30012`.
3. Verified the deployment and service status.
4. Accessed the Node application in the browser.

By following these steps, you should be able to deploy and access the Node application on your Kubernetes cluster.


Date: 3 Jan 2025
Task: Fix issue with LAMP Environment in Kubernetes

One of the DevOps team member was trying to install a WordPress website on a LAMP stack which is essentially deployed on Kubernetes cluster. It was working well and we could see the installation page a few hours ago. However something is messed up with the stack now due to a website went down. Please look into the issue and fix it:

FYI, deployment name is lamp-wp and its using a service named lamp-service. The Apache is using http default port and nodeport is 30008. From the application logs it has been identified that application is facing some issues while connecting to the database in addition to other issues. Additionally, there are some environment variables associated with the pods like MYSQL_ROOT_PASSWORD, MYSQL_DATABASE,  MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST.

Also do not try to delete/modify any other existing components like deployment name, service name, types, labels etc.

Solution: 

1. Check the details for pods 

thor@jumphost ~$ kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/lamp-wp-56c7c454fc-n5qzx   2/2     Running   0          103s

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        26m
service/lamp-service    NodePort    10.96.164.173   <none>        80:30009/TCP   103s
service/mysql-service   ClusterIP   10.96.7.208     <none>        3306/TCP       103s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/lamp-wp   1/1     1            1           103s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/lamp-wp-56c7c454fc   1         1         1       103s
thor@jumphost ~$

2. Check the pod details  

thor@jumphost ~$ kubectl describe pod/lamp-wp-56c7c454fc-n5qzx
Name:             lamp-wp-56c7c454fc-n5qzx
Namespace:        default
Priority:         0
Service Account:  default
Node:             kodekloud-control-plane/172.17.0.2
Start Time:       Fri, 03 Jan 2025 13:51:54 +0000
Labels:           app=lamp
                  pod-template-hash=56c7c454fc
                  tier=frontend
Annotations:      <none>
Status:           Running
IP:               10.244.0.5
IPs:
  IP:           10.244.0.5
Controlled By:  ReplicaSet/lamp-wp-56c7c454fc
Containers:
  httpd-php-container:
    Container ID:   containerd://0667c0575f0668dec68e689d2ccd5dd415ea5ec8e6f331619c19911ad06ee354
    Image:          webdevops/php-apache:alpine-3-php7
    Image ID:       docker.io/webdevops/php-apache@sha256:bb68c986d4947d4cb49e2753a268e33ad3d69df29c8e9a7728090f4738d5bdb9
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 03 Jan 2025 13:52:05 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      MYSQL_ROOT_PASSWORD:  <set to the key 'password' in secret 'mysql-root-pass'>  Optional: false
      MYSQL_DATABASE:       <set to the key 'database' in secret 'mysql-db-url'>     Optional: false
      MYSQL_USER:           <set to the key 'username' in secret 'mysql-user-pass'>  Optional: false
      MYSQL_PASSWORD:       <set to the key 'password' in secret 'mysql-user-pass'>  Optional: false
      MYSQL_HOST:           <set to the key 'host' in secret 'mysql-host'>           Optional: false
    Mounts:
      /opt/docker/etc/php/php.ini from php-config-volume (rw,path="php.ini")
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2mqsb (ro)
  mysql-container:
    Container ID:   containerd://8bbeea4d5643ec60bf1fc0cd4feb35f9550379908c68d597d0407c4f5af7c628
    Image:          mysql:5.6
    Image ID:       docker.io/library/mysql@sha256:20575ecebe6216036d25dab5903808211f1e9ba63dc7825ac20cb975e34cfcae
    Port:           3306/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 03 Jan 2025 13:52:19 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      MYSQL_ROOT_PASSWORD:  <set to the key 'password' in secret 'mysql-root-pass'>  Optional: false
      MYSQL_DATABASE:       <set to the key 'database' in secret 'mysql-db-url'>     Optional: false
      MYSQL_USER:           <set to the key 'username' in secret 'mysql-user-pass'>  Optional: false
      MYSQL_PASSWORD:       <set to the key 'password' in secret 'mysql-user-pass'>  Optional: false
      MYSQL_HOST:           <set to the key 'host' in secret 'mysql-host'>           Optional: false
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2mqsb (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  php-config-volume:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      php-config
    Optional:  false
  kube-api-access-2mqsb:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m38s  default-scheduler  Successfully assigned default/lamp-wp-56c7c454fc-n5qzx to kodekloud-control-plane
  Normal  Pulling    2m37s  kubelet            Pulling image "webdevops/php-apache:alpine-3-php7"
  Normal  Pulled     2m27s  kubelet            Successfully pulled image "webdevops/php-apache:alpine-3-php7" in 9.710543119s (9.710565107s including waiting)
  Normal  Created    2m27s  kubelet            Created container httpd-php-container
  Normal  Started    2m27s  kubelet            Started container httpd-php-container
  Normal  Pulling    2m27s  kubelet            Pulling image "mysql:5.6"
  Normal  Pulled     2m14s  kubelet            Successfully pulled image "mysql:5.6" in 12.892638104s (12.892667637s including waiting)
  Normal  Created    2m14s  kubelet            Created container mysql-container
  Normal  Started    2m13s  kubelet            Started container mysql-container
thor@jumphost ~$ 

3. Login to container  httpd-php-container

thor@jumphost ~$ kubectl exec --stdin --tty lamp-wp-56c7c454fc-n5qzx -c httpd-php-container -- /bin/bash
bash-4.3# 

thor@jumphost ~$ kubectl exec --stdin --tty lamp-wp-56c7c454fc-n5qzx -c httpd-php-container -- /bin/bash

4. Check the Apache status. 

bash-4.3# service apache2 status
apache:apached                   RUNNING   pid 93, uptime 0:04:58
bash-4.3# 

5. Check the index.php file 

bash-4.3# cd /app/
bash-4.3# cat index.php 
<?php
$dbname = $_ENV['MYSQL_DATABASE'];
$dbuser = $_ENV['MYSQL_USER'];
$dbpass = $_ENV[''MYSQL_PASSWORD""];
$dbhost = $_ENV['MYSQL-HOST'];


$connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");

6. Do the required change in index.php file and restart apache2 services 

bash-4.3# vi index.php 
bash-4.3# service apache2 restart
bash-4.3# cat /app/index.php 
<?php
$dbname = $_ENV['MYSQL_DATABASE'];
$dbuser = $_ENV['MYSQL_USER'];
$dbpass = $_ENV['MYSQL_PASSWORD'];
$dbhost = $_ENV['MYSQL_HOST'];


$connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");

$test_query = "SHOW TABLES FROM $dbname";
$result = mysqli_query($test_query);

if ($result->connect_error) {
   die("Connection failed: " . $conn->connect_error);
}
  echo "Connected successfully";
bash-4.3# 

7. Check the URL

bash-4.3# curl http://localhost:80
Connected successfullybash-4.3# 

8. Check the ports. 

thor@jumphost ~$ kubectl get service
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        52m
lamp-service    NodePort    10.96.164.173   <none>        80:30009/TCP   28m
mysql-service   ClusterIP   10.96.7.208     <none>        3306/TCP       28m
thor@jumphost ~$ 

9. Edit the port 

thor@jumphost ~$ kubectl edit service/lamp-service
service/lamp-service edited

10. Check server status 

thor@jumphost ~$ kubectl get service
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        54m
lamp-service    NodePort    10.96.164.173   <none>        80:30008/TCP   29m
mysql-service   ClusterIP   10.96.7.208     <none>        3306/TCP       29m
thor@jumphost ~$

11. Click on URL  



Date: 7 Feb 2025
Task: Deploy Apache Web Server on Kubernetes CLuster

There is an application that needs to be deployed on Kubernetes cluster under Apache web server. The Nautilus application development team has asked the DevOps team to deploy it. We need to develop a template as per requirements mentioned below:
  1. Create a namespace named as httpd-namespace-datacenter.
  2. Create a deployment named as httpd-deployment-datacenter under newly created namespace. For the deployment use httpd image with latest tag only and remember to mention the tag i.e httpd:latest, and make sure replica counts are 2.
  3. Create a service named as httpd-service-datacenter under same namespace to expose the deployment, nodePort should be 30004.
Solutions:

thor@jumphost ~$ kubectl get nodes
NAME                      STATUS   ROLES           AGE   VERSION
kodekloud-control-plane   Ready    control-plane   65m   v1.27.16-1+f5da3b717fc217
thor@jumphost ~$ kubectl create namespace httpd-namespace-datacenter
namespace/httpd-namespace-datacenter created
thor@jumphost ~$ kubectl get ns
NAME                          STATUS   AGE
default                       Active   74m
httpd-deployment-datacenter   Active   5m31s
httpd-namespace-datacenter    Active   74s
kube-node-lease               Active   74m
kube-public                   Active   74m
kube-system                   Active   74m
local-path-storage            Active   74m
thor@jumphost ~$ cat httpd-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deployment-datacenter
  namespace: httpd-namespace-datacenter
spec:
  replicas: 2
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd:latest
        ports:
        - containerPort: 80
thor@jumphost ~$ kubectl apply -f httpd-deployment.yaml 
deployment.apps/httpd-deployment-datacenter created
thor@jumphost ~$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   76m
thor@jumphost ~$ cat httpd-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: httpd-service-datacenter
  namespace: httpd-namespace-datacenter
spec:
  type: NodePort
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30004
thor@jumphost ~$ kubectl apply -f httpd-service.yaml 
service/httpd-service-datacenter created
thor@jumphost ~$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   76m
thor@jumphost ~$ kubectl get service -n httpd-namespace-datacenter
NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
httpd-service-datacenter   NodePort   10.96.31.144   <none>        80:30004/TCP   66s
thor@jumphost ~$ 

Date: 18 Feb 2025
Task: Deploy Lamp Stack on Kubernetes Cluster
The Nautilus DevOps team want to deploy a PHP website on Kubernetes cluster. They are going to use Apache as a web server and Mysql for database. The team had already gathered the requirements and now they want to make this website live. Below you can find more details:
1) Create a config map php-config for php.ini with variables_order = "EGPCS" data.
2) Create a deployment named lamp-wp.
3) Create two containers under it. First container must be httpd-php-container using image webdevops/php-apache:alpine-3-php7 and second container must be mysql-container from image mysql:5.6. Mount php-config configmap in httpd container at /opt/docker/etc/php/php.ini location.
4) Create kubernetes generic secrets for mysql related values like myql root password, mysql user, mysql password, mysql host and mysql database. Set any values of your choice.
5) Add some environment variables for both containers:
a) MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD and MYSQL_HOST. Take their values from the secrets you created. Please make sure to use env field (do not use envFrom) to define the name-value pair of environment variables.
6) Create a node port type service lamp-service to expose the web application, nodePort must be 30008.
7) Create a service for mysql named mysql-service and its port must be 3306.
8) We already have /tmp/index.php file on jump_host server.
a) Copy this file into httpd container under Apache document root i.e /app and replace the dummy values for mysql related variables with the environment variables you have set for mysql related parameters. Please make sure you do not hard code the mysql related details in this file, you must use the environment variables to fetch those values.
b) You must be able to access this index.php on node port 30008 at the end, please note that you should see Connected successfully message while accessing this page.

Solution: 
https://www.nbtechsupport.co.in/2021/09/deploy-lamp-stack-on-kubernetes-cluster.html

Date: 22 Feb 2025
Task: Init Containers in Kubernetes
There are some applications that need to be deployed on Kubernetes cluster and these apps have some pre-requisites where some configurations need to be changed before deploying the app container. Some of these changes cannot be made inside the images so the DevOps team has come up with a solution to use init containers to perform these tasks during deployment. Below is a sample scenario that the team is going to test first.
  • Create a Deployment named as ic-deploy-datacenter.
  • Configure spec as replicas should be 1, labels app should be ic-datacenter, template's metadata lables app should be the same ic-datacenter.
  • The initContainers should be named as ic-msg-datacenter, use image fedora, preferably with latest tag and use command '/bin/bash', '-c' and 'echo Init Done - Welcome to xFusionCorp Industries > /ic/ecommerce'. The volume mount should be named as ic-volume-datacenter and mount path should be /ic.
  • Main container should be named as ic-main-datacenter, use image fedora, preferably with latest tag and use command '/bin/bash', '-c' and 'while true; do cat /ic/ecommerce; sleep 5; done'. The volume mount should be named as ic-volume-datacenter and mount path should be /ic.
  • Volume to be named as ic-volume-datacenter and it should be an emptyDir type.

Solution:
thor@jumphost ~$ cat ic-deploy-datacenter.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ic-deploy-datacenter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ic-datacenter
  template:
    metadata:
      labels:
        app: ic-datacenter
    spec:
      initContainers:
      - name: ic-msg-datacenter
        image: fedora:latest
        command: ['/bin/bash', '-c', 'echo Init Done - Welcome to xFusionCorp Industries > /ic/ecommerce']
        volumeMounts:
        - name: ic-volume-datacenter
          mountPath: /ic
      containers:
      - name: ic-main-datacenter
        image: fedora:latest
        command: ['/bin/bash', '-c', 'while true; do cat /ic/ecommerce; sleep 5; done']
        volumeMounts:
        - name: ic-volume-datacenter
          mountPath: /ic
      volumes:
      - name: ic-volume-datacenter
        emptyDir: {}

thor@jumphost ~$ kubectl apply -f ic-deploy-datacenter.yaml 
deployment.apps/ic-deploy-datacenter created
thor@jumphost ~$ kubectl get deploy
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
ic-deploy-datacenter   1/1     1            1           11s
thor@jumphost ~$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
ic-deploy-datacenter-945995ff7-6pz2l   1/1     Running   0          21s
thor@jumphost ~$ kubectl describe pod/ic-deploy-datacenter-945995ff7-6pz2l
Name:             ic-deploy-datacenter-945995ff7-6pz2l
Namespace:        default
Priority:         0
Service Account:  default
Node:             kodekloud-control-plane/172.17.0.2
Start Time:       Sat, 22 Feb 2025 05:59:39 +0000
Labels:           app=ic-datacenter
                  pod-template-hash=945995ff7
Annotations:      <none>
Status:           Running
IP:               10.244.0.5
IPs:
  IP:           10.244.0.5
Controlled By:  ReplicaSet/ic-deploy-datacenter-945995ff7
Init Containers:
  ic-msg-datacenter:
    Container ID:  containerd://e933f359089c24133194a4fa5507a07e9504e8630a44c925b4ede7281f881b1c
    Image:         fedora:latest
    Image ID:      docker.io/library/fedora@sha256:3ec60eb34fa1a095c0c34dd37cead9fd38afb62612d43892fcf1d3425c32bc1e
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/bash
      -c
      echo Init Done - Welcome to xFusionCorp Industries > /ic/ecommerce
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Sat, 22 Feb 2025 05:59:46 +0000
      Finished:     Sat, 22 Feb 2025 05:59:46 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /ic from ic-volume-datacenter (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-cc8rw (ro)
Containers:
  ic-main-datacenter:
    Container ID:  containerd://09ca4ce6b43d3869ac1c7d87d627c739c0cab4f3ac994d16039bf774ca75abf9
    Image:         fedora:latest
    Image ID:      docker.io/library/fedora@sha256:3ec60eb34fa1a095c0c34dd37cead9fd38afb62612d43892fcf1d3425c32bc1e
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/bash
      -c
      while true; do cat /ic/ecommerce; sleep 5; done
    State:          Running
      Started:      Sat, 22 Feb 2025 05:59:48 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /ic from ic-volume-datacenter (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-cc8rw (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  ic-volume-datacenter:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
  kube-api-access-cc8rw:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m12s  default-scheduler  Successfully assigned default/ic-deploy-datacenter-945995ff7-6pz2l to kodekloud-control-plane
  Normal  Pulling    3m11s  kubelet            Pulling image "fedora:latest"
  Normal  Pulled     3m5s   kubelet            Successfully pulled image "fedora:latest" in 5.786731623s (5.786747739s including waiting)
  Normal  Created    3m5s   kubelet            Created container ic-msg-datacenter
  Normal  Started    3m5s   kubelet            Started container ic-msg-datacenter
  Normal  Pulling    3m4s   kubelet            Pulling image "fedora:latest"
  Normal  Pulled     3m3s   kubelet            Successfully pulled image "fedora:latest" in 156.530465ms (156.544666ms including waiting)
  Normal  Created    3m3s   kubelet            Created container ic-main-datacenter
  Normal  Started    3m3s   kubelet            Started container ic-main-datacenter
thor@jumphost ~$ kubectl exec -it ic-deploy-datacenter-945995ff7-6pz2l -c ic-main-datacenter -- /bin/bash
[root@ic-deploy-datacenter-945995ff7-6pz2l /]# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         969G  601G  369G  62% /
tmpfs           103G     0  103G   0% /proc/acpi
udev            103G     0  103G   0% /dev/tty
tmpfs           103G     0  103G   0% /proc/scsi
tmpfs            64M     0   64M   0% /dev
/dev/sda1       969G  601G  369G  62% /ic --- > 
tmpfs           103G     0  103G   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
tmpfs           205G   12K  205G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs           103G     0  103G   0% /sys/firmware
[root@ic-deploy-datacenter-945995ff7-6pz2l /]# cat /ic/ecommerce 
Init Done - Welcome to xFusionCorp Industries
[root@ic-deploy-datacenter-945995ff7-6pz2l /]# 

No comments:

Post a Comment