DEV Community

Cover image for Multi-Container Sidecar Pattern on Kubernetes with Hands-on Sample
Γ–mer Berat Sezer
Γ–mer Berat Sezer

Posted on • Edited on

Multi-Container Sidecar Pattern on Kubernetes with Hands-on Sample

The sidecar container pattern in Kubernetes is a design approach where a secondary container (the "sidecar") runs alongside the primary container in the same pod. This pattern is used to add functionality or support to the primary application without modifying its code. The sidecar container shares the same network and storage as the main container, making it highly effective for certain scenarios.

Sidecars can handle tasks like:

  • Logging: A sidecar container might collect, aggregate, and forward application logs.
  • Monitoring: Sidecars can collect application metrics and send them to a monitoring system.
  • Proxying/Networking: Sidecars can act as service proxies (e.g., Envoy or Istio sidecars) for service mesh implementations.
  • Security: Sidecars can handle certificate rotation or inject secrets securely into the application.

Real-World Use Cases for Sidecar Containers

  • Logging & Monitoring: Sidecar Containers can collect and forward logs (e.g., Fluentd), expose metrics (e.g., Prometheus exporters).
  • Service Mesh: They help to manage service communication, encryption, and telemetry (e.g., Istio, Linkerd).
  • Configuration & Secrets: They help to fetch and update configs or secrets (e.g., HashiCorp Vault).
  • Data Synchronization: They help to sync files/data from external sources (e.g., S3, FTP).
  • Network Proxying & Security: They can act as reverse proxies (e.g., NGINX) or handle SSL/TLS.
  • Caching: They can provide a caching layer (e.g., Redis, Memcached).
  • Testing & Debugging: You can run debugging tools in sidecar containers (e.g., tcpdump) or generate test traffic.
  • Background Tasks: They can handle periodic jobs like cleanup or health checks.
  • API Gateway/Translator: They can translate or adapt API requests (e.g., gRPC to REST).
  • CI/CD: Helper function run as sidecar container (e.g., Gitlab runner helpers).
  • Automated Backups: A sidecar container periodically backs up database data to a remote storage location like AWS S3.
  • Log Archiving: A sidecar compresses and archives old logs from the primary container.
  • Vulnerability Scanning: They can scan app for risks (e.g., Clair, Trivy).
  • Retries & Circuit Breaker: They can help to retry failed requests, manage service health (e.g., Envoy).
  • Data Backups: They can help periodic database backups (e.g., mysqldump, AWS CLI).
  • Rate Limiting: They can help to throttle API requests (e.g., Kong, Envoy).

Hands-On Sample

This hands-on illustrates the simple sample data synchronization real-world use-case. This scenario shows:

  • how to create multicontainer in one pod,
  • how the multicontainers in the same pod have same ethernet interface (IPs),
  • how the multicontainers in the same pod can reach the shared volume area,
  • how to make port-forwarding to host PC ports

How to install Minikube?

  • Minikube is local Kubernetes, focusing on making it easy to learn and develop for Kubernetes.

  • It includes essential Kubernetes components like the API server, scheduler, controller manager, and etcd, along with optional add-ons like the dashboard and ingress. Minikube supports multiple platforms and integrates with kubectl for seamless interaction with the cluster.

  • All you need is Docker (or similarly compatible) container or a Virtual Machine environment, and Kubernetes is a single command away: minikube start

  • To install: https://minikube.sigs.k8s.io/docs/start/

Steps

  • Run minikube (in this scenario, K8s runs on WSL2- Ubuntu 20.04) ("minikube start")
user@k8s:$ minikube start
πŸ˜„  minikube v1.35.0 on Ubuntu 20.04
✨  Automatically selected the docker driver
πŸ“Œ  Using Docker driver with root privileges
πŸ‘  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.46 ...
πŸ”₯  Creating docker container (CPUs=2, Memory=3100MB) ...
❗  Failing to connect to https://registry.k8s.io/ from inside the minikube container
πŸ’‘  To pull new external images, you may need to configure a proxy: https://minikube.sigs.k8s.io/docs/reference/networking/proxy/
🐳  Preparing Kubernetes v1.32.0 on Docker 27.4.1 ...
    β–ͺ Generating certificates and keys ...
    β–ͺ Booting up control plane ...
    β–ͺ Configuring RBAC rules ...
πŸ”—  Configuring bridge CNI (Container Networking Interface) ...
πŸ”Ž  Verifying Kubernetes components...
    β–ͺ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass

πŸ„  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
Enter fullscreen mode Exit fullscreen mode

YAML File explanation:

  • name: webcontainer => container name: webcontainer
  • image: nginx => image from nginx
  • containerPort: 80 => opening-port: 80
  • mountPath: /usr/share/nginx/html => path in the container
  • image: busybox => sidecar, second container image is busybox
  • command: ["/bin/sh"] => suppose args run on shell
  • args: ["-c", "while true; do wget -O /var/log/index.html https://raw.githubusercontent.com/omerbsezer/Fast-Kubernetes/main/index.html; sleep 15; done"] => it pulls index.html file from github every 15 seconds
  • volumes: name: sharedvolume => define emptydir temporary volume, when the pod is deleted, volume also deleted
  • name: sharedvolume => name of volume
  • emptyDir: {} => volume type emtpydir: creates empty directory where the pod is runnning

multicontainer.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: multicontainer
spec:
  containers:
  - name: webcontainer                           
    image: nginx                                 
    ports:                                       
      - containerPort: 80
    volumeMounts:
    - name: sharedvolume                          
      mountPath: /usr/share/nginx/html          
  - name: sidecarcontainer
    image: busybox                              
    command: ["/bin/sh"]                        
    args: ["-c", "while true; do wget -O /var/log/index.html https://raw.githubusercontent.com/omerbsezer/Fast-Kubernetes/main/index.html; sleep 15; done"]
    volumeMounts:
    - name: sharedvolume
      mountPath: /var/log
  volumes:                           
  - name: sharedvolume                          
    emptyDir: {}         
Enter fullscreen mode Exit fullscreen mode

First version of index.html on internet link (GitHub):

<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World! 
  <p>
    This is the multicontainer scenario!
  </p>
  </h1>
</center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

After 2-3 mins, implement second version of index.html on internet link (GitHub) and push the second version. However, updating raw.githubusercontent on GitHub takes some time (e.g. 4-6 mins) (https://raw.githubusercontent.com/):

<!-- MultiContainer Update Page -->
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World! This file is created for the multicontainer-sidecar github update. 
  <p>
    This is the multicontainer scenario! Second version.
  </p>
  </h1>
</center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Create multicontainer on the pod (webcontainer and sidecarcontainer):
user@k8s:$ kubectl apply -f multicontainer.yaml
pod/multicontainer created

user@k8s:$ kubectl get pods -o wide
NAME             READY   STATUS              RESTARTS   AGE   IP       NODE       NOMINATED NODE   READINESS GATES
multicontainer   0/2     ContainerCreating   0          16s   <none>   minikube   <none>           <none>

user@k8s:$ kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
multicontainer   2/2     Running   0          20s   10.244.0.3   minikube   <none>           <none>
Enter fullscreen mode Exit fullscreen mode
  • Connect webcontainer in the multicontainer pod (bash of the webcontainer) and install net-tools to show ethernet interface (IP: 10.244.0.3)
user@k8s:$ kubectl exec -it multicontainer -c webcontainer -- bash
root@multicontainer:/# ifconfig
bash: ifconfig: command not found

root@multicontainer:/# apt update
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Get:4 http://deb.debian.org/debian bookworm/main amd64 Packages [8792 kB]
Get:5 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [13.5 kB]
Get:6 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [241 kB]
Fetched 9302 kB in 2s (4603 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

root@multicontainer:/# apt install net-tools
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 243 kB of archives.
After this operation, 1001 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian bookworm/main amd64 net-tools amd64 2.10-0.1 [243 kB]
Fetched 243 kB in 0s (1244 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package net-tools.
(Reading database ... 7580 files and directories currently installed.)
Preparing to unpack .../net-tools_2.10-0.1_amd64.deb ...
Unpacking net-tools (2.10-0.1) ...
Setting up net-tools (2.10-0.1) ...

root@multicontainer:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.244.0.3  netmask 255.255.0.0  broadcast 10.244.255.255
        inet6 fe80::dc22:5dff:fe50:1574  prefixlen 64  scopeid 0x20<link>
        ether de:22:5d:50:15:74  txqueuelen 0  (Ethernet)
        RX packets 2862  bytes 9831210 (9.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1505  bytes 118298 (115.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@multicontainer:/# exit
Enter fullscreen mode Exit fullscreen mode
  • Connect sidecarcontainer in the multicontainer pod (/bin/sh of the sidecarcontainer) and show ethernet interface (IP: 10.244.0.3).
  • Containers running on same pod have same ethernet interfaces and same IPs (10.244.0.3).
user@k8s:$ kubectl exec -it multicontainer -c sidecarcontainer -- /bin/sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr DE:22:5D:50:15:74
          inet addr:10.244.0.3  Bcast:10.244.255.255  Mask:255.255.0.0
          inet6 addr: fe80::dc22:5dff:fe50:1574/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3243 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1890 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:9965052 (9.5 MiB)  TX bytes:155052 (151.4 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # exit
Enter fullscreen mode Exit fullscreen mode
  • Under the webcontainer, the shared volume with sidecarcontainer can be reachable:
user@k8s:$ kubectl exec -it multicontainer -c webcontainer -- bash
root@multicontainer:/# cd /usr/share/nginx/html

root@multicontainer:/usr/share/nginx/html# ls
index.html

root@multicontainer:/usr/share/nginx/html# cat index.html
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World!
  <p>
    This is the multicontainer scenario!
  </p>
  </h1>
</center>
</body>
</html>

root@multicontainer:/usr/share/nginx/html# exit
exit
Enter fullscreen mode Exit fullscreen mode
  • It can be seen from sidecarcontainer. Both of the container can reach same volume area.
  • If the new file is created on this volume, other container can also reach same new file.
user@k8s:$ kubectl exec -it multicontainer -c sidecarcontainer -- /bin/sh
/ # cd /var/log
/var/log # ls
index.html
/var/log # cat index.html
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World!
  <p>
    This is the multicontainer scenario!
  </p>
  </h1>
</center>
</body>
</html>
/var/log # exit
Enter fullscreen mode Exit fullscreen mode
user@k8s:$ kubectl logs -f multicontainer -c sidecarcontainer
Connecting to raw.githubusercontent.com (185.199.111.133:443)
wget: note: TLS certificate validation not implemented
saving to '/var/log/index.html'
index.html           100% |********************************|   307  0:00:00 ETA
'/var/log/index.html' saved
Connecting to raw.githubusercontent.com (185.199.111.133:443)
wget: note: TLS certificate validation not implemented
saving to '/var/log/index.html'
index.html           100% |********************************|   307  0:00:00 ETA
'/var/log/index.html' saved
Connecting to raw.githubusercontent.com (185.199.110.133:443)
wget: note: TLS certificate validation not implemented
saving to '/var/log/index.html'
index.html           100% |********************************|   307  0:00:00 ETA
'/var/log/index.html' saved
Enter fullscreen mode Exit fullscreen mode
  • We can forward the port of the pod to the host PC port (hostPort:containerPort, e.g: 8080:80):
user@k8s:$ kubectl port-forward pod/multicontainer 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080

Enter fullscreen mode Exit fullscreen mode
user@k8s:$ curl 127.0.0.1:8080
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World!
  <p>
    This is the multicontainer scenario!
  </p>
  </h1>
</center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • After updating the content of the index.html, new html page will be downloaded by the sidecarcontainer:
user@k8s:$ curl 127.0.0.1:8080
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World!
  <p>
    This is the multicontainer scenario!
  </p>
  </h1>
</center>
</body>
</html>

user@k8s:$ curl 127.0.0.1:8080
<!-- MultiContainer Update Page -->
<html>
<body style="background-color:gray">
<center>
  <h1 style="color:red">
    Hello World! This file is created for the multicontainer-sidecar github update.
  <p>
    This is the multicontainer scenario! Second version.
  </p>
  </h1>
</center>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Delete multicontainer pod, emptydir volume also deleted. The data in an emptyDir volume is transient and exists only as long as the Pod is running on the node. When the Pod is deleted or rescheduled, the data is lost.:
user@k8s:$ kubectl delete -f multicontainer.yaml
pod "multicontainer" deleted

user@k8s:$ kubectl get pods -o wide
No resources found in default namespace.

user@k8s:$  minikube delete
πŸ”₯  Deleting "minikube" in docker ...
πŸ”₯  Deleting container "minikube" ...
πŸ”₯  Removing /home/omer/.minikube/machines/minikube ...
πŸ’€  Removed all traces of the "minikube" cluster.
Enter fullscreen mode Exit fullscreen mode

Conclusion

This post explores sidecar containers (multiple containers within a single pod) and provides hands-on examples to demonstrate their relationships and shared resources. We also mentioned containers' network connection, port-forwarding, emptydir volume, volume sharing between containers in one pod.

If you're interested in exploring other Kubernetes components, please have a look:

Other K8s Feature Post:

If you found the tutorial interesting, I’d love to hear your thoughts in the blog post comments. Feel free to share your reactions or leave a comment. I truly value your input and engagement πŸ˜‰

For other posts πŸ‘‰ https://dev.to/omerberatsezer 🧐

Follow for Tips, Tutorials, Hands-On Labs for AWS, Kubernetes, Docker, Linux, DevOps, Ansible, Machine Learning, Generative AI.

Top comments (0)