├── challenge-1 ├── namespace.yaml ├── jekyll-node-service.yaml ├── jekyll-pvc.yaml ├── developer-role.yaml ├── developer-rolebinding.yaml ├── jekyll-pod.yaml └── README.md ├── old-challenges ├── challenge-2-CI-CD │ ├── img │ │ ├── Arch.jpg │ │ └── 01-weekly-jenkins.png │ ├── nodejs-k8s │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── service.yml │ │ │ ├── deployment.yml │ │ │ └── _helpers.tpl │ │ ├── values.yaml │ │ └── .helmignore │ ├── app │ │ ├── routes │ │ │ └── root.js │ │ └── server.js │ ├── Dockerfile │ ├── package.json │ ├── Jenkinsfiles │ │ └── nodejs │ │ │ └── Jenkinsfile │ └── README.md └── challenge-1-wordpress │ ├── k8s │ ├── 03-secret.yml │ ├── 01-mysql-pvc.yml │ ├── 02-wordpress-pvc.yml │ ├── 00-wordpress-mysql-pv.yml │ ├── 04-mysql-deploy.yml │ └── 05-wordpress-deploy.yml │ ├── nfs │ └── nfs.sh │ ├── app │ ├── Dockerfile │ └── docker-entrypoint.sh │ └── README.md ├── challenge-3 ├── vote-namespace.yml ├── db-service.yml ├── redis-service.yml ├── vote-service.yml ├── result-service.yml ├── worker.yml ├── vote-deployment.yml ├── result-deployment.yml ├── redis-deployment.yml ├── db-deployment.yml └── README.md ├── challenge-2 ├── fileserver-pvc.yaml ├── fileserver-pv.yaml ├── fileserver-svc.yaml ├── fileserver-pod.yaml └── README.md ├── challenge-4 ├── redis-cluster-service.yaml ├── pv-cluster.yaml ├── redis-statefulset.yaml └── README.md └── README.md /challenge-1/namespace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | creationTimestamp: null 6 | name: development 7 | 8 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/img/Arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kodekloudhub/kubernetes-challenges/HEAD/old-challenges/challenge-2-CI-CD/img/Arch.jpg -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/03-secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: mysql-pass 5 | type: Opaque 6 | data: 7 | password: YWRtaW4= 8 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "1.0" 3 | description: A Helm chart for Kubernetes 4 | name: nodejs-k8s 5 | version: 0.1.0 6 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/img/01-weekly-jenkins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kodekloudhub/kubernetes-challenges/HEAD/old-challenges/challenge-2-CI-CD/img/01-weekly-jenkins.png -------------------------------------------------------------------------------- /challenge-3/vote-namespace.yml: -------------------------------------------------------------------------------- 1 | # To create a new namespace from the CLI command :- kubectl create namespace vote 2 | --- 3 | apiVersion: v1 4 | kind: Namespace 5 | metadata: 6 | name: vote 7 | -------------------------------------------------------------------------------- /challenge-2/fileserver-pvc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: data-pvc 6 | spec: 7 | accessModes: ["ReadWriteMany"] 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | volumeName: data-pv 12 | 13 | -------------------------------------------------------------------------------- /challenge-3/db-service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: db 6 | namespace: vote 7 | spec: 8 | type: ClusterIP 9 | ports: 10 | - port: 5432 11 | targetPort: 5432 12 | selector: 13 | app: db-deployment 14 | 15 | -------------------------------------------------------------------------------- /challenge-2/fileserver-pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolume 3 | apiVersion: v1 4 | metadata: 5 | name: data-pv 6 | spec: 7 | accessModes: ["ReadWriteMany"] 8 | capacity: 9 | storage: 1Gi 10 | hostPath: 11 | path: /web 12 | type: DirectoryOrCreate 13 | 14 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/app/routes/root.js: -------------------------------------------------------------------------------- 1 | module.exports = function(req, res, next) { 2 | res.contentType = "text/html"; 3 | res.end('
Hello Kubernetes!
'); 4 | next(); 5 | }; 6 | -------------------------------------------------------------------------------- /challenge-3/redis-service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: redis 6 | namespace: vote 7 | spec: 8 | type: ClusterIP 9 | ports: 10 | - port: 6379 11 | targetPort: 6379 12 | selector: 13 | app: redis-deployment 14 | 15 | -------------------------------------------------------------------------------- /challenge-3/vote-service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: vote-service 6 | namespace: vote 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 5000 11 | targetPort: 80 12 | nodePort: 31000 13 | selector: 14 | app: vote-deployment 15 | -------------------------------------------------------------------------------- /challenge-1/jekyll-node-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | namespace: development 6 | name: jekyll 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 8080 11 | targetPort: 4000 12 | nodePort: 30097 13 | selector: 14 | run: jekyll 15 | 16 | -------------------------------------------------------------------------------- /challenge-1/jekyll-pvc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: jekyll-site 6 | namespace: development 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | storageClassName: local-storage 11 | resources: 12 | requests: 13 | storage: 1Gi 14 | 15 | -------------------------------------------------------------------------------- /challenge-3/result-service.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: result-service 6 | namespace: vote 7 | spec: 8 | type: NodePort 9 | ports: 10 | - port: 5001 11 | targetPort: 80 12 | nodePort: 31001 13 | selector: 14 | app: result-deployment 15 | 16 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:carbon 2 | 3 | WORKDIR /usr/src/app 4 | 5 | # Install app dependencies 6 | COPY package.json /usr/src/app/ 7 | RUN npm install 8 | # Copy app 9 | COPY . /usr/src/app 10 | 11 | 12 | # Expose for api 13 | EXPOSE 3000 14 | 15 | CMD [ "node", "app/server.js"] 16 | 17 | -------------------------------------------------------------------------------- /challenge-4/redis-cluster-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: redis-cluster-service 5 | spec: 6 | ports: 7 | - port: 6379 8 | name: client 9 | targetPort: 6379 10 | - port: 16379 11 | name: gossip 12 | targetPort: 16379 13 | selector: 14 | app: redis-cluster 15 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/templates/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: node-svc 5 | spec: 6 | ports: 7 | - port: {{ .Values.service.internalPort }} 8 | nodePort: {{ .Values.service.externallPort }} 9 | selector: 10 | app: nodejs 11 | type: {{ .Values.service.type }} 12 | -------------------------------------------------------------------------------- /challenge-1/developer-role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: developer-role 7 | namespace: development 8 | rules: 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - pods 13 | - services 14 | - persistentvolumeclaims 15 | verbs: 16 | - '*' 17 | 18 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for nodejs-k8s. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 2 6 | 7 | image: 8 | repository: NULL 9 | tag: NULL 10 | 11 | service: 12 | type: NodePort 13 | internalPort: 3000 14 | externallPort: 30333 15 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/01-mysql-pvc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: mysql-persistent-storage 5 | labels: 6 | app: wordpress 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 1Gi 13 | selector: 14 | matchLabels: 15 | tier: "mysql" 16 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/02-wordpress-pvc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: wordpress-persistent-storage 5 | labels: 6 | app: wordpress 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 1Gi 13 | selector: 14 | matchLabels: 15 | tier: "frontend" 16 | -------------------------------------------------------------------------------- /challenge-1/developer-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | creationTimestamp: null 6 | name: developer-rolebinding 7 | namespace: development 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: developer-role 12 | subjects: 13 | - apiGroup: rbac.authorization.k8s.io 14 | kind: User 15 | name: martin 16 | 17 | -------------------------------------------------------------------------------- /challenge-2/fileserver-svc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | creationTimestamp: null 6 | labels: 7 | app: gop-fs-service 8 | name: gop-fs-service 9 | spec: 10 | ports: 11 | - name: 8080-8080 12 | port: 8080 13 | protocol: TCP 14 | targetPort: 8080 15 | nodePort: 31200 16 | selector: 17 | run: gop-file-server 18 | type: NodePort 19 | 20 | 21 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ctr-test-restifyjs", 3 | "version": "1.0.4", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node app/server.js", 8 | "test": "node_modules/.bin/mocha app/test" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "restify": "^6.3.4" 14 | }, 15 | "devDependencies": { 16 | "chai": "^4.1.2", 17 | "mocha": "^5.0.1", 18 | "sinon": "^4.4.2" 19 | } 20 | } -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/app/server.js: -------------------------------------------------------------------------------- 1 | var restify = require("restify"); 2 | var server = restify.createServer(); 3 | var pkg = require("../package.json"); 4 | var rootResponder = require("./routes/root"); 5 | 6 | server.get("/", rootResponder); 7 | 8 | server.listen(3000, function() { 9 | console.log("restifyjs version %s running on port 3000", pkg.version); 10 | setInterval(function() { 11 | console.log("restifyjs version %s running on port 3000", pkg.version); 12 | }, 10000); 13 | }); 14 | -------------------------------------------------------------------------------- /challenge-2/fileserver-pod.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | labels: 6 | run: gop-file-server 7 | name: gop-file-server 8 | spec: 9 | volumes: 10 | - name: data-store 11 | persistentVolumeClaim: 12 | claimName: data-pvc 13 | containers: 14 | - image: kodekloud/fileserver 15 | imagePullPolicy: IfNotPresent 16 | name: gop-file-server 17 | volumeMounts: 18 | - name: data-store 19 | mountPath: /web 20 | dnsPolicy: ClusterFirst 21 | restartPolicy: Never 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/templates/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: node-deploy 5 | spec: 6 | replicas: {{ .Values.replicaCount }} 7 | selector: 8 | app: nodejs 9 | template: 10 | metadata: 11 | name: nodejs 12 | labels: 13 | app: nodejs 14 | spec: 15 | containers: 16 | - name: nodejs 17 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 18 | ports: 19 | - name: nodejsport 20 | containerPort: {{ .Values.service.internalPort }} 21 | -------------------------------------------------------------------------------- /challenge-1/jekyll-pod.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | namespace: development 6 | name: jekyll 7 | labels: 8 | run: jekyll 9 | spec: 10 | containers: 11 | - name: jekyll 12 | image: gcr.io/kodekloud/customimage/jekyll-serve 13 | volumeMounts: 14 | - mountPath: /site 15 | name: site 16 | initContainers: 17 | - name: copy-jekyll-site 18 | image: gcr.io/kodekloud/customimage/jekyll 19 | command: [ "jekyll", "new", "/site" ] 20 | volumeMounts: 21 | - mountPath: /site 22 | name: site 23 | volumes: 24 | - name: site 25 | persistentVolumeClaim: 26 | claimName: jekyll-site 27 | 28 | -------------------------------------------------------------------------------- /challenge-3/worker.yml: -------------------------------------------------------------------------------- 1 | # kubectl create deployment worker --image=kodekloud/examplevotingapp_worker --dry-run=client -o yaml -n vote > worker.yaml 2 | 3 | --- 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | creationTimestamp: null 8 | labels: 9 | app: worker 10 | name: worker 11 | namespace: vote 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: worker 17 | strategy: {} 18 | template: 19 | metadata: 20 | creationTimestamp: null 21 | labels: 22 | app: worker 23 | spec: 24 | containers: 25 | - image: kodekloud/examplevotingapp_worker 26 | name: examplevotingapp-worker-s7cwx 27 | 28 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/nfs/nfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Info 4 | echo -n "Installing all updates, this may take a few minutes ......"; 5 | apt-get update -y ; 6 | 7 | ## Install NFS 8 | echo -n "Installing NFS ......"; 9 | apt-get install nfs-kernel-server -y 10 | 11 | 12 | ## NFS Folders 13 | echo -n "Creating/Adjusting Folder /mysql & /html and editing /etc/exports ......"; 14 | 15 | mkdir /{mysql,html} >/dev/null 2>&1 16 | chmod -R 755 /{mysql,html} 17 | chown nobody:nogroup {/mysql,/html} 18 | 19 | 20 | echo "/ *(rw,sync,no_root_squash,no_all_squash)" >> /etc/exports 21 | 22 | ## Restart Services 23 | echo -n "Restarting Services ......"; 24 | service nfs-kernel-server restart 25 | -------------------------------------------------------------------------------- /challenge-3/vote-deployment.yml: -------------------------------------------------------------------------------- 1 | # kubectl create deployment vote-deployment --image=kodekloud/examplevotingapp_vote:before -n vote --dry-run=client -o yaml > deploy.yaml 2 | 3 | --- 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | creationTimestamp: null 8 | labels: 9 | app: vote-deployment 10 | name: vote-deployment 11 | namespace: vote 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: vote-deployment 17 | strategy: {} 18 | template: 19 | metadata: 20 | creationTimestamp: null 21 | labels: 22 | app: vote-deployment 23 | spec: 24 | containers: 25 | - image: kodekloud/examplevotingapp_vote:before 26 | name: vote 27 | resources: {} 28 | 29 | 30 | -------------------------------------------------------------------------------- /challenge-3/result-deployment.yml: -------------------------------------------------------------------------------- 1 | # kubectl create deployment result-deployment --image=kodekloud/examplevotingapp_result:before --dry-run=client -oyaml -n vote > result-deployment.yaml 2 | 3 | --- 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | creationTimestamp: null 8 | labels: 9 | app: result-deployment 10 | name: result-deployment 11 | namespace: vote 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: result-deployment 17 | strategy: {} 18 | template: 19 | metadata: 20 | creationTimestamp: null 21 | labels: 22 | app: result-deployment 23 | spec: 24 | containers: 25 | - image: kodekloud/examplevotingapp_result:before 26 | name: examplevotingapp-result-shxrp 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /challenge-3/redis-deployment.yml: -------------------------------------------------------------------------------- 1 | # kubectl create deployment redis-deployment --image=redis:alpine --dry-run=client -o yaml -n vote > redis-deployment.yaml 2 | # Add emptyDir type volume under the volumes section. 3 | 4 | --- 5 | apiVersion: apps/v1 6 | kind: Deployment 7 | metadata: 8 | labels: 9 | app: redis-deployment 10 | name: redis-deployment 11 | namespace: vote 12 | spec: 13 | replicas: 1 14 | selector: 15 | matchLabels: 16 | app: redis-deployment 17 | template: 18 | metadata: 19 | labels: 20 | app: redis-deployment 21 | spec: 22 | containers: 23 | - image: redis:alpine 24 | name: redis-deployment 25 | volumeMounts: 26 | - mountPath: /data 27 | name: redis-data 28 | volumes: 29 | - name: redis-data 30 | emptyDir: {} 31 | 32 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/00-wordpress-mysql-pv.yml: -------------------------------------------------------------------------------- 1 | # Create PersistentVolume 2 | # change the ip of NFS server 3 | apiVersion: v1 4 | kind: PersistentVolume 5 | metadata: 6 | name: wordpress-persistent-storage 7 | labels: 8 | app: wordpress 9 | tier: frontend 10 | spec: 11 | capacity: 12 | storage: 1Gi 13 | accessModes: 14 | - ReadWriteMany 15 | nfs: 16 | server: nfs01 17 | # Exported path of your NFS server 18 | path: "/html" 19 | 20 | --- 21 | apiVersion: v1 22 | kind: PersistentVolume 23 | metadata: 24 | name: mysql-persistent-storage 25 | labels: 26 | app: wordpress 27 | tier: mysql 28 | spec: 29 | capacity: 30 | storage: 1Gi 31 | accessModes: 32 | - ReadWriteMany 33 | nfs: 34 | server: nfs01 35 | # Exported path of your NFS server 36 | path: "/mysql" 37 | -------------------------------------------------------------------------------- /challenge-3/db-deployment.yml: -------------------------------------------------------------------------------- 1 | # kubectl create deployment db-deployment --image=postgres:9.4 --dry-run=client -o yaml -n vote > db-deployment.yaml 2 | 3 | --- 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | labels: 8 | app: db-deployment 9 | name: db-deployment 10 | namespace: vote 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: db-deployment 16 | template: 17 | metadata: 18 | labels: 19 | app: db-deployment 20 | spec: 21 | containers: 22 | - image: postgres:9.4 23 | name: postgres 24 | env: 25 | - name: POSTGRES_HOST_AUTH_METHOD 26 | value: trust 27 | volumeMounts: 28 | - mountPath: /var/lib/postgresql/data 29 | name: db-data 30 | volumes: 31 | - name: db-data 32 | emptyDir: {} 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Kubernetes Challenges Series](https://kodekloud.com/courses/kubernetes-challenges/) 2 | 3 | These are fun and exciting Kubernetes challenges from the __[Kubernetes Challenges Series](https://kodekloud.com/courses/kubernetes-challenges/)__ hosted on **KodeKloud** platform available for free. 4 | 5 | These challenges are specially designed to give you more hands-on and challenges that would help you excel in Kubernetes. 6 | 7 | 8 | # Sections 9 | 10 | - [Challenge-1](https://kodekloud.com/topic/kubernetes-challenge-1/) 11 | - [Solutions](https://github.com/kodekloudhub/kubernetes-challenges/tree/master/challenge-1) 12 | 13 | - [Challenge-2](https://kodekloud.com/topic/kubernetes-challenge-2/) 14 | - [Solutions](https://github.com/kodekloudhub/kubernetes-challenges/tree/master/challenge-2) 15 | 16 | - [Challenge-3](https://kodekloud.com/topic/kubernetes-challenge-3/) 17 | - [Solutions](https://github.com/kodekloudhub/kubernetes-challenges/tree/master/challenge-3) 18 | 19 | - [Challenge-4](https://kodekloud.com/topic/kubernetes-challenge-4/) 20 | - [Solutions](https://github.com/kodekloudhub/kubernetes-challenges/tree/master/challenge-4) 21 | 22 | 23 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/nodejs-k8s/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "nodejs-k8s.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "nodejs-k8s.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "nodejs-k8s.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/04-mysql-deploy.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: wordpress-mysql 5 | labels: 6 | app: wordpress 7 | spec: 8 | ports: 9 | - port: 3306 10 | selector: 11 | app: wordpress 12 | tier: mysql 13 | clusterIP: None 14 | --- 15 | apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2 16 | kind: Deployment 17 | metadata: 18 | name: mysql 19 | labels: 20 | app: wordpress 21 | spec: 22 | selector: 23 | matchLabels: 24 | app: wordpress 25 | tier: mysql 26 | strategy: 27 | type: Recreate 28 | template: 29 | metadata: 30 | labels: 31 | app: wordpress 32 | tier: mysql 33 | spec: 34 | containers: 35 | - image: mysql:5.7 36 | name: mysql 37 | env: 38 | - name: MYSQL_ROOT_PASSWORD 39 | valueFrom: 40 | secretKeyRef: 41 | name: mysql-pass 42 | key: password 43 | ports: 44 | - containerPort: 3306 45 | name: mysql 46 | volumeMounts: 47 | - name: mysql-persistent-storage 48 | mountPath: "/var/lib/mysql" 49 | volumes: 50 | - name: mysql-persistent-storage 51 | persistentVolumeClaim: 52 | claimName: mysql-persistent-storage 53 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/Jenkinsfiles/nodejs/Jenkinsfile: -------------------------------------------------------------------------------- 1 | node{ 2 | def gitUrl = "https://github.com/kodekloudhub/kubernetes-challenges.git" 3 | def ImageName = "mohamedayman/nodejs-demo" 4 | def gitCred = "git" 5 | def dockerhubCred = "dockerhub" 6 | 7 | try{ 8 | stage('Checkout'){ 9 | git credentialsId: "$gitCred", url: "$gitUrl" 10 | // tag image with th commit id 11 | sh "git rev-parse --short HEAD > .git/commit-id" 12 | imageTag = readFile('.git/commit-id').trim() 13 | 14 | } 15 | 16 | stage('Docker Build, Push'){ 17 | withDockerRegistry([credentialsId: "${dockerhubCred}", url: 'https://index.docker.io/v1/']) { 18 | sh "docker build -t ${ImageName}:${imageTag} ." 19 | sh "docker push ${ImageName}:${imageTag}" 20 | } 21 | 22 | } 23 | 24 | stage('Deploy nodejs App on K8s'){ 25 | sh script: """ 26 | set +e 27 | helm install nodejs --set image.repository=${ImageName} --set image.tag=${imageTag} ./nodejs-k8s 28 | set -e 29 | """ 30 | // update to New version 31 | sh "helm upgrade --wait --recreate-pods --set image.repository=${ImageName} --set image.tag=${imageTag} nodejs ./nodejs-k8s" 32 | 33 | 34 | } 35 | } catch (err) { 36 | currentBuild.result = 'FAILURE' 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/k8s/05-wordpress-deploy.yml: -------------------------------------------------------------------------------- 1 | # create a service for wordpress 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: wordpress 6 | labels: 7 | app: wordpress 8 | spec: 9 | ports: 10 | - port: 80 11 | nodePort: 31004 12 | selector: 13 | app: wordpress 14 | tier: frontend 15 | type: NodePort 16 | 17 | 18 | 19 | --- 20 | apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2 21 | kind: Deployment 22 | metadata: 23 | name: wordpress 24 | labels: 25 | app: wordpress 26 | spec: 27 | replicas: 2 28 | selector: 29 | matchLabels: 30 | app: wordpress 31 | tier: frontend 32 | strategy: 33 | type: Recreate 34 | template: 35 | metadata: 36 | labels: 37 | app: wordpress 38 | tier: frontend 39 | spec: 40 | containers: 41 | - image: wordpress 42 | name: wordpress 43 | env: 44 | - name: WORDPRESS_DB_HOST 45 | value: wordpress-mysql 46 | - name: WORDPRESS_DB_PASSWORD 47 | valueFrom: 48 | secretKeyRef: 49 | name: mysql-pass 50 | key: password 51 | ports: 52 | - containerPort: 80 53 | name: wordpress 54 | volumeMounts: 55 | - name: wordpress-persistent-storage 56 | mountPath: "/var/www/html" 57 | volumes: 58 | - name: wordpress-persistent-storage 59 | persistentVolumeClaim: 60 | claimName: wordpress-persistent-storage 61 | -------------------------------------------------------------------------------- /challenge-4/pv-cluster.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: List 4 | items: 5 | - kind: PersistentVolume 6 | apiVersion: v1 7 | metadata: 8 | name: redis01 9 | spec: 10 | accessModes: ["ReadWriteOnce"] 11 | capacity: 12 | storage: 1Gi 13 | hostPath: 14 | path: /redis01 15 | - kind: PersistentVolume 16 | apiVersion: v1 17 | metadata: 18 | name: redis02 19 | spec: 20 | accessModes: ["ReadWriteOnce"] 21 | capacity: 22 | storage: 1Gi 23 | hostPath: 24 | path: /redis02 25 | - kind: PersistentVolume 26 | apiVersion: v1 27 | metadata: 28 | name: redis03 29 | spec: 30 | accessModes: ["ReadWriteOnce"] 31 | capacity: 32 | storage: 1Gi 33 | hostPath: 34 | path: /redis03 35 | - kind: PersistentVolume 36 | apiVersion: v1 37 | metadata: 38 | name: redis04 39 | spec: 40 | accessModes: ["ReadWriteOnce"] 41 | capacity: 42 | storage: 1Gi 43 | hostPath: 44 | path: /redis04 45 | - kind: PersistentVolume 46 | apiVersion: v1 47 | metadata: 48 | name: redis05 49 | spec: 50 | accessModes: ["ReadWriteOnce"] 51 | capacity: 52 | storage: 1Gi 53 | hostPath: 54 | path: /redis05 55 | - kind: PersistentVolume 56 | apiVersion: v1 57 | metadata: 58 | name: redis06 59 | spec: 60 | accessModes: ["ReadWriteOnce"] 61 | capacity: 62 | storage: 1Gi 63 | hostPath: 64 | path: /redis06 65 | 66 | -------------------------------------------------------------------------------- /challenge-4/redis-statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: StatefulSet 4 | metadata: 5 | name: redis-cluster 6 | labels: 7 | run: redis-cluster 8 | spec: 9 | serviceName: redis-cluster-service 10 | replicas: 6 11 | selector: 12 | matchLabels: 13 | app: redis-cluster 14 | template: 15 | metadata: 16 | name: redis-cluster 17 | labels: 18 | app: redis-cluster 19 | spec: 20 | volumes: 21 | - name: conf 22 | configMap: 23 | name: redis-cluster-configmap 24 | defaultMode: 0755 25 | containers: 26 | - image: redis:5.0.1-alpine 27 | name: redis 28 | command: 29 | - "/conf/update-node.sh" 30 | - "redis-server" 31 | - "/conf/redis.conf" 32 | env: 33 | - name: POD_IP 34 | valueFrom: 35 | fieldRef: 36 | fieldPath: status.podIP 37 | apiVersion: v1 38 | ports: 39 | - containerPort: 6379 40 | name: client 41 | - name: gossip 42 | containerPort: 16379 43 | volumeMounts: 44 | - name: conf 45 | mountPath: /conf 46 | readOnly: false 47 | - name: data 48 | mountPath: /data 49 | readOnly: false 50 | volumeClaimTemplates: 51 | - metadata: 52 | name: data 53 | spec: 54 | accessModes: ["ReadWriteOnce"] 55 | resources: 56 | requests: 57 | storage: 1Gi 58 | 59 | 60 | -------------------------------------------------------------------------------- /old-challenges/challenge-1-wordpress/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.0-apache 2 | 3 | # install the PHP extensions we need 4 | RUN set -ex; \ 5 | \ 6 | savedAptMark="$(apt-mark showmanual)"; \ 7 | \ 8 | apt-get update; \ 9 | apt-get install -y --no-install-recommends \ 10 | libjpeg-dev \ 11 | libpng-dev \ 12 | ; \ 13 | \ 14 | docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ 15 | docker-php-ext-install gd mysqli opcache zip; \ 16 | \ 17 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 18 | apt-mark auto '.*' > /dev/null; \ 19 | apt-mark manual $savedAptMark; \ 20 | ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \ 21 | | awk '/=>/ { print $3 }' \ 22 | | sort -u \ 23 | | xargs -r dpkg-query -S \ 24 | | cut -d: -f1 \ 25 | | sort -u \ 26 | | xargs -rt apt-mark manual; \ 27 | \ 28 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 29 | rm -rf /var/lib/apt/lists/* 30 | 31 | # set recommended PHP.ini settings 32 | # see https://secure.php.net/manual/en/opcache.installation.php 33 | RUN { \ 34 | echo 'opcache.memory_consumption=128'; \ 35 | echo 'opcache.interned_strings_buffer=8'; \ 36 | echo 'opcache.max_accelerated_files=4000'; \ 37 | echo 'opcache.revalidate_freq=2'; \ 38 | echo 'opcache.fast_shutdown=1'; \ 39 | echo 'opcache.enable_cli=1'; \ 40 | } > /usr/local/etc/php/conf.d/opcache-recommended.ini 41 | 42 | RUN a2enmod rewrite expires 43 | 44 | VOLUME /var/www/html 45 | 46 | ENV WORDPRESS_VERSION 4.9.7 47 | ENV WORDPRESS_SHA1 7bf349133750618e388e7a447bc9cdc405967b7d 48 | 49 | RUN set -ex; \ 50 | curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ 51 | echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ 52 | # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress 53 | tar -xzf wordpress.tar.gz -C /usr/src/; \ 54 | rm wordpress.tar.gz; \ 55 | chown -R www-data:www-data /usr/src/wordpress 56 | 57 | COPY docker-entrypoint.sh /usr/local/bin/ 58 | RUN chmod u+x /usr/local/bin/docker-entrypoint.sh 59 | 60 | ENTRYPOINT ["docker-entrypoint.sh"] 61 | CMD ["apache2-foreground"] 62 | -------------------------------------------------------------------------------- /old-challenges/challenge-2-CI-CD/README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes 2 | 3 | In this lab, we will achieve the CI/CD for a "Hello Kubernetes" NodeJS App using 4 | 5 | - Jenkins 6 | - Docker 7 | - DockerHub 8 | - Kubernetes 9 | - Helm package Manager 10 | 11 |  12 | 13 | 14 | 15 | ### Prepare Jenkins VM 16 | 17 | Install Java 18 | 19 | $ sudo apt update -y 20 | $ sudo apt upgrade -y 21 | $ sudo apt-get install default-jre -y 22 | 23 | Install Jenkins 24 | 25 | $ wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add - 26 | $ sudo echo "deb https://pkg.jenkins.io/debian-stable binary/" >> /etc/apt/sources.list 27 | $ sudo apt-get update 28 | $ sudo apt-get install jenkins -y 29 | 30 | Start /Enable Jenkins on next Boot 31 | 32 | $ systemctl start jenkins 33 | $ systemctl enable jenkins 34 | $ cat /var/lib/jenkins/secrets/initialAdminPassword 35 | 36 | On your browser Jenkins-IP:8080, paste the previous password and select "Install suggested plugins" 37 | 38 | 39 | Installing Docker 40 | 41 | $ curl -fsSL https://get.docker.com -o get-docker.sh 42 | $ sudo sh get-docker.sh 43 | 44 | Add User Jenkins to Docker Group 45 | 46 | $ sudo usermod -aG docker jenkins 47 | 48 | Installing the helm client 49 | 50 | - Download your desired version https://github.com/helm/helm/releases 51 | 52 | - Unpack it (tar -zxvf helm-v2.0.0-linux-amd64.tgz) 53 | 54 | - Find the helm binary in the unpacked directory, and move it to its desired destination (mv linux-amd64/helm /usr/local/bin/helm) 55 | 56 | $ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.11.0-linux-amd64.tar.gz 57 | 58 | $ tar -xzvf helm-v2.11.0-linux-amd64.tar.gz 59 | 60 | $ sudo mv linux-amd64/helm /usr/local/bin/ 61 | 62 | $ helm version 63 | 64 | Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"} 65 | 66 | 67 | 68 | 69 | 70 | 71 | ### Creating a pipeline 72 | 73 | Create a Github and DockerHub creds Id "git, dockerhub" 74 | 75 | Go to jenkins-IP:8080/credentials/store/system/domain/ to add your git access with id 76 | 77 |  78 | 79 | Create "New Item" with "Pipeline" type, then copy the content under "jenkinsfiles/nodejs/Jenkinsfile" to the Pipeline and replace 80 | - the 2nd line with your repo 81 | - the 3rd line with dockerhub-username/repo-name 82 | ### Add Changes to the Code 83 | 84 | - under the repository, navigate "app/routes/root.js", change the "background-color" to red 85 | 86 | - run Jenkins pipline 87 | 88 | - Open your browser IP:30333 89 | -------------------------------------------------------------------------------- /challenge-1/README.md: -------------------------------------------------------------------------------- 1 | # Challenge 1 2 | 3 | Deploy the given architecture diagram for implementing a `Jekyll SSG`. Find the lab [here](https://kodekloud.com/topic/kubernetes-challenge-1/). 4 | 5 | As ever, the order you create the resources is significant, and largely governed by the direction of the arrows in the diagram. 6 | 7 | For this challenge, all the namespaced resources are to be created in the existing namespace `development`. When writing YAML manifests, you must include `namespace: development` in the `metadata` section 8 | 9 | Solve in the following order: 10 | 11 | All are solved by creating a YAML manifest for each resource as directed by the details as you select each icon, with the exception of 7 and 8 which are done with `kubectl config`. Expand solutions below by clicking on the arrowhead icons. 12 | 13 | You should study the manifests provided in the repo carefully and understand how they provide what the question asks. 14 | 15 | 1. `jekyll-pv` - The PV is pre-created, however you should examine it and check its properties. Getting the PVC correct depends on this. 16 | 1./root/.kube/config, User = kubernetes-admin Cluster: Server Port = 6443registry.k8s.io/coredns/coredns:v1.8.6