[Runtime Defense & Monitoring] - (1) Introduction

โ˜๏ธ ํดํด 5๊ธฐ ์‹œ์ฆŒ 1 ์Šคํ„ฐ๋”” : 90DaysOfDevOps ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ณต๋ถ€ํ•ฉ๋‹ˆ๋‹ค!

 

๐Ÿƒ 28 > System monitoring and auditing

 

90DaysOfDevOps/2023/day28.md at main · MichaelCade/90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things Dev...

github.com

 

๐Ÿ“ System monitoring and auditing

  • ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง → ์‹œ์Šคํ…œ ๋‚ด์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ๊ฐ€์‹œ์„ฑ ์ œ๊ณต→ ๋ณด์•ˆ ์‚ฌ๊ณ  ๊ฐ์ง€ ๋ฐ ๋Œ€์‘
  • ๋Ÿฐํƒ€์ž„ ๋ณด์•ˆ์— ๋ชจ๋‹ˆํ„ฐ๋ง์ด ์ค‘์š”ํ•œ ์ด์œ  5๊ฐ€์ง€
    1. Identifying security incidents(๋ณด์•ˆ ์‚ฌ๊ณ  ๊ฐ์ง€)
    2. Mitigating risks(์‚ฌ์ „ ์กฐ์น˜ → ์œ„ํ—˜ ์™„ํ™”)
    3. Complying with regulations(๊ทœ์ • ์ค€์ˆ˜)
    4. Improving incident response(์‚ฌ๊ณ  ๋Œ€์‘ ์™„ํ™”)
    5. Gaining visibility(๊ฐ€์‹œ์„ฑ ํ™•๋ณด) → ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐ ๋ฌธ์ œ ํ•ด๊ฒฐ์— ์ธ์‚ฌ์ดํŠธ ์ œ๊ณต

๐Ÿ“What to monitor and record?

  • ๋ชจ๋‹ˆํ„ฐ๋ง ํ•ด์•ผ ํ•˜๋Š” ์š”์†Œ๋“ค 7๊ฐ€์ง€
    1. Control plane logging : ์ธํ”„๋ผ์˜ ๋ชจ๋“  ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์ด ์ œ์–ด ํ”Œ๋ ˆ์ธ์„ ํ†ตํ•ด ์ด๋ค„์ง€๊ธฐ ๋•Œ๋ฌธ
    2. Operating level logs : ์šด์˜ ์ฒด์ œ ์ˆ˜์ค€ ์ด๋ฒคํŠธ → ์‹œ์Šคํ…œ ํ™œ๋™ ์ถ”์ , ์˜ค๋ฅ˜์™€ ๋ณด์™„ ์ด๋ฒคํŠธ ๊ฐ์ง€
    3. Network activity : ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ๋ชจ๋‹ˆํ„ฐ๋ง → ๋น„์ •์ƒ์ , ๋น„ํ—ˆ๊ฐ€ ํ™œ๋™ ์‹๋ณ„
    4. Application activity and performance : ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ˆ˜์ค€์—์„œ ์˜ค์ž‘๋™, ๊ณต๊ฒฉ ๊ฐ์ง€
    5. Resource utilization : CPU, ๋ฉ”๋ชจ๋ฆฌ, ๋””์Šคํฌ ๊ณต๊ฐ„ → ๋ณ‘๋ชฉ ํ˜„์ƒ ๊ฐ™์€ ์„ฑ๋Šฅ ๋ฌธ์ œ ์‹๋ณ„
    6. Security configurations : ๋ฐฉํ™”๋ฒฝ ๊ทœ์น™, ์‚ฌ์šฉ์ž ์•ก์„ธ์Šค ์ œ์–ด ๋“ฑ
    7. Backup and disaster recovery systems : ๋ฐฑ์—… ๋ฐ ์žฌํ•ด ๋ณต๊ตฌ ์‹œ์Šคํ…œ

๐Ÿ“์‹ค์ œ ๊ตฌํ˜„ ์‹ค์Šต

(1) Control plane monitoring

 

Auditing

Kubernetes auditing provides a security-relevant, chronological set of records documenting the sequence of actions in a cluster. The cluster audits the activities generated by users, by applications that use the Kubernetes API, and by the control plane its

kubernetes.io

  • Audit policy : k8s API ์„œ๋ฒ„์— ๋ฌด์—‡์„ ๊ธฐ๋กํ•ด์•ผํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ๋Š” ๊ตฌ์„ฑ (ํŒŒ์ผ ์ €์žฅ or ์›น ํ›…์œผ๋กœ ์ „์†ก)

 

๐Ÿš€ ์‹ค์Šต

 

1๏ธโƒฃ audit-policy ์„ค์ • ํ›„ minikube ์‹œ์ž‘

mkdir -p ~/.minikube/files/etc/ssl/certs
cat <<EOF > ~/.minikube/files/etc/ssl/certs/audit-policy.yaml
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
EOF
minikube start --extra-config=apiserver.audit-policy-file=/etc/ssl/certs/audit-policy.yaml --extra-config=apiserver.audit-log-path=-

 

โ–ผ Output

 

 

2๏ธโƒฃ log ํŒŒ์ผ๋กœ ์–ด๋–ค ๋‚ด์šฉ์ด ์ €์žฅ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ

kubectl logs kube-apiserver-minikube -n kube-system | grep audit.k8s.io/v1

→ ๋ชจ๋“  API ๋™์ž‘์ด stream์— ๋กœ๊ทธ๋˜์–ด์„œ ์ธํ”„๋ผ ์š”์ฒญ์˜ ๋ชจ๋“  ์ฃผ์š” ์š”์†Œ(๋ˆ„๊ฐ€, ๋ฌด์—‡์„ ์–ธ์ œ)๊ฐ€ ๊ธฐ๋ก๋œ๋‹ค.

→ ํŒŒ์ผ ์ €์žฅ๋ณด๋‹ค๋Š” ๋กœ๊น… ์‹œ์Šคํ…œ ๋ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ „๋‹ฌ

 

โ–ผ ๊ธฐ๋ณธ k8s์—์„œ Promtail์„ ์‚ฌ์šฉํ•ด์„œ Prometheus์— ๋กœ๊ทธ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •

โ–ผ Output

{
 "kind":"Event",
 "apiVersion":"audit.k8s.io/v1",
 "level":"RequestResponse",
 "auditID":"940c44ba-867c-4b10-b8d0-d1909439828d",
 "stage":"RequestReceived",
 "requestURI":"/apis/storage.k8s.io/v1/csidrivers?limit=500\u0026resourceVersion=0",
 "verb":"list",
 "user":{"username":"system:node:minikube",
 "groups":["system:nodes","system:authenticated"]},
 "sourceIPs":["192.168.49.2"],
 "userAgent":"kubelet/v1.28.3 (linux/arm64) kubernetes/a8a1abc",
 "objectRef":{"resource":"csidrivers","apiGroup":"storage.k8s.io","apiVersion":"v1"},
 "requestReceivedTimestamp":"2024-03-24T18:51:57.319828Z",
 "stageTimestamp":"2024-03-24T18:51:57.319828Z"
 }
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"2a25f269-a98f-4d38-9968-8fc3ced5d7c4","stage":"RequestReceived","requestURI":"/healthz","verb":"get","user":{"username":"system:kube-controller-manager","groups":["system:authenticated"]},"sourceIPs":["192.168.49.2"],"userAgent":"kube-controller-manager/v1.28.3 (linux/arm64) kubernetes/a8a1abc/shared-informers","requestReceivedTimestamp":"2024-03-24T18:51:57.320857Z","stageTimestamp":"2024-03-24T18:51:57.320857Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"2a25f269-a98f-4d38-9968-8fc3ced5d7c4","stage":"ResponseComplete","requestURI":"/healthz","verb":"get","user":{"username":"system:kube-controller-manager","groups":["system:authenticated"]},"sourceIPs":["192.168.49.2"],"userAgent":"kube-controller-manager/v1.28.3 (linux/arm64) kubernetes/a8a1abc/shared-informers","responseStatus":{"metadata":{},"status":"Failure","message":"forbidden: User \"system:kube-controller-manager\" cannot get path \"/healthz\"","reason":"Forbidden","details":{},"code":403},"responseObject":{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \"system:kube-controller-manager\" cannot get path \"/healthz\"","reason":"Forbidden","details":{},"code":403},"requestReceivedTimestamp":"2024-03-24T18:51:57.320857Z","stageTimestamp":"2024-03-24T18:51:57.321207Z","annotations":{"authorization.k8s.io/decision":"forbid","authorization.k8s.io/reason":""}}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"b840d8dc-4a8e-4035-aba6-67f313cb95a2","stage":"RequestReceived","requestURI":"/api/v1/nodes?fieldSelector=metadata.name%3Dminikube\u0026limit=500\u0026resourceVersion=0","verb":"list","user":{"username":"system:node:minikube","groups":["system:nodes","system:authenticated"]},"sourceIPs":["192.168.49.2"],"userAgent":"kubelet/v1.28.3 (linux/arm64) kubernetes/a8a1abc","objectRef":{"resource":"nodes","name":"minikube","apiVersion":"v1"},"requestReceivedTimestamp":"2024-03-24T18:51:57.321209Z","stageTimestamp":"2024-03-24T18:51:57.321209Z"}

 

์‹ค์ œ๋กœ๋Š” ์˜ˆ์˜๊ฒŒ ์ถœ๋ ฅ์„ ํ•ด์ฃผ์ง€ ์•Š์•„์„œ... ์šฐ์„  ์‚ฌ์ง„์€ ์ฒจ๋ถ€ํ•ด๋‘๋ก ํ•˜๊ฒ ๋‹ค

 


(2) Resource monitoring

  • Prometheus(๋กœ๊น… ๋ฐ ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค) + Grafana(UI ๋ฐ ๋Œ€์‹œ๋ณด๋“œ) ์กฐํ•ฉ์ด ๐Ÿ‘๐Ÿป
  • brew install helm ๋กœ helm ๋ฏธ๋ฆฌ ์„ค์น˜ ํ•„์š”ํ•˜๋‹ค! 

 

๐Ÿš€ ์‹ค์Šต

1๏ธโƒฃ helm ์ฐจํŠธ์—์„œ prometheus์™€ grafana ์„ค์น˜ ํ›„ k8s์— ์„œ๋น„์Šค expose

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm install prometheus prometheus-community/prometheus
helm install grafana grafana/grafana
kubectl expose service grafana --type=NodePort --target-port=3000 --name=grafana-np

 

โ–ผ Output

๋”๋ณด๊ธฐ
"prometheus-community" has been added to your repositories
"grafana" has been added to your repositories
NAME: prometheus
LAST DEPLOYED: Mon Mar 25 04:10:07 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The Prometheus server can be accessed via port 80 on the following DNS name from within your cluster:
prometheus-server.default.svc.cluster.local


Get the Prometheus server URL by running these commands in the same shell:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=prometheus,app.kubernetes.io/instance=prometheus" -o jsonpath="{.items[0].metadata.name}")
  kubectl --namespace default port-forward $POD_NAME 9090


The Prometheus alertmanager can be accessed via port 9093 on the following DNS name from within your cluster:
prometheus-alertmanager.default.svc.cluster.local


Get the Alertmanager URL by running these commands in the same shell:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=alertmanager,app.kubernetes.io/instance=prometheus" -o jsonpath="{.items[0].metadata.name}")
  kubectl --namespace default port-forward $POD_NAME 9093
#################################################################################
######   WARNING: Pod Security Policy has been disabled by default since    #####
######            it deprecated after k8s 1.25+. use                        #####
######            (index .Values "prometheus-node-exporter" "rbac"          #####
###### .          "pspEnabled") with (index .Values                         #####
######            "prometheus-node-exporter" "rbac" "pspAnnotations")       #####
######            in case you still need it.                                #####
#################################################################################


The Prometheus PushGateway can be accessed via port 9091 on the following DNS name from within your cluster:
prometheus-prometheus-pushgateway.default.svc.cluster.local


Get the PushGateway URL by running these commands in the same shell:
  export POD_NAME=$(kubectl get pods --namespace default -l "app=prometheus-pushgateway,component=pushgateway" -o jsonpath="{.items[0].metadata.name}")
  kubectl --namespace default port-forward $POD_NAME 9091

For more information on running Prometheus, visit:
https://prometheus.io/
NAME: grafana
LAST DEPLOYED: Mon Mar 25 04:10:09 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:

   kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo


2. The Grafana server can be accessed via port 80 on the following DNS name from within your cluster:

   grafana.default.svc.cluster.local

   Get the Grafana URL to visit by running these commands in the same shell:
     export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}")
     kubectl --namespace default port-forward $POD_NAME 3000

3. Login with the password from step 1 and the username: admin
#################################################################################
######   WARNING: Persistence is disabled!!! You will lose your data when   #####
######            the Grafana pod is terminated.                            #####
#################################################################################
service/grafana-np exposed

 

 

2๏ธโƒฃ Grafana ๋น„๋ฐ€๋ฒˆํ˜ธ ์–ป๊ธฐ

kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

 

  • Output : Grafana ๋น„๋ฐ€๋ฒˆํ˜ธ (e.g : `rsv2K5qMKZSznzjnJXgLXr2b1MMlSBYwm3qvEVxL`)

 

3๏ธโƒฃ Grafana URL ์–ป๊ธฐ

minikube service grafana-np --url

 

โ–ผ Output ( โš ๏ธํ„ฐ๋ฏธ๋„ ๊ณ„์† ์ผœ๋‘ฌ์•ผ ํ•œ๋‹ค!)

 

 

4๏ธโƒฃ  Grafana ๋กœ๊ทธ์ธํ•˜๊ธฐ

 

3๏ธโƒฃ ์—์„œ ์–ป๋Š” URL ์ฃผ์†Œ๋กœ ๋“ค์–ด๊ฐ„๋‹ค!

username์—๋Š” admin, Password์—๋Š” 2๏ธโƒฃ์—์„œ ์•Œ๋ ค์ค€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋กœ๊ทธ์ธ์ด ๋œ๋‹ค!

 

๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™”๋ฉด์ด ๋œฌ๋‹ค!

 

 

5๏ธโƒฃ  ๊ทธ๋ผํŒŒ๋‚˜์™€ ํ”„๋กœ๋ฉ”ํ…Œ์Šค์™€ ์—ฐ๊ฒฐํ•˜๊ธฐ

  1. ๋ฐ์ดํ„ฐ ์†Œ์Šค(Data sources)์—์„œ prometheus ํด๋ฆญํ•˜๊ณ  ์ถ”๊ฐ€ํ•œ๋‹ค.
  2. Connection์— http://prometheus-server ๋ผ๊ณ  ์ž…๋ ฅํ•ด์ฃผ๊ณ  ๋งจ ์•„๋ž˜๋กœ ์Šคํฌ๋กค ๋‚ด๋ ค์„œ Save & Test ํด๋ฆญํ•ด์„œ ์ €์žฅํ•œ๋‹ค

 

 

6๏ธโƒฃ ๋Œ€์‹œ๋ณด๋“œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

๋Œ€์‹œ๋ณด๋“œ(Dashboards) ํƒญ์œผ๋กœ ๊ฐ€์„œ ํŒŒ๋ž€ ๋ฒ„ํŠผ์—์„œ Import ์„ ํƒํ•œ๋‹ค.

 

์ค‘๊ฐ„์— ๋ณด์ด๋Š” Find and import dashboards for common applications ... ์— 6126 ์ ๊ณ  Load ํด๋ฆญํ•œ๋‹ค.

์ด ๋ฒˆํ˜ธ๋Š” ๊ณต๊ฐœ๋œ ๋Œ€์‹œ๋ณด๋“œ ์˜ˆ์‹œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค์™€ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ

DataSource-Prometheus์—์„œ default์ธ prometheus ์„ ํƒ

 

 

์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์ด ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋ฉด ์„ฑ๊ณต~!

'๐Ÿ DevOps & Cloud > 90DaysOfDevOps' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Service Mesh (6) - Ambient Mesh  (1) 2024.04.27
Service Mesh (5) - Security  (1) 2024.04.27
Service Mesh (4) - Observability  (0) 2024.04.26
Service Mesh (3) - Traffic Engineering  (0) 2024.04.26
Service Mesh (2) - Istio Getting-started  (0) 2024.04.26