├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── images
├── kubernetes01.png
├── kubernetes02.png
├── kubernetes03.png
└── multi-container-diagram.png
├── kubernetes-cluster-us-east-1.yaml
└── log-app
├── Dockerfile
├── app.py
├── data
└── example.old
├── eks
├── 00-namespace.yaml
├── 01-deployment.yaml
└── 02-service.yaml
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | venv
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EKS Multi Container Pod Logging
2 |
3 | This demonstration has the purpose of showing how to use multi-container Pods to export application logs to stdout on Amazon EKS, in that way a log proccessor can collect all the logs and send to a log centralizer.
4 |
5 | **This demonstration was tested in us-east-1 region**
6 |
7 | ## Architecture
8 |
9 |
10 |
11 |
12 |
13 | ## Pre Reqs
14 |
15 | - [eksctl](https://eksctl.io/)
16 | - [awscli](https://aws.amazon.com/cli/)
17 | - [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/)
18 |
19 | ## Provision EKS cluster
20 |
21 | We are going to use eksctl to provision our EKS cluster for this demonstration, eksctl will provision the Kubernetes master, nodes and **also the VPC**.
22 |
23 | ```shell
24 | eksctl create cluster -f kubernetes-cluster-us-east-1.yaml
25 | ```
26 |
27 | Now we have to configure our `~/.kube/config` file in order to access our cluster using kubectl.
28 |
29 | ```shell
30 | aws eks --region us-east-1 update-kubeconfig --name kubelogs-cluster
31 | ```
32 |
33 | This will update your kube config file, now let's test if we can access our cluster.
34 |
35 | ```shell
36 | kubectl get nodes
37 | ```
38 |
39 | ## Creating our application Docker image and ECR repository
40 |
41 | In this step we are going to build our application Docker image and create our ECR repository, after that we are going to push the image to the repository, so we will be able to create our application inside our Amazon EKS cluster.
42 |
43 | ```shell
44 | aws ecr create-repository --repository-name multi-container-pod-demo
45 | ```
46 |
47 | Let's build our Docker image
48 |
49 | ```shell
50 | cd log-app && docker build -t multi-container-pod-demo .
51 | ```
52 |
53 | Retrieve an authentication token and authenticate your Docker client to your registry, replace the variables **<>** with your information
54 |
55 | ```shell
56 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr.us-east-1.amazonaws.com
57 | ```
58 |
59 | After the build completes, tag your image so you can push the image to ECR repository.
60 |
61 | ```shell
62 | docker tag multi-container-pod-demo:latest .dkr.ecr..amazonaws.com/multi-container-pod-demo:latest
63 | ```
64 |
65 | Run the following command to push this image to your newly created AWS repository
66 |
67 | ```shell
68 | docker push .dkr.ecr..amazonaws.com/multi-container-pod-demo:latest
69 | ```
70 |
71 | ## Kubernetes Manifests
72 |
73 | In order to our app work we will need to replace the variable inside our Deployment manifest with our new image that we just published in the ECR.
74 |
75 | Open `log-app/eks/01-deployment.yaml` and change `__IMAGE_URI__` to your image URI.
76 |
77 | ```yaml
78 | containers:
79 | - name: python-app
80 | image: __IMAGE_URI__
81 | ports:
82 | - containerPort: 5000
83 | ```
84 |
85 | It will look like the following
86 |
87 | ```yaml
88 | containers:
89 | - name: python-app
90 | image: .dkr.ecr..amazonaws.com/multi-container-pod-demo:latest
91 | ports:
92 | - containerPort: 5000
93 | ```
94 |
95 | Let's deploy our application inside the cluster.
96 |
97 | ```shell
98 | kubectl apply -f eks/
99 | ```
100 |
101 | It will create 3 objecs, namespace, deployment and service.
102 |
103 |
104 |
105 |
106 |
107 | ## Checking application logs
108 |
109 | It's time to check if our multi-container pod works.
110 |
111 | Let's check our Pod
112 |
113 | ```shell
114 | kubectl get pods -n prd
115 | ```
116 |
117 | Get logs of our Python application
118 |
119 | ```
120 | kubectl logs po/ -c python-app -n prd
121 | ```
122 |
123 |
124 |
125 |
126 |
127 | It will return just the logs of the server initialization, but not the request logs because it writes in a file.
128 |
129 | Get logs of our side car container that is responsible to output the logs to stdout.
130 |
131 | ```shell
132 | kubectl logs po/ -c sidecar -n prd -f
133 | ```
134 |
135 | As you can see it show our requests logs, let this terminal open and open other terminal.
136 |
137 | Open a new terminal and get the service URL.
138 |
139 | ```shell
140 | kubectl get svc -n prd | awk '{print $4}'
141 | ```
142 |
143 | Now execute a request to the service public URL.
144 |
145 | ```shell
146 | curl -IL -XGET http:///log
147 | ```
148 |
149 |
150 |
151 |
152 | It will generate random log messsages, as you can see above.
153 |
154 | Let's once again check the logs of the python-app container.
155 |
156 | ```shell
157 | kubectl logs po/ -nprd -c python-app
158 | ```
159 |
160 |
161 |
162 |
163 | No new logs were generated.
164 |
165 | ## Security
166 |
167 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
168 |
169 | ## License
170 |
171 | This library is licensed under the MIT-0 License. See the LICENSE file.
172 |
173 |
--------------------------------------------------------------------------------
/images/kubernetes01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-multi-container-pod-logging/0f3ca8a13944b24e5a59386507fcc262ad64a35a/images/kubernetes01.png
--------------------------------------------------------------------------------
/images/kubernetes02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-multi-container-pod-logging/0f3ca8a13944b24e5a59386507fcc262ad64a35a/images/kubernetes02.png
--------------------------------------------------------------------------------
/images/kubernetes03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-multi-container-pod-logging/0f3ca8a13944b24e5a59386507fcc262ad64a35a/images/kubernetes03.png
--------------------------------------------------------------------------------
/images/multi-container-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-multi-container-pod-logging/0f3ca8a13944b24e5a59386507fcc262ad64a35a/images/multi-container-diagram.png
--------------------------------------------------------------------------------
/kubernetes-cluster-us-east-1.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: eksctl.io/v1alpha5
2 | kind: ClusterConfig
3 | # It will create a dedicated VPC for the cluster
4 | metadata:
5 | name: kubelogs-cluster
6 | region: us-east-1
7 | version: "1.19"
8 |
9 | availabilityZones: ["us-east-1a", "us-east-1b", "us-east-1c"]
10 |
11 | managedNodeGroups:
12 | - name: nodegroup
13 | desiredCapacity: 1
14 | instanceType: t3.medium # This host cluster is using the smallest EC2
15 | ssh:
16 | enableSsm: true
17 | iam:
18 | withAddonPolicies: # Add-on policies to nodes
19 | autoScaler: true
20 | externalDNS: true
21 | certManager: true
22 | appMesh: true
23 | albIngress: true
24 | xRay: true
25 | cloudWatch: true
26 |
27 | # Enable all of the control plane logs
28 | cloudWatch:
29 | clusterLogging:
30 | enableTypes: ["*"]
31 |
--------------------------------------------------------------------------------
/log-app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6-alpine
2 |
3 | #Implementation of Layer Caching
4 | COPY requirements.txt /requirements.txt
5 | RUN pip install -r /requirements.txt
6 | COPY . /app
7 | WORKDIR /app
8 |
9 | EXPOSE 5000
10 |
11 | ENTRYPOINT [ "python" ]
12 | CMD [ "app.py"]
--------------------------------------------------------------------------------
/log-app/app.py:
--------------------------------------------------------------------------------
1 | # import files
2 | from flask import Flask, render_template, request, session, url_for, redirect, jsonify
3 | from datetime import datetime
4 | import uuid
5 | import logging
6 |
7 |
8 | logging.basicConfig(filename='data/example.log', level=logging.INFO)
9 |
10 | app = Flask(__name__)
11 |
12 |
13 | @app.route("/")
14 | def index():
15 | return jsonify({"Status" : "Ok"})
16 |
17 |
18 | @app.route("/health")
19 | def health():
20 | return jsonify({"Status" : "Ok"})
21 |
22 |
23 | @app.route("/log")
24 | def log():
25 |
26 | for i in range(6):
27 | random_string = lowercase_str = uuid.uuid4().hex
28 | now = datetime.now()
29 | dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
30 | log_message = f"This is the new log message generated {random_string} at {dt_string}"
31 | logging.info(log_message)
32 |
33 | return jsonify({"Status" : "Ok"})
34 |
35 |
36 | if __name__ == "__main__":
37 | app.run(debug=True, host='0.0.0.0')
--------------------------------------------------------------------------------
/log-app/data/example.old:
--------------------------------------------------------------------------------
1 | WARNING:werkzeug: * Running on all addresses.
2 | WARNING: This is a development server. Do not use it in a production deployment.
3 | INFO:werkzeug: * Running on http://192.168.0.11:5000/ (Press CTRL+C to quit)
4 | INFO:werkzeug: * Restarting with stat
5 | WARNING:werkzeug: * Debugger is active!
6 | INFO:werkzeug: * Debugger PIN: 728-283-238
7 |
--------------------------------------------------------------------------------
/log-app/eks/00-namespace.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | kind: Namespace
3 | apiVersion: v1
4 | metadata:
5 | name: prd
--------------------------------------------------------------------------------
/log-app/eks/01-deployment.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: python-app
6 | namespace: prd
7 | labels:
8 | app: python-app
9 | spec:
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | app: python-app
14 | template:
15 | metadata:
16 | labels:
17 | app: python-app
18 | spec:
19 | volumes:
20 | - name: shared-data
21 | emptyDir: {}
22 | containers:
23 | - name: python-app
24 | image: __IMAGE_URI__ # Change the value here
25 | ports:
26 | - containerPort: 5000
27 | readinessProbe:
28 | exec:
29 | command:
30 | - cat
31 | - /app/data/example.log
32 | initialDelaySeconds: 5
33 | periodSeconds: 5
34 | livenessProbe:
35 | httpGet:
36 | path: /health
37 | port: 5000
38 | initialDelaySeconds: 5
39 | periodSeconds: 5
40 | volumeMounts:
41 | - name: shared-data
42 | mountPath: /app/data
43 | - name: sidecar
44 | image: busybox
45 | volumeMounts:
46 | - name: shared-data
47 | mountPath: /app/data
48 | command: ["/bin/sh"]
49 | args: ["-c", "tail -f /app/data/example.log"]
50 |
--------------------------------------------------------------------------------
/log-app/eks/02-service.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: python-app-service
6 | namespace: prd
7 | spec:
8 | selector:
9 | app: python-app
10 | ports:
11 | - protocol: TCP
12 | port: 80
13 | targetPort: 5000
14 | type: LoadBalancer
--------------------------------------------------------------------------------
/log-app/requirements.txt:
--------------------------------------------------------------------------------
1 | click==8.0.1
2 | Flask==2.0.1
3 | itsdangerous==2.0.1
4 | Jinja2==3.0.1
5 | MarkupSafe==2.0.1
6 | Werkzeug==2.0.1
7 |
--------------------------------------------------------------------------------