Hands-On OpenTelemetry, Docker, and K8s
Deploy Application to K8s
Update the Dockerfile #
With Kubernetes, environment variables are typically managed in the .yaml manifest files rather
than baking them into the Docker image. So let’s remove the following two environment variables from the Dockerfile:
vi /home/splunk/workshop/docker-k8s-otel/helloworld/DockerfileThen remove the following two environment variables:
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_RESOURCE_ATTRIBUTES='deployment.environment=otel-$INSTANCE'To save your changes in vi, press the
esckey to enter command mode, then type:wq!followed by pressing theenter/returnkey.
Build a new Docker Image #
Let’s build a new Docker image that excludes the environment variables:
cd /home/splunk/workshop/docker-k8s-otel/helloworld
docker build -t helloworld:1.2 .Note: we’ve used a different version (1.2) to distinguish the image from our earlier version. To clean up the older versions, run the following command to get the container id:
bashdocker ps -a | grep helloworldThen run the following command to delete the container:
bashdocker rm <old container id> --forceNow we can get the container image id:
bashdocker images | grep 1.1Finally, we can run the following command to delete the old image:
bashdocker image rm <old image id>
Import the Docker Image to Local Container Repository #
Normally we’d push our Docker image to a repository such as Docker Hub.
But for this workshop, we’ll push the Docker image to the local container
repository running on our EC2 instance at localhost:9999
# Update the image tag
docker tag helloworld:1.2 localhost:9999/helloworld:1.2
# Import the image into the local repository
docker push localhost:9999/helloworld:1.2Deploy the .NET Application #
Hint: To enter edit mode in vi, press the ‘i’ key. To save changes, press the
esckey to enter command mode, then type:wq!followed by pressing theenter/returnkey.
To deploy our .NET application to K8s, let’s create a file named deployment.yaml in /home/splunk:
vi /home/splunk/deployment.yamlAnd paste in the following:
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
spec:
selector:
matchLabels:
app: helloworld
replicas: 1
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: localhost:9999/helloworld:1.2
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"What is a Deployment in Kubernetes?
The deployment.yaml file is a kubernetes config file that is used to define a deployment resource. This file is the cornerstone of managing applications in Kubernetes! The deployment config defines the deployment’s desired state and Kubernetes then ensures the actual state matches it. This allows application pods to self-heal and also allows for easy updates or roll backs to applications.
Then, create a second file in the same directory named service.yaml:
vi /home/splunk/service.yamlAnd paste in the following:
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
type: ClusterIP
selector:
app: helloworld
ports:
- port: 8080
protocol: TCPWhat is a Service in Kubernetes?
A Service in Kubernetes is an abstraction layer, working like a middleman, giving you a fixed IP address or DNS name to access your Pods, which stays the same, even if Pods are added, removed, or replaced over time.
Then, create a third file in the same directory named ingress.yaml:
vi /home/splunk/ingress.yamlAnd paste in the following:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helloworld-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
ingressClassName: traefik
rules:
- host: helloworld.localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: helloworld
port:
number: 8080What is an Ingress in Kubernetes?
An Ingress in Kubernetes is a Kubernetes API object that manages external access to services within a cluster, typically HTTP and HTTPS traffic. It acts as a set of rules for routing incoming connections to the correct internal services and pods, handling functions like load balancing, SSL/TLS termination, and name-based virtual hosting
We can then use these manifest files to deploy our application:
cd /home/splunk
# create the deployment
kubectl apply -f deployment.yaml
# create the service
kubectl apply -f service.yaml
# create the ingress
kubectl apply -f ingress.yamldeployment.apps/helloworld created
service/helloworld created
ingress.networking.k8s.io/helloworld-ingress createdTest the Application #
Use the following command to access the application:
curl http://helloworld.localhost/hello/KubernetesConfigure OpenTelemetry #
The .NET OpenTelemetry instrumentation was already baked into the Docker image. But we need to set a few environment variables to tell it where to send the data.
Add the following to deployment.yaml file you created earlier:
IMPORTANT replace
$INSTANCEin the YAML below with your instance name, which can be determined by runningecho $INSTANCE.
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=otel-$INSTANCE" The complete deployment.yaml file should be as follows (with your instance name rather than $INSTANCE):
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
spec:
selector:
matchLabels:
app: helloworld
replicas: 1
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: localhost:9999/helloworld:1.2
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=otel-$INSTANCE" Apply the changes with:
kubectl apply -f deployment.yamldeployment.apps/helloworld configuredThen use the following command to generate some traffic:
curl http://helloworld.localhost/hello/KubernetesAfter a minute or so, you should see traces flowing in the o11y cloud. But, if you want to see your trace sooner, we have …
A Challenge For You #
If you are a developer and just want to quickly grab the trace id or see console feedback, what environment variable could you add to the deployment.yaml file?
