[{"Value":"","Discard":false,"Expires":9999999999}]
La entrada <h1>🔍 Observability: The Superpower Behind Healthy Servers 🚀</h1> se publicó primero en CloudArch.
]]>You might think it’s “just for DevOps”, but in reality, these practices protect your users, your revenue, and yes… even your weekend sleep 
What Is Observability (and Why Should You Care)?Let’s break it down:
Imagine your servers are a spaceship.
Monitoring is your dashboard—gauges, lights, speed indicators.
Observability is the system logs, black box, and mission control data that explain why the ship shakes when you press a button.
And alerting is the alarm that yells: “
Engine overheating!”
Without these, you’re flying blind. With them, you’re in control. 
The 3 Pillars of ObservabilityObservability is powered by:
— Numbers that reflect system performance (CPU, RAM, latency, etc.)
— Time-stamped records of system events.
— Data that follows the path of requests across services (crucial in microservices).Together, they give you deep visibility into how your system behaves—not just in a single spot, but across your entire stack.
Why It MattersLet’s get real.
Without observability:
With observability:
You detect issues earlier
You fix them faster
You prevent them from happening again
You reduce stress for your team and downtime for your users
Real Business Impact (with Data!)
Return on InvestmentA 2023 Observability Forecast by New Relic showed that:
“We were able to go from 12 hours of downtime a month to almost zero.”
— DevOps Manager, financial sector
Outage Cost Reduction
Without observability:
Average outage cost = $9.83M/year
With full-stack observability:
Reduced to $6.17M/year
That’s a savings of $3.66M annually… just by having the right insights! 
Faster Recovery = Happier Users
William Hill improved MTTR by 80%
Seven Network maintained 100% uptime during peak streaming
BlackLine cut cloud spend by $16M/year
Developer Experience“We spend $80K/month on observability to protect $15M/year in revenue. One missed SLA costs us $250K.”
— Reddit /r/devops user
The Role of Smart AlertsMonitoring is great, but alerting is what protects you from waking up to angry clients (or worse, a dead business). 
But not all alerts are created equal.
Bad alerting = noisy Slack channels and alert fatigue
Good alerting = smart, context-aware signals that only fire when something really needs attention
Combine alerts with automation (like restarting services or scaling infrastructure) and you’re moving toward self-healing systems 
A Real ExampleImagine your WordPress site is sluggish on mobile. 
Monitoring says all systems are “green”.
But using traces, you discover that a mobile-specific JS file fails to load, causing timeouts.
Without observability? You’d be in the dark.
With it? You fix it in 5 minutes—before users even notice.
In Conclusion: Why Observability Is EssentialIt’s not just about logs and dashboards.
It’s about trust, speed, resilience, and business success.
Catch problems early
Troubleshoot faster
Optimize cost and performance
Keep your team and customers happy
Innovate without fearObservability is your infrastructure’s early warning system, diagnosis tool, and performance coach—all in one. 

Want to See It in Action?Check out our live Grafana Demo Dashboard where we simulate a WordPress-based Linux server running real-time fake data. Perfect for learning, showing clients, or testing dashboards. 

Final WordsIn the world of cloud-native infrastructure, ignorance is never bliss.
Investing in monitoring, observability, and alerting isn’t a nice-to-have…
…it’s the foundation of a stable, scalable, and successful system. 
Until next time—stay observable, stay reliable, and may your error budgets be low! 
La entrada <h1>🔍 Observability: The Superpower Behind Healthy Servers 🚀</h1> se publicó primero en CloudArch.
]]>La entrada How to mount Secrets in our Deployments se publicó primero en CloudArch.
]]>For this reason, Kubernetes introduces Secrets which are defined as the following:
A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Such information might otherwise be put in a Pod specification or in a container image. Using a Secret means that you don’t need to include confidential data in your application code.
Because Secrets can be created independently of the Pods that use them, there is less risk of the Secret (and its data) being exposed during the workflow of creating, viewing, and editing Pods. Kubernetes, and applications that run in your cluster, can also take additional precautions with Secrets, such as avoiding writing sensitive data to nonvolatile storage.
Secrets are similar to ConfigMaps but are specifically intended to hold confidential data.
https://kubernetes.io/docs/concepts/configuration/secret/
Now, in order to learn how to create them and mount them, let’s image the next case scenario:
Currently, the webapp-deployment is running with sensitive database environment variables directly embedded in the deployment YAML. To enhance security and protect the sensitive data, perform the following steps:
db-secret with the below sensitive database environment variable values:DB_Host , Value: mysql-hostDB_User , Value: rootDB_Password , Value: dbpasswordwebapp-deployment to load the sensitive database environment variables from the newly created db-secret Secret.First of all, let’s start by creating the Secret. A secret is basically an object with a name that contains one or multiple keys with values. So we can have for this example a secret for the database data with three keys for the needed details with its values. We can create it using the kubectl create secret command. This allows to create secrets from string passed as arguments or even passed as files.
controlplane $ kubectl create secret generic db-secret /
--from-literal=DB_Host=mysql-host /
--from-literal=DB_User=root /
--from-literal=DB_Password=dbpassword
secret/db-secret createdOnce we have created it we can check the content.
controlplane $ k get secret
NAME TYPE DATA AGE
db-secret Opaque 3 10s
controlplane $ k describe secret db-secret
Name: db-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
DB_Host: 10 bytes
DB_Password: 10 bytes
DB_User: 4 bytesWe can see now the secret, but it doesn’t display the content. As it’s stored in base64 we would need to retrieve first the values and then decode to make sure everything is right.
controlplane $ kubectl get secret db-secret -o jsonpath='{.data}'
{"DB_Host":"bXlzcWwtaG9zdA==","DB_Password":"ZGJwYXNzd29yZA==","DB_User":"cm9vdA=="}
controlplane $ echo 'ZGJwYXNzd29yZA==' | base64 --decode
dbpasswordAfter decoding it, we can see that the value for DB_Password matches with what we specified.
Now we can see it because we have permissions to get Secrets, but other entities using Service Accounts which doesn’t have permissions to get the Secrets won’t be able to see the content.
As mentioned in the case scenario, we have already a working deployment but this one has the data hardcoded in the yaml file. For security reasons, it’s much a better choice to mount and use the Secret we just created instead of writing the values there since someone who hasn’t have permissions to see Secrets will be able to see our sensitive data.
controlplane $ k get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
webapp-deployment 1/1 1 1 14m
controlplane $ k describe deploy
Name: webapp-deployment
Namespace: default
CreationTimestamp: Mon, 24 Jun 2024 09:03:46 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=webapp
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=webapp
Containers:
webapp-container:
Image: nginx:latest
Port: 80/TCP
Host Port: 0/TCP
Environment:
DB_Host: mysql-host
DB_User: root
DB_Password: dbpassword
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: webapp-deployment-b4ddb5755 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 15m deployment-controller Scaled up replica set webapp-deployment-b4ddb5755 to 1Inside of the YAML we would see:
controlplane $ k edit deploy webapp-deployment
....
containers:
- env:
- name: DB_Host
value: mysql-host
- name: DB_User
value: root
- name: DB_Password
value: dbpasswordTo change it, instead of value we would need to use valueFrom: and secretKeyRef as following
containers:
- env:
- name: DB_Host
valueFrom:
secretKeyRef:
name: db-secret
key: DB_Host
- name: DB_User
valueFrom:
secretKeyRef:
name: db-secret
key: DB_User
- name: DB_Password
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PasswordNow if we apply these changes we will see how our deployment starts using the new references instead of the hardcoded values, making our deployment much cleaner and safer.
controlplane $ k describe deploy
Name: webapp-deployment
Namespace: default
CreationTimestamp: Mon, 24 Jun 2024 09:03:46 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
Selector: app=webapp
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=webapp
Containers:
webapp-container:
Image: nginx:latest
Port: 80/TCP
Host Port: 0/TCP
Environment:
DB_Host: <set to the key 'DB_Host' in secret 'db-secret'> Optional: false
DB_User: <set to the key 'DB_User' in secret 'db-secret'> Optional: false
DB_Password: <set to the key 'DB_Password' in secret 'db-secret'> Optional: false
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: webapp-deployment-b4ddb5755 (0/0 replicas created)
NewReplicaSet: webapp-deployment-6ff644ffb8 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 23m deployment-controller Scaled up replica set webapp-deployment-b4ddb5755 to 1
Normal ScalingReplicaSet 89s deployment-controller Scaled up replica set webapp-deployment-6ff644ffb8 to 1
Normal ScalingReplicaSet 87s deployment-controller Scaled down replica set webapp-deployment-b4ddb5755 to 0 from 1If you want to know more about Kubernetes, check all our posts in Kubernetes
La entrada How to mount Secrets in our Deployments se publicó primero en CloudArch.
]]>La entrada How to expose a Pod internally in Kubernetes se publicó primero en CloudArch.
]]>A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.
Pods are exposed through EndpointSlices. The Service’s selector will be evaluated continuously and the results will be POSTed to an EndpointSlice that is connected to the Service using a labels. When a Pod dies, it is automatically removed from the EndpointSlices that contain it as an endpoint. New Pods that match the Service’s selector will automatically get added to an EndpointSlice for that Service.
We can use the expose option within kubectl command to create it. My personal favourite option is to export that yaml as a file, modify it to satisfy my needs and then apply that file.
In this example we already have a pod called nginx-pod which is running a Nginx service on port 80. We are gonna create a new service called nginx-service which will expose that pod on port 80.
controlplane $ k get po
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 3m52s
controlplane $ k expose pod nginx-pod --port=80 --target-port=80 --dry-run=client -oyaml > service.yaml
controlplane $ cat service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx-pod
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
status:
loadBalancer: {}
controlplane As we can see, we created the service giving the pod name; however it’s not using it. The Service just take the pod to retrieve its selector app: nginx to use it in the service. Thanks to this, every pod that is created with that label, will be added as an endpoint to the Service taking its private IP.
As we want to give it another name. We are gonna edit the file and change the name to nginx-service in the metadata.name section. Then we will apply that file.
controlplane $ vim service.yaml
controlplane $ k apply -f service.yaml
service/nginx-service created
controlplane $ k get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26d
nginx-service ClusterIP 10.99.122.67 <none> 80/TCP 6s
controlplane $ k describe service nginx-service
Name: nginx-service
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.122.67
IPs: 10.99.122.67
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 192.168.1.4:80
Session Affinity: None
Events: <none>
controlplane $As we can see, we already have the service created and the endpoint has been automatically added. Now if our pod dies and a new one comes to life, it will be automatically added to the service and we won’t need to change the endpoint in the applications that are using it. If we look at the Pod description we will see how the IPs are the same
controlplane $ k describe po nginx-pod
Name: nginx-pod
Namespace: default
Priority: 0
Service Account: default
Node: node01/172.30.2.2
Start Time: Wed, 08 May 2024 10:08:43 +0000
Labels: app=nginx
Annotations: cni.projectcalico.org/containerID: 15c844a02dfd1a5b293f640bfa552fe0c4b30a0bc677d780847b7d75d4b658af
cni.projectcalico.org/podIP: 192.168.1.4/32
cni.projectcalico.org/podIPs: 192.168.1.4/32
Status: Running
IP: 192.168.1.4
IPs:
IP: 192.168.1.4Also if we get more pods with that label, they will be automatically load-balanced by the service.
We can check if the service is working by using a curl command to the Service IP and the assigned port.
controlplane $ curl http://10.99.122.67:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>Note that if we change the label in the pod, it will be removed from the service and won’t be available anymore.
If you want to know more about Kubernetes, read our articles and visit the official documentation.
La entrada How to expose a Pod internally in Kubernetes se publicó primero en CloudArch.
]]>