Files
kodekloud-engineer/100 - days of devops/devops-61-70.md

31 KiB
Raw Blame History

Task 61

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-xfusion.

Configure spec as replicas should be 1, labels app should be ic-xfusion, template's metadata lables app should be the same ic-xfusion.

The initContainers should be named as ic-msg-xfusion, use image fedora with latest tag and use command '/bin/bash', '-c' and 'echo Init Done - Welcome to xFusionCorp Industries > /ic/blog'. The volume mount should be named as ic-volume-xfusion and mount path should be /ic.

Main container should be named as ic-main-xfusion, use image fedora with latest tag and use command '/bin/bash', '-c' and 'while true; do cat /ic/blog; sleep 5; done'. The volume mount should be named as ic-volume-xfusion and mount path should be /ic.

Volume to be named as ic-volume-xfusion and it should be an emptyDir type.

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.

Solution

Create ic-deploy-xfusion deployment

kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ic-deploy-xfusion
  labels:
    app: ic-xfusion
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ic-xfusion
  template:
    metadata:
      labels:
        app: ic-xfusion
    spec:
      initContainers:
        - name: ic-msg-xfusion
          image: fedora:latest
          command: ["/bin/bash", "-c", "echo Init Done - Welcome to xFusionCorp Industries > /ic/blog"]
          volumeMounts:
            - name: ic-volume-xfusion
              mountPath: /ic
      containers:
        - name: ic-main-xfusion
          image: fedora:latest
          command: ["/bin/bash", "-c", "while true; do cat /ic/blog; sleep 5; done"]
          volumeMounts:
            - name: ic-volume-xfusion
              mountPath: /ic
      volumes:
        - name: ic-volume-xfusion
          emptyDir: {}
EOF

Verify

kubectl get deployment ic-deploy-xfusion
kubectl get pods -l app=ic-xfusion
kubectl logs -l app=ic-xfusion -c ic-main-xfusion

Want: deployment 1/1 ready, pod Running, and the main container's logs printing Init Done - Welcome to xFusionCorp Industries every 5s.

Task 62

The Nautilus DevOps team is working to deploy some tools in Kubernetes cluster. Some of the tools are licence based so that licence information needs to be stored securely within Kubernetes cluster. Therefore, the team wants to utilize Kubernetes secrets to store those secrets. Below you can find more details about the requirements:

We already have a secret key file ecommerce.txt under the /opt/ directory. Create a generic secret named ecommerce, it should contain the password/license-number present in ecommerce.txt file.

Also create a pod named secret-nautilus.

Configure pod's spec as container name should be secret-container-nautilus, image should be debian with latest tag (remember to mention the tag with image). Use sleep command for container so that it remains in running state. Consume the created secret and mount it under /opt/games within the container.

To verify you can exec into the container secret-container-nautilus, to check the secret key under the mounted path /opt/games. Before hitting the Check button please make sure pod/pods are in running state, also validation can take some time to complete so keep patience.

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.

Solution

Create secret + pod that mounts it

Step 1 — create the generic secret from the file

kubectl create secret generic ecommerce --from-file=/opt/ecommerce.txt

Step 2 — create the pod mounting the secret at /opt/games

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: secret-nautilus
spec:
  containers:
    - name: secret-container-nautilus
      image: debian:latest
      command: ["sleep", "infinity"]
      volumeMounts:
        - name: secret-volume
          mountPath: /opt/games
  volumes:
    - name: secret-volume
      secret:
        secretName: ecommerce
EOF

Verify

kubectl get secret ecommerce
kubectl get pod secret-nautilus
kubectl exec secret-nautilus -- ls -l /opt/games
kubectl exec secret-nautilus -- cat /opt/games/ecommerce.txt

Want: secret ecommerce exists, pod Running, and /opt/games/ecommerce.txt present with the license content inside the container.

Task 63

There is an iron gallery app that the Nautilus DevOps team was developing. They have recently customized the app and are going to deploy the same on the Kubernetes cluster. Below you can find more details:

Create a namespace iron-namespace-nautilus

Create a deployment iron-gallery-deployment-nautilus for iron gallery under the same namespace you created.

:- Labels run should be iron-gallery. :- Replicas count should be 1. :- Selector's matchLabels run should be iron-gallery. :- Template labels run should be iron-gallery under metadata. :- The container should be named as iron-gallery-container-nautilus, use kodekloud/irongallery:2.0 image ( use exact image name / tag ). :- Resources limits for memory should be 100Mi and for CPU should be 50m. :- First volumeMount name should be config, its mountPath should be /usr/share/nginx/html/data. :- Second volumeMount name should be images, its mountPath should be /usr/share/nginx/html/uploads. :- First volume name should be config and give it emptyDir and second volume name should be images, also give it emptyDir.

Create a deployment iron-db-deployment-nautilus for iron db under the same namespace. :- Labels db should be mariadb. :- Replicas count should be 1. :- Selector's matchLabels db should be mariadb. :- Template labels db should be mariadb under metadata. :- The container name should be iron-db-container-nautilus, use kodekloud/irondb:2.0 image ( use exact image name / tag ). :- Define environment, set MYSQL_DATABASE its value should be database_apache, set MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD value should be with some complex passwords for DB connections, and MYSQL_USER value should be any custom user ( except root ).

:- Volume mount name should be db and its mountPath should be /var/lib/mysql. Volume name should be db and give it an emptyDir.

Create a service for iron db which should be named iron-db-service-nautilus under the same namespace. Configure spec as selector's db should be mariadb. Protocol should be TCP, port and targetPort should be 3306 and its type should be ClusterIP.

Create a service for iron gallery which should be named iron-gallery-service-nautilus under the same namespace. Configure spec as selector's run should be iron-gallery. Protocol should be TCP, port and targetPort should be 80, nodePort should be 32678 and its type should be NodePort.

Note: We don't need to make connection b/w database and front-end now, if the installation page is coming up it should be enough for now.

The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.

Solution

Iron Gallery app — namespace, deployments, services

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Namespace
metadata:
  name: iron-namespace-nautilus
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iron-gallery-deployment-nautilus
  namespace: iron-namespace-nautilus
  labels:
    run: iron-gallery
spec:
  replicas: 1
  selector:
    matchLabels:
      run: iron-gallery
  template:
    metadata:
      labels:
        run: iron-gallery
    spec:
      containers:
        - name: iron-gallery-container-nautilus
          image: kodekloud/irongallery:2.0
          resources:
            limits:
              memory: "100Mi"
              cpu: "50m"
          volumeMounts:
            - name: config
              mountPath: /usr/share/nginx/html/data
            - name: images
              mountPath: /usr/share/nginx/html/uploads
      volumes:
        - name: config
          emptyDir: {}
        - name: images
          emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iron-db-deployment-nautilus
  namespace: iron-namespace-nautilus
  labels:
    db: mariadb
spec:
  replicas: 1
  selector:
    matchLabels:
      db: mariadb
  template:
    metadata:
      labels:
        db: mariadb
    spec:
      containers:
        - name: iron-db-container-nautilus
          image: kodekloud/irondb:2.0
          env:
            - name: MYSQL_DATABASE
              value: "database_apache"
            - name: MYSQL_ROOT_PASSWORD
              value: "R00t_C0mpl3x_P@ss"
            - name: MYSQL_PASSWORD
              value: "Us3r_C0mpl3x_P@ss"
            - name: MYSQL_USER
              value: "iron_user"
          volumeMounts:
            - name: db
              mountPath: /var/lib/mysql
      volumes:
        - name: db
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: iron-db-service-nautilus
  namespace: iron-namespace-nautilus
spec:
  type: ClusterIP
  selector:
    db: mariadb
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: iron-gallery-service-nautilus
  namespace: iron-namespace-nautilus
spec:
  type: NodePort
  selector:
    run: iron-gallery
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 32678
EOF

Verify

kubectl get all -n iron-namespace-nautilus
kubectl get pods -n iron-namespace-nautilus
kubectl get svc -n iron-namespace-nautilus

Want: both deployments 1/1, both pods Running, db service ClusterIP on 3306, gallery service NodePort on 32678. Then the iron gallery install page should load via the nodePort.

Task 64

One of the DevOps engineers was trying to deploy a python app on Kubernetes cluster. Unfortunately, due to some mis-configuration, the application is not coming up. Please take a look into it and fix the issues. Application should be accessible on the specified nodePort.

The deployment name is python-deployment-devops, its using poroko/flask-demo-app image. The deployment and service of this app is already deployed.

nodePort should be 32345 and targetPort should be python flask app's default port.

Note: The kubectl utility on the jump-host has been configured to work with the Kubernetes cluster.

Solution

kubectl set image deployment/python-deployment-devops python-container-devops=poroko/flask-demo-app

kubectl patch svc python-service-devops --type=json -p='[
  {"op":"replace","path":"/spec/ports/0/targetPort","value":5000},
  {"op":"replace","path":"/spec/ports/0/nodePort","value":32345}
]'

Task 65

The Nautilus application development team observed some performance issues with one of the application that is deployed in Kubernetes cluster. After looking into number of factors, the team has suggested to use some in-memory caching utility for DB service. After number of discussions, they have decided to use Redis. Initially they would like to deploy Redis on kubernetes cluster for testing and later they will move it to production. Please find below more details about the task:

Create a redis deployment with following parameters:

Create a config map called my-redis-config having maxmemory 2mb in redis-config.

Name of the deployment should be redis-deployment, it should use redis:alpine image and container name should be redis-container. Also make sure it has only 1 replica.

The container should request for 1 CPU.

Mount 2 volumes: a. An Empty directory volume called data at path /redis-master-data. b. A configmap volume called redis-config at path /redis-master. c. The container should expose the port 6379.

Finally, redis-deployment should be up and running.

Solution

Redis deployment with configmap

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-redis-config
data:
  redis-config: |
    maxmemory 2mb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis-container
          image: redis:alpine
          resources:
            requests:
              cpu: "1"
          ports:
            - containerPort: 6379
          volumeMounts:
            - name: data
              mountPath: /redis-master-data
            - name: redis-config
              mountPath: /redis-master
      volumes:
        - name: data
          emptyDir: {}
        - name: redis-config
          configMap:
            name: my-redis-config
EOF

Verify

kubectl get configmap my-redis-config
kubectl get deployment redis-deployment
kubectl get pods -l app=redis
kubectl describe pod -l app=redis | grep -A3 -i "requests\|mounts"

Want: configmap exists, deployment 1/1 ready, pod Running, CPU request 1, both volumes mounted.

Task 66

A new MySQL server needs to be deployed on Kubernetes cluster. The Nautilus DevOps team was working on to gather the requirements. Recently they were able to finalize the requirements and shared them with the team members to start working on it. Below you can find the details:

1.) Create a PersistentVolume mysql-pv, its capacity should be 250Mi, set other parameters as per your preference.

2.) Create a PersistentVolumeClaim to request this PersistentVolume storage. Name it as mysql-pv-claim and request a 250Mi of storage. Set other parameters as per your preference.

3.) Create a deployment named mysql-deployment, use any mysql image as per your preference. Mount the PersistentVolume at mount path /var/lib/mysql.

4.) Create a NodePort type service named mysql and set nodePort to 30007.

5.) Create a secret named mysql-root-pass having a key pair value, where key is password and its value is YUIidhb667, create another secret named mysql-user-pass having some key pair values, where first key is username and its value is kodekloud_pop, second key is password and value is BruCStnMT5, create one more secret named mysql-db-url, key name is database and value is kodekloud_db10

6.) Define some environment variables within the container: a.) name: MYSQL_ROOT_PASSWORD, should pick value from secretKeyRef name: mysql-root-pass and key: password b.) name: MYSQL_DATABASE, should pick value from secretKeyRef name: mysql-db-url and key: database c.) name: MYSQL_USER, should pick value from secretKeyRef name: mysql-user-pass key key: username d.) name: MYSQL_PASSWORD, should pick value from secretKeyRef name: mysql-user-pass and key: password

Solution

MySQL deployment with secrets, PV/PVC, service

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: mysql-root-pass
type: Opaque
stringData:
  password: YUIidhb667
---
apiVersion: v1
kind: Secret
metadata:
  name: mysql-user-pass
type: Opaque
stringData:
  username: kodekloud_pop
  password: BruCStnMT5
---
apiVersion: v1
kind: Secret
metadata:
  name: mysql-db-url
type: Opaque
stringData:
  database: kodekloud_db10
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  storageClassName: manual
  capacity:
    storage: 250Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/mysql-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 250Mi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deployment
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-root-pass
                  key: password
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: mysql-db-url
                  key: database
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-user-pass
                  key: username
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-user-pass
                  key: password
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: NodePort
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306
      nodePort: 30007
EOF

Verify

kubectl get secrets
kubectl get pv mysql-pv
kubectl get pvc mysql-pv-claim
kubectl get deployment mysql-deployment
kubectl get pods -l app=mysql
kubectl get svc mysql

Want: 3 secrets, PV+PVC Bound, deployment 1/1, pod Running, service NodePort 30007.

Task 67

The Nautilus Application development team has finished development of one of the applications and it is ready for deployment. It is a guestbook application that will be used to manage entries for guests/visitors. As per discussion with the DevOps team, they have finalized the infrastructure that will be deployed on Kubernetes cluster. Below you can find more details about it.

BACK-END TIER

Create a deployment named redis-master for Redis master.

a.) Replicas count should be 1. b.) Container name should be master-redis-devops and it should use image redis. c.) Request resources as CPU should be 100m and Memory should be 100Mi. d.) Container port should be redis default port i.e 6379.

Create a service named redis-master for Redis master. Port and targetPort should be Redis default port i.e 6379.

Create another deployment named redis-slave for Redis slave.

a.) Replicas count should be 2. b.) Container name should be slave-redis-devops and it should use gcr.io/google_samples/gb-redisslave:v3 image. c.) Requests resources as CPU should be 100m and Memory should be 100Mi. d.) Define an environment variable named GET_HOSTS_FROM and its value should be dns. e.) Container port should be Redis default port i.e 6379.

Create another service named redis-slave. It should use Redis default port i.e 6379.

Create another service named redis-follower. Port and targetPort should be Redis default port i.e 6379. Its selector app should be redis-slave.

FRONT END TIER

Create a deployment named frontend.

a.) Replicas count should be 3. b.) Container name should be php-redis-devops and it should use gcr.io/google-samples/gb-frontend@sha256:a908df8486ff66f2c4daa0d3d8a2fa09846a1fc8efd65649c0109695c7c5cbff image. c.) Request resources as CPU should be 100m and Memory should be 100Mi. d.) Define an environment variable named as GET_HOSTS_FROM and its value should be dns. e.) Container port should be 80.

Create a service named frontend. Its type should be NodePort, port should be 80 and its nodePort should be 30009.

Finally, you can check the guestbook app by clicking on App button.

You can use any labels as per your choice.

Solution

Guestbook app — full stack

kubectl apply -f - <<'EOF'
# ===== BACK-END: redis-master =====
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-master
  labels:
    app: redis-master
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-master
  template:
    metadata:
      labels:
        app: redis-master
    spec:
      containers:
        - name: master-redis-devops
          image: redis
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
          ports:
            - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-master
spec:
  selector:
    app: redis-master
  ports:
    - port: 6379
      targetPort: 6379
---
# ===== BACK-END: redis-slave =====
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-slave
  labels:
    app: redis-slave
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis-slave
  template:
    metadata:
      labels:
        app: redis-slave
    spec:
      containers:
        - name: slave-redis-devops
          image: gcr.io/google_samples/gb-redisslave:v3
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
          env:
            - name: GET_HOSTS_FROM
              value: dns
          ports:
            - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
spec:
  selector:
    app: redis-slave
  ports:
    - port: 6379
      targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-follower
spec:
  selector:
    app: redis-slave
  ports:
    - port: 6379
      targetPort: 6379
---
# ===== FRONT-END =====
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: php-redis-devops
          image: gcr.io/google-samples/gb-frontend@sha256:a908df8486ff66f2c4daa0d3d8a2fa09846a1fc8efd65649c0109695c7c5cbff
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
          env:
            - name: GET_HOSTS_FROM
              value: dns
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30009
EOF

Verify

kubectl get deployments
kubectl get pods
kubectl get svc
kubectl get pods -o wide | grep -E "redis|frontend"

Want: redis-master 1/1, redis-slave 2/2, frontend 3/3, all four services present, frontend NodePort 30009. Then the App button loads the guestbook.

Task 68

The DevOps team at xFusionCorp Industries is initiating the setup of CI/CD pipelines and has decided to utilize Jenkins as their server. Execute the task according to the provided requirements:

  1. Install Jenkins on the jenkins server using the apt utility only, and start it using the service command.

If you face a timeout issue while starting the Jenkins service, first check the service status with service jenkins status Then review the logs in /var/log/jenkins/jenkins.log to identify the cause. 2. Jenkin's admin user name should be theadmin, password should be Adm!n321, full name should be Mariyam and email should be mariyam@jenkins.stratos.xfusioncorp.com.

Note:

  1. To access the jenkins server, connect from the jump host using the root user with the password S3curePass.

  2. After Jenkins server installation, click the Jenkins button on the top bar to access the Jenkins UI and follow on-screen instructions to create an admin user.

Solution

Install Jenkins on jenkins server + create admin user

Access the server

From the jump host, SSH in as root:

ssh root@jenkins
# password: S3curePass

Part 1 — Install Jenkins (CLI)

Step 1: Install Java (Jenkins prerequisite)

apt update
apt install -y fontconfig openjdk-17-jre
java -version

apt update
apt install -y openjdk-21-jre

# make Java 21 the default (in case 17 is still selected)
update-alternatives --config java

Step 2: Add the Jenkins apt repository + signing key

wget -O /usr/share/keyrings/jenkins-keyring.asc \
  https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key

echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
  "https://pkg.jenkins.io/debian-stable binary/" | \
  tee /etc/apt/sources.list.d/jenkins.list > /dev/null

Step 3: Install Jenkins

apt update
apt install -y jenkins

Step 4: Start Jenkins using the service command

service jenkins start
service jenkins status

If you hit a startup timeout

service jenkins status
cat /var/log/jenkins/jenkins.log

The log identifies the cause — most commonly a missing/wrong Java version. Ensure openjdk-17-jre is installed and set as default (update-alternatives --config java), then restart:

service jenkins restart

Jenkins can take 6090s on first start; a first-attempt timeout doesn't always mean failure — re-check status after waiting.


Part 2 — Create the admin user (Web UI)

Step 1: Get the initial unlock password

cat /var/lib/jenkins/secrets/initialAdminPassword

Copy the output.

Step 2: Open the Jenkins UI

Click the Jenkins button on the top bar.

Step 3: Unlock Jenkins

Paste the initial admin password from Step 1 → Continue.

Step 4: Install plugins

Choose "Install suggested plugins" and wait for completion.

Step 5: Create the First Admin User

Fill in exactly:

Field Value
Username theadmin
Password Adm!n321
Full name Mariyam
Email mariyam@jenkins.stratos.xfusioncorp.com

Click Save and ContinueSave and FinishStart using Jenkins.


Verify

  • service jenkins status shows Jenkins active/running.
  • You can log into the Jenkins UI as theadmin / Adm!n321.
  • The dashboard loads with theadmin as the logged-in user.

Key points

  • Java first — Jenkins is a Java app; without a JRE it won't start (the exact timeout the task warns about). Java 17 is the safe LTS-compatible choice.
  • Repo + keyring required — Jenkins isn't in Ubuntu base repos; add pkg.jenkins.io with its signing key before apt install jenkins.
  • debian-stable = Jenkins LTS line (more stable than weekly).
  • service jenkins start per the task (not systemctl).
  • initialAdminPassword unlocks the first UI screen before you can create theadmin.
  • Admin user is created via the web wizard, not CLI — the four field values must be exact for the grader.
  • Take a screenshot of the finished admin-user setup / dashboard for review.

Task 69

The Nautilus DevOps team has recently setup a Jenkins server, which they want to use for some CI/CD jobs. Before that they want to install some plugins which will be used in most of the jobs. Please find below more details about the task

  1. Click on the Jenkins button on the top bar to access the Jenkins UI. Login using username admin and password Adm!n321.
  2. Once logged in, install the Git and GitLab plugins. You may need to restart Jenkins to complete the plugin installation; if required, opt to Restart Jenkins when installation is complete and no jobs are running on the plugin installation/update page (Update Centre).

Note:

  1. After restarting Jenkins, wait for the login page to reappear before proceeding.
  2. For tasks involving web UI changes, capture screenshots to share for review or consider using screen recording software like loom.com for documentation and sharing.

Solution

Install Git + GitLab plugins in Jenkins

Step 1 — Log in

Click the Jenkins button on the top bar. Log in with:

  • Username: admin
  • Password: Adm!n321

Step 2 — Navigate to Plugin Manager

Manage JenkinsPlugins (under System Configuration; older versions: Manage Plugins).

Step 3 — Find and select the plugins

Go to the Available plugins tab.

In the search box, search and check each:

  • Search Git → check the Git plugin
  • Search GitLab → check the GitLab plugin

Step 4 — Install

Click Install (or Download now and install after restart).

Step 5 — Restart Jenkins

On the installation progress page, check the box: "Restart Jenkins when installation is complete and no jobs are running"

Jenkins restarts. Wait for the login page to reappear before doing anything else.

Step 6 — Verify

After restart, log back in and check: Manage JenkinsPluginsInstalled plugins tab → search Git and GitLab — both should be listed.

Task 70

The Nautilus team is integrating Jenkins into their CI/CD pipelines. After setting up a new Jenkins server, they're now configuring user access for the development team, Follow these steps:

  1. Click on the Jenkins button on the top bar to access the Jenkins UI. Login with username admin and password Adm!n321.
  2. Create a jenkins user named rose with the password TmPcZjtRQx. Their full name should match Rose.
  3. Utilize the Project-based Matrix Authorization Strategy to assign overall read permission to the rose user.
  4. Remove all permissions for Anonymous users (if any) ensuring that the admin user retains overall Administer permissions.
  5. For the existing job, grant rose user only read permissions, disregarding other permissions such as Agent, SCM etc.

Note:

  1. You may need to install plugins and restart Jenkins service. After plugins installation, select Restart Jenkins when installation is complete and no jobs are running on plugin installation/update page.
  2. After restarting the Jenkins service, wait for the Jenkins login page to reappear before proceeding. Avoid clicking Finish immediately after restarting the service.
  3. Capture screenshots of your configuration for review purposes. Consider using screen recording software like loom.com for documentation and sharing.

Solution:

Configure Jenkins user access for rose

Step 1 — Log in

Click Jenkins button → login admin / Adm!n321.

Step 2 — Install Matrix Authorization Strategy plugin (if not present)

Manage Jenkins → Plugins → Available plugins → search "Matrix Authorization Strategy" → check it → Download now and install after restart.

Wait for Jenkins to fully restart, wait for the login page to reappear, log back in.

Step 3 — Create user rose

Manage Jenkins → Users → Create User:

  • Username: rose
  • Password: TmPcZjtRQx
  • Full name: Rose
  • (email can be left blank or any value)

Click Create User.

Step 4 — Switch to Project-based Matrix Authorization Strategy

Manage Jenkins → Security (or Configure Global Security):

  • Under Authorization, select "Project-based Matrix Authorization Strategy"
  • A permission matrix appears.

Step 5 — Set global permissions

In the matrix:

  • Add user admin → grant Overall / Administer (full row, or at minimum Administer). Do this FIRST — critical.
  • Add user rose → grant Overall / Read only.
  • Anonymous row → uncheck ALL permissions (remove everything).

Click Save.

Step 6 — Grant rose read-only on the existing job

Go to the existing job → Configure → enable "Enable project-based security" (checkbox in the job config):

  • Add user rose
  • Grant only Read (under Job → Read). Leave Agent, SCM, Build, etc. unchecked.

Click Save.

Verify

  • admin retains Administer (you can still access everything).
  • rose can log in, sees the job (read), can't configure/build.
  • Anonymous has no permissions.