Side-Car container
A Pod is composed of one or more application containers. A sidecar container is a utility container and its purpose is to support the main container.
It is important to note that a standalone sidecar does not serve any purpose, it must be paired with one or more containers.
Generally, a sidecar container is reusable and can be paired with numerous type of main containers.
Example
Create a Pod that defines the main application container that writes the current date to a log file every five seconds.
The sidecar container is nginx serving that logfile. (In practice, your sidecar is likely to be a log collection container that uploads to external storage.
Let's create a file called pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-sidecar
spec:
# Create a volume called 'shared-logs' that the
# app and sidecar share.
volumes:
- name: shared-logs
emptyDir: {}
# In the sidecar pattern, there is a main application
# container and a sidecar container.
containers:
# Main application container
- name: app-container
# Simple application: write the current date
# to the log file every five seconds
image: alpine # alpine is a simple Linux OS image
command: ["/bin/sh"]
args: ["-c", "while true; do date >> /var/log/app.txt; sleep 5;done"]
# Mount the pod's shared log file into the app
# container. The app writes logs here.
volumeMounts:
- name: shared-logs
mountPath: /var/log
# Sidecar container
- name: sidecar-container
# Simple sidecar: display log files using nginx.
# In reality, this sidecar would be a custom image
# that uploads logs to a third-party or storage service.
image: nginx:1.7.9
ports:
- containerPort: 80
# Mount the pod's shared log file into the sidecar
# container. In this case, nginx will serve the files
# in this directory.
volumeMounts:
- name: shared-logs
mountPath: /usr/share/nginx/html # nginx-specific mount path
Execute the file
kubectl apply -f pod.yaml
Connect to the sidecar pod
kubectl exec pod-with-sidecar -c sidecar-container -it bash
Install curl on the sidecar
apt-get update && apt-get install curl
Access the log file via the sidecar
curl 'http://localhost:80/app.txt'
Adapter Container
It is a container that transforms main application data in such a way that it should be understood by an end system means it is used for data transformation.
For example, you are running pods with microservices that are to be monitored by a monitoring tool like Prometheus, but microservices are developed in different programming languages and these are generating data in different formats so in this case, we can apply an Adapter pattern to transform data which would be understood by Prometheus
Example
Create a Config Map which overwrites the default website of Nginx, lets call the file name configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
data:
default.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location /nginx_status {
stub_status;
allow 127.0.0.1; #only allow requests from localhost
deny all; #deny all other hosts
}
}
Create a Pod that implements the Adapter pattern to transform the data so that we can feed it to Prometheus. Let's have filename as adapter.yaml
apiVersion: v1
kind: Pod
metadata:
name: webserver-1
labels:
app: webserver
spec:
volumes:
- name: nginx-conf
configMap:
name: nginx-conf
items:
- key: default.conf
path: default.conf
containers:
- name: webserver
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d
name: nginx-conf
readOnly: true
- name: adapter
image: nginx/nginx-prometheus-exporter:0.4.2
args: ["-nginx.scrape-uri","http://localhost/nginx_status"]
ports:
- containerPort: 9113
To access the application let's have a service.yaml file
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport-service
labels:
app: myapp-service-httpd
tier: frontend
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30008
name: nginx
- targetPort: 9113
port: 9113
nodePort: 30009
name: adaptor
selector:
app: webserver
Execute
kubectl apply -f .
kubectl exec -it webserver bash
apt update && apt install curl -y
curl localhost/nginx_status
curl localhost:9113/metrics
Ambassador Container
The Ambassador container is a special type of sidecar container which simplifies accessing services outside the Pod. When you are running applications on kubernetes it’s a high chance that you should access the data from the external services. The Ambassador container hides the complexity and provides the uniform interface to access these external services.
Imagine that you have the pod with one container running successfully but, you need to access external services. But, these external services are dynamic in nature or difficult to access. Sometimes there is a different format that external service returns. There are some other reasons as well and you don’t want to handle this complexity in the main container. So, we use the Ambassador containers to handle these kinds of scenarios
Example
Microservice for this example:-Fake API
Ambassador Container
Let’s look at the Ambassador container which is a simple NGINX server that acts as a reverse proxy. Here is the simple nginx.conf file.
worker_processes 4;
events { worker_connections 1024; }
http {
server {
listen 3000;
location / {
proxy_pass https://fakestoreapi.com/products;
}
}
}
Create a Docker file
FROM nginx:alpine
#!/bin/sh
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf
## Remove default nginx index page
RUN rm -rf /usr/share/nginx/html/*
EXPOSE 3000
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Create a Docker image and push it to docker hub
docker build -t nginx-server-proxy .
docker tag nginx-server-proxy ramansharma95/nginx-server-proxy
docker push ramansharma95/nginx-server-proxy
Main Container
The main container is the nodejs express server that serves on the port 9000. This server calls the reverse proxy and this proxy intern calls the actual API. Here is the server.js file.
Let's create files which are required for nodejs app
package.json
{
"name": "main-container",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"request": "^2.88.2",
"request-promise": "^4.2.6"
}
}
package-lock.json
server.js
const express = require("express");
const app = express();
const port = 9000;
var rp = require('request-promise');
var options = {
method: 'GET',
uri: 'http://localhost:3000'
}
app.get("/", (req, res) => {
rp(options).then(function (body) {
res.json(JSON.parse(body))
}).catch(function (err) {
console.log(err);
});
})
app.listen(port, () => {
console.log('Server listening on port ', port);
})
Docker file
FROM node:slim
COPY ./package.json .
RUN npm install
COPY ./server.js .
CMD ["node", "server.js"]
Execute below commands
docker build -t main-container .
docker tag main-container ramansharma95/main-container
docker push ramansharma95/main-container
Create Pod(pod.yaml)
apiVersion: v1
kind: Pod
metadata:
name: ambassador-container
spec:
containers:
- image: ramansharma95/main-container
name: main-container
imagePullPolicy: Always
resources: {}
ports:
- containerPort: 9000
- image: ramansharma/nginx-server-proxy
name: ambassador-container
imagePullPolicy: Always
resources: {}
ports:
- containerPort: 3000
Execute
0 comments:
Post a Comment