diff --git a/ANSWERS.md b/ANSWERS.md new file mode 100644 index 0000000..e5f55e3 --- /dev/null +++ b/ANSWERS.md @@ -0,0 +1,19 @@ +How long did it take to finish the test? + It took me 3 days to built the setup and deploy the code. + +If you had more time, how could you improve your solution? + for basic development enviroment its sufficent + +What changes would you do to your solution to be deployed in a production environment? + I will implement some security features such as TLS termination in web proxy. + I will enhance the deployment.yaml file where I will add more objects such as relplicaset , resource limit where I will descrbie the CPU and RAM utilization. I will create seperate namespace for producton pods . + I will create RBAC feature where only seelceted team can access the pods. + I will deloy some metrics agenst suh as prometheus for alerting and log analaytics. + +Why did you choose this language over others? + I am proficent in python and I want to enhance my skill in this language. + +What was the most challenging part and why? + For me most chalanging part was wrting ingress yaml file and setting it in the cluster since I have used my local dektop ingress was not working properly. + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2e4b3ee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +#Pulling base python image +FROM python:3.6-slim + +# Updating the repo +RUN apt-get clean && apt-get -y update + +# Creating working directory in container +WORKDIR /wuaki + +#Adding project folder +ADD . /wuaki/ + +#Installing flask modules +RUN pip3 install -r requirements.txt + +CMD ["python", "/wuaki/wuaki.py"] \ No newline at end of file diff --git a/README.md b/README.md index e01f853..c04e7b1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Rakuten TV SysAdmin/DevOps challenge +**************************************************************************************************** + +Clear instructions on how to use your solution. The clarity and precision of these instructions will be a key part of the test. +Software requirements. +The rationale explaining why you chose this solution over others. + ## Introduction @@ -8,77 +13,74 @@ We need to deploy a new microservice that given a `GET` request to the `/hello` { "hello": "world" } ``` -## Architecture - -This microservice will have two components: -* Web Application -* Web proxy - -### Web Application - -Write a simple HTTP application in **any language** that listens to the port 8080. The application only needs to respond to following request: - -> `GET /hello` -> Expected response: `{ "hello": "world" }` -> Expected status: `200` - -Example: -``` -$ curl http://localhost:8080/hello -{ "hello": "world" } -``` - -Any language can be used to develop this application, but we recommend you to use a simple language and framework. - -### Web Proxy - -A reverse HTTP proxy needs to handle all the requests and send them to the backend application. - -Requirements for the proxy: -* Pass `HTTP` (port 80) requests to the backend application (port 8080) -* Pass `HTTPS` requests (port 443) to the backend application (port 8080) **(OPTIONAL)** - * In case `HTTPS` is implemented, redirect port 80 requests to 443 - -We suggest to use `Nginx` or `Apache` as the proxy application, but any other software will also be accepted. - -## Deployment - -Using **one single command** we want to deploy all the required infrastructure for this application to work. After the application is working, we should get the following result: - -``` -$ curl -L http://IP_ADDRESS/hello -{ "hello": "world" } -``` - -## Required files - -### README.md - -The provided solution needs to be uploaded into a public GitHub repository with a `README.md` file providing the following information: - -1. Clear instructions on how to use your solution. The clarity and precision of these instructions will be a key part of the test. -2. Software requirements. -3. The rationale explaining why you chose this solution over others. - -Please make sure the names *Rakuten*, *Rakuten TV* or *Wuaki* are not referenced in any place in your code or documentation. - -### ANSWERS.md - -Please answer the following questions in a markdown formated file called `ANSWERS.md`: - -1. How long did it take to finish the test? -2. If you had more time, how could you improve your solution? -3. What changes would you do to your solution to be deployed in a production environment? -4. Why did you choose this language over others? -5. What was the most challenging part and why? - -### whoami.json - -Please, describe yourself using JSON. - -## Additional notes - -* If `HTTPS` is implemented, the certificate can be self-signed. -* Simplicity is valued over complexity. -* If you get stuck in any step, you can still submit your proposal and explain the challenges you faced and what you did to try to solve them. -* Commit from the very beginning and commit often. We value the possibility to review your git log. +Approach:- + My approach is simple yet eligent . I am more focussed towards code and uniformity of the application and setup. Keeping uniformity in my mind + I have used kuberenetes and docker for this deployment. I have created setup which is more inclined towards infrastructure as code. + For programming , I have used simple python flask framework because it is light weight and easy to understand. Also given application is not tightly + coupled with database. I have written the code in my local virtual environment which has got all its dependencies in requirements.txt file. + + steps involved :- + 1. Write code in wuaki.py + I have used flask simplying importing the flask module. Created the flask object and used function decorator route to reroute all the request to /hello URI path , then wrote the hello() which print hello world in json format using jsonify object. Then run the app {0.0.0.0} which will allow the connection from any host by default on 8080 port. + + 2. Write Dockerfile. + First line in the docker file is simplying pulling the pyton base image . Second line is simply updating the apt repo . I then created the project folder wuaki and copied all the root directory file inside it, then installed requirements.txt file for all dependencies such as flask. + command used -- pip freeze > requirements.txt + pip install requirements.txt + + 3. Build docker image. + Once the dockerfile is created , build the image. + command i used ; + docker build -t wuakitv . --> To build the docker image + image sha256:25859e029feabd574fa648c5c1822b427611e0bff697def8ddf0d9d6bdd1d333 + To see the docker images -> docker images + wuakitv latest 25859e029fea 41 seconds ago 157MB + I have tagged the image and push to my repository . Here I have used docker hub as repo. + docker tag wuakitv ranjan21/wuakitv + docker push ranjan21/wuakitv. + + 4. Create Kuberentes Resource. + Since i have used docer desktop for this project where kubernetes single nodes comes by defult. Now My approach is to create kubernetes resources for the deployment of the web application. + In deployement.yaml file I have written k8 spec where i created deployment and service api endpoints of k8. + Here i used my self build docker image which i created in the above steps - docker.io/ranjan21/wuakitv. + I exposed the service as load balancer since i wnated to have this application on internet. + command used :- + kubectl apply -f deployment.yaml + kubect get deployment + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % kubectl get deployment + NAME READY UP-TO-DATE AVAILABLE AGE + wuakitv-app 1/1 1 1 2d14h + + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % kubectl get svc + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + kubernetes ClusterIP 10.96.0.1 443/TCP 11d + wuakitv-service LoadBalancer 10.100.33.201 localhost 8080:31437/TCP 2d14h + + From the above command output we can clearly see all our service and resource is deployed. and wuakitv servcie is exposed to loadbalancer. + + 5. Deploy web proxy. + Since I have used kuberenetes , I make use of inbuilt feature of nginx-ingress controller to act as web proxy. + I cretaed ingress yaml file where i described rule to route any incoming traffic to loacalhost to /hello path based routing attached to service wuakitv-service. + Here i havent used tls termination rule as it was optional but there is room for improvement where we can have tls certificate and do ssl termination in nginx controller. + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % kubectl get ing + NAME CLASS HOSTS ADDRESS PORTS AGE + wuaki-ingress nginx localhost localhost 80 37h + + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % curl -L http://127.0.0.1:8080/hello + {"Hello":"World"} + + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % curl -L http://127.0.0.1:80/hello + curl: (52) Empty reply from server + abhishekranjan@Abhisheks-MacBook-Pro sysadmin-challenge % curl -L http://127.0.0.1:8081/hello + curl: (7) Failed to connect to 127.0.0.1 port 8081: Connection refused + + + +Software requirements: + We need to have docker and kuberentes cluster and signed docker registry to upload the images. + +The rationale explaining why you chose this solution over others. + I chose this solution because this is more articulate and prominently used in IT industries . We dont require too many of hardware. Also kuberenetes is flagship technology which eases the code deployment and helps in CICD approach . While making this setup i have retwiked the code several times and rebuild the image n number of times. For me it took almost minute to complete the cycle. Once the setup is ready ,modification and other enhancement is quite easy as you can implement your changes too quickly. + Secind best part is everything is mainatined as code in a central repo so changes are done are reflected easily. + + \ No newline at end of file diff --git a/images/cli-outut-1.png b/images/cli-outut-1.png new file mode 100644 index 0000000..c3c7069 Binary files /dev/null and b/images/cli-outut-1.png differ diff --git a/images/dokcerhub.png b/images/dokcerhub.png new file mode 100644 index 0000000..71015c1 Binary files /dev/null and b/images/dokcerhub.png differ diff --git a/images/localhosturl.png b/images/localhosturl.png new file mode 100644 index 0000000..eddd49e Binary files /dev/null and b/images/localhosturl.png differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a81e1a7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +click +Flask +importlib-metadata +itsdangerous +Jinja2 +MarkupSafe +Werkzeug +zipp diff --git a/whoami.json b/whoami.json new file mode 100644 index 0000000..b33395c --- /dev/null +++ b/whoami.json @@ -0,0 +1,16 @@ + +{ + "name": “Abhishek”, + "lastname": “Ranjan”, + "age": 30, + "nationality": “Indian”, + "livesin": “Japan”, + "passions": [ + “Reading books”, + "Playing baskeball” + ], + “Tech Intro”: [ + "Apprx 9+ yrs experienced Devops Engineer with a demonstrated history of working in the information technology and services industry. Skilled in Linux Administrator,AWS Cloud, DevOps, CI/CD, Automation, Servers, and Vmware. + Worked on different technology stack including git ,cloud ,kubernetes ,nginx ,chef,shell scripting,python,groovy ,php,terraform." + ] +} \ No newline at end of file diff --git a/wuaki-deployment.yaml b/wuaki-deployment.yaml new file mode 100644 index 0000000..b0974de --- /dev/null +++ b/wuaki-deployment.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + name: wuakitv-service +spec: + selector: + app: wuakitv-app + ports: + - protocol: "TCP" + port: 8080 + targetPort: 8080 + type: LoadBalancer + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: wuakitv-app +spec: + selector: + matchLabels: + app: wuakitv-app + replicas: 1 + template: + metadata: + labels: + app: wuakitv-app + spec: + containers: + - name: wuakitv-app + image: docker.io/ranjan21/wuakitv + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + \ No newline at end of file diff --git a/wuaki-ingress.yaml b/wuaki-ingress.yaml new file mode 100644 index 0000000..07720e8 --- /dev/null +++ b/wuaki-ingress.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: wuaki-ingress +spec: + ingressClassName: nginx + rules: + - host: localhost + http: + paths: + - path: /hello + pathType: Prefix + backend: + service: + name: wuakitv-service + port: + number: 8080 \ No newline at end of file diff --git a/wuaki.py b/wuaki.py new file mode 100644 index 0000000..c6c6db2 --- /dev/null +++ b/wuaki.py @@ -0,0 +1,17 @@ +import os +from flask import Flask, jsonify + +'''new microservice that given a GET request to the /hello endpoint it will return a JSON response with the following content:''' +app = Flask(__name__) + +@app.route("/") +@app.route("/hello") +def hello(): + result = {'Hello': 'World'} + return jsonify(result) + + +if __name__ == "__main__": + app.run(host="0.0.0.0",port=8080) + +