Skip to content

Commit 3740263

Browse files
committed
Added session 2
1 parent e5b41c4 commit 3740263

File tree

5 files changed

+568
-1
lines changed

5 files changed

+568
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ If you are the host for the RUM workshop, please check this [README](https://git
2222

2323
Latest versions of the workshop are:
2424
- [v4.39](https://signalfx.github.io/observability-workshop/v4.39/)
25-
25+
- [v4.38](https://signalfx.github.io/observability-workshop/v4.38/)
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
---
2+
title: Code to Kubernetes - Python
3+
linkTitle: Code to Kubernetes
4+
weight: 4
5+
---
6+
7+
## Code to Kubernetes - Python
8+
9+
**Objective:** Understand activities to instrument a python application and run it on Kubernetes.
10+
11+
- Verify the code
12+
- Containerize the app
13+
- Deploy the container in Kubernetes
14+
15+
**Note:** these steps do not involve Splunk
16+
17+
**Duration:** 15 Minutes
18+
19+
## Verify the code - Review service
20+
21+
Inspect review.py (workshop/flask_apps_start/review)
22+
23+
``` python
24+
from flask import Flask, jsonify
25+
import random
26+
import subprocess
27+
28+
review = Flask(__name__)
29+
num_reviews = 8635403
30+
num_reviews = 100000
31+
reviews_file = '/var/appdata/yelp_academic_dataset_review.json'
32+
33+
@review.route('/')
34+
def hello_world():
35+
return jsonify(message='Hello, you want to hit /get_review. We have ' + str(num_reviews) + ' reviews!')
36+
37+
@review.route('/get_review')
38+
def get_review():
39+
random_review_int = str(random.randint(1,num_reviews))
40+
line_num = random_review_int + 'q;d'
41+
command = ["sed", line_num, reviews_file] # sed "7997242q;d" <file>
42+
random_review = subprocess.run(command, stdout=subprocess.PIPE, text=True)
43+
return random_review.stdout
44+
45+
if __name__ == "__main__":
46+
review.run(host ='0.0.0.0', port = 5000, debug = True)
47+
```
48+
49+
Inspect requirements.txt
50+
51+
``` text
52+
Flask==2.0.2
53+
```
54+
55+
Create a virtual environment and Install the necessary python packages
56+
57+
``` bash
58+
cd Workshop/flask_apps_start/review
59+
60+
python3 -m venv rtapp-workshop
61+
source rtapp-workshop/bin/activate
62+
63+
pip freeze #note output
64+
pip install -r requirements.txt
65+
pip freeze #note output
66+
```
67+
68+
Start the REVIEW service. **Note:** You can stop the app with control+C
69+
70+
``` bash
71+
python3 review.py
72+
73+
* Serving Flask app 'review' (lazy loading)
74+
* Environment: production
75+
...snip...
76+
* Running on http://10.160.145.246:5000/ (Press CTRL+C to quit)
77+
* Restarting with stat
78+
127.0.0.1 - - [17/May/2022 22:46:38] "GET / HTTP/1.1" 200 -
79+
127.0.0.1 - - [17/May/2022 22:47:02] "GET /get_review HTTP/1.1" 200 -
80+
127.0.0.1 - - [17/May/2022 22:47:58] "GET /get_review HTTP/1.1" 200 -
81+
```
82+
83+
Verify that the service is working
84+
- Hit the URL http://localhost:5000 and http://localhost:5000/get_review with a browser
85+
- Or, use curl in your terminal
86+
87+
``` bash
88+
curl localhost:5000
89+
{
90+
"message": "Hello, you want to hit /get_review. We have 100000 reviews!"
91+
}
92+
93+
curl localhost:5000/get_review
94+
{"review_id":"NjbiESXotcEdsyTc4EM3fg","user_id":"PR9LAM19rCM_HQiEm5OP5w","business_id":"UAtX7xmIfdd1W2Pebf6NWg","stars":3.0,"useful":0,"funny":0,"cool":0,"text":"-If you're into cheap beer (pitcher of bud-light for $7) decent wings and a good time, this is the place for you. Its generally very packed after work hours and weekends. Don't expect cocktails. \n\n-You run into a lot of sketchy characters here sometimes but for the most part if you're chilling with friends its not that bad. \n\n-Friendly bouncer and bartenders.","date":"2016-04-12 20:23:24"}
95+
```
96+
97+
{{% alert title="Workshop Question" color="danger" %}}
98+
99+
- What does this application do?
100+
- Do you see the yelp dataset being used?
101+
- Why did the output of pip freeze differ each time you ran it?
102+
- Which port is the REVIEW app listening on? Can other python apps use this same port?
103+
104+
{{% /alert %}}}
105+
106+
## Create a REVIEW container
107+
108+
To create a container image, you need to create a Dockerfile, run docker build to build the image referencing the Docker file and push it up to a remote repository so it can be pulled by other sources.
109+
110+
- Create a Dockerfile
111+
- Creating a Dockerfile typically requires you to consider the following:
112+
- Identify an appropriate container image
113+
- ubuntu vs. python vs. alpine/slim
114+
- ubuntu - overkill, large image size, wasted resources when running in K8
115+
- this is a python app, so pick an image that is optimized for it
116+
- avoid alpine for python
117+
- Order matters
118+
- you're building layers.
119+
- re-use the layers as much as possible
120+
- have items that change often towards the end
121+
- Other Best practices for writing Dockerfiles
122+
123+
Dockerfile for review
124+
125+
``` dockerfile
126+
FROM python:3.10-slim
127+
WORKDIR /app
128+
COPY requirements.txt /app
129+
RUN pip install -r requirements.txt
130+
COPY ./review.py /app
131+
EXPOSE 5000
132+
CMD [ "python", "review.py" ]
133+
```
134+
135+
Create a container image (locally)
136+
Run ‘docker build’ to build a local container image referencing the Dockerfile
137+
138+
``` bash
139+
(venv)% docker build -f Dockerfile -t localhost:8000/review:0.01 .
140+
[+] Building 35.5s (11/11) FINISHED
141+
=> [internal] load build definition from Dockerfile 0.0s
142+
...snip...
143+
=> [3/5] COPY requirements.txt /app 0.0s
144+
=> [4/5] RUN pip install -r requirements.txt 4.6s
145+
=> [5/5] COPY ./review.py /app 0.0s
146+
=> exporting to image 0.2s
147+
=> => exporting layers 0.2s
148+
=> => writing image sha256:61da27081372723363d0425e0ceb34bbad6e483e698c6fe439c5 0.0s
149+
=> => naming to docker.io/localhost:8000/review:0.1 0.0
150+
```
151+
152+
Push the container image into a container repository
153+
Run ‘docker push’ to place a copy of the REVIEW container to a remote location
154+
155+
``` bash
156+
docker push localhost:8000/review:0.01
157+
The push refers to repository [docker.io/localhost:8000/review]
158+
02c36dfb4867: Pushed
159+
...snip...
160+
fd95118eade9: Pushed
161+
0.1: digest: sha256:3651f740abe5635af95d07acd6bcf814e4d025fcc1d9e4af9dee023a9b286f38 size: 2202
162+
```
163+
164+
Verify that the image is in Docker Hub. The same info can be found in Docker Desktop
165+
166+
``` bash
167+
curl -s http://localhost:8000/v2/_catalog
168+
{"repositories":["review"]}
169+
```
170+
171+
## Run REVIEW in Kubernetes
172+
173+
Create K8 deployment yaml file for the REVIEW app
174+
Reference: Creating a Deployment
175+
176+
review.deployment.yaml
177+
178+
``` yaml
179+
apiVersion: apps/v1
180+
kind: Deployment
181+
metadata:
182+
name: review
183+
labels:
184+
app: review
185+
spec:
186+
replicas: 1
187+
selector:
188+
matchLabels:
189+
app: review
190+
template:
191+
metadata:
192+
labels:
193+
app: review
194+
spec:
195+
imagePullSecrets:
196+
- name: regcred
197+
containers:
198+
- image: localhost:8000/review:0.01
199+
name: review
200+
volumeMounts:
201+
- mountPath: /var/appdata
202+
name: appdata
203+
volumes:
204+
- name: appdata
205+
hostPath:
206+
path: /var/appdata
207+
```
208+
209+
Notes regarding review.deployment.yaml:
210+
211+
- labels - K8 uses labels and selectors to tag and identify resources
212+
- In the next step, we'll create a service and associate it to this deployment using the label
213+
- replicas = 1
214+
- K8 allows you to scale your deployments horizontally
215+
- We'll leverage this later to add load and increase our ingestion rate
216+
- regcred provides this deployment with the ability to access your dockerhub credentials which is necessary to pull the container image.
217+
- The volume definition and volumemount make the yelp dataset visible to the container
218+
219+
Create a K8 service yaml file for the review app. Reference: Creating a service:
220+
221+
review.service.yaml
222+
223+
``` yaml
224+
apiVersion: v1
225+
kind: Service
226+
metadata:
227+
name: review
228+
spec:
229+
type: NodePort
230+
selector:
231+
app: review
232+
ports:
233+
- port: 5000
234+
targetPort: 5000
235+
nodePort: 30000
236+
```
237+
238+
Notes about review.service.yaml:
239+
240+
- the selector associates this service to pods with the label app with the value being review
241+
- the review service exposes the review pods as a network service
242+
- other pods can now ping 'review' and they will hit a review pod.
243+
- a pod would get a review if it ran 'curl http://review:5000'
244+
- NodePort service
245+
- the service is accessible to the K8 host by the nodePort, 30000
246+
- Another machine that has this can get a review if it ran 'curl http://<k8 host ip>:30000'
247+
248+
Apply the review deployment and service
249+
250+
``` bash
251+
kubectl apply -f review.service.yaml -f review.deployment.yaml
252+
```
253+
254+
Verify that the deployment and services are running:
255+
256+
``` text
257+
ubuntu@ip-10-0-1-54:/tmp$ kubectl get deployments
258+
NAME READY UP-TO-DATE AVAILABLE AGE
259+
review 1/1 1 1 19h
260+
261+
ubuntu@ip-10-0-1-54:/tmp$ kubectl get services
262+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
263+
review NodePort 10.43.175.21 <none> 5000:30000/TCP 154d
264+
265+
ubuntu@ip-10-0-1-54:/tmp$ curl localhost:30000
266+
{
267+
"message": "Hello, you want to hit /get_review. We have 100000 reviews!"
268+
}
269+
ubuntu@ip-10-0-1-54:/tmp$ curl localhost:30000/get_review
270+
{"review_id":"Vv9rHtfBrFc-1M1DHRKN9Q","user_id":"EaNqIwKkM7p1bkraKotqrg","business_id":"TA1KUSCu8GkWP9w0rmElxw","stars":3.0,"useful":1,"funny":0,"cool":0,"text":"This is the first time I've actually written a review for Flip, but I've probably been here about 10 times. \n\nThis used to be where I would take out of town guests who wanted a good, casual, and relatively inexpensive meal. \n\nI hadn't been for a while, so after a long day in midtown, we decided to head to Flip. \n\nWe had the fried pickles, onion rings, the gyro burger, their special burger, and split a nutella milkshake. I have tasted all of the items we ordered previously (with the exception of the special) and have been blown away with how good they were. My guy had the special which was definitely good, so no complaints there. The onion rings and the fried pickles were greasier than expected. Though I've thought they were delicious in the past, I probably wouldn't order either again. The gyro burger was good, but I could have used a little more sauce. It almost tasted like all of the ingredients didn't entirely fit together. Something was definitely off. It was a friday night and they weren't insanely busy, so I'm not sure I would attribute it to the staff not being on their A game...\n\nDon't get me wrong. Flip is still good. The wait staff is still amazingly good looking. They still make delicious milk shakes. It's just not as amazing as it once was, which really is a little sad.","date":"2010-10-11 18:18:35"}
271+
```
272+
273+
{{% alert title="Workshop Question" color="danger" %}}
274+
275+
- What changes are required if you need to make an update to your Dockerfile now?
276+
277+
{{% /alert %}}
278+
279+
## END OF TKO LAB
280+
281+
We hope you found this session and lab useful. We have optional exercise you can do if you finish ahead of schedule, or if you would like to run this at home. Remember this resource can be used at customers to show the value / ease of OTEL.
282+
283+
Please be sure to review our session and provide feedback so we may improve your experience.
284+
285+
Happy Splunking!!

0 commit comments

Comments
 (0)