Proxy Injection (Meshing)
Why Linkerd injection?
The benefit of Linkerd injection is that it provides observability, reliability, and security features to the services in the Kubernetes cluster without the need for developers to modify their code. This makes it easier to manage microservices and ensure that they are communicating with each other in a secure and reliable way.
How does Linkerd injection work?
Linkerd injection works in Kubernetes by automatically adding a sidecar container running Linkerd’s proxy to each pod that is deployed in the cluster. This is accomplished through the use of Kubernetes admission controllers, which can modify Kubernetes objects before they are applied
- Admission controllers are a Kubernetes feature that runs when creating new resources within the cluster.
- The Mutating Webhook Configuration is an admission controller type triggered during resource loading in Kubernetes.
- The webhook configuration defines an HTTP API endpoint that receives YAML for a resource and returns an updated version.
- For Linkerd, the webhook configuration directs to the injection service in the Linkerd control plane.
- The injection service adds Linkerd sidecar containers to the resource definition.
- The modified resource definition is then submitted to Kubernetes for creation.
- Now, the K8s controller will deploy the new deployment file, and Linkerd will add an init container to your application pod.
First Check, The Linkerd Pods & Mutating webhook status in your cluster, using the below command-
# kubectl get deploy -n linkerd
linkerd-destination 3/3 3 3 2h
linkerd-identity 3/3 3 3 2h
linkerd-proxy-injector 3/3 3 3 2h # This one
# kubectl get mutatingwebhookconfiguration
linkerd-proxy-injector-webhook-config 1 2h
“The linkerd-proxy-injector deployment mentioned here is utilized by the Linkerd mutating webhook configuration to inject the Linkerd sidecar containers.”
If you want more detail about the mutatingwebhookconfiguration use the below command-
kubectl get mutatingwebhookconfiguration -o yaml
# How to USE LinkerD Annotations on Kubernetes -
1:- Pod Annotation -
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
annotations: <<<<< Injected annotation
linkerd.io/inject: enabled <<<<< Injected annotation
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Mind the annotation placement on the above pod definition —
annotations:
linkerd.io/inject: enabled
2:- Deployment Annotation —
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
annotations: <<<<< Injected annotation
linkerd.io/inject: enabled <<<<< Injected annotation
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
In the case of a deployment, the linkerd.io/inject
the annotation should be placed under the spec.template.metadata.annotations
else it won’t work.
First, deploy a sample application by running the following command:”
wget https://raw.githubusercontent.com/linkerd/website/main/run.linkerd.io/public/emojivoto.yml
kubectl apply -f emojivoto.yml
Check the pod's status after applying the above yaml.
“In the above image, under the READY column, 1/1 means that only one container is running on this pod. This also implies that no LinkerD init container is currently running because we have not injected the annotation yet.”
It’s time to inject the LinkerD container. Add the annotation to all the deployment files and apply them as discussed above.
Here’s an example:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: web
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/version: v11
name: web
namespace: emojivoto
spec:
replicas: 1
selector:
matchLabels:
app: web-svc
version: v11
template:
metadata:
labels:
app: web-svc
version: v11
annotations: <<<<<<< # Injected annotation
linkerd.io/inject: enabled <<<<<<< # Injected annotation
spec:
containers:
. .. ...........
. .............
“Now, try running the below command and observe the Containers Number. It should be 2/2. The reason for 2/2 is that one container is related to your application code, and the other container is for LinkerD.”
“ONE more way to inject LinkerD annotation into your deployment is by using the following command:”
linkerd inject deployment.yml
In our case, we are using emojivoto.yml, so our command looks like this.
linkerd inject emojivoto.yml
Output —
apiVersion: v1
kind: Namespace
metadata:
annotations:
linkerd.io/inject: enabled
name: emojivoto
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: emoji
namespace: emojivoto
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: voting
namespace: emojivoto
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: web
namespace: emojivoto
---
apiVersion: v1
kind: Service
metadata:
name: emoji-svc
namespace: emojivoto
spec:
ports:
- name: grpc
port: 8080
targetPort: 8080
- name: prom
port: 8801
targetPort: 8801
selector:
app: emoji-svc
---
apiVersion: v1
kind: Service
metadata:
name: voting-svc
namespace: emojivoto
spec:
ports:
- name: grpc
port: 8080
targetPort: 8080
- name: prom
port: 8801
targetPort: 8801
selector:
app: voting-svc
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: emojivoto
spec:
ports:
- name: http
port: 80
targetPort: 8080
selector:
app: web-svc
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: emoji
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/version: v11
name: emoji
namespace: emojivoto
spec:
replicas: 1
selector:
matchLabels:
app: emoji-svc
version: v11
template:
metadata:
annotations: <<<< Injected annotation
linkerd.io/inject: enabled <<<< Injected annotation
labels:
app: emoji-svc
version: v11
spec:
containers:
- env:
- name: GRPC_PORT
value: "8080"
- name: PROM_PORT
value: "8801"
image: docker.l5d.io/buoyantio/emojivoto-emoji-svc:v11
name: emoji-svc
ports:
- containerPort: 8080
name: grpc
- containerPort: 8801
name: prom
resources:
requests:
cpu: 100m
serviceAccountName: emoji
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: vote-bot
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/version: v11
name: vote-bot
namespace: emojivoto
spec:
replicas: 1
selector:
matchLabels:
app: vote-bot
version: v11
template:
metadata:
annotations: <<<< Injected annotation
linkerd.io/inject: enabled <<<< Injected annotation
labels:
app: vote-bot
version: v11
spec:
containers:
- command:
- emojivoto-vote-bot
env:
- name: WEB_HOST
value: web-svc.emojivoto:80
image: docker.l5d.io/buoyantio/emojivoto-web:v11
name: vote-bot
resources:
requests:
cpu: 10m
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: voting
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/version: v11
name: voting
namespace: emojivoto
spec:
replicas: 1
selector:
matchLabels:
app: voting-svc
version: v11
template:
metadata:
annotations: <<<< Injected annotation
linkerd.io/inject: enabled <<<< Injected annotation
labels:
app: voting-svc
version: v11
spec:
containers:
- env:
- name: GRPC_PORT
value: "8080"
- name: PROM_PORT
value: "8801"
image: docker.l5d.io/buoyantio/emojivoto-voting-svc:v11
name: voting-svc
ports:
- containerPort: 8080
name: grpc
- containerPort: 8801
name: prom
resources:
requests:
cpu: 100m
serviceAccountName: voting
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: web
app.kubernetes.io/part-of: emojivoto
app.kubernetes.io/version: v11
name: web
namespace: emojivoto
spec:
replicas: 1
selector:
matchLabels:
app: web-svc
version: v11
template:
metadata:
annotations: <<<< Injected annotation
linkerd.io/inject: enabled <<<< Injected annotation
labels:
app: web-svc
version: v11
spec:
containers:
- env:
- name: WEB_PORT
value: "8080"
- name: EMOJISVC_HOST
value: emoji-svc.emojivoto:8080
- name: VOTINGSVC_HOST
value: voting-svc.emojivoto:8080
- name: INDEX_BUNDLE
value: dist/index_bundle.js
image: docker.l5d.io/buoyantio/emojivoto-web:v11
name: web-svc
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: 100m
serviceAccountName: web
I hope this post is informative and useful for you :)
If you enjoy the blog, please give me a Clap : ) and Follow me for more such content.
Crafting these articles demands countless hours of ideation, research, and writing. This year has seen me invest over 500 hours into this craft alone. If my work has brought you joy, would you kindly consider supporting me with a coffee? Your gesture would mean the world to me. If not, thank you dearly for your readership. ❤️